.
以前の記事
f17: twist api で 新規スレッド投稿
https://qiita.com/cxfgp/items/85fe57686e5e360fa255
(外部から twist のチャンネル/スレッドへ投稿)
の逆 ( incoming -> outgoing ) になります
その設定メモです
上記記事でも触れてますが、
こちらの方が、
twist api を用いた記事を書いております
(golang + outgoing ですね)
TwistのchatbotをGoで作ってみた
https://qiita.com/usk81/items/bfd15ec3c5ecc23d0b8f
こちらでも
・twist について
・twist webhook について
の解説がありますのでご参考ください
今回は 「outgoing -> 外部 php へPOST」 になります
[ 実現すること ]
twist のチャンネルのスレッドに、手動で投稿したら、
bot が検知して、外部サーバーに設置した php に POST される
(今回は、そのデータをメールに送信)
[ 00. メニュー ]
01. キッチン
02. ポイント (outgoing + test token)
03. 仕込み1 (token の発行/url の設定)
04. 仕込み2 (POSTされる側のスクリプト作成)
05. 仕込み3 (bot のスレッド参加)
06. 味見 (スレッド投稿 -> メール受信)
07. デザート
[ 01. キッチン ]
・ さくらのレンタルサーバー
・ php
・ twist の ID 登録
https://twist.com/login?lang=ja
[ 02. ポイント (outgoing + test token) ]
twist api で outgoing webhook (外部へポスト) を行う場合、
本来は、購読(subscribe) api を使って、
どのイベントをどのURLに送るかを明示的に登録する必要があります
「登録と外部ポストの流れ」
1. oauth認証でアクセストークンを取得
2. 購読(subscribe)api で webhook イベントを登録
3. 指定イベントを実行
4. ポストされるスクリプト(例: webhook.php)で json データを受信
参考:twist 公式ドキュメント(英語)
twist Developer 「Outgoing webhook」
https://developer.twist.com/v3/#outgoing-webhook
ですが、
TwistのchatbotをGoで作ってみた
-> Botの場合、General Integrationを設定すれば
subscribeの登録も不要なのでかなり楽です。
この方もおっしゃられているとおり、
購読(subscribe)等の設定を行わずに
手っ取り早く、POST する方法 (OAuth 2 test token の利用)
が用意されているのでそちらを使ってみます
その名の通り、test (テスト) token ですので、制約もあります
・特定のチャンネルのみを検知する、といったスコープの制限ができません
・token の有効期限は不明だが突然無効になる可能性あり
・検知対象が意図しない範囲に広がるリスクがある
明示的にチャンネル制限をかけたいなら、
通常の access token + 購読(subscribe)設定
で制御する必要があります
(長期運用には refresh token の仕組みが必要です)
実際、test token にて、webhook テストをしてみた結果、
bot が参加した チャンネルA 内が範囲のようでした
(outgoing の場合は、なのかもしれません)
-> チャンネルA のすべてのスレッド内投稿を検知
-> チャンネルB のスレッド内投稿は検知されなかった
このあたりについては不透明な部分が多く、
例えば、チャンネルB に、incoming webhook を設定して
投稿の無限ループに陥る、というようなことにならないようご注意ください
(自己責任でお願いします)
参考:twist 公式ドキュメント(英語)
twist Developer 「OAuth 2」
https://developer.twist.com/v3/#oauth-2
[ 03. 仕込み1 (token の発行/url の設定) ]
まずは、outgoing 用に、test token の発行と、
webhook URL の設定を行います
twist に web でログイン後、
Integration Management
https://twist.com/app_console
へ遷移します
01. 「token」 の発行
「create a new app」 ボタン押下し、
「Create Integration」 ページにて
・Integration type: General integration
・Integration name: (例: test-hook2)
を設定し 「Create integration」 ボタン押下にて、
api token が発行されます
02. 「OAuth 2 test token」 の取得
使用する token は oauth2: から始まる
「OAuth 2 test token」 です
(トークンのコピーボタンはないので、
最後の桁までコピーできてることを確認して、
どこかに控えておきます)
03. 「Bot」 の設定と、webhook URL の設定
「Name」 (例: abc)
「Outgoing webhook URL」 ご自身のサーバーの スクリプト設定
を設定し 「Add bot」 ボタン押下にて、
bot を作成します
[ 04. 仕込み2 (POSTされる側のスクリプト作成) ]
04. webhook URL を設定した外部サーバーに
設置したスクリプトの作成
<?php
// レスポンス 200 を応答しておく
http_response_code(200);
header('Content-Type: text/plain; charset=utf-8');
// メール用設定
mb_language("Japanese");
mb_internal_encoding("UTF-8");
// 時刻設定
date_default_timezone_set('Asia/Tokyo');
$ndate = date("Y/m/d H:i:s");
// json 取得
$raw_post = file_get_contents('php://input');
// 重複投稿防止用キー取得
$key = sha1($raw_post);
// 重複投稿チェック(おまけ的ハッシュ値チェック)
// php スクリプトの同階層に /processed/ ディレクトリを作成し、
// 完全同一の投稿が存在しない場合のみ処理を進める
if (!file_exists("processed/$key")) {
// 重複投稿防止用ファイル作成
file_put_contents("processed/$key", $raw_post);
// json デコード
$data1 = json_decode($raw_post, true);
// empty case
if (empty($data1)) {
$subject1 = "twist-posted: ng: 400-1: ".$ndate;
$text1 = "\n"."400: no data received"."\n";
// json が不正な場合
} elseif (json_last_error() !== JSON_ERROR_NONE) {
$subject1 = "twist-posted: ng: 400-2: ".$ndate;
$text1 = "\n"."400: invalid json data"."\n";
} else {
$subject1 = "twist-posted: ok: ".$ndate;
// 重複投稿チェック用のキーファイル(/processed/$key)に、
// 全項目が出力されているので、
// その中からお好きな項目を抜き出して、本文としてセットする
// ちなみに、
// $ndate は、日本時間('Asia/Tokyo')
// $data1["posted"] は、twist 現地サーバー時間 (US?) です
$col1 = trim($data1["posted"]);
$col2 = trim($data1["url"]);
$col3 = trim($data1["channel_id"]);
$col4 = trim($data1["thread_id"]);
$col5 = trim($data1["id"]);
$col6 = trim($data1["content"]);
$text1 = "\n".$col1."\n".$col2."\n".$col3."\n".$col4."\n".$col5."\n".$col6."\n";
}
$ipes1 = $_SERVER['REMOTE_ADDR'];
$page1 = $_SERVER['REQUEST_URI'];
// ログ出力
$logs1 = "[$ndate] $ipes1 $page1 $text1\n";
file_put_contents('post1.log', $logs1, FILE_APPEND);
$text2 = htmlspecialchars_decode($text1, ENT_NOQUOTES);
$message1 = "\n".$ndate."\n".$ipes1."\n".$page1."\n".$text2."\n";
$headers1 = 'From: from@mailaddress.com';
// return address
$param1 = 'from@mailaddress.com';
$too1 = 'to@mailaddress.com';
$ccc1 = 'cc@mailaddress.com';
$bcc1 = '';
// cc
if (!empty($ccc1)) {
$headers1 = '\n';
$headers1 = 'Cc:'.$ccc1;
}
// bcc
if (!empty($bcc1)) {
$headers1 = '\n';
$headers1 = 'Bcc:'.$bcc1;
}
// メール送信
if (mb_send_mail($too1, $subject1, $message1, $headers1, $param1)) {
// echo "send mail ok";
// などの処理を書く
} else {
// echo "send mail ng";
// などの処理を書く
}
}
?>
[ 05. 仕込み3 (bot のスレッド参加) ]
05. スレッド投稿に反応(検知)して、外部にPOSTされるように、
スレッドに bot を参加させます
05-1) チャンネル (例: チャンネルA) 作成
・「Channels」 -> + Create new channel
・「Privacy」 -> Public - Anyone on your team can join
・「Set default participants」 -> Everyone in channel
05-2) ひとまず手動で新規スレッドにてテスト投稿
URLより、以下確認
https://twist.com/a/1111/ch/2222/t/3333/
a -> ワークスペース ID
ch -> チャンネル ID
t -> スレッド ID
05-3) 上記 チャンネルA のスレッド指定で curl (bot のスレッド参加)
(test token は、oauth2:部分も含めて記載する)
curl -X POST https://api.twist.com/api/v3/comments/add \
-H "Authorization: Bearer oauth2:xxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"thread_id": "3333",
"content": "監視中"
}'
この curl による post が、無事、
指定スレッドに書き込みされましたら、
以降のスレッド投稿で、指定した webhook URL へポストされます
[ 06. 味見 (スレッド投稿 -> メール受信) ]
チャンネルのスレッド内で手動投稿を行い、
指定の外部 webhook URL に post され、
メール受信されれば完了です
(メールが届かない場合は、ログ確認で
・サーバーに到達しているか
・到達しているけどスクリプトエラーか
・スクリプト処理は正常でメールフィルターにひっかかってないか
などの切り分け)
[ 07. デザート ]
多くの サービスは、
ポーリング監視または常駐監視による
outgoing の実現が多い中、
twist は知名度は低いですが、
slack と同様、イベント駆動型で
outgoing が利用できる素敵なサービスです
.