Comment créer un bot de chat pour VKontakte en utilisant Python, Django et webhook

Pourquoi un autre article sur la création d'un chat bot?


J'ai peut-être mal cherché, mais je n'ai pas pu trouver de guide détaillé sur la création d'un bot python à l'aide du framework Django et de l'approche webhook, qui est hébergé par une société russe. La plupart des documents parlent d'utiliser le framework Flask et d'utiliser l'hébergement gratuit de Heroku et PythonAnywhere. L'expérience de la communauté Habr m'aide, alors j'ai décidé, en signe de gratitude, de passer du temps à écrire cet article. Je décrirai l'expérience pratique acquise pour permettre à tous ceux qui sont intéressés par cela de gagner du temps et de mieux comprendre comment faire un bot en Python en utilisant le framework Django sur leur hébergement en utilisant l'approche webhook.

Pourquoi l'hébergement payant?


À mon avis, une version viable du bot est quand elle est indépendante de votre ordinateur local et est disponible 24/7. Pour ce faire, vous avez besoin d'un hébergement sur lequel il y a: un serveur web, un système de gestion de base de données (pour développer les capacités du bot), l'enregistrement d'un nom de domaine, l'obtention d'un certificat SSL pour celui-ci et un support technique pour toute cette économie. Ces services coûtent de l'argent. Je paie l'hébergement 138 roubles par mois pour maintenir l'infrastructure pour que le bot fonctionne: support pour Python + Django, MySQL DBMS 25 Go, support pour SSH.
Dans la plupart des leçons, j'ai vu qu'un ordinateur personnel est utilisé comme serveur ou hébergement gratuit avec des restrictions sur les heures de travail, etc. Dans les exemples, le bot interroge périodiquement le serveur de messagerie pour les nouveaux messages des utilisateurs. Il s'agit d'une charge supplémentaire sur les serveurs de messagerie, de sorte que le bot peut être "banni" pendant un certain temps. Tout cela, à mon avis, n'est pas vital pour une utilisation productive. Mais pour le test et la formation est tout à fait possible.

Qu'est-ce que le webhook et pourquoi?


Pour le produit, je considère la bonne décision d'utiliser un webhook, c'est-à-dire une approche dans laquelle notre bot attend des messages du serveur de messagerie et ne les "martèle" pas avec des requêtes périodiques: y a-t-il de nouveaux messages ou non. Avec un webhook, ce sera comme ceci: l'utilisateur a écrit un message, le serveur de messagerie l'a envoyé à votre bot, il a reçu le message, l'a traité et a répondu.

Pourquoi Django


J'ai décidé de faire un bot en python, j'ai donc connecté le support python sur l'hébergement. Mais je n'avais pas le choix d'un framework - l'hébergement n'a que Django. Ils disent que cela fonctionne sur Instagram, Pinterest, Bitbucket et Mozilla. C'est peut-être pourquoi l'hébergement le propose.

Pourquoi VKontakte, pas Telegram ou Viber?


Pour passer du simple au complexe, il était important pour moi de trouver le moyen le plus simple et le plus intuitif de mettre en place un webhook. VKontakte s'est avéré être le plus compréhensible pour moi en raison de l'aide claire et de la facilité de connexion du webhook dans le panneau de contrôle de la communauté dans la section "Gestion - Travailler avec l'API". Une description de la façon dont j'ai tout configuré et connecté sera plus loin. À l'avenir, je veux rendre mon bot disponible dans Viber. Mais avec Telegram, ce n'est pas encore en route, car mon hébergement est en Russie et Telegram est bloqué de Russie. Pour éviter les problèmes avec Telegram, vous pouvez acheter un hébergement à l'étranger.

Comment installer le webhook pour le bot VK?


Nom de domaine https: // . Vous devez d'abord enregistrer le nom de domaine du site et obtenir un certificat SSL pour celui-ci.

Je ne voulais pas utiliser le domaine racine pour le chatbot, donc après avoir enregistré le domaine, j'ai créé un sous-domaine et reçu un certificat SSL pour celui-ci.

J'ai fait toutes ces manipulations sur le site d'hébergement dans mon compte personnel.
En conséquence, j'ai reçu l'adresse du site mybot.mysite.ru et le certificat ssl correspondant.

Nous obtenons la clé VK (token) pour le bot. J'ai d'abord créé un groupe fermé, puis je suis entré dans la "gestion" du groupe, dans la section "Travailler avec l'API". Dans l'onglet "Clés d'accès" se trouve un jeton, et dans l'onglet "API de rappel" les paramètres du webhook.



Installez et configurez Django . Peut-être que vous n'avez pas besoin de Django pour exécuter votre script python, mais je ne sais pas comment faire autrement.

En utilisant PuTTY, je me suis connecté au serveur via SSH, configuré et activé l'environnement virtuel.

SSH:
virtualenv-2.7 virtualenv/myEnv . virtualenv/myEnv/bin/activate 

la commande de la première ligne crée un environnement virtuel et la commande de la deuxième ligne l'active (notez l'espace après le point). La version 2.7 est dictée par l'hébergement et peut différer dans votre cas. Par conséquent, lisez l'aide à l'hébergement.

Django installé suivant
SSH:
 pip install 'django<2' 

J'ai installé la version de Django pas plus tôt que la seconde, car python 2.7 est utilisé sur l'hébergement, et seule la version de Django inférieure à 2 fonctionne avec.

Et installé le module python pour fonctionner avec l'API VKontakte
SSH:
 pip install vk 


FTP:
Création d'un dossier pour les projets django dans le répertoire racine de l'hébergement. Il l'a appelée django.

SSH:
Créé un nouveau projet.
 cd django/ django-admin.py startproject mybot 

en conséquence, un dossier avec le nom du projet sera créé (dans notre cas, c'est «mybot») dans le dossier / django. Il contiendra les fichiers de projet initiaux créés automatiquement:
/ django
/ mybot - dossier de projet
/ mybot - module avec les paramètres de notre projet
__init__.py
settings.py
urls.py
wsgi.py
manage.py

Un projet dans Django est un groupe d'applications. Une application dans Django est un programme qui effectue les actions définies par le développeur.

SSH:
Création d'une application.
 cd mybot python manage.py startapp vk_bot 

Je suis allé dans le dossier / django / mybot et j'ai créé une nouvelle application appelée "vk_bot".
Un dossier portant le nom de l'application a été créé dans le dossier du projet contenant les fichiers d'application créés automatiquement:

/ django
/ mybot - dossier de projet
/ mybot - module avec les paramètres de notre projet
__init__.py
settings.py
urls.py
wsgi.py
manage.py
/ vk_bot - dossier d'application
__init__.py
admin.py
apps.py
models.py
tests.py
views.py

FTP:
J'ai téléchargé tous les fichiers du projet sur mon ordinateur portable pour travailler avec du code.
Pour travailler avec les fichiers de projet et la programmation, j'ai utilisé l'application Atom.

Atome:
Modifié les paramètres du projet dans le fichier /django/mybot/mybot/settings.py
 ... DEBUG = False ... ALLOWED_HOSTS = [ u'mybot.mysite.ru', ] ... 

Atome:
Paramètres de routage d'URL modifiés dans le fichier /django/mybot/mybot/urls.py
 ... urlpatterns = [ url(r'^vk_bot/', include('vk_bot.urls')), ] ... 

FTP:
Création d'un fichier /django/mybot/vk_bot/urls.py avec le contenu suivant :
 from django.conf.urls import url from . import views app_name = 'vk_bot' urlpatterns = [ url(r'^$', views.index, name='index'), ] 

Atome:
Modification du fichier /django/mybot/vk_bot/views.py - ajout d'une fonction appelée index qui sera exécutée lorsque l'adresse sera demandée dans le navigateur
  https://mybot.mysite.ru/vk_bot/ 


views.py
 # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.views.decorators.csrf import csrf_exempt from django.shortcuts import render from django.http import HttpResponse from bot_config import * # import token, confirmation_token and over constants from bot_config.py import json, vk # vk is library from VK """ Using VK Callback API version 5.5 For more ditalies visit https://vk.com/dev/callback_api """ """ From Django documentation (https://docs.djangoproject.com/en/1.11/ref/request-response/) When a page is requested, Django automatically creates an HttpRequest object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest as the first argument to the view function. This argiment is <request> in def index(request): Decorator <@csrf_exempt> marks a view as being exempt from the protection ensured by the Django middleware. For cross site request protection will be used secret key from VK """ @csrf_exempt #exempt index() function from built-in Django protection def index(request): #url: https://mybot.mysite.ru/vk_bot/ if (request.method == "POST"): data = json.loads(request.body)# take POST request from auto-generated variable <request.body> in json format if (data['secret'] == secret_key):# if json request contain secret key and it's equal my secret key if (data['type'] == 'confirmation'):# if VK server request confirmation """ For confirmation my server (webhook) it must return confirmation token, whitch issuing in administration web-panel your public group in vk.com. Using <content_type="text/plain"> in HttpResponse function allows you response only plain text, without any format symbols. Parametr <status=200> response to VK server as VK want. """ # confirmation_token from bot_config.py return HttpResponse(confirmation_token, content_type="text/plain", status=200) if (data['type'] == 'message_new'):# if VK server send a message session = vk.Session() api = vk.API(session, v=5.5) user_id = data['object']['user_id'] # token from bot_config.py api.messages.send(access_token = token, user_id = str(user_id), message = "Hello, I'm bot!") return HttpResponse('ok', content_type="text/plain", status=200) else: return HttpResponse('see you :)') 

Dans le script views.py , dans la fonction index (request) , j'ai dû désactiver la protection intégrée à Django CSRF, car J'obtenais l'erreur "403 Interdit". CSRF - Cross Site Request Forgery protection - protection contre la contrefaçon de demande intersite. Comment CSRF fonctionne, vous pouvez lire dans cet article .
Pour désactiver la protection, j'ai utilisé le décorateur @csrf_exempt . Mais afin de fournir cette protection tout de même, mais de manière plus simple, j'ai utilisé une clé secrète, qui est enregistrée dans la section de gestion de groupe sur le site Web de VKontakte.

Ce morceau de code est responsable du traitement des demandes du serveur qu'il enverra afin de connecter notre webhook pour le traitement des événements. Disons simplement «confirmation» de notre webhook.
 if (data['type'] == 'confirmation'):# if VK server request confirmation """ For confirmation my server (webhook) it must return confirmation token, whitch issuing in administration web-panel your public group in vk.com. Using <content_type="text/plain"> in HttpResponse function allows you response only plain text, without any format symbols. Parametr <status=200> response to VK server as VK want. """ # confirmation_token from bot_config.py return HttpResponse(confirmation_token, content_type="text/plain", status=200) 

Veuillez noter que je conserve tous les paramètres de configuration dans un fichier de configuration de bot distinct bot_config.py et que je le connecte donc au début du script:
 from bot_config import * # import token, confirmation_token and over constants from bot_config.py 

bot_config.py
 # -*- coding: utf-8 -*- """ Configuration file for VK bot """ # token issued on the VK group web-administration page token = '...' # confirmation token issued on the VK group web-administration page in "Callback API" section confirmation_token = '...' # secret key for cross site request forgery protection. It will be in each VK server request secret_key = '...' 

Et dans ce morceau de code, il traite les messages des utilisateurs:
 if (data['type'] == 'message_new'):# if VK server send a message session = vk.Session() api = vk.API(session, v=5.5) user_id = data['object']['user_id'] # token from bot_config.py api.messages.send(access_token = token, user_id = str(user_id), message = "Hello, I'm bot!") return HttpResponse('ok', content_type="text/plain", status=200) 

Si quelque chose vous semblait incompréhensible, vous pouvez également lire l' article sur la première configuration de Django .

La magie du serveur Web . Pour configurer l'adressage des requêtes au serveur web, je suis allé sur le serveur dans le dossier avec les domaines via le client FTP FileZilla et y ai créé le dossier " mybot.mysite.ru ", y ai mis trois fichiers dont le contenu a été repris de l'aide sur l'hébergement:

.htaccess
 AddHandler wsgi-script .wsgi RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /django.wsgi/$1 [QSA,PT,L] RewriteCond %{HTTP:X-Forwarded-Protocol} !=https RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L] 

django.wsgi
 import os, sys virtual_env = os.path.expanduser('~/virtualenv/myEnv') activate_this = os.path.join(virtual_env, 'bin/activate_this.py') execfile(activate_this, dict(__file__=activate_this)) sys.path.insert(0, os.path.join(os.path.expanduser('~'), 'django/mybot')) os.environ['DJANGO_SETTINGS_MODULE'] = 'mybot.settings' from django.core.wsgi import get_wsgi_application application = get_wsgi_application() 

Ici «myEnv» est le nom de l'environnement virtuel que vous avez créé, «django» est le dossier dans la section racine du système de fichiers sur l'hébergement, «mybot» est le nom du projet que nous avons créé en utilisant Django.

index.html
    

«Liez» notre webhook au traitement des messages dans le groupe VKontakte créé.
Pour ce faire, nous reviendrons sur la section de gestion de notre groupe sur le site VKontakte (voir la capture d'écran ci-dessus). Nous entrerons notre adresse de webhook dans le champ "Adresse"
  https://mybot.mysite.ru/vk_bot/ 
et cliquez sur le bouton «Confirmer». Si notre fonction d' index (demande) , écrite dans le fichier /django/mybot/vk_bot/views.py, fonctionne correctement, c'est-à-dire qu'elle ne contient pas de fautes de frappe et d'erreurs, une coche verte apparaîtra, symbolisant que tout va bien.

Pour que notre webhook reçoive des messages du serveur VKontakte sur les nouveaux messages des utilisateurs, dans la section de gestion de notre groupe sur le site Web de VKontakte, dans l'onglet "Types d'événements", cochez la case "messages entrants".

En conséquence, notre script recevra ces messages au format json :

 {"type":"message_new","object":{"id":891,"date":1541599508,"out":0,"user_id":1...1,"read_state":0,"title":"","body":"  "},"group_id":1...4,"secret":"uxSBw"} 

Veuillez noter qu'il y a un champ "secret" dans le message json . Il s'agit de la même clé secrète que j'ai enregistrée dans la section de gestion de groupe du site Web de VKontakte, au lieu de la protection intégrée à Django CSRF, que j'ai dû désactiver.

Comment rendre un bot plus intelligent et meilleur?


Vous pouvez créer une base de données avec des réponses à l'utilisateur et apprendre au bot à choisir la réponse qui se rapproche le plus de la question de l'utilisateur. J'en parlerai dans un article séparé.
Il est possible et nécessaire de programmer des scénarios d'interaction utilisateur, pour ainsi dire, pour maintenir une conversation.

Bonne chance dans votre travail créatif!

Source: https://habr.com/ru/post/fr429628/


All Articles