✏️ 編集
Clasp 環境から Slack API を使ってメッセージの送受信を行ってみたので、その時のメモを残す。
Clasp 環境は過去記事の環境を使用している。
Docker で clasp 環境を構築する | yamamoto-yuta.github.io
Slack App の作成
https://api.slack.com/apps から Slack App を作成する、
OAuth & Permissions から下記の Scope を設定してワークスペースへインストールする。
GAS でのメッセージ送受信部分の実装
Bot User Token と Slack App のメンバー ID を GAS のスクリプトプロパティに登録する。
メッセージ送受信部分の実装は次のとおり。 main.ts
の実装は下記記事のコードをほぼほぼベースにしている。
Slack で動く ChatGPT のチャットボットを Google Apps Script(GAS)でサクッと作ってみる
index.ts
:
1
2
3
4
5
6
| import { doPost } from "./main";
declare const global: any;
// GAS において doPost() は特別な関数なので、global の名前は doPost にしておく必要がある
global.doPost = doPost;
|
main.ts
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| import URLFetchRequestOptions = GoogleAppsScript.URL_Fetch.URLFetchRequestOptions;
// Slack へのメッセージ送信関数
const sendMessageToSlack = (channel: string, message: string) => {
const SLACK_BOT_TOKEN =
PropertiesService.getScriptProperties().getProperty("SLACK_BOT_TOKEN");
if (!SLACK_BOT_TOKEN) throw new Error("SLACK_BOT_TOKEN is not set.");
const url = "https://slack.com/api/chat.postMessage";
const payload = {
channel: channel,
text: "echo: " + message,
};
const options: URLFetchRequestOptions = {
method: "post",
contentType: "application/json",
headers: { Authorization: `Bearer ${SLACK_BOT_TOKEN}` },
payload: JSON.stringify(payload),
};
UrlFetchApp.fetch(url, options);
};
export const doPost = (e: any) => {
const reqObj = JSON.parse(e.postData.getDataAsString());
// Slackから認証コードが送られてきた場合(初回接続時)
// これをやっておかないと Event Subscriptions で URL が Verify されない
if (reqObj.type == "url_verification") {
// 認証コードをそのまま返すことで、アプリをSlackに登録する処理が完了する
return ContentService.createTextOutput(reqObj.challenge);
}
// Slackからのコールバック以外の場合、OKを返して処理を終了する
if (reqObj.type !== "event_callback" || reqObj.event.type !== "message") {
return ContentService.createTextOutput("OK");
}
// メッセージが編集または削除された場合、OKを返して処理を終了する
if (reqObj.event.subtype !== undefined) {
return ContentService.createTextOutput("OK");
}
// Slackから送信されたトリガーメッセージ
const triggerMsg = reqObj.event;
// ユーザーID
const userId = triggerMsg.user;
// メッセージID
const msgId = triggerMsg.client_msg_id;
// チャンネルID
const channelId = triggerMsg.channel;
// タイムスタンプ
const ts = triggerMsg.ts;
// Bot自身によるメッセージである場合、OKを返して処理を終了する
const SLACK_BOT_USER_ID =
PropertiesService.getScriptProperties().getProperty("SLACK_BOT_USER_ID");
if (!SLACK_BOT_USER_ID) throw new Error("SLACK_BOT_USER_ID is not set.");
if (userId === SLACK_BOT_USER_ID) {
return ContentService.createTextOutput("OK");
}
sendMessageToSlack(channelId, triggerMsg.text);
return ContentService.createTextOutput("OK");
};
|
Slack App の Event Subscription の設定
GAS 側が実装できたら、 GAS からウェブアプリとしてデプロイする。
デプロイ後、ウェブアプリの URL を Slack App の Events Subscriptions の Request URL に貼り付ける。
次の bot events を subscribe するよう設定する。
実際に動かしてみる
作成した Slack App をチャンネルに招待してメッセージを送信すると、送信した文章を Slack App が echo するはず。
ローカルからデプロイする
clasp deploy
でローカルからデプロイできる。が、いくつか注意点がある。
① appsscript.json
に下記設定を追加しないと、「ウェブアプリ」ではなく「ライブラリ」としてデプロイされてしまう=ウェブアプリの URL が発行されない
1
2
3
4
| "webapp": {
"access": "ANYONE_ANONYMOUS",
"executeAs": "USER_DEPLOYING"
},
|
設定内容は下記画像と同じ。
② clasp deploy
時にデプロイ ID を指定しないと新しいデプロイが作成されてしまい、ウェブアプリの URL が変わってしまう( → 公式ドキュメント )
clasp deployment
でアクティブなデプロイの一覧が取得できる。再デプロイする場合、デプロイ一覧の中から最新のデプロイ ID を取得し、それを clasp deploy
で指定する。今回は次のような再デプロイ用スクリプトを作成して対処した。
redeploy.sh
:
1
2
3
4
5
6
7
8
9
10
11
12
13
| #!/bin/bash
# Build
yarn webpack --mode production
# Push
yarn clasp push
# Get last deployment id
LAST_DEPLOYMENT_ID=$(yarn clasp deployments | tail -n 2 | head -n 1 | awk '{print $2}')
# Deploy
yarn clasp deploy --deploymentId $LAST_DEPLOYMENT_ID
|
クリプトは次の記事が参考になった。
Google Apps Script の Clasp で Web アプリの URL を変えないでデプロイする方法 - ある SE のつぶやき・改
参考記事