Saltear al contenido principal

Cómo construir su primer bot de Slack con Python – Lenguaje Python

Los bots son una forma útil de interactuar con servicios de chat como Flojo. Si nunca ha creado un bot antes, esta publicación proporciona un tutorial de inicio fácil para combinar el API de Slack con Python para crear su primer bot.

Contrata a un experto en Python para iniciar tu proyecto hoy mismo:

Le explicaremos cómo configurar su entorno de desarrollo, obtener un token de bot de la API de Slack y codificar nuestro bot simple en Python.

Herramientas que necesitamos

Nuestro bot, que llamaremos «StarterBot», requiere Python y la API de Slack. Para ejecutar nuestro código Python necesitamos:

También es útil tener el Documentos de la API de Slack útil mientras construyes este tutorial.

Todo el código de este tutorial está disponible en código abierto bajo la licencia MIT en el robot de arranque flojo repositorio público.

Estableciendo nuestro entorno

Ahora sabemos qué herramientas necesitamos para nuestro proyecto, así que configuremos nuestro entorno de desarrollo. Vaya a la terminal (o al símbolo del sistema en Windows) y cambie al directorio donde desea almacenar este proyecto. Dentro de ese directorio, cree un nuevo virtualenv para aislar nuestras dependencias de aplicaciones de otros proyectos de Python.

Activar virtualenv:

source starterbot/bin/activate

Su mensaje ahora debería verse como el de esta captura de pantalla.

Símbolo del sistema con el virtualenv de starterbot activado.

El oficial slackclient La biblioteca auxiliar de API creada por Slack puede enviar y recibir mensajes desde un canal de Slack. Instale la biblioteca slackclient con el pip mando:

pip install slackclient==1.3.2

Cuando pip está terminado, debería ver un resultado como este y volverá al indicador.

Resultado del uso del comando pip install slackclient con un virtualenv activado.

También necesitamos crear una aplicación de Slack para recibir un token de API para su bot. Utilice «Starter Bot» como nombre de su aplicación. Si ha iniciado sesión en más de un espacio de trabajo, elija un Espacio de trabajo de desarrollo del menú desplegable.

Crear un formulario de la aplicación Slack llenado

Después de enviar el formulario, mantenga abierta la página de configuración de la aplicación.

Configuración de aplicaciones y API de Slack

Queremos que nuestro Starter Bot se parezca a cualquier otro usuario de su equipo; participará en conversaciones dentro de canales, grupos y DM. En una aplicación de Slack, esto se llama usuario de bot, que configuramos eligiendo «Usuarios de bot» en la sección «Funciones». Después de hacer clic en «Agregar un usuario de bot», debe elegir un nombre para mostrar, elegir un nombre de usuario predeterminado y guardar sus opciones haciendo clic en «Agregar usuario de bot». Terminará con una página que se parece a la siguiente:

Se agregó un usuario de bot a la aplicación Slack.

los slackclient biblioteca simplifica el uso de Slack API de RTM y API web. Usaremos ambos para implementar Starter Bot, y cada uno requiere autenticación. Convenientemente, el usuario de bot que creamos anteriormente se puede usar para autenticar ambas API.

Haga clic en «Instalar aplicación» en la sección «Configuración». El botón de esta página instalará la aplicación en nuestro espacio de trabajo de desarrollo. Una vez que la aplicación está instalada, muestra un token de acceso oauth de usuario bot para la autenticación como usuario del bot.

Después de la instalación en el espacio de trabajo de desarrollo, puede copiar el token de acceso oauth del usuario bot

Una práctica común para los desarrolladores de Python es exportar tokens secretos como variables de entorno. De vuelta en su terminal, exporte el token de Slack con el nombre SLACK_BOT_TOKEN:

export SLACK_BOT_TOKEN='your bot user access token here'

Bien, ahora estamos autorizados a usar Slack RTM y las API web como usuario de bot.

Codificación de nuestro bot de inicio

Tenemos todo lo que necesitamos para escribir el código del Starter Bot. Crea un nuevo archivo llamado starterbot.py e incluya el siguiente código en él.

import os
import time
import re
from slackclient import SlackClient

Con nuestras dependencias importadas, podemos usarlas para obtener los valores de las variables de entorno y luego crear una instancia del cliente de Slack.

# instantiate Slack client
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
# starterbot's user ID in Slack: value is assigned after the bot starts up
starterbot_id = None

# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "do"
MENTION_REGEX = "^<@(|[WU].+?)>(.*)"

El código instancia el SlackClient cliente con nuestro SLACK_BOT_TOKEN
exportado como una variable de entorno. También declara una variable que podemos usar para almacenar el ID de usuario de Slack de nuestro Starter Bot. También se declaran algunas constantes, y cada una de ellas se explicará a medida que se utilicen en el código que sigue.

if __name__ == "__main__":
    if slack_client.rtm_connect(with_team_state=False):
        print("Starter Bot connected and running!")
        # Read bot's user ID by calling Web API method `auth.test`
        starterbot_id = slack_client.api_call("auth.test")["user_id"]
        while True:
            command, channel = parse_bot_commands(slack_client.rtm_read())
            if command:
                handle_command(command, channel)
            time.sleep(RTM_READ_DELAY)
    else:
        print("Connection failed. Exception traceback printed above.")

El cliente de Slack se conecta a la API de Slack RTM. Una vez conectado, llama a un método API web (auth.test) para encontrar el ID de usuario del Starter Bot.

Cada usuario de bot tiene una identificación de usuario para cada espacio de trabajo en el que está instalada la aplicación Slack. El almacenamiento de esta identificación de usuario ayudará al programa a comprender si alguien ha mencionado al bot en un mensaje.

A continuación, el programa entra en un bucle infinito, donde cada vez que se ejecuta el bucle, el cliente recibe cualquier evento que llega de la API RTM de Slack. Observe que antes de que finalice el ciclo, el programa se detiene durante un segundo para que no se repita demasiado rápido y pierda el tiempo de la CPU.

Para cada evento que se lee, el parse_bot_commands() La función determina si el evento contiene un comando para Starter Bot. Si es así, entonces command contendrá un valor y el handle_command() La función determina qué hacer con el comando.

Hemos sentado las bases para procesar eventos de Slack y llamar a métodos de Slack en el programa. A continuación, agregue tres funciones nuevas sobre el fragmento anterior para completar los comandos de manejo:

def parse_bot_commands(slack_events):
    """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If its not found, then this function returns None, None.
    """
    for event in slack_events:
        if event["type"] == "message" and not "subtype" in event:
            user_id, message = parse_direct_mention(event["text"])
            if user_id == starterbot_id:
                return message, event["channel"]
    return None, None

def parse_direct_mention(message_text):
    """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None
    """
    matches = re.search(MENTION_REGEX, message_text)
    # the first group contains the username, the second group contains the remaining message
    return (matches.group(1), matches.group(2).strip()) if matches else (None, None)

def handle_command(command, channel):
    """
        Executes bot command if the command is known
    """
    # Default response is help text for the user
    default_response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND)

    # Finds and executes the given command, filling in response
    response = None
    # This is where you start to implement more commands!
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"

    # Sends the response back to the channel
    slack_client.api_call(
        "chat.postMessage",
        channel=channel,
        text=response or default_response
    )

los parse_bot_commands() La función toma eventos de Slack y determina si son comandos dirigidos al Starter Bot. Hay muchos tipos de eventos que nuestro bot encontrará, pero para encontrar comandos solo queremos considerar eventos de mensaje. Los eventos de mensaje también tienen subtipos, pero los comandos que queremos encontrar no tendrán ningún subtipo definido. La función filtra los eventos no interesantes comprobando estas propiedades. Ahora sabemos que el evento representa un mensaje con algo de texto, pero queremos saber si Starter Bot se menciona en el texto. los parse_direct_mention()
La función descubrirá que el texto del mensaje comienza con una mención, y luego lo comparamos con el ID de usuario que almacenamos anteriormente para Starter Bot. Si son iguales, entonces sabemos que se trata de un comando de bot y devolvemos el texto del comando con el ID del canal.

los parse_direct_mentions() La función utiliza una expresión regular para determinar si se menciona a un usuario. al principio del mensaje. Devuelve el ID de usuario y el mensaje restante (y None, None si no se encontró ninguna mención).

La última función, handle_command() es donde en el futuro agregarás todos los comandos interesantes, el humor y la personalidad para Starter Bot. Por ahora, solo tiene un comando de ejemplo: hacer. Si el comando comienza con un comando conocido, tendrá una respuesta adecuada. Si no es así, se utiliza una respuesta predeterminada. La respuesta se envía a Slack llamando al
chat.postMessage Método API web con el canal.

Así es como debe verse todo el programa cuando esté todo junto (también puede ver el archivo en GitHub):

import os
import time
import re
from slackclient import SlackClient


# instantiate Slack client
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
# starterbot's user ID in Slack: value is assigned after the bot starts up
starterbot_id = None

# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "do"
MENTION_REGEX = "^<@(|[WU].+?)>(.*)"

def parse_bot_commands(slack_events):
    """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If its not found, then this function returns None, None.
    """
    for event in slack_events:
        if event["type"] == "message" and not "subtype" in event:
            user_id, message = parse_direct_mention(event["text"])
            if user_id == starterbot_id:
                return message, event["channel"]
    return None, None

def parse_direct_mention(message_text):
    """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None
    """
    matches = re.search(MENTION_REGEX, message_text)
    # the first group contains the username, the second group contains the remaining message
    return (matches.group(1), matches.group(2).strip()) if matches else (None, None)

def handle_command(command, channel):
    """
        Executes bot command if the command is known
    """
    # Default response is help text for the user
    default_response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND)

    # Finds and executes the given command, filling in response
    response = None
    # This is where you start to implement more commands!
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"

    # Sends the response back to the channel
    slack_client.api_call(
        "chat.postMessage",
        channel=channel,
        text=response or default_response
    )

if __name__ == "__main__":
    if slack_client.rtm_connect(with_team_state=False):
        print("Starter Bot connected and running!")
        # Read bot's user ID by calling Web API method `auth.test`
        starterbot_id = slack_client.api_call("auth.test")["user_id"]
        while True:
            command, channel = parse_bot_commands(slack_client.rtm_read())
            if command:
                handle_command(command, channel)
            time.sleep(RTM_READ_DELAY)
    else:
        print("Connection failed. Exception traceback printed above.")

Ahora que todo nuestro código está en su lugar, podemos ejecutar nuestro Starter Bot en la línea de comando con el python starterbot.py mando.

Salida de consola cuando el StarterBot se está ejecutando y conectado a la API.

En Slack, crea un nuevo canal e invita al Starter Bot o invítalo a un canal existente.

En la interfaz de usuario de Slack, cree un nuevo canal e invite a StarterBot.

Ahora comience a dar comandos de Starter Bot en su canal.

Da comandos a StarterBot en tu canal de Slack.

Nota adicional: Actualmente hay un problema con el websocket paquete y el certificado de CA que utiliza, por lo que si encuentra un error como:

...
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
...
slackclient.server.SlackConnectionError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
Connection failed. Exception traceback printed above.

Hay un par de cosas que se pueden hacer: 1. Degradar la biblioteca del cliente websocket a 0.47.0
2. O descargue el certificado (wget https://www.tbs-certificats.com/issuerdata/DigiCertGlobalRootCA.crt), luego configure la variable de entorno export WEBSOCKET_CLIENT_CA_BUNDLE=DigiCertGlobalRootCA.crt

¿Necesitas ayuda para revisar el código de tu proyecto?



Esta entrada tiene 0 comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Volver arriba