Führen Sie den in Python (Flask) implementierten LINE Bot "ohne Verwendung von Heroku" aus.

Über diesen Artikel

Wie der Titel schon sagt. Es gibt viele Artikel über LINEBot in verschiedenen Sprachen, aber soweit ich gesucht habe, sollten fast alle in einer PaaS-Umgebung wie Heroku funktionieren. In diesem Artikel werde ich beschreiben, wie Sie in Ihrer eigenen Umgebung arbeiten können, ohne Heroku usw. zu verwenden.

Anwendungskonfiguration

Siehe die Abbildung unten. linebot_arch.png Flask Framework für die Entwicklung von Webanwendungen für Python. Obwohl es eine Funktion als Webserver hat, dient es der minimalen Funktionsprüfung. Für den Produktionsbetrieb ist ein separater Webserver erforderlich. Offiziell: https://flask.palletsprojects.com/de/1.1.x/ uWSGI WSGI ist eine Abkürzung für Web Server Gateway Interface, die einen Webserver und eine Anwendung verbindet. Python-spezifische Spezifikationen. uWSGI ist ein Server, der diese Spezifikation erfüllt, und diesmal spielt er die Rolle der Verbindung der Flask-Anwendung und Nginx, die später beschrieben wird. Es ist auch der Anwendungsserver, auf dem Flask ausgeführt wird. Offiziell: https://uwsgi-docs.readthedocs.io/en/latest/ Nginx Webserver. Empfängt eine Anfrage von einem Client und gibt eine Antwort darauf zurück. Da der LINE-Server diesmal zwischen dem Client und dem Client liegt, wird die Anforderung vom LINE-Server empfangen. Da für LINE Bot eine ** SSL-Konvertierung des Webservers ** erforderlich ist, muss auch eine separate Domäne und ein separates SSL-Zertifikat angefordert werden (ein Oreore-Zertifikat ist nicht möglich). Offiziell: https://nginx.org/en/

LINE-Server

Ein Ort, der direkt mit der LINE-App des Kunden kommuniziert. Nehmen Sie im Browser auf der Konsole mit dem Namen LINE Developers verschiedene Einstellungen vor.

Entwicklungsumgebung

Einstellungen auf der Seite der LINE-Entwickler

Kanal erstellen

Es ist in Ordnung, wenn Sie gemäß Offizielle Referenz festlegen. Früher wurde ich gebeten, hier einen Plan aufzustellen (kostenlos oder bezahlt), aber bis Mai 2020 wurde ich nicht gefragt. Darüber hinaus ist die PUSH-API, die im kostenlosen Plan nicht verfügbar sein sollte, verfügbar geworden, bevor ich es wusste. .. ..

Bot einrichten

Nehmen Sie Einstellungen in der LINE Developers-Konsole vor. Dies ist auch in Ordnung, wenn Sie gemäß Offizielle Referenz festlegen. Zu diesem Zeitpunkt müssen Sie die Bot-Server-Endpunkt-URL noch nicht eingeben. Die wichtigen Punkte hier sind wie folgt

Erstellen Sie einen LINE-Bot in Ihrer eigenen Umgebung

Installieren Sie zuerst Flask, line-bot-sdk, uWSGI

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

Erstellen einer Anwendung mit Flask

Erstellt im Verzeichnis line_bot mit der folgenden Konfiguration. Die Einstellungsdatei ist eine separate Datei, aber ich frage mich, ob sie mir hier gefällt

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

app.py Erstellt unter Bezugnahme auf Beispielprogramm von line-bot-sdk-python. Wenn der Benutzer Text sendet, gibt er einen Papagei zurück, und wenn ein Bild, Video oder Stempel gesendet wird, gibt er eine feste Phrase zurück.

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__":
    #Geben Sie diesmal 9999 für den Port an
    port = int(os.getenv("PORT", 9999))
    #Flask ist nicht nach außen exponiert, auch wenn es standardmäßig ausgeführt wird. Geben Sie daher die IP-Adresse und den Port im Argument run an
    app.run(host="0.0.0.0", port=port)

conf.json Legen Sie das Kanalgeheimnis und das Kanalzugriffstoken fest, die von LINE-Entwicklern erhalten wurden. Dieses Mal habe ich es auf eine externe Datei gesetzt, aber ich denke, Sie können es direkt in app.py schreiben

conf.json


{
"CHANNEL_SECRET": "Kanalgeheimnis setzen",
"CHANNEL_ACCESS_TOKEN": "Kanalzugriffstoken festlegen"
}

logging.conf Ich mag es total.

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

Nginx-Einstellungen

Nginx verhält sich wie in / etc / nginx /. Wenn Sie die Konfigurationsdatei nicht geändert haben, wird sie wahrscheinlich /etc/nginx/conf.d/*.conf lesen und konfigurieren. Erstellen Sie die linebot.conf unter /etc/nginx/conf.d/ und beschreiben Sie Folgendes. Da diesmal Port 9998 verwendet wird, muss der Port separat geöffnet werden.

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     [Geben Sie den Speicherort an, an dem die CRT-Datei abgelegt wird];
    ssl_certificate_key [Geben Sie den Speicherort an, an dem die Schlüsseldatei abgelegt wird];
    ssl_session_timeout 10m;

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

Starten Sie Nginx nach dem Einstellen neu

$ sudo systemctl restart nginx

uWSGI-Einstellungen

Erstellen Sie die uWSGI-Einstellungsdatei uwsgi.ini in derselben Ebene wie app.py und beschreiben Sie Folgendes

uwsgi.ini


# uwsgi.ini

[uwsgi]

#wsgi-Datei
wsgi-file=[app.py Pfad]
callable=app

#Berechtigungshost:Hafen
http=0.0.0.0:9999

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

pidfile=/home/[Der Pfad, in dem Sie die PID-Datei ausgeben möchten]/uwsgi.pid

#Wenn Daemonize angegeben ist, wird es zu einem Daemon. Stdout zum angegebenen Pfad/Ausgabe stderr
daemonize=/[Der Pfad, in dem Sie die Protokolldatei ausgeben möchten]/uwsgi.log

Wenn Sie danach uWSGI mit dem folgenden Befehl starten, können Sie darauf zugreifen.

$ uwsgi --ini myapp.ini

Um zu stoppen, töte einfach -QUIT mit der PID von uwsgi.pid.

Funktionsprüfung

Es spielt keine Rolle, ob es sich um einen Browser oder eine Locke handelt. Wenn Sie also "https: //www.example.com: 9998 / test" besuchen, sollten Sie "Ich lebe!" Erhalten. Nachdem Sie dies bestätigt haben, geben Sie "https: //www.example.com: 9998 / callback" als Webhook-URL in LINE Developers an und aktivieren Sie "Webhook verwenden". (Die Schaltfläche "Überprüfen" am unteren Rand des URL-Eingabefelds verursacht aus irgendeinem Grund einen Fehler. Wir untersuchen dies.) Der von Ihnen erstellte LINE-Bot sollte jetzt funktionieren. linebot_sc.png

Persönliche zukünftige Herausforderungen

abschließend

Ich habe keine Seite geschrieben, die das Verfahren zum Ausführen von LINE Bot mit Heroku beschreibt. Im Falle des freien Rahmens geht Heroku in den Ruhezustand, wenn es für einen bestimmten Zeitraum (ca. 30 Minuten?) Nicht funktioniert. Die Verbindung läuft ab, was nicht sehr praktisch ist. Wenn Sie nicht daran denken, einen kostenpflichtigen Plan einzuführen, sollten Sie ihn ausführen, wenn Sie über eine eigene Umgebung verfügen.

Ich würde mich freuen, wenn Sie mich wissen lassen könnten, ob die von mir bereitgestellten Informationen fehlerhaft sind.

Recommended Posts

Führen Sie den in Python (Flask) implementierten LINE Bot "ohne Verwendung von Heroku" aus.
Asynchrone Verarbeitung mit LINE BOT: RQ (Redis Queue) in Python
Implementiert in 1 Minute! LINE Benachrichtigen in Python
Platzierung von Fabicon (bei Verwendung von Python, Flask, Heroku)
Entwicklung eines Slack Bot mit Python mit chat.postMessage
LINE Heroku Python
SimRank in Python implementiert
Shiritori in Python implementiert
Erstellen Sie mit Selenium einen Datenerfassungsbot in Python
[Python] Verwenden der Linien-API [1. Erstellung des Beauty-Bots]
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
Lassen Sie Python in einer Zeile segfo, ohne ctypes zu verwenden
Leichter Thread-Leistungsbenchmark mit async / await, implementiert in Python 3.5
Zeichenfolgen ohne Zeilenumbrüche in Python anzeigen (persönliches Memo)
Fizzbuzz in Python (in einer Zeile)
Berühre Flask + laufe mit Heroku
Führen Sie automatisierte Jobs in Python aus
Führen Sie Shell-Befehle in Python aus
Versuchen Sie LINE Notify mit Python
Deaktivieren Sie die SSL-Validierung, ohne in Python-Anforderungen verify = False zu verwenden
Versuchen Sie, ein neuronales Netzwerk in Python aufzubauen, ohne eine Bibliothek zu verwenden
Implementierte Supreme Solver in Python 3
Ermöglichen Sie die schnelle Ausführung von Python-Skripten in Cloud Run mithilfe des Responders
Online-Übertragung mit Python
Übersetzt mit Googletrans in Python
Verwenden des Python-Modus in der Verarbeitung
Einfach! Implementieren Sie einen Twitter-Bot, der auf Heroku in Python ausgeführt wird
Python-Anfänger haben Hello World in 30 Sekunden mit der Mikroframework-Flasche ausprobiert
Verbinden Sie SORACOM mit Haushaltsgeräten und LINE Bot [Python / Flask / Raspberry Pi]
Segfo Python in einer Zeile
GUI-Programmierung in Python mit Appjar
[Python] Erstelle deinen eigenen LINE-Bot
Implementierte Bildsegmentierung in Python (Union-Find)
Lassen Sie uns "Python -m Antigravitation" in Python ausführen
Führen Sie den Shell-Befehl / Python in R aus
[Python3] Google übersetzt Google Übersetzung ohne Verwendung von API
Drucken Sie mit python3 ohne Unterbrechungen
Führen Sie die App mit Flask + Heroku aus
Versuchen Sie es mit LevelDB mit Python (plyvel)
In Python implementierte Widrow-Hoff-Lernregeln
Verwenden Sie als nächstes Python (Flask) für Heroku!
Implementierte Methode zur Weitergabe von Etiketten in Python
Erstellen Sie Google Mail in Python ohne Verwendung der API
Verwendung globaler Variablen in Python-Funktionen
Python, Slice ohne Doppelpunkt (:). a .__ getitem__ (Slice (3,5)).
Tastenanschläge in Python erkennen (ohne Eingabe)
Mal sehen, wie man Eingaben in Python verwendet
Gesamtleistung in Python (mit Funktools)
Implementierte Perceptron-Lernregeln in Python
Führen Sie unittest in Python aus (für Anfänger)
Führen Sie Ansible über Python mithilfe der API aus
Führen Sie einen einfachen Algorithmus in Python aus
Handschriftliche Zeichenerkennung mit KNN in Python
Ich habe Line Benachrichtigung in Python versucht
Versuchen Sie es mit LeapMotion mit Python
[Einführung] Fügen Sie Zeilenumbrüche in Python 3 ein
Suche nach Tiefenpriorität mit Stack in Python
Bei Verwendung regulärer Ausdrücke in Python
Erstellen Sie mit Django einen LINE-Bot