Made Mattermost Bot avec Python (+ Flask)

Mise en garde

L'article a dormi pendant environ 9 mois, conservé dans le projet, de sorte que les informations peuvent être obsolètes. .. .. Je l'ai tellement écrit que je l'afficherai comme un service commémoratif. ..

Contexte

Il a été décidé de déplacer l'outil de communication interne vers Mattermost. J'aimerais pouvoir migrer mon Bot existant vers Mattermost, alors J'ai également réimplémenté Bot for Mattermost en Python [^ 1] pour ma propre étude. J'ai beaucoup recherché lors de la mise en œuvre de Bot, je vais donc résumer les informations pour moi-même.

environnement

D'une certaine manière, j'avais l'impression de vouloir toucher à la fois CentOS et Ubuntu. Ubuntu 18.04 est livré avec Python 3 par défaut, j'ai donc essayé de l'utiliser. Bref, ça ne veut rien dire.

Environnement

Introduction de Mattermost

Mattermost peut être facilement installé avec Docker, alors installez d'abord Docker.

CentOS


#Installer Docker
$ yum install -y yum-utils device-mapper-persistent-data lvm2
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ yum install docker-ce docker-ce-cli containerd.io

#Confirmation d'installation
$ docker --version
Docker version 19.03.5, build 633a0ea
$

#Démarrer Docker
$ systemctl status docker
$ systemctl enable docker
$ systemctl start docker
$ systemctl status docker

#Contrôle de fonctionnement
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:4df8ca8a7e309c256d60d7971ea14c27672fc0d10c5f303856d7bc48f8cc17ff
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

$

Une fois Docker installé, vous pouvez installer et démarrer Mattermost ci-dessous.

$ docker run --name mattermost-preview -d --publish 8065:8065 --add-host dockerhost:127.0.0.1 mattermost/mattermost-preview

Une fois installé, il peut être démarré / arrêté comme suit.

#Commencez
$ docker start mattermost-preview

#Arrêtez
$ docker stop mattermost-preview

#Confirmation du processus
$ docker ps

■ Référence ・ Qiita: Installer Docker sur CentOS7

Paramètres les plus importants

Une fois que Mattermost peut être démarré, il sera accessible depuis le navigateur.

http://xxx.xxx.xxx.xxx:8065

Si vous pouvez y accéder, créez un compte administrateur. Toute adresse e-mail est OK. 192.168.56.101_8065_signup_email_02.png

Créez une équipe de manière appropriée. 192.168.56.101_8065_create_team_display_name.png 192.168.56.101_8065_create_team_team_url_MASK.png

Traduire en japonais.

Main Menu -> Account Settings -> Display -> Language 192.168.56.101_8065_bot-test_channels_town-square.png

Par défaut, les restrictions de connexion sont appliquées aux réseaux privés. Si le serveur de destination de communication du Webhook se trouve dans le même segment, il est nécessaire de définir l'autorisation de communication. (J'étais assez accro ici.)

Menu principal-> Console système-> Développeurs-> Autoriser les connexions internes non approuvées 192.168.56.101_8065_admin_console_environment_developer.png

Par défaut, vous ne pouvez pas créer de compte Bot, alors activez-le.

Menu principal-> Console système-> Compte Bot-> Activer la création de compte Bot 192.168.56.101_8065_admin_console_integrations_bot_accounts.png

Créez un webhook sortant.

Menu principal-> Intégration-> Webhooks sortants

Type de contenu: application / json (j'ai choisi JSON cette fois) Channel: canal pour surveiller le déclenchement Mot déclencheur: mot qui déclenche l'activation du Webhook URL de rappel: URL de la destination du message (serveur Bot) (puisque Flask est utilisé cette fois, le port par défaut 5000 est spécifié) 192.168.56.201_8065_bot-test_integrations_outgoing_webhooks_add_01.png 192.168.56.201_8065_bot-test_integrations_outgoing_webhooks_add_02.png 192.168.56.201_8065_bot-test_integrations_outgoing_webhooks.png

Créez un compte Bot.

Menu principal-> Intégration-> Compte Bot 192.168.56.101_8065_bot-test_integrations_bots_add.png Les autorisations de publication de bot sont définies ici.

192.168.56.101_8065_bot-test_integrations_confirm_type=bots&id=5o4eejp977fqzqdprd7ji13gac&token=3tpdq6cc1tfi3cshkrazr7a6be_MASK.png Assurez-vous de noter le jeton de compte Bot car il n'y a aucun moyen de le vérifier plus tard sur l'écran du menu. Cependant, même si vous l'oubliez, vous pouvez le vérifier avec la commande suivante.

$ docker exec -t -e MYSQL_PWD=mostest mattermost-preview mysql -u mmuser mattermost_test -e "select * from UserAccessTokens;"
+----------------------------+----------------------------+----------------------------+-------------+----------+
| Id                         | Token                      | UserId                     | Description | IsActive |
+----------------------------+----------------------------+----------------------------+-------------+----------+
| xxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxx | ?????????   |        1 |
+----------------------------+----------------------------+----------------------------+-------------+----------+
$

Vérifiez si vous pouvez publier depuis votre compte Bot avec la commande curl. Tout d'abord, vérifiez l'ID de canal de la destination de publication.

Chaîne-> Afficher les informations 192.168.56.101_8065_bot-test_channels_town-square_03.png 192.168.56.101_8065_bot-test_channels_town-square_02_MASK.png

Vous pouvez également vérifier avec la commande suivante.

$ docker exec -t -e MYSQL_PWD=mostest mattermost-preview mysql -u mmuser mattermost_test -e "select * from Channels;"
+----------------------------+---------------+---------------+----------+----------------------------+------+-------------+--------------------------------------------------------+--------+---------+---------------+---------------+---------------+-----------+----------+------------------+
| Id                         | CreateAt      | UpdateAt      | DeleteAt | TeamId                     | Type | DisplayName | Name                                                   | Header | Purpose | LastPostAt    | TotalMsgCount | ExtraUpdateAt | CreatorId | SchemeId | GroupConstrained |
+----------------------------+---------------+---------------+----------+----------------------------+------+-------------+--------------------------------------------------------+--------+---------+---------------+---------------+---------------+-----------+----------+------------------+
| xxxxxxxxxxxxxxxxxxxxxxxxxx | 1574487544576 | 1574487544576 |        0 | xxxxxxxxxxxxxxxxxxxxxxxxxx | O    | Off-Topic   | off-topic                                              |        |         | 1574487544652 |             0 |             0 |           | NULL     |             NULL |
| xxxxxxxxxxxxxxxxxxxxxxxxxx | 1574489265292 | 1574489265292 |        0 |                            | D    |             | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |        |         | 1574489265315 |             1 |             0 |           | NULL     |             NULL |
| xxxxxxxxxxxxxxxxxxxxxxxxxx | 1574487544570 | 1574487544570 |        0 | xxxxxxxxxxxxxxxxxxxxxxxxxx | O    | Town Square | town-square                                            |        |         | 1574487544611 |             0 |             0 |           | NULL     |             NULL |
+----------------------------+---------------+---------------+----------+----------------------------+------+-------------+--------------------------------------------------------+--------+---------+---------------+---------------+---------------+-----------+----------+------------------+
$

Spécifiez l'ID de canal et le jeton de bot, puis envoyez une requête POST à l'API avec la commande curl.

$ curl -i -X POST -H 'Content-Type: application/json' -d '{"channel_id":"[Channel ID]", "message":"This is a message from a bot"}' -H 'Authorization: Bearer [Bot Token]' http://xxx.xxx.xxx.xxx:8065/api/v4/posts

192.168.56.101_8065_bot-test_channels_town-square_04.png J'ai pu confirmer que je pouvais publier avec mon compte Bot.

■ Référence ・ Ingénieur logiciel habituel: Comment créer un compte Bot avec Mattermost

Réponse au webhook

Cela semblait facile de le faire avec Flask pour le faire avec Python, alors je l'ai implémenté avec Flask. Publiez simplement JSON sur l'API comme vous le faites avec curl.

Ubuntu


$ sudo apt install python3-pip
$ pip3 -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)
$
$ pip3 install flask
$ pip3 install requests

bottest.py


import json

import requests
from flask import Flask, request

BOT_TOKEN = '[Bot Token]'
CHANNEL_ID = '[Channel ID]'
MM_API_ADDRESS = 'http://xxx.xxx.xxx.xxx:8065/api/v4/posts'

app = Flask(__name__)

@app.route('/bot-test', methods=['POST'])  #URL de rappel du webhook sortant
def bot_reply():
    posted_user = request.json['user_name']
    posted_msg  = request.json['text']

    reply_headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + BOT_TOKEN,
    }

    reply_data = {
        "channel_id": CHANNEL_ID,
        "message": f"@{posted_user} Bot reply message.",
        "props": {
            "attachments": [
                    {
                "author_name": posted_user,
                "text": posted_msg,
                }
            ]
        },
    }

    reply_request = requests.post(
        MM_API_ADDRESS,
        headers = reply_headers,
        data = json.dumps(reply_data)
    )

    return reply_request

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0')

Testez si vous pouvez obtenir une réponse. Démarrez le serveur de test de Flask.

Ubuntu


$ python3 bottest.py

Publiez un message contenant un mot déclencheur dans Mattermost. 192.168.56.201_8065_bot-test_channels_town-square.png

J'ai pu confirmer que je pouvais publier à partir du compte Bot en utilisant le Webhook comme déclencheur. Tout ce que vous avez à faire est d'implémenter la logique Bot.

Au fait, le JSON qui provient du Webhook de Mattermost ressemble à ceci.

{
    'token': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 
    'team_id': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 
    'team_domain': 'bot-test', 
    'channel_id': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 
    'channel_name': 'town-square', 
    'timestamp': 1234567890123, 
    'user_id': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 
    'user_name': 'mmadmin', 
    'post_id': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 
    'text': '#bot test', 
    'trigger_word': '#bot', 
    'file_ids': ''
}

■ Référence ・ [NOBWAK'S LAIR: Faisons BOT of SLACK / MATTERMOST avec FLASK of PYTHON](http://april.fool.jp/blogs/2016/06/02/slackmattermost%E3%81%AEbot%E3%82%92python % E3% 81% AEflacon% E3% 81% A7% E4% BD% 9C% E3% 82% 8D% E3% 81% 86 /) ・ Qiita: Créez un robot simple avec Mattermost et Python + Flask

prime

Une fois le Bot terminé, vous aurez besoin d'un serveur Web et d'un serveur WSGI pour l'exécuter en tant qu'application Web. Après de nombreuses recherches, j'ai choisi Nginx + Gunicorn. (Parce que je sentais que c'était le plus simple et le plus facile) Cette zone n'est toujours pas claire, je vais donc me précipiter pour l'écrire sous forme de mémo. ..

Gunicorn est installé avec pip.

Ubuntu


$ sudo pip3 install gunicorn

gunicorn [nom du script Python]: lancé avec [nom de l'instance Flask]. (Le port par défaut est 8000) (Ce qui suit lance une instance d'application dans bottest.py)

#Exécuter dans le répertoire où se trouve le script Python
$ cd /path/bot
$ sudo gunicorn bottest:app
[YYYY-MM-DD hh:mm:ss +0900] [1699] [INFO] Starting gunicorn 20.0.2
[YYYY-MM-DD hh:mm:ss +0900] [1699] [INFO] Listening at: http://127.0.0.1:8000 (1699)
[YYYY-MM-DD hh:mm:ss +0900] [1699] [INFO] Using worker: sync
[YYYY-MM-DD hh:mm:ss +0900] [1703] [INFO] Booting worker with pid: 1703

Si vous souhaitez utiliser le même port que le serveur de test de Flask, OK avec ce qui suit (Lorsqu'il est difficile de modifier les paramètres du Webhook du côté le plus important)

$ sudo gunicorn bottest:app -b 0.0.0.0:5000

Vous pouvez utiliser l'option chdir sans avoir à accéder à l'emplacement du script Python.

$ sudo gunicorn --chdir /path/bot bottest:app -b 0.0.0.0:5000

À l'arrêt, appuyez sur Ctrl + C pour arrêter le processus.

Si vous voulez exécuter Gunicorn seul, c'est bien, mais vous ne pouvez pas travailler avec Nginx tel quel. Tout d'abord, installez Nginx.

Ubuntu


$ sudo apt install nginx
$ nginx -v
nginx version: nginx/1.14.0 (Ubuntu)
$

Réglez Nginx. Une prise est requise pour la communication avec Gunicorn. (Créé dans / tmp ci-dessous)

/etc/nginx/sites-available/default


upstream bot-test {
    server unix:/tmp/bot-test.sock;
}

server {
    listen 5000;

    root path/bot;
    server_name localhost;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /bot-test {
        try_files $uri @flask;
    }

    location @flask {
        proxy_pass http://bot-test;
    }
}

Confirmation de l'opération Nginx.

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$
$ sudo systemctl status nginx
$ sudo systemctl restart nginx
$ sudo systemctl status nginx

Si les paramètres Nginx sont corrects, créez un fichier de configuration Gunicorn. L'emplacement et le nom du fichier de paramètres peuvent être n'importe quoi Décrivez le socket décrit précédemment dans le fichier de configuration Nginx.

$ vim gunicorn_conf.py

gunicorn_conf.py


bind = 'unix:/tmp/bot-test.sock'
daemon = True
reload = True

Spécifiez le fichier de paramètres avec l'option -c et OK s'il peut être démarré

$ sudo gunicorn bottest:app -c gunicorn_conf.py

Tuez le processus lorsqu'il est arrêté.

$ sudo pkill gunicorn

Pour être honnête, je fais la partie supplémentaire avec l'esprit que je devrais bouger pour le moment, donc Il doit y avoir un meilleur moyen. ..

■ Référence ・ Qiita: gunicorn + Flask + nginx + Systemd ・ [Journal de "Un étudiant avec le mauvais département à entrer": Procédure de déploiement manuel d'Ubuntu + Nginx + Gunicorn](https: //nnsnodnb.hatenablog) .jp / entrée / ubuntu-nginx-gunicorn-deploy) ・ Qiita: Mémo pour faire de python un démon

[^ 1]: remontage des roues https://www.slideshare.net/RansuiIso/python-115121978 https://www.youtube.com/watch?v=kO4FNg648qE

Recommended Posts

Made Mattermost Bot avec Python (+ Flask)
J'ai fait une loterie avec Python.
J'ai créé un démon avec Python
J'ai fait un Twitter BOT avec GAE (python) (avec une référence)
J'ai essayé de faire LINE BOT avec Python et Heroku
J'ai fait un compteur de caractères avec Python
J'ai créé une application de livre simple avec python + Flask ~ Introduction ~
J'ai fait une carte hexadécimale avec Python
J'ai fait un jeu rogue-like avec Python
J'ai fait un simple blackjack avec Python
J'ai créé un fichier de configuration avec Python
J'ai fait un simulateur de neurones avec Python
J'ai créé un formulaire de tweet Nyanko avec Python, Flask et Heroku
J'ai fait un robot de remplacement de tampon avec une ligne
J'ai fait une prévision météo de type bot avec Python.
J'ai créé une application graphique avec Python + PyQt5
J'ai essayé de créer un bloqueur de filles pourries sur Twitter avec Python ①
[Python] J'ai créé un téléchargeur Youtube avec Tkinter.
J'ai créé un Bot LINE avec Serverless Framework!
J'ai fait un blackjack avec du python!
J'ai fait un texte Python
J'ai fait un robot discord
J'ai créé wordcloud avec Python.
J'ai créé un bot de livre de compte de ménage avec LINE Bot
J'ai fait un jeu d'éclairage de sapin de Noël avec Python
J'ai créé une application de notification de nouvelles en ligne avec Python
Bases de SNS Python faites avec Flask
J'ai fait un Line-bot avec Python!
J'ai fait un wikipedia gacha bot
J'ai fait un jeu de frappe simple avec tkinter de Python
J'ai créé un package pour filtrer les séries chronologiques avec python
J'ai essayé de créer LINE-bot avec Python + Flask + ngrok + LINE Messaging API
J'ai fait un jeu de puzzle (comme) avec Tkinter of Python
[AWS] J'ai créé un BOT de rappel avec LINE WORKS (implémentation)
J'ai fait un programme de gestion de la paie en Python!
J'ai dessiné une carte thermique avec Seaborn [Python]
J'ai essayé un langage fonctionnel avec Python
Ce que j'ai fait avec les tableaux Python
J'ai fait un jeu de vie avec Numpy
J'ai fait un générateur Hanko avec GAN
Après avoir étudié Python3, j'ai créé un Slackbot
J'ai fait une application WEB avec Django
J'ai fait un circuit simple avec Python (AND, OR, NOR, etc.)
J'ai créé une bibliothèque qui lit facilement les fichiers de configuration avec Python
J'ai fait un package qui peut comparer des analyseurs morphologiques avec Python
J'ai créé beaucoup de fichiers pour la connexion RDP avec Python
J'ai fait un shuffle qui peut être réinitialisé (inversé) avec Python
[Introduction] Je veux créer un robot Mastodon avec Python! 【Débutants】
J'ai créé un fichier de dictionnaire python pour Neocomplete
〇✕ J'ai fait un jeu
Créer un bot Twitter Trend avec heroku + Python
Les débutants en Python ont décidé de créer un bot LINE avec Flask (commentaire approximatif de Flask)
J'ai créé un outil pour parcourir automatiquement plusieurs sites avec Selenium (Python)
J'ai fait mon chien "Monaka Bot" avec Line Bot
Créer un LINE BOT avec Minette pour Python
Je veux faire un jeu avec Python
Procédure de création d'un LineBot réalisé avec Python