Criando um bot para WhatsApp que se comunica com o Jira

mensonones

Emerson Vieira

Posted on February 26, 2023

Criando um bot para WhatsApp que se comunica com o Jira

Este projeto faz uso dos seguintes módulos node:

1 - whatsapp-web.js
2 - axios, axios-cookiejar-support e tough-cookie
3 - node-cron
4 - qrcode-terminal

OBS: Crie um projeto node e adicione os módulos acima

Estrutura do Projeto

project
├── services
│   └── api.js
├── utils
│   └── jiraUtils.js
├── index.js
├── jiraClient.js
└── package.json
Enter fullscreen mode Exit fullscreen mode

Código do Projeto

// api.js

const axios = require("axios");
const { wrapper } = require("axios-cookiejar-support");
const { CookieJar } = require("tough-cookie");

const cookieJar = new CookieJar();

axios.defaults.withCredentials = true;
axios.defaults.jar = cookieJar;

const instance = wrapper(
  axios.create({
    baseURL: process.env.JIRA_REST_API_URL,
  })
);

module.exports = instance;
Enter fullscreen mode Exit fullscreen mode

Os módulos axios-cookiejar-support e tough-cookie ajudam a tratar e manipualr cookies.

// jiraClient.js

const instance = require("./services/api");

const loginJira = async () => {
  try {
    const result = await instance.post("/rest/auth/1/session", {
      username: process.env.JIRA_USERNAME;,
      password: process.env.JIRA_PASSWORD,
    });
    if (result.status === 200) {
      console.log("Login realizado com sucesso");
      return true;
    }
  } catch (error) {
    console.log("Erro ao realizar o login:", error.message);
  }
  return false;
};

const getIssue = async (id) => {
  const result = await instance.get(`/rest/api/2/issue/${id}`);
  return result;
};

const jiraClient = async (id) => {
  try {
    const result = await instance.get("/rest/auth/1/session");
    if (result) {
      console.log("Sessão ativa");
      const issue = await getIssue(id);
      return issue;
    }
  } catch (error) {
    if (error.response.status === 401) {
      console.log("Não autorizado");
      const loginResult = await loginJira();
      if (loginResult) {
        return jiraClient(id);
      } else {
        throw error;
      }
    } else {
      console.log("Erro ao obter a sessão:", error);
      throw error;
    }
  }
};

module.exports = jiraClient;
Enter fullscreen mode Exit fullscreen mode
// jiraUtils.js

const jiraClient = require(".././jiraClient");

const JIRA_REMINDER_MESSAGE = "Não esquecer de logar as horas no Jira!";

const makeResponseJira = async (id) => {
  try {
    const jiraIssue = await jiraClient(id);
    return `Issue: ${jiraIssue?.data?.key}\nLabel: ${jiraIssue?.data?.fields?.labels[0]}\nAssignee: ${jiraIssue?.data?.fields?.assignee?.name}\nDescription: ${jiraIssue?.data?.fields?.description}`;
  } catch (error) {
    if (error.response.status === 404) {
      return `Issue ${id} não encontrada!`;
    }
    if (error.response.status === 401) {
      return `Verifique suas credenciais!`;
    }
  }
};

const processMsgReceived = async (msg) => {
  let response;
  if (msg.body.startsWith("DEV-")) {
    response = await makeResponseJira(msg.body);
  } else if (msg.body.startsWith("!lembrete")) {
    response = JIRA_REMINDER_MESSAGE;
  } else {
    return null;
  }
  return response;
};

module.exports = processMsgReceived;
Enter fullscreen mode Exit fullscreen mode

OBS: DEV refere-se ao padrão de nomenclatura das issues do Jira durante os testes
Exemplo de issue: DEV-100

// index.js 

const qrcode = require("qrcode-terminal");
const { Client, MessageMedia, LocalAuth } = require("whatsapp-web.js");
const cron = require("node-cron");
const processMsgReceived = require("./utils/jiraUtils");

const GROUP_ID = process.env.WPP_GROUP_ID;
const JIRA_LOGO_URL =
  "https://visuresolutions.com/wp-content/uploads/2022/07/Logo-Jira.png";
const JIRA_REMINDER_MESSAGE = "Não esquecer de logar as horas no Jira!";

const newBotClient = async () => {
  const client = new Client({ authStrategy: new LocalAuth() });
  return client;
};

const botJira = async (client) => {
  client.initialize();

  client.on("qr", (qr) => {
    qrcode.generate(qr, { small: true });
  });

  client.on("authenticated", () => {
    console.log("AUTHENTICATED");
  });

  client.on("ready", async () => {
    console.log("Client is ready!");
    cron.schedule(
      "0 17 * * *",
      async () => {
        // running a task every day 17 hrs
        const media = await MessageMedia.fromUrl(JIRA_LOGO_URL);
        let message = JIRA_REMINDER_MESSAGE;
        client.sendMessage(GROUP_ID, media, {
          caption: message,
        });
      },
      {
        scheduled: true,
        timezone: process.env.TIMEZONE || "America/Sao_Paulo",
      }
    );
    client.on("message", async (message) => {
      const processedMsg = await processMsgReceived(message);
      console.log("processedMsg MSG: ", processedMsg);
      if (processedMsg !== null) {
        const media = await MessageMedia.fromUrl(JIRA_LOGO_URL);
        const response = client.sendMessage(message.from, media, {
          caption: processedMsg,
        });

        return response;
      }
    });
  });
};

const startBot = async () => {
  try {
    const client = await newBotClient();
    botJira(client);
    console.log("Bot started!");
  } catch (error) {
    console.log("ERROR INIT BOT: ", error);
  }
};

startBot();
Enter fullscreen mode Exit fullscreen mode

Alguns pontos a serem explicados:

1 - Ao Startar o projeto, será exibido um QR Code no terminal. Você deverá ler o mesmo utilizando a conta do WhatsApp que será o bot.
2 - GROUP_ID refere-se ao grupo do WhatsApp em que o bot será adicionado para responder.
3 - cron.schedule é utilizado para disparar um lembrete todo dia às 17hrs

Link do projeto: https://github.com/mensonones/bot-jira-tutorial

Por hora é isso! Espero que seja útil e qualquer dúvida basta comentar ou entrar em contato comigo. Até a próxima :)

💖 💪 🙅 🚩
mensonones
Emerson Vieira

Posted on February 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related