
開始: Slack: メッセージ受信時
Start: Slack: Message Received
このアイテムは、Slack Bot がダイレクトメッセージかメンションされたメッセージを受信すると、プロセスを開始します。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_Secret
- C1: Signing Secret を設定した認証設定 *
- conf_Text
- C2: メッセージを保存するデータ項目 *
- conf_UserId
- C3: Slack ユーザ ID を保存するデータ項目
- conf_ChannelId
- C4: チャンネル ID を保存するデータ項目
- conf_ThreadId
- C5: スレッド ID を保存するデータ項目
Notes
- この開始イベントを利用するには、以下の手順が必要です
- [Slack アプリの作成とインストール] Slack のアプリ一覧ページ を開き、新しい Slack アプリを作成します
- “From an app manifest” を選択し、このページの Appendix にあるマニフェストを貼り付けてください
- 作成した Slack アプリをワークスペースにインストールするのを忘れないようにしてください
- [Questetra ワークフローアプリの作成とリリース] Questetra BPM Suite で「開始: Slack: メッセージ受信時」を使用したワークフローアプリを作成し、リリースします
- C1 に設定する Signing Secret は、手順 1 で作成した Slack アプリの Basic Information に表示されます
- [イベント URL の変更] 「開始: Slack: メッセージ受信時」に表示されている URL をコピーし、手順 1 で作成した Slack アプリの Event Subscriptions に表示されている Request URL を、その URL で更新します
- Request URL が verified ステータスになっていることを確認し、”Save Changes” をクリックします
- [Slack アプリの作成とインストール] Slack のアプリ一覧ページ を開き、新しい Slack アプリを作成します
- Bot が投稿したメッセージでは、プロセスは開始されません
Capture

Appendix
Bot を作成するための Slack アプリのマニフェスト
メンションされたメッセージに反応する Bot
- この Bot をチャンネルに追加してください
- この Bot は、直接メンションされたメッセージにのみ反応します
- @channel や @here のついたメッセージでは、プロセスは開始されません
display_information:
name: Questetra Bot (Mentioned Messages)
features:
bot_user:
display_name: Questetra Bot (Mentioned Messages)
always_online: true
oauth_config:
redirect_urls:
- https://s.questetra.net/oauth2callback
scopes:
bot:
- app_mentions:read
- chat:write
- users:read
- users:read.email
settings:
event_subscriptions:
request_url: https://example.questetra.net/System/Event/Start/
bot_events:
- app_mention
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
ダイレクトメッセージに反応する Bot
display_information:
name: Questetra Bot (Direct Messages)
features:
app_home:
home_tab_enabled: false
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: Questetra Bot (Direct Messages)
always_online: true
oauth_config:
redirect_urls:
- https://s.questetra.net/oauth2callback
scopes:
bot:
- chat:write
- im:history
- users:read
- users:read.email
settings:
event_subscriptions:
request_url: https://example.questetra.net/System/Event/Start/
bot_events:
- message.im
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- slack-message-received.xml (C) Questetra, Inc. (MIT License)
- コードの参考用にご利用ください
- アドオンとしてワークフローアプリにインポートすることはできません
- slack-message-received.xml (C) Questetra, Inc. (MIT License)
const post = ({body, headers}) => {
const secret = configs.getObject('conf_Secret').getToken();
if (!verifyRequest(secret, {body, headers})) {
return {
status: 400
};
}
const json = JSON.parse(body);
switch (json.type) {
case 'url_verification':
engine.log(`succeed to verification`);
return {
'content-type': 'text/plain',
'body': json.challenge
};
case 'event_callback':
receive(json);
return {
'content-type': 'text/plain',
'body': ''
};
default:
engine.log(body);
return {
status: 400
};
}
};
/**
* event 受信処理
* @param json
*/
const receive = (json) => {
const {
type,
subtype,
channel,
user,
bot_id,
text,
ts,
thread_ts
} = json.event;
if (type !== 'message' && type !== 'app_mention') {
// event type が message または app_mention でないものは無視
engine.log(`ignore event. type: ${type}`);
return;
}
if ((subtype !== undefined && subtype !== 'thread_broadcast') || bot_id !== undefined) {
// ユーザのメッセージ投稿以外によるイベントを無視するため、subtype に thread_broadcast 以外が指定されているものを無視
// bot によるメッセージも無視
engine.log(`ignore event. type: ${type} subtype: ${subtype} bot_id: ${bot_id}`);
return;
}
saveData('conf_ChannelId', channel);
saveData('conf_UserId', user);
saveData('conf_Text', text);
saveData('conf_ThreadId', thread_ts === undefined ? ts : thread_ts);
engine.setStartProcess(true);
};
/**
* データ項目への保存
* @param configName
* @param data
*/
const saveData = (configName, data) => {
const def = configs.getObject(configName);
if (def === null) {
return;
}
engine.setData(def, data);
};
/**
* リクエストのチェック
* @param secret Singining Secret
* @param body リクエストボディ
* @param headers リクエストヘッダ
* @returns {boolean} false の場合、不正リクエスト
*/
const verifyRequest = (secret, {body, headers}) => {
const signature = headers.getFirst('X-Slack-Signature');
const timestamp = headers.getFirst('X-Slack-Request-Timestamp');
if (Date.now() - timestamp * 1000 > 5 * 60 * 1000) {
engine.log(`Timestamp: ${timestamp}`);
return false;
}
const baseString = `v0:${timestamp}:${body}`;
const calcString = hex.encodeToString(hmac.sha256(secret, baseString));
if ('v0=' + calcString !== signature) {
engine.log(`Failed to verification`);
engine.log(`Timestamp: ${timestamp}`);
engine.log(`Signature: ${signature}`);
engine.log(body);
engine.log(`hmac: ${calcString}`);
return false;
}
return true;
};