<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas de Medeiros</title>
    <description>The latest articles on DEV Community by Lucas de Medeiros (@lukehxh).</description>
    <link>https://dev.to/lukehxh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F158995%2F5b74a725-ccd2-4cfd-9297-fc02d6cbbeeb.jpeg</url>
      <title>DEV Community: Lucas de Medeiros</title>
      <link>https://dev.to/lukehxh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lukehxh"/>
    <language>en</language>
    <item>
      <title>Minha experiência migrando projetos para estrutura de Monorepo com lerna.js</title>
      <dc:creator>Lucas de Medeiros</dc:creator>
      <pubDate>Mon, 14 Sep 2020 15:26:32 +0000</pubDate>
      <link>https://dev.to/lukehxh/minha-experiencia-migrando-projetos-para-estrutura-de-monorepo-com-lerna-js-218i</link>
      <guid>https://dev.to/lukehxh/minha-experiencia-migrando-projetos-para-estrutura-de-monorepo-com-lerna-js-218i</guid>
      <description>&lt;p&gt;Recentemente, adotei a estrutura de &lt;strong&gt;Monorepo&lt;/strong&gt; em um de meus projetos pessoais, o &lt;a href="https://github.com/lucasmedeiros/game-slot"&gt;Game Slot&lt;/a&gt;. Alguns motivos que me levaram a tomar essa decisão envolvem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;o escopo bem fechado e definido, sendo uma aplicação React, armazenada em um repositório chamado &lt;strong&gt;game-slot&lt;/strong&gt;, que se comunica com uma API feita em NodeJS, antes no repositório &lt;strong&gt;game-slot-api&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;features que realizavam mudanças no backend e no frontend da aplicação agora podem ser resolvidas em uma única Pull Request para apenas um repositório;&lt;/li&gt;
&lt;li&gt;maior praticidade de lidar com configurações e dependências.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A princípio, fazer isso me pareceu uma tarefa simples, mas fui me deparando com alguns aspectos que irei discorrer ao longo deste artigo que acabaram tornando o processo um pouquinho menos trivial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Versionamento
&lt;/h2&gt;

&lt;p&gt;Inicialmente, pensei em apenas copiar todo o código da API que existia no repositório &lt;strong&gt;game-slot-api&lt;/strong&gt; e colar dentro de uma pasta &lt;code&gt;backend/&lt;/code&gt; no &lt;strong&gt;game-slot&lt;/strong&gt;, repositório que consistiria o monorepo, e também mover o código React para uma pasta &lt;code&gt;frontend/&lt;/code&gt;. Isso transformaria a estrutura do repo em algo parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root/
├── backend/
│   ├── .eslintrc
│   ├── package.json
│   └── ...
├── frontend/
│   ├── .eslintrc
│   ├── package.json
│   └── ...
├── .gitignore
└── README.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Porém, simplesmente copiar e colar o código da API dentro do monorepo significaria perder todos os commits que já tinham sido feitos no &lt;strong&gt;game-slot-api&lt;/strong&gt; e apenas criaria um commit cheio de alterações.&lt;/p&gt;

&lt;p&gt;Você pode até pensar que a perda desse histórico pode não se tornar algo crítico ou até não ser algo relevante para se preocupar. Eu concordo que, para o meu caso, não iria ter tanto impacto, mas fazer isso definitivamente não é uma boa prática, principalmente se você toma essa decisão em um cenário em que vários projetos e pacotes que já estão em produção e sendo utilizados por uma quantidade considerável de usuários são afetados.&lt;/p&gt;

&lt;p&gt;Incomodado com essa situação, pesquisei sobre alguma forma de manter o histórico de um repositório em um monorepo, e descobri que utilizar o &lt;a href="https://github.com/lerna/lerna"&gt;lerna&lt;/a&gt; poderia tornar minha vida muito mais fácil, já que é uma ferramenta feita especificamente para gerenciar projetos em JavaScript feitos em múltiplos pacotes, como sua própria descrição diz. Um de seus comandos é o &lt;a href="https://github.com/lerna/lerna/tree/master/commands/import#readme"&gt;lerna import&lt;/a&gt;, que importa o projeto (ou pacote) de um repositório, preservando os autores, as mensagens e datas dos commits.&lt;/p&gt;

&lt;p&gt;Então, iniciei um novo projeto lerna dentro da pasta raiz do repositório &lt;strong&gt;game-slot&lt;/strong&gt; com &lt;code&gt;npx lerna init&lt;/code&gt;, e rodei o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx lerna import ~/game-slot-api &lt;span class="nt"&gt;--dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
Dependendo do tamanho e organização do projeto que você tentar importar, esse comando pode causar alguns problemas. Você pode acessar a &lt;a href="https://github.com/lerna/lerna/tree/master/commands/import#readme"&gt;documentação do comando import&lt;/a&gt; e verificar algumas flags adicionais que possam auxiliar no processo.





&lt;p&gt;Isso gerou uma pasta &lt;strong&gt;packages/&lt;/strong&gt;, que contém todos os pacotes do monorepo, e mandou para lá o novo pacote &lt;strong&gt;backend&lt;/strong&gt; com todos os commits existentes no repositório antigo &lt;em&gt;automagicamente&lt;/em&gt;! Depois, movi o código React já existente para &lt;strong&gt;packages/frontend&lt;/strong&gt;. Também renomeei a pasta &lt;strong&gt;packages/&lt;/strong&gt; para &lt;strong&gt;game-slot/&lt;/strong&gt; e fiz as modificações necessárias no arquivo &lt;code&gt;lerna.json&lt;/code&gt; e &lt;code&gt;package.json&lt;/code&gt; a fim de poder chamar meus dois "pacotes" de &lt;code&gt;@game-slot/frontend&lt;/code&gt; e &lt;code&gt;@game-slot/backend&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependências
&lt;/h2&gt;

&lt;p&gt;Agora eu tinha meus dois projetos importados dentro de um único repositório preservando os commits de todos, do jeito que eu queria! Mas depois, percebi que não estava tirando proveito de uma das melhores vantagens de se usar Monorepo: facilidade no gerenciamento de dependências.&lt;/p&gt;

&lt;p&gt;Existiam várias dependências que eram compartilhadas entre os dois projetos, como o &lt;code&gt;node-fetch&lt;/code&gt;, &lt;code&gt;eslint&lt;/code&gt;, entre outras, que estavam nos arquivos &lt;code&gt;package.json&lt;/code&gt; de ambos backend e frontend.&lt;/p&gt;

&lt;p&gt;Depois de uma análise de dependências que apareciam nos dois pacotes e para cada uma encontrada, adicionei como dependência global do projeto, rodando o seguinte comando na pasta raiz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx lerna add &amp;lt;nome-do-pacote&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
Novamente, para ter acesso a flags e opções a mais do comando add, verifique &lt;a href="https://github.com/lerna/lerna/tree/master/commands/add#readme"&gt;sua documentação&lt;/a&gt;





&lt;p&gt;Isso me possibilitou algo que achei bastante vantajoso: usar a mesma versão de cada uma das dependências em ambos os projetos e uma maior praticidade para gerenciá-las futuramente. Lindo, né?&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploys
&lt;/h2&gt;

&lt;p&gt;Com os dois projetos configurados e com um fácil gerenciamento de dependências, agora foi a vez de resolver o problema do deploy, tanto do backend quanto do frontend. Eu já estava utilizando o &lt;strong&gt;Heroku&lt;/strong&gt; para deploy da API do Game Slot e o &lt;strong&gt;Netlify&lt;/strong&gt; para o sistema web com React, e acabei encontrando soluções pesquisando por casos similares de problemas que outras pessoas já passaram e resolveram.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para o frontend, eu utilizei o &lt;a href="https://docs.netlify.com/configure-builds/common-configurations/#monorepos"&gt;guia do Netlify&lt;/a&gt; para configurações comuns de build para variados estilos de projeto, incluindo monorepo.&lt;/li&gt;
&lt;li&gt;Já no backend, eu segui este &lt;a href="https://stackoverflow.com/a/53221996"&gt;tutorial&lt;/a&gt; para automatizar os deploys no Heroku em uma estrutura de monorepo, fazendo adaptações para o meu caso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fluxo de desenvolvimento
&lt;/h2&gt;

&lt;p&gt;O fluxo de desenvolvimento se manteve quase o mesmo, qualquer pessoa pode criar uma issue e atribuí-la a mim ou a ela mesma para que seja resolvida. Então, é aberta uma PR que irá passar pelo processo de review. A única mudança é que agora o repositório também receberá issues e contribuições de backend também.&lt;/p&gt;

&lt;p&gt;Para desenvolver, primeiramente deve-se configurar as variáveis de ambiente necessárias, explicadas no &lt;code&gt;README&lt;/code&gt; de cada um dos projetos, e em seguida rodar os comandos abaixo para rodar backend e frontend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn bootstrap &lt;span class="c"&gt;# instalação de todos os pacotes e dependências do projeto&lt;/span&gt;
yarn start:backend &lt;span class="c"&gt;# rodar o backend em modo de desenvolvimento&lt;/span&gt;
yarn start:frontend &lt;span class="c"&gt;# rodar o frontend em modo de desenvolvimento&lt;/span&gt;

&lt;span class="c"&gt;# ou opcionalmente&lt;/span&gt;

npm run bootstrap &lt;span class="c"&gt;# instalação de todos os pacotes e dependências do projeto&lt;/span&gt;
npm run start:backend &lt;span class="c"&gt;# rodar o backend em modo de desenvolvimento&lt;/span&gt;
npm run start:frontend &lt;span class="c"&gt;# rodar o frontend em modo de desenvolvimento&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Algumas motivações citadas que me levaram a aplicar &lt;strong&gt;Monorepo&lt;/strong&gt; no meu projeto podem variar facilmente de um contexto para outro. Dando uma boa pesquisada, você vai encontrar argumentos &lt;a href="https://medium.com/@ricardo.mello/um-ano-de-monorepo-o-que-aprendemos-e-porque-voc%C3%AA-deveria-us%C3%A1-lo-d3130280bd7d"&gt;a favor&lt;/a&gt; e &lt;a href="https://medium.com/@mattklein123/monorepos-please-dont-e9a279be011b"&gt;contra&lt;/a&gt; a sua utilização, e também debates bem acalorados em fóruns e discussões por aí.&lt;/p&gt;

&lt;p&gt;É bom citar que o meu caso consiste em um projeto pessoal de faculdade em que eu apliquei um pouco mais de esforço, e a única pessoa realmente responsável pelo desenvolvimento desse código sou eu, não existe um time. Ou seja, obviamente isso pode não funcionar em times com organizações e tamanhos diferentes. Adotar ou não esse padrão requer muito debate, e todos os integrantes do time devem ter espaço para opinar!&lt;/p&gt;

&lt;p&gt;Dito isso, espero que tenham gostado desse artigo, e que tenha sido útil de alguma forma 😄.&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>monorepo</category>
      <category>lerna</category>
    </item>
    <item>
      <title>Criar um App com a Slack Web API para impulsionar seu time</title>
      <dc:creator>Lucas de Medeiros</dc:creator>
      <pubDate>Mon, 11 May 2020 15:33:11 +0000</pubDate>
      <link>https://dev.to/lukehxh/criar-um-slack-app-para-impulsionar-seu-time-33dh</link>
      <guid>https://dev.to/lukehxh/criar-um-slack-app-para-impulsionar-seu-time-33dh</guid>
      <description>&lt;p&gt;Ter um workspace no &lt;a href="https://slack.com/"&gt;Slack&lt;/a&gt; para seu time/empresa é uma ótima opção para tornar a comunicação interna mais profissional que outras plataformas de mensagens de texto instantâneas e sem a "burocracia" das trocas de e-mail. Para atingir esse objetivo, o Slack disponibiliza uma infinidade de features, como ampla capacidade de customização, praticidade para compartilhamento de arquivos, &lt;em&gt;snippets&lt;/em&gt;, chamadas de voz, entre outras. E ainda tem um plus: também é disponibilizada uma &lt;a href="https://api.slack.com/"&gt;API&lt;/a&gt; muito completa para desenvolvimento de aplicações incríveis!&lt;/p&gt;

&lt;h2&gt;
  
  
  Como uma aplicação slack poderia ser útil?
&lt;/h2&gt;

&lt;p&gt;Com uma aplicação customizada, você tem ainda mais opções para expandir os benefícios do seu workspace Slack, como criação de bots e interações automáticas para aumentar a praticidade e comodidade, criação de &lt;a href="https://slack.com/intl/pt-br/help/articles/201259356-Como-usar-comandos-de-barra-integrados"&gt;comandos &lt;em&gt;slash&lt;/em&gt;&lt;/a&gt;, criar ferramentas internas, automatizar a gerência do seu workspace, de canais, e muito mais. Você pode se aprofundar e &lt;a href="https://api.slack.com/start/overview"&gt;ler mais sobre Slack Apps aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos agora criar uma pequena aplicação capaz de lidar com comandos &lt;em&gt;slash&lt;/em&gt; customizados e realizar ações no workspace. Todo o código produzido aqui &lt;a href="https://github.com/lucasmedeiros/slack_app_example"&gt;está disponível no Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Etapa 1: Criação de um workspace
&lt;/h2&gt;

&lt;p&gt;O primeiro passo a ser tomado é garantir que você tenha privilégios de administrador em um workspace Slack. Se você ainda não obedece essa condição em nenhum dos workspaces em que você está cadastrado, acesse a &lt;a href="https://slack.com/"&gt;página inicial&lt;/a&gt; do Slack, selecione a opção &lt;strong&gt;Criar um novo workspace&lt;/strong&gt; e siga o fluxo de criação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ZisPmwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rmw9w0554dz57h8kec00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ZisPmwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rmw9w0554dz57h8kec00.png" alt="Novo workspace slack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GJxDt6G_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g0nugjltsg66wxcsfvjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GJxDt6G_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g0nugjltsg66wxcsfvjz.png" alt="Slack Home"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EWpT4QmQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/45xmfvr0q0snj2pxooy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EWpT4QmQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/45xmfvr0q0snj2pxooy7.png" alt="New Workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Preencha as informações restantes, e seu workspace estará criado! Você será redirecionado automaticamente ao término do processo de criação. Lá, conclua a configuração de algumas informações (como sua senha de acesso) e, caso queira, faça o pequeno tutorial de utilização da plataforma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Etapa 2: Criando o Slack App
&lt;/h2&gt;

&lt;p&gt;Acessando a página &lt;a href="https://api.slack.com/apps"&gt;Applications&lt;/a&gt; da API do Slack, você verá um botão em cima com a opção "Create New App". Ao selecioná-la, você deverá informar o nome da sua aplicação (neste exemplo, usarei &lt;strong&gt;Slack App Example&lt;/strong&gt;) e o seu workspace de desenvolvimento, que é o workspace em que você usará para testar sua aplicação enquanto estiver em modo de desenvolvimento. Futuramente, você pode &lt;a href="https://api.slack.com/start/distributing"&gt;distribuí-la&lt;/a&gt; e permitir que seja instalada em outros workspaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y_xyTlGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l0mclk42n05u5vntmhj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y_xyTlGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l0mclk42n05u5vntmhj6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se tudo ocorreu bem até agora, você será redirecionado para a tela de informações básicas do seu app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z43XR7OF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b9mcoco5w825bd57figb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z43XR7OF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b9mcoco5w825bd57figb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No menu lateral, selecione &lt;strong&gt;App Home&lt;/strong&gt;, e lá você deve clicar no botão &lt;strong&gt;Review Scopes to Add&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gf7hUBEj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6eira75km3kiorc0c29b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gf7hUBEj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6eira75km3kiorc0c29b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na seção &lt;strong&gt;Bot Token Scopes&lt;/strong&gt;, você deve, basicamente, definir que permissões seu app/bot terá no workspace. Para ler mais sobre permissões e escopos do Slack, acesse &lt;a href="https://api.slack.com/legacy/oauth-scopes"&gt;este link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As permissões e escopos necessárias para a aplicação que vamos desenvolver são:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chat:write
Send messages as Slack App Example

chat:write.public
Send messages to channels @slack_app_example isn't a member of

commands
Add shortcuts and/or slash commands that people can use

im:read
View basic information about direct messages that Slack App Example has been added to
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Após selecionar as permissões, ao voltar para a &lt;strong&gt;App Home&lt;/strong&gt; no menu lateral, veremos uma mudança na página. Agora, nosso app tem um &lt;strong&gt;Bot Token&lt;/strong&gt;, que permite que ele se comunique e realize determinadas ações no nosso workspace baseadas nas permissões que definimos anteriormente. Você pode customizar o nome que o nosso bot terá e decidir se quer que ele apareça sempre online.&lt;/p&gt;

&lt;p&gt;Ao terminar a configuração, você deve ir para a página &lt;strong&gt;Install App&lt;/strong&gt;, também acessível pelo menu lateral, e instalar sua aplicação no workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cIdo_iK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8crpeomv4k8p2qn8fchk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cIdo_iK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8crpeomv4k8p2qn8fchk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto, nosso app está criado e instalado no workspace!&lt;/p&gt;

&lt;p&gt;Claro, ele ainda não é magicamente capaz de se comunicar no workspace do jeito que queremos, nem de disponibilizar nossos comandos &lt;em&gt;slash&lt;/em&gt; automaticamente, mas vamos torná-lo capaz disso nas próximas etapas. Perceba que na página agora tem um &lt;strong&gt;Bot User OAuth Access Token&lt;/strong&gt;, com um prefixo &lt;code&gt;xoxb-&lt;/code&gt;. &lt;strong&gt;Spoiler&lt;/strong&gt;: precisaremos dele.&lt;/p&gt;

&lt;h2&gt;
  
  
  Etapa 3: Criando um pequeno servidor com Express
&lt;/h2&gt;

&lt;p&gt;Para lidar com as requisições dos nossos comandos &lt;em&gt;slash&lt;/em&gt;, precisamos criar uma API própria. Para que isso seja feito da maneira mais simples possível neste tutorial, vou criar um servidor básico com node e &lt;code&gt;express&lt;/code&gt;. Caso ainda não esteja familiarizado com essas tecnologias, siga esse &lt;a href="https://udgwebdev.github.io/node-js-para-leigos-instalacao-e-configuracao/"&gt;tutorial&lt;/a&gt; para configurar seu ambiente com NodeJS e o gerenciador de dependências &lt;code&gt;npm&lt;/code&gt; (você também pode querer instalar o &lt;a href="https://yarnpkg.com/"&gt;yarn&lt;/a&gt;). Para ter acesso à mais informações do &lt;code&gt;express&lt;/code&gt;, você pode acessar a documentação a partir de sua &lt;a href="https://expressjs.com/"&gt;página inicial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Para iniciar o desenvolvimento, abra o terminal e digite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir slack_app_example
cd slack_app_example
npm init -y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Isso vai iniciar um projeto node dentro da pasta &lt;code&gt;slack_app_example&lt;/code&gt;, a raiz do nosso projeto. Agora vamos criar um diretório chamado &lt;code&gt;src&lt;/code&gt; e lá estarão o arquivo &lt;code&gt;index.js&lt;/code&gt; e as pastas &lt;code&gt;routes&lt;/code&gt;, &lt;code&gt;services&lt;/code&gt; e &lt;code&gt;controllers&lt;/code&gt;. Assim será definida a estrutura do nosso projeto. No terminal, instale o &lt;code&gt;express&lt;/code&gt;, &lt;code&gt;cors&lt;/code&gt;, &lt;code&gt;@slack/web-api&lt;/code&gt; e, caso prefira, também o &lt;code&gt;nodemon&lt;/code&gt; em modo dev para facilitar o desenvolvimento com reload automático:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i express cors @slack/web-api
npm i -D nodemon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;No arquivo &lt;code&gt;package.json&lt;/code&gt;, adicione os seguintes scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon src/index.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Agora, no arquivo &lt;code&gt;index.js&lt;/code&gt;, inicie seu servidor &lt;code&gt;express&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERVER_PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SERVER_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SERVER_PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Agora, vamos criar a nossa primeira rota, que será capaz de receber um comando slash &lt;code&gt;/hello&lt;/code&gt; de um usuário do workspace, e deve mandar uma mensagem "Olá, mundo!" para um canal de texto do workspace, visível para todos.&lt;/p&gt;

&lt;p&gt;Dentro das pastas &lt;code&gt;routes&lt;/code&gt;, &lt;code&gt;controllers&lt;/code&gt; e &lt;code&gt;services&lt;/code&gt;, vamos criar um arquivo chamado &lt;code&gt;slack.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Em &lt;code&gt;services/slack.js&lt;/code&gt;, estará nossa instância da &lt;code&gt;WebAPI&lt;/code&gt; do Slack, e usaremos os métodos dela. Você precisará setar aqui aquele &lt;strong&gt;Bot User OAuth Access Token&lt;/strong&gt; que citamos na etapa anterior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cuidado&lt;/strong&gt;: essa informação é sensível, e caso seu código seja open-source, não faça um commit publicamente contendo este token, ou seu workspace estará vulnerável a utilizações indesejadas de terceiros. Você pode fazer uma configuração de variáveis de ambiente no seu projeto para protegê-lo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/services/slack.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@slack/web-api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BOT_USER_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR-TOKEN-HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;web&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BOT_USER_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SlackService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;postTextMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageArguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageArguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SlackService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Com isso, temos um método genérico no serviço de Slack para enviar mensagens para algum canal ou mensagem direta, recebendo as opções pelo parâmetro &lt;code&gt;messageArguments&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora, no controlador, vamos chamar esse método que acabamos de definir para que seja enviada uma mensagem com texto "Olá, mundo!" para o canal &lt;code&gt;#general&lt;/code&gt; (como a configuração do meu workspace está em português, o nome fica &lt;code&gt;#geral&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/controllers/slack.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slackService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../services/slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SlackController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;slackService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postTextMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geral&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Canal de sua preferência&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Olá, mundo!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mensagem enviada com sucesso!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SlackController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;No arquivo de configuração das rotas &lt;code&gt;routes/slack.js&lt;/code&gt;, vamos expor esse endpoint para requisições &lt;code&gt;POST&lt;/code&gt; (o Slack enviará requisições POST nos comandos cadastrados no seu app).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/routes/slack.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../controllers/slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Agora, para fazer nossa aplicação funcionar, devemos criar um &lt;code&gt;index.js&lt;/code&gt; dentro da pasta &lt;code&gt;routes&lt;/code&gt;, chamando a rota que acabamos de criar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slackRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slackRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ao rodar o servidor com &lt;code&gt;npm run dev&lt;/code&gt; (iniciando em modo de desenvolvimento com reload automático a cada mudança que fizer no código, caso tenha optado por utilizar o &lt;code&gt;nodemon&lt;/code&gt;) ou &lt;code&gt;npm start&lt;/code&gt;, a aplicação deve imprimir a seguinte mensagem no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;Server listening on port 5500
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Etapa 4: Expondo seu servidor com ngrok
&lt;/h2&gt;

&lt;p&gt;Como o Slack não permite URL's locais, você pode expor sua URL de desenvolvimento local para não precisar hospedar sua aplicação apenas para testar. Crie uma conta no &lt;a href="https://ngrok.com/download"&gt;site do ngrok&lt;/a&gt; e faça o download do seu &lt;code&gt;.zip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Uma vez que o ngrok estiver instalado e configurado seguindo os passos listados na sua página, certifique-se de que seu servidor também está rodando em uma aba de seu terminal, inicie outra sessão no terminal e rode o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok http &amp;lt;PORT&amp;gt; --region=eu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Substituindo &lt;code&gt;&amp;lt;PORT&amp;gt;&lt;/code&gt; pela porta utilizada pelo seu servidor, nesse caso, a porta &lt;code&gt;5500&lt;/code&gt;, como foi definido no arquivo &lt;code&gt;index.js&lt;/code&gt; na pasta raiz do projeto. Copie a URL que será mostrada na tela do terminal, deve ser algo como &lt;code&gt;https://s0m3th1ng.ngrok.io&lt;/code&gt;, que aparecerá em alguma das linhas que serão mostradas após rodar o comando (recomendo escolher a opção com &lt;code&gt;https&lt;/code&gt;). Essa URL será o prefixo de todas as outras URL's que serão utilizadas ao decorrer deste tutorial, e para fins didáticos vou chamá-la de &lt;code&gt;:path:&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Etapa 5: Conectando o Slack App com a API
&lt;/h2&gt;

&lt;p&gt;De volta à página de informações básicas de seu App, acesse a opção &lt;strong&gt;Slash Commands&lt;/strong&gt; no menu lateral. Lá, você deve clicar na opção &lt;strong&gt;Create New Command&lt;/strong&gt;. Defina o comando como &lt;code&gt;/hello&lt;/code&gt;, a &lt;strong&gt;Request URL&lt;/strong&gt; deve ser &lt;code&gt;:path:/slack/hello&lt;/code&gt;, que é o endpoint de nossa API que acabamos de criar, e caso queira, coloque uma descrição do comando e algumas dicas de uso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5mEQ6R22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j59wo62ndi8f6n4mqw0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5mEQ6R22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j59wo62ndi8f6n4mqw0u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após clicar em &lt;strong&gt;Save&lt;/strong&gt;, o seu novo comando personalizado estará disponível para uso no seu workspace!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dyZsyAum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u8egkb7jgiliyblfx5pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dyZsyAum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u8egkb7jgiliyblfx5pp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZrJtfleq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i2dwpcze4fuzpv8xnagm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZrJtfleq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i2dwpcze4fuzpv8xnagm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Este foi um pequeno exemplo de como podemos criar um Slack App e conectá-lo com uma API interna para criar comandos customizados. Você pode expandir seus horizontes e criar modais e componentes interativos para facilitar a experiência ao chamar os comandos, por exemplo. Leia mais aqui sobre &lt;a href="https://api.slack.com/interactivity/slash-commands"&gt;interatividade com comandos &lt;em&gt;slash&lt;/em&gt;&lt;/a&gt;. E com Slack Apps, você pode fazer também muito mais!&lt;/p&gt;

&lt;p&gt;Espero que tenham gostado desse tutorial, e que tenha sido útil de alguma forma 😄.&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>tutorial</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Contribuindo para projetos open source com GitHub</title>
      <dc:creator>Lucas de Medeiros</dc:creator>
      <pubDate>Sat, 03 Aug 2019 22:04:45 +0000</pubDate>
      <link>https://dev.to/opendevufcg/contribuindo-para-projetos-open-source-com-github-3i76</link>
      <guid>https://dev.to/opendevufcg/contribuindo-para-projetos-open-source-com-github-3i76</guid>
      <description>&lt;p&gt;Criado em 2008 e bem aperfeiçoado desde então, o GitHub não apenas é, atualmente, o mais conhecido serviço web que oferece diversas funcionalidades aplicadas ao Git para hospedagem e versionamento de código-fonte, como também é um grande impulsionador da iniciativa open source e do trabalho em equipe. Cada vez mais, a plataforma tem adquirido uma cara de rede social, visando engajar mais pessoas em relação a contribuição em projetos de código aberto, participação em suas respectivas comunidades, além de dar mais visibilidade a tais projetos. Isso foi possível devido a inúmeras funcionalidades adotadas e implementadas pelo GitHub a fim de atingir esses objetivos, e algumas delas serão introduzidas nesse post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fca2pyzgamadnsl53fbgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fca2pyzgamadnsl53fbgn.png" alt="Página inicial do GitHub atualmente"&gt;&lt;/a&gt;&lt;/p&gt;
Screenshot da página inicial do GitHub atualmente.



&lt;h2&gt;
  
  
  Comunidade open source
&lt;/h2&gt;

&lt;p&gt;Antes de prosseguir no post, é preciso deixar claro um conceito para comunidade open source. Uma comunidade é formada por &lt;strong&gt;Users&lt;/strong&gt;, &lt;strong&gt;Contributors&lt;/strong&gt; e &lt;strong&gt;Mantainers&lt;/strong&gt;. O grupo de usuários (&lt;em&gt;users&lt;/em&gt;) é composto por pessoas que vão utilizar um sistema que está sendo desenvolvido em código aberto, e são ativas na comunidade reportando possíveis bugs no desenvolvimento e dando sugestões de melhoria e de novas &lt;em&gt;features&lt;/em&gt;. Além disso, dependendo da licença utilizada pelo projeto, usuários podem fazer modificações livremente, por exemplo, alterar partes do sistema para uso pessoal, utilização como componente em outro projeto e até comercializá-lo. Para saber o que pode e o que não pode fazer, é sempre bom checar o arquivo &lt;strong&gt;LICENSE&lt;/strong&gt; do repositório e verificar as permissões.&lt;/p&gt;

&lt;p&gt;O que diferencia um usuário de um contribuidor (&lt;em&gt;contributor&lt;/em&gt;) é a efetividade para a organização que encabeça o projeto. O contribuidor levanta discussões mais profundas e úteis para a organização, altera diretamente o código e faz requisições de anexação do seu conteúdo ao original. Os motivos que levam alguém a contribuir com uma organização podem ser diversos: o desejo de melhorar aplicações que ele mesmo utiliza, identificação com a organização, aplicação prática de conhecimentos acerca de uma tecnologia, ganhar visibilidade com contribuições úteis e reais, entre outros. Esse é o espírito do open source.&lt;/p&gt;

&lt;p&gt;Vale ressaltar dois pontos: primeiro, o contribuidor não está vinculado à organização. Isso significa que alguém pode aparecer repentinamente para contribuir e, da mesma forma, pode parar a qualquer momento. Segundo, é muito comum que a organização estabeleça regras para contribuição e é importantíssimo que o contribuidor esteja por dentro de todas elas antes de começar. Por isso, ele deve ler bem o que há nos arquivos &lt;strong&gt;README.md&lt;/strong&gt;, &lt;strong&gt;CONTRIBUTING.md&lt;/strong&gt; e &lt;strong&gt;CODE_OF_CONDUCT.md&lt;/strong&gt;, caso existam.&lt;/p&gt;

&lt;p&gt;Por fim, temos os mantenedores (&lt;em&gt;maintainers&lt;/em&gt;). Estes são os administradores responsáveis por manter o projeto "vivo" e atualizado, pois eles são membros &lt;strong&gt;efetivos&lt;/strong&gt; da organização, e têm privilégios de administrador no repositório do GitHub. Eles devem estar por dentro das discussões que envolvem o projeto, fazer correções de bugs, implementar features, revisar requisições de contribuidores e são os responsáveis por manter o projeto organizado: disposição dos arquivos e diretórios no repositório, alocação de &lt;em&gt;tasks&lt;/em&gt;, categorização dos tópicos das discussões, entre outras obrigações.&lt;/p&gt;

&lt;p&gt;Agora, com o conceito de comunidades open source mais claro, podemos começar a falar sobre as maneiras que o GitHub encontrou para impulsioná-las e como você pode utilizar a plataforma para fazer parte de uma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stars e forks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpu4yui075180v6w6k318.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpu4yui075180v6w6k318.png" alt="Stars e forks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao acessar um repositório público no GitHub, você pode dar uma &lt;strong&gt;star&lt;/strong&gt;, &lt;em&gt;feature&lt;/em&gt; similar às "curtidas" das redes sociais mais famosas, e também pode fazer um &lt;strong&gt;fork&lt;/strong&gt;, que consiste na criação de uma cópia independente deste repositório, que contém todo o seu conteúdo, para a sua conta de usuário no GitHub. Na tela inicial, são mostradas as &lt;strong&gt;stars&lt;/strong&gt; e &lt;strong&gt;forks&lt;/strong&gt; que as pessoas que você segue dão em repositórios públicos, uma funcionalidade que tem por objetivo a ampliação do alcance dos projetos open source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Requests (PR's) e Issues
&lt;/h2&gt;

&lt;p&gt;A partir de um &lt;strong&gt;fork&lt;/strong&gt;, quando terminar de fazer as alterações que julgar necessárias, você pode submeter uma requisição de anexação do seu conteúdo modificado ao conteúdo original do repositório escolhido. Essa requisição é a &lt;strong&gt;pull request&lt;/strong&gt;, a forma mais característica de contribuição a um projeto na plataforma, que será revisada por um maintainer. Observe abaixo o processo para abrir uma nova PR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FDsAq3NW.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FDsAq3NW.gif" alt="Submetendo uma nova PR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Também é importante ter em mente que uma contribuição para um projeto open source vai além de modificações diretas no código-fonte. Um feedback, alerta de bugs no software que está sendo desenvolvido, discussões a respeito de um novo passo que pode ser tomado em prol do projeto, troca de ideias e sugestões podem impactar profundamente no futuro do projeto e até da organização. Por isso, é extremamente importante que uma organização fique sempre atenta ao que sua comunidade tem a dizer.&lt;/p&gt;

&lt;p&gt;Tendo em vista esse contexto, o GitHub disponibiliza as &lt;strong&gt;issues&lt;/strong&gt;, um espaço que pode ser utilizado tanto por usuários comuns quanto por maintainers, para a finalidade de todos os pontos citados e também para priorização e organização das tarefas a serem desenvolvidas. Observe abaixo o processo para abrir uma nova issue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fn0TkrzC.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fn0TkrzC.gif" alt="Submetendo uma nova issue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Descobrindo repositórios e contribuindo
&lt;/h2&gt;

&lt;p&gt;É muito comum que não se saiba muito bem por onde começar a contribuir no início da "aventura" pelo mundo open source. Para minimizar essa dificuldade, você pode visualizar a seção &lt;strong&gt;&lt;a href="https://github.com/discover" rel="noopener noreferrer"&gt;discover repositories&lt;/a&gt;&lt;/strong&gt;, que traz recomendações muito interessantes de projetos, baseadas em outros repositórios que você deu star, em pessoas que você segue, em tecnologias recentes que você trabalhou e também em popularidade do projeto, os &lt;strong&gt;trendings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Depois de localizar um projeto com o qual se identificou, você pode explorar o arquivo &lt;strong&gt;README.md&lt;/strong&gt; a fim de obter informações a respeito do que se trata o projeto, com quais tecnologias ele trabalha, como rodar na sua máquina, link da página principal, entre outras. É importante ter em mente que a disponibilidade dessas informações nesse arquivo depende bastante da organização que criou o projeto, e como ela organiza suas atividades.&lt;/p&gt;

&lt;p&gt;Depois de se informar sobre esse projeto e decidir que quer contribuir para ele, um ótimo ponto de partida é olhar as issues abertas e verificar as suas &lt;strong&gt;labels&lt;/strong&gt;, que consistem em uma forma de categorização e priorização de issues e PR's para ajudar na organização do trabalho. A fim de te deixar mais confortável para começar a contribuir, é interessante que a procura inicial seja por labels de &lt;strong&gt;good first issue&lt;/strong&gt;, &lt;strong&gt;easy&lt;/strong&gt; e &lt;strong&gt;help wanted&lt;/strong&gt;, por exemplo. Vale ressaltar também que essa categorização de issues e PR's por labels também depende de como a organização "se organiza".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpjm9maf3lt611kbhjlzr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpjm9maf3lt611kbhjlzr.png"&gt;&lt;/a&gt;&lt;/p&gt;
Screenshot da página de issues do &lt;a href="https://github.com/OpenDevUFCG/Tamburetei" rel="noopener noreferrer"&gt;Tamburetei&lt;/a&gt; com suas labels.



&lt;p&gt;Você pode contribuir com novas ideias nas discussões a respeito de alguma das issues ou fazer uma PR que a resolva. Posteriormente, quando estiver mais à vontade na organização, você pode abrir novas issues ou tentar resolver algumas mais complexas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explorando o GitHub
&lt;/h2&gt;

&lt;p&gt;Outra forma de ter acesso a novidades de projetos open source é acessando o &lt;strong&gt;&lt;a href="https://github.com/explore" rel="noopener noreferrer"&gt;Explore&lt;/a&gt;&lt;/strong&gt;, uma página do GitHub que além de mostrar projetos recomendados, como mostrado no tópico anterior, também possibilita uma conexão entre as comunidades desses projetos. Você pode explorar conteúdos de curadores, buscar projetos por tópicos e labels, ter acesso a informações de posts, artigos, eventos e meetups relacionados com as tecnologias recomendadas para você, entre outras informações.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fngl2p0mpmwzd6x8dzziq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fngl2p0mpmwzd6x8dzziq.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essas são algumas das principais maneiras que o GitHub encontrou para dar visibilidade a projetos de código aberto e fomentar a colaboração dos desenvolvedores para eles. Você pode se aprofundar mais a respeito do funcionamento do Git e do GitHub e obter informações mais técnicas &lt;a href="https://medium.com/@Juliobguedes/entendendo-git-883464f379de" rel="noopener noreferrer"&gt;neste outro post&lt;/a&gt;, e começar também a apoiar o open source agora mesmo!&lt;/p&gt;

&lt;p&gt;Muito obrigado pela leitura! Fique atento: em breve, teremos novos artigos de contribuidores do OpenDevUFCG aqui no &lt;strong&gt;dev.to&lt;/strong&gt;. Acompanhe o OpenDevUFCG no &lt;a href="https://twitter.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, no &lt;a href="https://instagram.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; e, claro, no &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>community</category>
      <category>github</category>
      <category>ptbr</category>
    </item>
  </channel>
</rss>
