🔔

Slack platformを使って絵文字登録の通知をしてくれるBotを作ってみた

2022/11/03に公開約5,400字

目的

ちょっと前にDenoを利用したSlackの新プラットフォームがオープンベータとしてリリースされました
https://api.slack.com/future
TypeScriptでの実装ができ、かつインフラを自前で用意する必要がないため手を出しやすい物になってます
せっかくなのでこれを活用して需要のありそうなBotアプリを作ってみたので紹介したいと思います

環境

  • MacBookPro M1(zsh)
  • Slack CLI 1.14.0
  • deno-slack-sdk 1.3.0
  • deno-slack-api 1.2.0

成果物
https://github.com/seki-shinnosuke/slack-deno-emoji-notice

内容

今回は作り物の話だけでなく以下の点も記載したいと思います

  • Slack platformで抑えるべきTrigger/Workflow/Functionの概要と流れ
  • 作成したBotアプリのソースコード説明

記載しないこと

Slack platformのTrigger/Workflow/Function

まずはSlack platformで作成するアプリは3つの項目で構成されています

項目 説明
Trigger 何を起因にWorkflowを開始するか定義するよ!
例: Botに対してメンションをしたら起動!
Workflow どういう順番でFunctionを実行していくか定義するよ!
例: 入力フォームを表示させて!入力が完了したらFunction①を呼び出して!
Function 実際の処理を書くよ!
例: 入力された内容はしかと受け取った!メッセージを送ろう

上から順にTrigger -> Workflow <-> Functionと実行され処理を完了させてくれる動きとなります
WorkflowとFunctionは一方通行な関係では無く、Functionの処理結果から次にどのFunctionを呼び出すのかをWorkflowで制御することも可能です
また、Workflowの中ではデフォルトで備わっている組み込み機能(メッセージ送信やチャンネル作成など)を利用することができるのでFunctionを作らなくても処理を完結させることもできます

作成したBotアプリの説明

それではここからは作成したBotアプリについて説明していきます

概要
Slackワークスペースに登録された絵文字を特定のチャンネルに通知してくれるBot

実際のソースをみていきましょう
まずは起因となるTriggerから

emoji_notice_event_trigger.ts
import { Trigger } from "deno-slack-api/types.ts";
import EmojiNoticeWorkflow from "../workflows/emoji_notice_workflow.ts";

const emojiNoticeEventTrigger: Trigger<typeof EmojiNoticeWorkflow.definition> =
  {
    type: "event",
    event: {
      event_type: "slack#/events/emoji_changed",
    },
    name: "Emoji notification",
    description: "新規登録された絵文字を通知してくれます",
    workflow: "#/workflows/emoji_notice_workflow",
    inputs: {
      subtype: {
        value: "{{data.subtype}}",
      },
      emojiName: {
        value: "{{data.name}}",
      },
    },
  };

export default emojiNoticeEventTrigger;

Triggerにはショートカットリンク押下やWebhookなども設定可能ですが今回はイベント検知の仕組みを採用しました
絵文字の更新が行われた場合はワークスペース全体に対し、イベント通知が送信されます
event_typeに設定している"emoji_changed"は絵文字更新のイベント通知を受信を起因にするという意味になり、Workflowにinputデータとしてsubtypeとnameを渡して起動するような定義になっています
https://api.slack.com/events/emoji_changed

WorkflowはとてもシンプルでTriggerから受け取った値をそのままFunctionに流すだけの1フローとなってます

emoji_notice_workflow.ts
import { DefineWorkflow, Schema } from "deno-slack-sdk/mod.ts";
import { EmojiNoticeFunction } from "../functions/emoji_notice_function.ts";

const EmojiNoticeWorkflow = DefineWorkflow({
  callback_id: "emoji_notice_workflow",
  title: "Emoji notice",
  description: "新規登録された絵文字を通知してくれます",
  input_parameters: {
    properties: {
      subtype: {
        type: Schema.types.string,
      },
      emojiName: {
        type: Schema.types.string,
      },
    },
    required: ["subtype"],
  },
});

EmojiNoticeWorkflow.addStep(
  EmojiNoticeFunction,
  {
    subtype: EmojiNoticeWorkflow.inputs.subtype,
    emojiName: EmojiNoticeWorkflow.inputs.emojiName,
  },
);

export default EmojiNoticeWorkflow;

Functionでは受け取った値から絵文字のイベントが登録かそれ以外を判定しメッセージを作って指定したチャンネルに送信するような処理となってます

emoji_notice_function.ts
import { DefineFunction, Schema, SlackFunction } from "deno-slack-sdk/mod.ts";
import { SlackAPI } from "deno-slack-api/mod.ts";
import env from "../../env.ts";

export const EmojiNoticeFunction = DefineFunction({
  callback_id: "emoji_notice_function",
  title: "Emoji notice",
  source_file: "src/functions/emoji_notice_function.ts",
  input_parameters: {
    properties: {
      subtype: {
        type: Schema.types.string,
        description: "Subtype",
      },
      emojiName: {
        type: Schema.types.string,
        description: "Emoji name",
      },
    },
    required: ["subtype"],
  },
});

export default SlackFunction(EmojiNoticeFunction, ({ inputs, token }) => {
  let message = "";
  if (inputs.subtype === "add" && inputs.emojiName != undefined) {
    message = `新しい絵文字「${inputs.emojiName}」が追加されました\n\n:${inputs.emojiName}:`;
  } else {
    return {
      outputs: {},
    };
  }

  const client = SlackAPI(token, {});
  client.chat.postMessage({
    channel: env.EMOJI_NOTIFICATION_CHANNEL_ID,
    text: message,
  });
  return {
    outputs: {},
  };
});

作り物としてはこれだけです
あとはBotに絵文字のイベント検知権限を与えるためにManifestにemoji:readを追加しenv.tsに通知を送りたいチャンネルのIDを記載します

manifest.ts
export default Manifest({
  name: "emoji-notice-bot",
  description: "登録された絵文字を通知してくれるBot",
  icon: "assets/icon.png",
  workflows: [EmojiNoticeWorkflow],
  outgoingDomains: [],
  botScopes: ["commands", "chat:write", "chat:write.public", "emoji:read"],
});
env.ts
export default {
  "EMOJI_NOTIFICATION_CHANNEL_ID": "CXXXXXXXXXX", // 絵文字を通知するチャンネルのID
};

それでは実際にアプリをワークスペースにデプロイし、Triggerを登録します

% slack deploy
% slack trigger create --trigger-def ./src/triggers/emoji_notice_event_trigger.ts

Slackの「ワークスペースのカスタマイズ」ページから絵文字を登録してみると1,2秒後くらいに指定したチャンネルに通知が飛んできます

これでアプリの説明は以上となります

まとめ

今回作ったアプリは

  • 登録された絵文字を活用してコミュニケーション活性につなげたい!
  • コンプライアンスに違反してるような絵文字を登録してないか監視したい。。。

と企業に取っては意外と需要があるのではと思ってます

作ってみると意外と簡単なんですがハマる(つまづく)ポイントとして公式サイトの説明やサンプルソースが正直イケてないです。。。
説明がかなり端的で伝わらない、そのままだと全く動かないことがほとんどです
ですがインフラ面でSlackBot開発を戸惑っていた方はせっかくなのでBot開発にトライしてみるのも良いかもしれません

Discussion

ログインするとコメントできます