前回の続きです。
前回のあらすじ:Slackの通知機能が不安定で、新着書き込みに気付かないことがある→書き込みあったらLINEに飛ばしてみよう!→サーバーを用意し、PythonとLINE Bot SDKをインストール
前回書ききれなかったのですが、Slackからの通知はoutgoing webhooksではなくslash commandsを今回使いました。前者は全発言をトリガーにできるのですが、プライベートチャンネルでは後者しか使えないらしい(弊社の場合それでは困る)ので。slash commandsではコマンドに続くメッセージしか送信されませんが、よく考えたら会話のきっかけだけ通知されれば今回の目的には十分なので、それで丁度いいかと思いました。
よって、Slackにブラウザログインして管理ページに行き、slash commandsに以下のスクリプトに繋がるURLを設定しておきます。
Slackからデータを受け取りLINEのAPIを叩くPythonのスクリプトはこんな感じにしてみました。前回貼ったものです。
from linebot import LineBotApi
from linebot.models import TextSendMessage
from linebot.exceptions import LineBotApiError
from flask import Flask, request, jsonify
line_bot_api = LineBotApi('CHANNEL ACCCES TOKEN')
app = Flask(__name__)
@app.route('/', methods=['POST'])
def slack_push():
if request.method == 'POST':
try:
linkUrl = 'https://example.com/slackredirect.php?team_id=' + request.form["team_id"]
if request.form["channel_name"] == 'directmessage':
linkUrl = linkUrl + '&user_id=' + request.form["user_id"]
else:
linkUrl = linkUrl + '&channel_id=' + request.form["channel_id"]
line_bot_api.push_message('GROUP ID', TextSendMessage(
text = request.form["user_name"] + ":\n" + request.form["text"] + "\n" + linkUrl)
)
return jsonify(text = "", response_type = "in_channel")
except LineBotApiError as e:
return e
return "good"
if __name__ == '__main__':
app.run(host='0.0.0.0', ssl_context=('/etc/letsencrypt/live/example.com/fullchain.pem', '/etc/letsencrypt/live/example.com/privkey.pem'))
簡単に解説。
・CHANNEL ACCCES TOKENの部分にはLINE側の管理ページで取得したChannel Access Tokenを入れる
・Flask(Webフレームワーク)でSlackからのPOSTを受け取る
・受け取ったデータからteam_id、channel_name、user_id、channel_idなどを取り出し、ダイレクトメッセージかどうかで出力パラメータを変える(LINEからSlackアプリを開くURLを生成するため←これはなくてもいいがあると便利なので付けた)
・push_messageでGROUP ID(後述)宛てに、Slackで発言したユーザー名とテキストと、Slackでそのチャンネルを開くためのURLを送信
・{text:””, response_type:”in_channel”}のJSONを返すと、コマンドを送ったSlack側ではテキストがそのまま普通に表示される
・Flaskはhost=’0.0.0.0’で起動し外部から接続を受け付けるように
・SSLで接続できるようssl_contextを上記のように(もちろん実際に合わせて)設定しておく
上で出てくるslackredirect.phpはSlackアプリを開くURLスキームにリダイレクトするだけのものです。slack://で始まるURLスキームはLINE上ではリンクにならないので、httpsでリンクにしてブラウザを噛ませることでLINEから1タップでSlackの発言があった部屋を開くようにしています。
<?php
parse_str($_SERVER['QUERY_STRING'], $params);
if (isset($params['user_id']) && isset($params['team_id'])){
header("Location: slack://user?team={$params['team_id']}&id={$params['user_id']}");
}
elseif (isset($params['channel_id']) && isset($params['team_id'])){
header("Location: slack://channel?team={$params['team_id']}&id={$params['channel_id']}");
}
exit;
上記のように、Slackで指定の部屋を開くURLスキームはダイレクトメッセージの場合 {TEAM_ID}&id={USER_ID}
チャンネル(グループ)の場合 {TEAM_ID}&id={CHANNEL_ID}
です。このPHP内ではuser_idとchannel_idどちらが定義されているかで判定しています。
続く。