10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リンクアンドモチベーションAdvent Calendar 2024

Day 16

Slack appでメッセージの取得用のアプリを作成しました

Last updated at Posted at 2024-12-15

本記事はリンクアンドモチベーションAdventCalendar2024の16日目の記事です。

きっかけ

アイデアを思いついた時slackに呟いてもそのアイデアがすぐ流れてしまっていました。
1プロダクト、複数チャンネル運用なので色んなチャンネルでアイデアが出るものの集約のコストが掛かっていました。
なので、簡単にアイデアをまとめられないものかと思っていました。

やりたかったこと

最終的に作ったものは以下のようなものです。
※ 実際は別のチャンネルに送信されるものですが、今回は同じチャンネルに送信しました。
image.png

  • メッセージに対してリアクションがつけられる
  • リアクションのついたメッセージが特定のチャンネルに送信される(メッセージ内容 / リンク付き)

解決策の方針

  • Slackのワークフローが便利なので、基本的には乗っかろうと思います

Slackは様々なevent でAPIを用意しています。詳しくはこちらを参照してください。リアクション追加は reaction_added というAPIです。

  • チャンネルをまたぐことになるので、どのメッセージのリンクかはわかるようにしたい
  • リンクによるプレビューだとメッセージが大きくなると全てを読めないので、メッセージも送信したい

生じた問題

slackのワークフローを使い、特定のメッセージにスタンプが押されると「アイデア集約chにメッセージを送信」するワークフローを組みました。
変数を利用すると、

  • 誰にリアクションされたか
  • どのメッセージにリアクションされたか

などは変数機能で簡単に取得することが出来ます。
とても便利で、簡単に作ることが出来ました。ただ、メッセージの本文の内容を取得することが出来ませんでした。

image.png
image.png
※ ここまでは楽だったが、肝心の本文が取得できない

再度解決策

そこでSlack appを使った解決を試みました。
https://api.slack.com/automation/run
リアクションの取得やチャンネルへの送信は引き続きテンプレートに頼りつつ、メッセージーの取得用のアプリを作成しました。

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

export const GetSlackMessageFunction = DefineFunction({
  callback_id: "get_slack_message_function",
  title: "slackのメッセージを取得",
  description: "slackのメッセージのURLから、元のメッセージを取得します",
  source_file: "functions/get_slack_message.ts",
  input_parameters: {
    properties: {
      url: {
        type: Schema.types.string,
        description: "取得したいslackのメッセージのURL",
      },
    },
    required: ["url"],
  },
  output_parameters: {
    properties: {
      message: {
        type: Schema.types.string,
        description: "取得したslackのメッセージ",
      },
    },
    required: ["message"],
  },
});

function parseSlackUrl(url: string): { channel: string; ts: string } | null {
  const regex = /https:\/\/[\w-]+\.slack\.com\/archives\/([\w-]+)\/p(\d+)/;
  const match = url.match(regex);
  if (match) {
    const [, channel, tsRaw] = match;
    const ts = `${tsRaw.slice(0, -6)}.${tsRaw.slice(-6)}`;
    return { channel, ts };
  }
  return null;
}

export default SlackFunction(
  GetSlackMessageFunction,
  async ({ inputs, client }) => {
    const { url } = inputs;

    const urlInfo = parseSlackUrl(url);
    if (!urlInfo) {
      return { error: "Invalid Slack message URL" };
    }

    const { channel, ts } = urlInfo;

    try {
      const response = await client.conversations.replies({
        channel: channel,
        ts: ts,
        limit: 1,
      });

      if (response.messages && response.messages.length > 0) {
        const message = response.messages[0].text;
        return {
          outputs: {
            message,
          },
        };
      } else {
        return { error: `Message not found. Error: ${response.error}` };
      }
    } catch (error) {
      return { error: `Failed to retrieve message: ${error.message}` };
    }
  },
);

※ 社内にすでにあった仕組みを一部改良しました。

セットアップ等はQuickStartを御覧ください。今回は割愛します。

このようにすることでリアクションがついたメッセージに対してそのメッセージ内容を他のチャンネルに送信することが出来るようになりました。

最後に

ローカルでの動作確認も簡単にできるので、開発体験もとてもよかったです!

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?