Start: Slack: Message Received

開始: Slack: メッセージ受信時

This item starts a process when Slack Bot has received a direct message or a mentioned message.

Basic Configs
Step Name
Note
Auto Step icon
Configs for this Auto Step
conf_Secret
C1: Authorization Setting in which Signing Secret is set *
conf_Text
C2: Data item to save Message *
conf_UserId
C3: Data item to save Slack user ID
conf_ChannelId
C4: Data item to save Channel ID
conf_ThreadId
C5: Data item to save Thread ID

Notes

  • To activate this start event, follow the instructions below:
    1. [Create & Install Slack App] Open Your Apps and create a new Slack App using one of the manifests shown in the Appendix section of this page
      • Remember to install your app onto your workspace
    2. [Create & Release Questetra Workflow App] Create a Workflow App on Questetra BPM Suite using “Start: Slack: Message Received”, and release it
      • Your Signing Secret to set in C1 is shown on the Basic Information page of the Slack App created in the Step 1
    3. [Change Event URL] Copy the URL shown in “Start: Slack: Message Received”, and set it as Request URL on the Event Subscriptions page of the Slack App created in the Step 1
      • Confirm that the Request URL is verified and click “Save Changes”
  • A process will not be started for the messages posted by a Bot

Capture

Appendix

Slack App Manifests to create a Bot

Bot to react to mentioned messages
  • Add the Bot to the channel
  • The Bot reacts only to the directly mentioned messages
    • A process will not be started for the messages with @channel or @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 to react to direct messages
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)
  • An XML file that contains the code below is available to download
    • slack-message-received.xml (C) Questetra, Inc. (MIT License)
      • Just use it for a reference for the codes
      • This file cannot be imported into a Workflow App as an Add-on

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;
};
%d bloggers like this: