フロントエンドをVue.js
バックエンドをFlask(python)
で作っているWebアプリを書いているのですが、そこにSlack botを組み込む必要がありました。
せっかくpythonで書いているので、slack bolt for pythonを使えば簡単にかけるはずです。
https://github.com/SlackAPI/bolt-python
このboltなのですが、 @seratch さんの尽力もあって、Flask用のexampleも書いてあるのです。ありがたや。
https://github.com/slackapi/bolt-python/tree/main/examples/flask
コード自体はそこに書いてあるとおりに書けば良いのですが、今回はもともと作っていたアプリに組み込みたい。そうなると、このままでは書けません。
イメージとしてはここにあるようなものです。
https://qiita.com/y-tsutsu/items/67f71fc8430a199a3efd
from flask import Flask, render_template
app = Flask(__name__, static_folder='../frontend/dist/static', template_folder='../frontend/dist')
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
return render_template('index.html')
if __name__ == '__main__':
app.run()
こんな風になっているので、そこに組み込みましょう。
from flask import Flask, render_template
app = Flask(__name__, static_folder='../frontend/dist/static', template_folder='../frontend/dist')
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
return render_template('index.html')
from .bolt import bolt as bolt_blueprint
app.register_blueprint(bolt_blueprint)
if __name__ == '__main__':
app.run()
bolt用のファイルは、別に分けたいのでblueprintで分割します。
新規に作るファイルはbackend/bolt.pyにします。
import logging
logging.basicConfig(level=logging.DEBUG)
from slack_bolt import App
from slack_bolt.adapter.flask import SlackRequestHandler
import os
bolt_app = App(
token=os.environ.get("SLACK_BOT_TOKEN"),
signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
)
@bolt_app.event("app_mention")
def event_test(body, say, logger):
logger.info(body)
say("What's up?")
@bolt_app.event("message")
def handle_message():
pass
handler = SlackRequestHandler(bolt_app)
bolt = Blueprint('bolt', __name__)
@bolt.route("/slack/events", methods=["POST"])
def slack_events():
return handler.handle(request)
こんな形になります。
blueprintで切り出してbolt.py側に持っていきます。
実はここでめちゃくちゃハマったのですが、ハマりどころがどこだったかというと
flask_app = Flask(__name__)
handler = SlackRequestHandler(app)
この二行ですね。
SlackRequestHandlerに入れるのはflask_appじゃないのです。
slack_boltで生成したappインスタンスなので注意してください。
handler = SlackRequestHandler(app)
flask_app = Flask(__name__)
こんな風に逆に書いてあったほうが勘違いしないかもしれない。
@bolt としたものは、main.pyから呼んだflaskのインスタンスです。
こいつを使ってrouteに設定した/slack/eventsに通ってきたリクエストをhandlerを通じてbolt側に渡して処理する形になっています。
処理の流れが分かってしまえば、理解しやすいのですが、初学者だとtypoに気付くのが辛いかもしれません。
どなたかの理解につながれば幸いです。