lappis-unb / rasa-ptbr-boilerplate

Um template para criar um FAQ chatbot usando Rasa, Rocket.chat, elastic search
https://lappis-unb.github.io/rasa-ptbr-boilerplate/
GNU General Public License v3.0
217 stars 202 forks source link

Problema na Integração coma Rocket.Chat #84

Closed arthurTemporim closed 3 years ago

arthurTemporim commented 5 years ago

Descreva o bug A integração com a Rocket.Chat não está funcionando depois da atualização da versão do Rasa para 1.2.2. Esse problema está acontecendo pois o script run-rocketchat.py foi removido e a utilização padrão do rasa, usando credentials foi feita, mas o Rasa não possui a integração correta com a Rocket.Chat. Provavelmente um PR corrigindo o Rasa seja necessário.

Para reproduzir o bug Passo-a-passo para reproduzir o comportamento do bug:

  1. Descomente a configuração da Rocket.Chat no `credentials.py
  2. Execute o container bot-rocketchat
  3. Bot não responde na rocket.chat

Comportamento esperado O bot deveria aparecer online e responder na Rocket.chat.

staticdev commented 4 years ago

@arthurTemporim tem que alterar o Rasa ou o boilerplate? O Rasa tinha integração com o rocket.chat e parou de funcionar?

O que não está funcionando é esse WebChat da documentação?

dudanogueira commented 4 years ago

Nem 1 nem Outro. Só o Rocketchat mesmo. Consegui integrar de boas somente usnado os webhooks do Rocketchat. Existe uma opção nas versões mais novas que designa os chats do livechat pra um bot do departamento, se houver (settings/Livechat_assign_new_conversation_to_bot)

A implementação do @arthurTemporim era melhor, pois mostrava o bot como ativo, e se não me engano, essa implementação minha, embora mais simples, não faz isso.

Estou/estava/estarei também implementando a parte de livechat na api "oficial" do rocketchat em Python. A idéia é permite que o próprio bot possa encaminhar o livechat pra um agente: https://github.com/jadolg/rocketchat_API/issues/47

Fiz essa integração em um app da minha empresa, segue abaixo o código do ambiente de testes (App em django, o código é um comando do django):

from django.core.management.base import BaseCommand

from django.conf import settings

from rocketchat_API.rocketchat import RocketChat

import json
import logging
import requests
import os

logger = logging.getLogger("Bot Config")
logger.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

formatter = logging.Formatter(
    "%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s")

ch.setFormatter(formatter)

logger.addHandler(ch)

host = getattr(settings, 'ROCKET_CHAT_SERVER', "http://rocketchat:3000")

if host[-1] == "/":
    host = host[:-1]

if not host.startswith("http://"):
    host = "http://" + host

path = "/api/v1/login"

bot = {
    "name": os.getenv("ROCKETCHAT_BOT_NAME", "Bot"),
    "username": os.getenv("ROCKETCHAT_BOT_USERNAME", "bot"),
    "password": os.getenv("ROCKETCHAT_BOT_PASSWORD", "bot"),
    "avatar": os.getenv(
        "ROCKETCHAT_BOT_AVATAR_URL",
        "https://raw.githubusercontent.com/"
        "lappis-unb/rouana/master/images/rouana_avatar.jpeg",
    ),
    "email": os.getenv("ROCKETCHAT_BOT_USERNAME", "bot") + "@email.com",
}

admin_name = settings.ROCKET_CHAT_USER
admin_password = settings.ROCKET_CHAT_PASSWORD

rasa_url = settings.RASA_URL

user_header = None

class Command(BaseCommand):
    help = "CONFIG THE DEV ROCKETCHAT"

    def handle(self, *args, **options):
        if not settings.DEBUG:
            print("#"*10)
            print("SO PODE RODAR EM DEBUG!!!!!")
            print("#"*10)
            return False

        try:
            self.user_header = self.get_authentication_token()
            print("\n\n --------- Rocket Chat CONNECTED! --------\n\n")
            print(user_header)
            print("\n\n --------- Rocket Chat CONNECTED! --------\n\n")

        except Exception:
            raise
            print("\n\n --------- Rocket Chat Unavailable! --------\n\n")

        if self.user_header:
            # desabilita o API Rate para não travar o rocketchat
            self.api_post("settings/API_Enable_Rate_Limiter", {"value": False})

            logger.info(">> Create user")
            self.create_bot_user()

            logger.info(">> Create livechat agent")
            self.bot_agent_id = self.create_livechat_agent()

            logger.info(">> Configure livechat")
            self.configure_livechat()

            logger.info(">> Configure Rocketchat")
            self.configure_rocketchat()

            logger.info(">> Configure Webhooks")
            self.configure_webhooks()

            logger.info(">> Create livechat department")
            self.create_department(self.bot_agent_id)

        else:
            logger.error("Login Failed")

    def api(self, endpoint, values=None, is_post=True):
        requests.adapters.DEFAULT_RETRIES = 5

        if endpoint[0] == "/":
            endpoint = endpoint[1:]

        url = host + "/api/v1/" + endpoint

        data = None
        if values:
            data = json.dumps(values)
        if is_post:
            response = requests.post(url, data=data, headers=self.user_header)
        else:
            response = requests.get(url, data=data, headers=self.user_header)

        if response.json()["success"] is True:
            logger.info("Success {} :: {}".format(url, response.json()))
        else:
            logger.error("ERROR {} :: {}".format(url, response.json()))
            raise EnvironmentError

        return response.json()

    def api_post(self, endpoint, values=None):
        return self.api(endpoint, values)

    def api_get(self, endpoint, values=None):
        return self.api(endpoint, values, False)

    def get_authentication_token(self):
        login_data = {"username": admin_name, "password": admin_password}
        print('login_data', login_data)
        response = requests.post(host + path, data=json.dumps(login_data))

        if response.json()["status"] == "success":
            logger.info("Login suceeded")

            authToken = response.json()["data"]["authToken"]
            userId = response.json()["data"]["userId"]
            user_header = {
                "X-Auth-Token": authToken,
                "X-User-Id": userId,
                "Content-Type": "application/json",
            }
            self.user_header = user_header
            return user_header

    def create_bot_user(self):
        try:
            self.api_post(
                "users.create",
                {
                    "name": bot["name"],
                    "email": bot["email"],
                    "password": bot["password"],
                    "username": bot["username"],
                    "requirePasswordChange": False,
                    "sendWelcomeEmail": True,
                    "roles": ["bot"],
                },
            )
        except Exception:
            print("User already created.")

        self.api_post(
            "users.setAvatar", {
                "avatarUrl": bot["avatar"], "username": bot["username"]},
        )

    def create_livechat_agent(self):
        response = self.api_post("livechat/users/agent", {"username": bot["username"]})
        return response["user"]["_id"]

    def configure_livechat(self):
        # Enable Livechat
        self.api_post("settings/Livechat_enabled", {"value": True})

        # Disable show pre-registration form
        self.api_post("settings/Livechat_registration_form", {"value": False})

        # Change Livechat Color
        self.api_post("settings/Livechat_title_color",
                {"value": "#039046", "editor": "color"})

        # Change Livechat Title
        self.api_post("settings/Livechat_title", {"value": bot["name"]})

        # Disable Livechat Email display
        self.api_post("settings/Livechat_show_agent_email", {"value": False})

        # Disable file upload
        self.api_post("settings/Livechat_fileupload_enabled", {"value": False})

        # Change Livechat Webhook URL
        self.api_post("settings/Livechat_webhookUrl", {"value": rasa_url})

        # Activate Livechat Webhook Send Request on Visitor Message
        self.api_post("settings/Livechat_webhook_on_visitor_message", {"value": True})

        # Activate Livechat Webhook Send Request on Agent Messages
        self.api_post("settings/Livechat_webhook_on_agent_message", {"value": True})

        # Assign All new Livechats to a bot
        self.api_post("settings/Livechat_assign_new_conversation_to_bot", {"value": True})

    def configure_webhooks(self):
        webooks = self.api_get("integrations.list")

        name = "Rasa Webhook"

        for integration in webooks["integrations"]:
            if integration.get("name") == name:
                logger.info("Intergration {} already exists!".format(name))
                return

        self.api_post(
            "integrations.create",
            {
                "name": name,
                "type": "webhook-outgoing",
                "enabled": True,
                "scriptEnabled": False,
                "event": "sendMessage",
                "urls": [rasa_url],
                "username": bot["username"],
                "channel": "@" + bot["username"],
            },
        )

    def configure_rocketchat(self):
        self.api_post("settings/Language", {"value": "pt_BR"})

        self.api_post("settings/Accounts_RegistrationForm", {"value": "Disable"})

        self.api_post("settings/Iframe_Integration_send_enable", {"value": True})

        self.api_post("settings/Iframe_Integration_receive_enable", {"value": True})

        self.api_post("settings/API_Enable_CORS", {"value": True})

    def create_department(self, bot_agent_id):
        get_departments_url = host + "/api/v1/livechat/department"

        get_departments_response = requests.get(
            get_departments_url, headers=self.user_header)

        number_of_departments = len(get_departments_response.json()["departments"])

        if number_of_departments == 0:
            self.api_post(
                "livechat/department",
                {
                    "department": {
                        "enabled": True,
                        "showOnRegistration": True,
                        "name": "department",
                        "description": "default department",
                        "email": "email@email.com",
                        "showOnOfflineForm": True
                    },
                    "agents": [
                        {
                            "agentId": bot_agent_id,
                            "username": bot["username"],
                            "count": 0,
                            "order": 0,
                        }
                    ],
                },
            )
dudanogueira commented 4 years ago

a propósito, se não me engano, essa implementação é um frankstein do que o @arthurTemporim fez pra configurar o Rocketchat no Boilerplate, hehehe

staticdev commented 4 years ago

@dudanogueira acredito que esse código pode ser adaptado para compor o boilerplate. Acredito que essa dependência do Django não é necessária.. o settings pode ser substituído por os.getenv. Só esse BaseCommand que não entendi direito o propósito.

RochaCarla commented 4 years ago

algum de vcs já resolveu esse problema? Podem contribuir para o boilerplate?

dudanogueira commented 4 years ago

Oi @RochaCarla eu posso tentar contribuir. Inclusive estou desenvolvendo em node (bem avançado já, inclusive) um integrador do Rocketchat com o Whatsapp usando API não oficial. Tá funcionando bem legal. Ainda não publiquei o código. Estou usando o https://github.com/pedroslopez/whatsapp-web.js

staticdev commented 4 years ago

@RochaCarla confesso que não investi em resolver o problema não. Achei que fosse algo mais simples, mas pelo visto não é bem assim.

RochaCarla commented 4 years ago

@dudanogueira abre um PR :P Assim, alem de resolver o problema :)

arthurTemporim commented 3 years ago

Esta isso foi finalizada no PR #183 feito pelo @guilherme1guy. Caso haja algum ponto que seja considerado em aberto, por favor reabra ;)