[PYTHON] Die Geschichte der Erstellung von Botonyan, das den Inhalt von Google Text & Tabellen als Antwort auf ein bestimmtes Keyword in Slack zurückgibt

Überblick

Hintergrund der Sache

Hallo Spin ich NYA. Leute auf der Seite und Leute auf der Seite schreiben oft Python. Als ich anfing, es zu schreiben, war ich begeistert und habe Slackbot mit Python + Flask gemacht.

https://github.com/supistar/Botnyan

Ingress und Slack

Der Ursprung der Sache ist so Ingress ^ 1 Ich bin mir sicher, dass viele von Ihnen Ingress bereits kennen, daher werde ich nicht auf Details eingehen. Aufgrund der Art des Spiels ist es jedoch wichtig, dass Spieler in einem bestimmten Bereich eine Community bilden und über diese Community interagieren und Operationen entwickeln. .. In dieser Community migrieren einige Communitys jetzt zu Slack.

Siehe Blog [^ 2] hier für den Übergang zu Slack.

Slack ist der erste Schritt, um der Community beizutreten

Mit dem Übergang zu Slack gab es viele Versuche und Irrtümer, um die Community komfortabler zu gestalten. Eine davon ist eine Leitbotschaft beim Beitritt zur Community.

Slack hat einen besonderen Aspekt, und ein großes Hindernis für Benutzer ist, dass die Anwendung auf Englisch basiert. Für Ingenieure ist Englisch eine Welt vor dem Frühstück, aber so wie Agenten keine Ingenieure sind, ist es nicht immer so, dass jeder an Englisch gewöhnt ist.

Höhere Hindernisse für den Beitritt zur Gemeinschaft werden die allgemeine Beteiligung verringern, die Bildung der Gemeinschaft behindern und den Zweck des Umzugs nach Slack in erster Linie ruinieren.

Um diese Barriere zu verringern, haben wir ein Handbuch mit Screenshots und ein Dokument mit Tipps erstellt und Verbesserungen vorgenommen, um neue Mitglieder anzuleiten. Dadurch wurden Tutorials und Leads für Erstbenutzer erstellt, die ihnen die Teilnahme erleichtern.

Überraschend schwieriger Slackbot

Diese Leitmeldung wurde jedoch zunächst manuell erstellt

Aufgrund häufiger Probleme wie wurde die Rolle auf Slackbot verschoben, das von Anfang an mit Slack bereitgestellt wird. Dadurch wurde die Leitmeldung automatisiert, aber dieser Bot ist ein ziemlicher Songwriter ...

Ich hatte das Problem "Ich möchte das irgendwie lösen ..." und das Ergebnis ist "Botnyan".

Wir stellen vor: Botnyan

Botnyan basiert auf Python + Flask und fungiert als Bot auf Slack, ausgelöst durch Outgoing-Webhook.

slack.png

Die Bedienung ist sehr einfach:

--Outgoing - Wenn der Beitrag das in Webhooks angegebene Schlüsselwort enthält, greifen Sie auf den angegebenen REST-Endpunkt (Botnyan) zu. --Botnyan greift auf Google Text & Tabellen zu, die dem angegebenen Keyword zugeordnet sind --Botnyan <-> Google Text & Tabellen stellt eine Verbindung über ein Dienstkonto her. Dokumentinhalte im Textdateiformat abrufen

Es ist geworden.

Seit seiner Einführung wurde es von anderen Agenten sehr gut aufgenommen.

Nachdem ich es erstellt hatte, hörte ich, dass die Nachbargemeinde ein ähnliches Problem hatte, und beschloss, das, was im privaten Repository verwaltet wurde, als öffentliche Quelle zu veröffentlichen. Zuerst habe ich es in der Apache + WSGI-Umgebung zum Laufen gebracht, aber ich habe einige Änderungen am Original vorgenommen, damit es auch in Heroku funktioniert.

Wir haben README-jp für die Einführungsmethode vorbereitet, schauen Sie also auch dort nach! https://github.com/supistar/Botnyan/blob/master/README-jp.md

Technische Geschichte

Hier finden Sie eine kurze Beschreibung des in Botonyan verwendeten technischen Inhalts.

1. Begrenzen Sie den von Flask veröffentlichten Endpunkt

Mit Flask können Sie den Zugriff auf Endpunkte mithilfe mehrerer Dekoratoren einschränken.

Ausgehende Webhooks in Slack greifen auf den durch "POST" + "application / x-www-form-urlencoded" angegebenen Endpunkt zu. Wenn Sie es daher nur auf diese beschränken möchten, gehen Sie wie folgt vor. Da Cross-Origin auch hier zulässig ist, fügen Sie ebenfalls "@cross_origin ()" hinzu.

python


@slack.route("/webhook", methods=['POST'])
@cross_origin()
@consumes('application/x-www-form-urlencoded')
def webhook():
    ~~~

2. Ausgehend - Etwas verbesserte Endpoint-Sicherheit, die von Webhooks verwendet wird

Outgoing-Webhooks müssen über einen Endpunkt verfügen, der auf die Öffentlichkeit zugreifen kann. Die Standardauthentifizierung kann nicht angewendet werden. Wenn Sie also einen Endpunkt erstellen, ohne sich dessen bewusst zu sein,

  1. Der Name der Heroku-Anwendung wurde bekannt gegeben
  2. Geben Sie ein geeignetes Schlüsselwort ein
  3. Wenn die Schlüsselwörter übereinstimmen, wird der Inhalt des Dokuments durchgesickert! Wichtige Informationen für die Gegenpartei! !! !!

Das könnte der Fall sein (´ ・ ω ・ `)

Slacks Outgoing-Webhooks gewährt jedoch Token für Anforderungen. Lassen Sie uns zunächst die Token überprüfen, die Outgoing-Webhooks Ihnen geben. Schauen Sie sich unten die Integrationen von Slack an.

01.png

Es ist perfekt mit diesem Token. Speichern Sie dieses Token dann auf der Anwendungsseite und vergleichen Sie es mit dem in der tatsächlichen Anforderung enthaltenen Token. Wenn das Token nicht auf der Anwendungsseite festgelegt ist oder wenn sich das Token von dem in der Anforderung unterscheidet, geben Sie einen Fehler mit "abort (401)" zurück.

form = request.form
request_token = Utils().parse_dic(form, 'token', 400)
token = os.environ.get('SLACK_WEBHOOK_TOKEN')
if not token or token != request_token:
    abort(401)

3. So verwalten Sie den privaten Schlüssel des Dienstkontos

Um ehrlich zu sein, war ich darüber am meisten besorgt: ängstlich: Es wäre einfacher, wenn ich die p12-Datei direkt in das Repository stellen würde, aber ich habe sie sofort abgelehnt, weil ich sie öffentlich gemacht habe. Die alternative Methode besteht darin, den privaten Schlüssel in "Config Variables" zu setzen.

Nehmen Sie zuerst den privaten Schlüssel aus der p12-Datei heraus

cd path/to/p12directory
openssl pkcs12 -passin pass:notasecret -in privatekey.p12 -nocerts -passout pass:notasecret -out key.pem
openssl pkcs8 -nocrypt -in key.pem -passin pass:notasecret -topk8 -out google-services-private-key.pem
rm key.pem
# google-services-private-key.pem ist der private Schlüssel! Du hast es geschafft!

Stellen Sie dies auf "Config Variables".

# heroku-Werkzeuggürtel verwenden...Diesen Weg
heroku config:add GOOGLE_PRIVATE_KEY=`cat path/to/p12directory/google-services-private-key.pem`

Greifen Sie von der Python-Codeseite aus mit "os.environ" zu. Der Rest entspricht dem Lesen aus einer p12-Datei. Wenn der private Schlüssel nicht festgelegt ist, ist es leicht zu verstehen, wenn Sie "abort ()" aufrufen, um einen bestimmten Statuscode zurückzugeben.

private_key = os.environ['GOOGLE_PRIVATE_KEY']
if not private_key:
    abort(401)
credentials = SignedJwtAssertionCredentials(os.environ['GOOGLE_CLIENT_EMAIL'],
                                            private_key,
                                            'https://www.googleapis.com/auth/drive',
                                            sub=os.environ['GOOGLE_OWNER_EMAIL'])
http = httplib2.Http()
credentials.authorize(http)
service = build('drive', 'v2', http=http)

4. Rufen Sie den Dokumentinhalt aus der GoogleDocs-Dokument-ID ab

Es ist der Kern von Botnyan. Rufen Sie die Datei mit der in (3) erstellten Dienstinstanz und Dokument-ID ab.

Wenn Sie es jedoch einfach erhalten, werden Dateien im Office-Format heruntergefahren, sodass die Verwendung schwierig ist. Also lasst es uns in einem Dateiformat von "text / plain" bekommen. Wenn Sie Folgendes tun, wird der Inhalt des Dokuments als Zeichenfolge in "Inhalt" gespeichert.

f = service.files().get(fileId=doc_id).execute()
if 'exportLinks' in f and 'text/plain' in f['exportLinks']:
    download = f['exportLinks']['text/plain']
    resp, content = service._http.request(download)
else:
    content = 'Fehler beim Lesen'

5. Lassen Sie den Bot den erworbenen Inhalt sprechen

Das ist sehr einfach. Ausgehend - Geben Sie einfach eine JSON-Antwort zurück, die der folgenden für Webhooks-Anforderungen ähnelt.

{"text": "Es ist der Inhalt des Dokuments! ∧_∧"}

Es wird nur JSON unter Verwendung des in (4) erhaltenen Inhalts zurückgegeben. Geben Sie "application / json" für den Inhaltstyp der Antwort an.

dic = {"text": content}
return Response(Utils().dump_json(dic), mimetype='application/json')

Verbleibende Herausforderungen

Das heißt nicht, dass alles gelöst ist.

--Outgoing-Webhook kann derzeit keine PrivateRoom-Bemerkungen erfassen

Damit

Welche Seite des Agenten bin ich ... ohne hier: Geist: Ich denke, dass Kommunikationsprobleme nicht nur im Ingress-Team, sondern auch in der Arbeit auftreten. Wenn es Ihnen gefällt, verwenden Sie es bitte.

Ich würde mich sehr freuen, wenn es hilft! Damit! : cat2:

Referenzseite

Recommended Posts

Die Geschichte der Erstellung von Botonyan, das den Inhalt von Google Text & Tabellen als Antwort auf ein bestimmtes Keyword in Slack zurückgibt
Die Geschichte des Erstellens eines Bots, der aktive Mitglieder in einem bestimmten Slack-Kanal mit Python anzeigt
Eine Geschichte über das Erstellen eines Programms, mit dem die Anzahl der Instagram-Follower in einer Woche von 0 auf 700 erhöht wird
Die Geschichte des Erstellens einer Datenbank mithilfe der Google Analytics-API
Ich bin gerade in Singapur. Eine Geschichte über das Erstellen eines LineBot und den Wunsch, einen unvergesslichen Job zu machen
Die Geschichte der Erstellung einer Website, auf der die Veröffentlichungsdaten von Büchern aufgeführt sind
Erstellen Sie eine Funktion, um den Inhalt der Datenbank in Go abzurufen
[Python] Ein Programm, das den Inhalt der Liste nach links dreht
[Google Photo & Slack Photo Bot] Eine Geschichte über das Erstellen eines Bots, der ein Foto in Google Photo erfasst und an Slack sendet.
So führen Sie den Übungscode des Buches "Profitable KI mit Python erstellen" in Google Colaboratory aus
Die Geschichte, wie ein Geschäft BOT (AI LINE BOT) nach Go To EAT in der Präfektur Chiba durchsucht (1)
Kopieren und Einfügen des Inhalts eines Blattes im JSON-Format mit einer Google-Tabelle (mithilfe von Google Colab)
Erstellen Sie einen Bot, der die Anzahl der Personen, die für das neue Corona-Virus in Tokio positiv sind, an Slack sendet
Ein einfacher Mock-Server, der den HTTP-Anforderungsheader einfach in den Hauptteil der Antwort einbettet und zurückgibt.
Die Geschichte, wie ein Geschäft BOT (AI LINE BOT) nach Go To EAT in der Präfektur Chiba durchsucht (2) [Übersicht]
Wie man eine Benutzergruppe mit Slack-Benachrichtigung erwähnt, wie man die ID einer Benutzergruppe überprüft
Die Geschichte der IPv6-Adresse, die ich auf ein Minimum beschränken möchte
Die Geschichte von Django, wie er eine Bibliothek erstellt, die vielleicht etwas nützlicher ist
[Python] Ändern Sie die Textfarbe und Hintergrundfarbe eines bestimmten Schlüsselworts in der Druckausgabe
Eine Geschichte von Versuch und Irrtum beim Versuch, eine dynamische Benutzergruppe in Slack zu erstellen
Ein Skript, das Tweets mit bestimmten Schlüsselwörtern auf Twitter in Echtzeit an Slack überträgt.
Eine Geschichte über den Versuch, Linter mitten in einem Python (Flask) -Projekt vorzustellen
Veröffentlichte die Anzahl der neuen Corona-Positiven in Tokio an Slack (auf Heroku bereitgestellt)
Eine Geschichte, die den Aufwand für Betrieb / Wartung reduziert
#Eine Funktion, die den Zeichencode einer Zeichenfolge zurückgibt
Eine Geschichte, die die Lieferung von Nico Nama analysierte.
Ein Server, der mit Flasche.py und OpenCV die Anzahl der Personen vor der Kamera zurückgibt
Erstellen Sie mit MeCab mit Discord einen Bot, der nur das Ergebnis der morphologischen Analyse zurückgibt
Die Geschichte der Schaffung eines "Geist- und Zeit-Chatrooms" exklusiv für Ingenieure im Unternehmen
Ruft den Wert eines bestimmten Schlüssels bis zum angegebenen Index der Wörterbuchliste in Python ab
Zusammenfassung der Punkte, die beim Schreiben eines Programms zu beachten sind, das unter Python 2.5 ausgeführt wird
[Python] Programmieren, um die Nummer von a in einer Zeichenfolge zu finden, die eine bestimmte Anzahl von Malen wiederholt.
[Hinweis] Ein Shell-Skript, das die CPU-Auslastung eines bestimmten Prozesses in einer while-Schleife überprüft.
Eine Geschichte, die das Debuggen von Modellen in der Django + SQLAlchemy-Umgebung einfacher macht
Eine Geschichte, die mithilfe einer kostenlosen Testversion der Google Cloud Platform zu einer neuen Koronaanalyse beiträgt
Slack-Benachrichtigung, wenn ein bestimmtes Wort auf Twitter mit Heroku mit Python gemurmelt wird
So zeichnen Sie einfach die Struktur eines neuronalen Netzwerks in Google Colaboratory mit "convnet-drawer"
Ich habe versucht, ein Skript zu erstellen, das die Tweets eines bestimmten Benutzers auf Twitter verfolgt und das veröffentlichte Bild sofort speichert
Die Geschichte der Einrichtung eines VIP-Kanals im internen Chatwork
[Ubuntu] So löschen Sie den gesamten Inhalt des Verzeichnisses
Hinweis zum Standardverhalten von collate_fn in PyTorch
Django gibt den Inhalt der Datei als HTTP-Antwort zurück
Holen Sie sich die Anzahl der spezifischen Elemente in der Python-Liste
Python-Skript, das den Inhalt zweier Verzeichnisse vergleicht
So verbinden Sie den Inhalt der Liste mit einer Zeichenfolge
Veröffentlichen Sie das erstellte Shell-Skript, um die Probleme beim Erstellen von LiveUSB unter Linux zu verringern
Eine kleine süchtig machende Geschichte mit den Berechtigungen des von expdp angegebenen Verzeichnisses (für Anfänger)
Ausbeute in einer Klasse, die unittest geerbt hat. TestCase funktionierte nicht mit der Nase (abhängig von der Version der Nase?)
Eine Geschichte, die nicht funktioniert hat, als ich versucht habe, mich mit dem Python-Anforderungsmodul anzumelden
Die Geschichte, ein Tool zu erstellen, das auf Mac und Windows auf der Spieleentwicklungsseite ausgeführt wird
[Python-Scraping] Geben Sie die URL und den Titel der Site mit einem bestimmten Schlüsselwort in eine Textdatei ein
[Python] Informationen zum Erstellen eines Tools zum Erstellen einer neuen Outlook-E-Mail basierend auf den Daten der JSON-Datei und dem Teil, der abgefangen wurde
Verarbeiten Sie den Inhalt der Datei der Reihe nach mit einem Shell-Skript
Die Geschichte, dass die Version von Python 3.7.7 nicht an Heroku angepasst wurde
pandas Ruft den Namen einer Spalte ab, die ein bestimmtes Zeichen enthält
So überprüfen Sie die Speichergröße einer Variablen in Python