Exécutez LINE Bot implémenté en Python (Flask) "sans utiliser Heroku"

À propos de cet article

Comme le dit le titre. Il existe de nombreux articles sur LINEBot dans différentes langues, mais d'après ce que j'ai recherché, presque tous étaient censés fonctionner dans un environnement PaaS tel que Heroku. Dans cet article, je décrirai comment fonctionner dans votre propre environnement sans utiliser Heroku, etc.

Configuration de l'application

Voir la figure ci-dessous. linebot_arch.png Flask Framework de développement d'applications Web pour Python. Bien qu'il ait une fonction de serveur Web, il s'agit d'un contrôle de fonctionnement minimum. Un serveur Web distinct est requis pour les opérations de production. Officiel: https://flask.palletsprojects.com/en/1.1.x/ uWSGI WSGI est une abréviation de Web Server Gateway Interface, qui connecte un serveur Web et une application. Spécifications spécifiques à Python. uWSGI est un serveur qui répond à cette spécification, et cette fois il joue le rôle de connecter l'application Flask et Nginx, qui sera décrit plus loin. C'est également le serveur d'applications qui exécute Flask. Officiel: https://uwsgi-docs.readthedocs.io/en/latest/ Nginx Serveur Web. Reçoit une demande d'un client et lui renvoie une réponse. Puisque le serveur LINE est cette fois pris en sandwich entre le client et le client, la requête sera reçue du serveur LINE. Puisque LINE Bot nécessite une ** conversion SSL du serveur Web **, il est également nécessaire d'obtenir un domaine et un certificat SSL séparés (le certificat Oreore n'est pas possible). Officiel: https://nginx.org/en/

Serveur LINE

Un lieu qui communique directement avec l'application LINE du client. Effectuez divers réglages à partir du navigateur de la console appelés LINE Developers.

Environnement de développement

Paramètres du côté des développeurs LINE

Créer une chaîne

C'est OK si vous définissez selon Référence officielle Auparavant, on m'avait demandé de mettre en place un plan ici (plan gratuit ou payant), mais en mai 2020, on ne m'a pas demandé. De plus, l'API PUSH, qui n'aurait pas dû être disponible dans le plan gratuit, est devenue disponible avant que je ne le sache. .. ..

Configurer le bot

Effectuez les réglages sur la console LINE Developers. C'est également OK si vous définissez selon Référence officielle Vous n'avez pas encore besoin d'entrer l'URL du point de terminaison du serveur Bot à ce stade. Les points importants ici sont les suivants

Créez un bot LINE dans votre propre environnement

Tout d'abord, installez Flask, line-bot-sdk, uWSGI

$ pip install flask 
$ pip install line-bot-sdk
$ pip install uwsgi

Créer une application avec Flask

Créé sous le répertoire line_bot avec la configuration suivante. Le fichier de configuration est un fichier séparé, mais je me demande si je l'aime ici

line_bot
 |-app.py
 |-conf.json
 |-logging.conf

app.py Créé en faisant référence à exemple de programme de line-bot-sdk-python. Lorsque l'utilisateur envoie du texte, il renvoie un perroquet et lorsqu'une image, une vidéo ou un tampon est envoyé, il renvoie une phrase fixe.

app.py


# -*- coding: utf-8 -*-

from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, ImageMessage, VideoMessage, StickerMessage, TextSendMessage
)
import os
import sys
import json
from logging import getLogger, config

app = Flask(__name__)

ABS_PATH = os.path.dirname(os.path.abspath(__file__))
with open(ABS_PATH+'/conf.json', 'r') as f:
    CONF_DATA = json.load(f)

CHANNEL_ACCESS_TOKEN = CONF_DATA['CHANNEL_ACCESS_TOKEN']
CHANNEL_SECRET = CONF_DATA['CHANNEL_SECRET']

line_bot_api = LineBotApi(CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(CHANNEL_SECRET)

config.fileConfig('logging.conf')
logger = getLogger(__name__)

@app.route("/test", methods=['GET', 'POST'])
def test():
    return 'I\'m alive!'

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))

@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text="Image"))

@handler.add(MessageEvent, message=VideoMessage)
def handle_video(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text="Video"))

@handler.add(MessageEvent, message=StickerMessage)
def handle_sticker(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text="Sticker"))

if __name__ == "__main__":
    #Spécifiez 9999 pour le port cette fois
    port = int(os.getenv("PORT", 9999))
    #Flask n'est pas exposé à l'extérieur même s'il est exécuté par défaut, spécifiez donc l'adresse IP et le port dans l'argument d'exécution
    app.run(host="0.0.0.0", port=port)

conf.json Définissez le secret du canal et le jeton d'accès au canal obtenus par les développeurs LINE. Cette fois, je l'ai défini sur un fichier externe, mais je pense que vous pouvez l'écrire directement dans app.py

conf.json


{
"CHANNEL_SECRET": "Définir le secret du canal",
"CHANNEL_ACCESS_TOKEN": "Définir le jeton d'accès au canal"
}

logging.conf Je l'aime totalement.

logging.conf


[loggers]
keys=root

[handlers]
keys=fileHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=INFO
handlers=fileHandler

[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
formatter=simpleFormatter
args=('app.log','MIDNIGHT')

[formatter_simpleFormatter]
format=%(asctime)s %(levelname)s %(message)s

Paramètres Nginx

Nginx procède comme s'il se trouvait dans / etc / nginx /. Si vous n'avez pas modifié le fichier de configuration, je pense qu'il est censé lire /etc/nginx/conf.d/*.conf et le configurer. Créez linebot.conf sous /etc/nginx/conf.d/ et décrivez ce qui suit. Puisque le port 9998 sera utilisé cette fois, il est nécessaire d'ouvrir le port séparément.

linebot.conf


server {
    listen       9998 ssl;
    server_name  example.com;

    ssl_protocols       TLSv1.2 TLSv1.1 TLSv1;
    ssl_ciphers         ALL:!aNULL:!SSLv2:!EXP:!MD5:!RC4:!LOW:+HIGH:+MEDIUM;
    ssl_certificate     [Spécifiez l'emplacement où le fichier CRT est placé];
    ssl_certificate_key [Spécifiez l'emplacement où le fichier de clé est placé];
    ssl_session_timeout 10m;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
        proxy_pass http://127.0.0.1:9999/;
    }
}

Après le réglage, redémarrez Nginx

$ sudo systemctl restart nginx

Paramètres uWSGI

Créez le fichier de paramètres uWSGI uwsgi.ini dans la même couche que app.py et décrivez ce qui suit

uwsgi.ini


# uwsgi.ini

[uwsgi]

#fichier wsgi
wsgi-file=[app.chemin py]
callable=app

#Hôte d'autorisation:Port
http=0.0.0.0:9999

socket=/tmp/uwsgi.sock
module=app
chmod-socket=666

pidfile=/home/[Le chemin où vous voulez sortir le fichier pid]/uwsgi.pid

#Si daemonize est spécifié, il devient un démon. Stdout vers le chemin spécifié/Sortie stderr
daemonize=/[Le chemin où vous souhaitez sortir le fichier journal]/uwsgi.log

Après cela, si vous démarrez uWSGI avec la commande suivante, vous pouvez y accéder.

$ uwsgi --ini myapp.ini

Pour arrêter, il suffit de tuer -QUIT avec le PID de uwsgi.pid.

Contrôle de fonctionnement

Peu importe que ce soit un navigateur ou un curl, donc lorsque vous visitez https: //www.example.com: 9998 / test, vous devriez obtenir" I'm alive! ". Après avoir confirmé cela, spécifiez https: //www.example.com: 9998 / callback comme URL du Webhook dans LINE Developers et activez Utiliser le webhook. (Le bouton "vérifier" en bas du champ de saisie de l'URL provoque une erreur pour une raison quelconque. Nous sommes en train d'enquêter) Le bot LINE que vous avez créé devrait maintenant fonctionner. linebot_sc.png

Défis personnels futurs

en conclusion

Je n'ai écrit aucune page décrivant la procédure pour exécuter LINE Bot avec Heroku. Dans le cas de la trame libre, Heroku s'endormira s'il ne fonctionne pas pendant un certain temps (environ 30 minutes?) La connexion expire, ce qui n'est pas très pratique. Si vous ne songez pas à introduire un plan payant, vous devriez l'exécuter si vous avez votre propre environnement.

Je vous serais reconnaissant de bien vouloir me faire savoir s'il y a des erreurs dans les informations que j'ai fournies.

Recommended Posts

Exécutez LINE Bot implémenté en Python (Flask) "sans utiliser Heroku"
Traitement asynchrone avec LINE BOT: RQ (Redis Queue) en Python
Implémenté en 1 minute! LINE Notify en Python
Placement de Fabicon (lors de l'utilisation de Python, Flask, Heroku)
Développement de slack bot avec python en utilisant chat.postMessage
LINE heroku python
Implémentation de SimRank en Python
Implémentation de Shiritori en Python
Créer un bot de collecte de données en Python à l'aide de Selenium
[Python] Utilisation de l'API Line [1ère création de Beauty Bot]
J'ai essayé de faire LINE BOT avec Python et Heroku
Laissez Python segfo sur une ligne sans utiliser de ctypes
Benchmark des performances de thread léger utilisant async / await implémenté dans Python 3.5
Afficher les chaînes de caractères sans saut de ligne en python (mémo personnel)
Fizzbuzz en Python (en une ligne)
Touch Flask + courir avec Heroku
Exécuter des tâches automatisées en Python
Exécuter des commandes shell en Python
Essayez LINE Notify avec Python
Désactiver la validation SSL sans utiliser verify = False dans les requêtes Python
Essayez de créer un réseau de neurones en Python sans utiliser de bibliothèque
Implémentation de Supreme Solver dans Python 3
Autoriser l'exécution rapide des scripts Python dans Cloud Run à l'aide du répondeur
Diffusion sur LINE en utilisant python
Traduit à l'aide de googletrans en Python
Utilisation du mode Python dans le traitement
Facile! Implémenter un bot Twitter qui s'exécute sur Heroku en Python
Un débutant en Python a essayé Hello World en 30 secondes en utilisant le microframework Flask
Associez SORACOM aux appareils ménagers et au LINE Bot [Python / Flask / Raspberry Pi]
Segfo python en une ligne
Programmation GUI en Python avec Appjar
[Python] Créez votre propre bot LINE
Implémentation de la segmentation d'image en python (Union-Find)
Lançons "python -m antigravity" en python
Exécutez la commande shell / Python dans R
[Python3] Google translate google translation sans utiliser l'API
Imprimez avec python3 sans interruption
Exécutez l'application avec Flask + Heroku
Essayez d'utiliser LevelDB avec Python (plyvel)
Règles d'apprentissage Widrow-Hoff implémentées en Python
Ensuite, utilisez Python (Flask) pour Heroku!
Implémentation de la méthode de propagation d'étiquettes en Python
Créez Gmail en Python sans utiliser l'API
Utilisation de variables globales dans les fonctions python
Python, découpez sans utiliser deux-points (:). a .__ getitem__ (tranche (3,5)).
Détecter les frappes en Python (sans Entrée)
Voyons voir l'utilisation de l'entrée en python
Puissance totale en Python (en utilisant functools)
Implémentation des règles d'apprentissage Perceptron en Python
Exécutez unittest en Python (pour les débutants)
Exécutez Ansible à partir de Python à l'aide de l'API
Exécutez un algorithme simple en Python
Reconnaissance de caractères manuscrits à l'aide de KNN en Python
J'ai essayé la notification de ligne en Python
Essayez d'utiliser LeapMotion avec Python
[Introduction] Insérer des sauts de ligne dans Python 3
Recherche de priorité de profondeur à l'aide de la pile en Python
Lors de l'utilisation d'expressions régulières en Python
Créer un bot LINE avec Django