🤖

Slack Platform で絵文字の追加を通知する bot を作った

2023/08/07に公開

お悩み

全員がフルリモートワークの弊社では Slack を使用して日々のやり取りをしています
文字だけのやり取りだと寂しいので大量の絵文字を追加して彩りを与えてくれる職人が弊社にはいますが、職人が最高の絵文字を追加しても誰も気づかずそのまま絵文字の山に埋もれてしまう問題がありました
ということで、絵文字が追加されたら通知してくれるボットを Slack Platform で作ってみました

Slack Platform とは?

https://api.slack.com/start/overview
(登場当初は Next-gen Slack Platform とか呼ばれていた気がします)
簡単に言うと今までの HTTP API ベースの処理ではなく、Trigger/Workflow/Function を定義していい感じに Slack のイベント処理ができる凄いやつです
言語は今最もアツい言語(※ワニ調べ)の Deno が採用されています
詳しくは公式サイトや Zenn に詳しく書いてくれている方がいるので読んでみてください

完成したもの

https://github.com/sugawani/slack-emoji-notifier
使い方は README を読んでください
Slack Platform さえ使えたらどの環境でも使えると思うので、ぜひ皆さんの絵文字パーティー活動に活かしてください
絵文字が追加されるとこんな感じで通知されます
notify-image

細かい実装については以下に書いていきます

フローチャート

フローチャート
絵文字の追加/削除/変更を行なうと各種 Trigger が発火して Workflow -> Function とデータが流れて最終的にメッセージが Slack にポストされます

実装詳細

Trigger

Event Type

eventemoji_changedです

EmojiAddedTrigger
type: TriggerTypes.Event,
event: {
  event_type: "slack#/events/emoji_changed",

filter

EmojiAddedTrigger
filter: {
  version: 1,
  root: {
    statement: "{{data.subtype}} == add",
  },
},

emoji_changedsubtypeadd|remove|rename の3種類で送ってくるので、それぞれの Triggerfilter を設定しています
Event Trigger は特定のイベントをキャッチする機能ですが、イベントの内容で分岐は発生しないため filter を使って subtype を判定しています
filter を設定しない場合、例えば add subtype のイベントで rename trigger が発火して input_paramrameters の不整合によってエラーが発生したりします

最初は1つの Trigger で全イベントを拾おうと考えていましたが、後述する Workflow/Functioninput_parameter.required の定義が難しいため subtype ごとに Trigger を作成しました

Workflow

input_parameters

AddWorkflow
input_parameters: {
  properties: {
    name: {
      type: Schema.types.string,
    },
    value: {
      type: Schema.types.string,
    },
  },
  required: ["name", "value"],
}

subtype ごとにワークフローを定義してあります
workflow には input_parameter に対して required を設定できますが、subtype ごとに以下のようにパラメータが異なります
https://api.slack.com/events/emoji_changed#emoji_changed-event-type__emoji_changed-subtypes
すべての subtype を1つの workflow で扱おうとすると辛いコードになるため、subtype ごとに workflow を定義しました

addStep

RemoveWorkflow
RemoveWorkflow.addStep(SendMessageFunction, {
  message: `emoji removed! ${RemoveWorkflow.inputs.names}`,
});

後続のメッセージ送信 function に渡すメッセージを定義しています
subtype: remove の場合は削除された絵文字に紐づくエイリアスも Trigger から渡ってくるため、以下のように string[] で定義されているのですが

RemoveWorkflow
names: {
  type: Schema.types.array,
  items: {
    type: Schema.types.string,
  },
},

addStep のタイミングでは {{inputs.names}} という文字列のまま評価されていないので Array.join(',') などを噛ませる事ができず、以下のようなメッセージになっています
emoji removed! ["test-emoji"]
function で処理することで対処できそうですが、今回はそこまで重要な処理でもない箇所のため許容することにしました
Workflow 内での解決策をご存じの方は教えてください

Function

SendMessageFunction
export default SlackFunction(
  SendMessageFunction,
  async ({ inputs, env, client }) => {
    const notifyChannelID = env["NOTIFY_CHANNEL_ID"];
    if (notifyChannelID == null) {
      return {
        outputs: { notified: false, message: "env NOTIFY_CHANNEL_ID is empty" },
      };
    }

    const { message } = inputs;
    await client.chat.postMessage({
      channel: notifyChannelID,
      text: message,
    });

    return { outputs: { notified: true, message: message } };
  },
);

env から送信先のチャンネル ID を取得し、受け取った message を送信するだけのシンプルな処理です

以上です
clone して env に送信先チャンネル ID を設定するだけで絵文字の追加を監視できるので、ぜひ使ってみてください
FB や改善希望等あればお気軽にコメントお願いします

EGSTOCK,Inc.

Discussion