💬

Slackの分報を社内Twitterに!皆の分報を一つのチャネルに集約するSlackボットを作ってみた

2021/03/21に公開

Slack の分報(times-xxxチャネル)は、自分の作業ログに使えたり、チームメンバーの状況を知るためにも使えたりとても良いですよね。

ただ、チームメンバーの数だけチャネルが増えるので、人数が増えるとそれぞれの分報チャネルを見て回るのが地味に大変です。

それを解決するためにそれぞれの分報チャネルの投稿を全て 1 つのチャネルに共有する Slack アプリを作ってみました。このアプリがあると、その集約チャネル(times-all等)を見るだけで 社内 Twitter 的に皆の分報を閲覧することが出来るので便利です。
この記事ではそのアプリの紹介と設定方法を書きます。

※ 元ネタは前職 Misocacurrent-allチャネルです。感謝 🙏
※ 分報の概要はこちら

作ったもの

各分報の投稿をひとつのチャネルに集約する Slack Bot です。
この Bot を分報チャネルと、分報の集約チャネルに追加すると、分報の投稿を全て集約チャネルにシェアしてくれます。

リポジトリはこちらです。

https://github.com/kawamataryo/times-all-bot

以降でセットアップ方法を解説します。

セットアップ

Slackアプリの作成

https://api.slack.com/apps にアクセスし、Create New Appで新しいアプリを作成します。

作成後、サイドバーから OAuth & Permissions にアクセスしてアプリの権限のスコープを設定します。設定するスコープはchat:writechannels:historyです。

その後、ページ上部の Install to Workspace でワークスペースにアプリを追加します。
アプリ追加後表示される OAuth Token は後で使うのでメモしましょう。

あと、サイドバーにあるBasic InformationにアクセスしてSigning Secretもメモしてください。

以上でいったん Slack アプリ側の設定は完了です。

Lambdaへのデプロイ

アプリの実態は AWS Lmabda にデプロイする Bolt フレームワークです。
まず任意のディレクトリにプロジェクトをクローンします。

$ git clone https://github.com/kawamataryo/times-all-bot.git
$ cd times-all-bot
$ npm i

デプロイ時に Slack の情報を参照するために環境変数使っています。プロジェクト直下に以下内容で.envを作成してください。SLACK_SIGNING_SECRETSLACK_BOT_TOKENは前述の Slack アプリの作成でメモしたSigning SecretOAuth Tokenの値です。AGGREGATE_CHANNEL_IDは分報の投稿を集約するチャネル(times-all等)の ID です。

※ チャネル ID の確認方法はこちらから。

SLACK_SIGNING_SECRET=<YOUR_TOKEN>
SLACK_BOT_TOKEN=<YOUR_TOKEN>
AGGREGATE_CHANNEL_ID=<CHANNEL_ID>

これで準備は完成です。以下コマンドで AWS Lambda にデプロイされます。

$ npm run deploy

無事デプロイが完了するとエンドポイントの URL が標準出力に出ます。
それをメモしてください。

# ...
endpoints:
  POST - https://u6db.execute-api.us-east-1.amazonaws.com/dev/slack/events
# ...

Slackアプリでのエンドポイント登録

最後にまた Slack アプリ側の設定です。
Slack アプリの管理画面からサイドバーのEvent Subscriptionsにアクセスし、Enable Eventsのチェックを ON にしてイベント購読を有効化します。

Request URLは先程デプロイ時に取得した Lambda のエンドポイントを設定してください。
そしてSubscribe to bot eventsmessage.channelsを追加します。

設定後、アプリを再インストールする必要があるので、OAuth & Permissionsから必ず行いましょう。これでアプリを追加したチャネルでイベントが発生するたびに Lambda にリクエストが飛びます。

分報チャネル・集約チャネルへのアプリの追加

各分報チャネルと集約チャネルに先程作成したアプリをインストールすれば完了です 🎉
※ 必ず両方に追加する必要があるので注意

以降は各分報チャネルに投稿した内容の全てが集約チャネルにシェアされます。

実装

実装はとてもシンプルです。
Lambda で Bolt for JavaScript を起動して分報のチャネルのイベントを購読し、集約チャネルに投稿しています。

ポイントは、パーマリンクの形式で投稿している点です。
chat.postMessageで直接分報の投稿内容を集約チャネルに投稿することもできるのですが、それを行うと@hereなどのメンションも展開されてしまいます。また、逆に添付ファイルなどは展開されないという問題もあります。

なので、集約チャネルにはパーマリンクを投稿し、チャネルでのスニペット展開で分報の投稿内容を確認できる形式にしています。

src/functions/slack/handler.ts
import { App, ExpressReceiver } from "@slack/bolt";
import serverlessExpress from "@vendia/serverless-express";

const aggregateChannelId = process.env.AGGREGATE_CHANNEL_ID;

const expressReceiver = new ExpressReceiver({
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  processBeforeResponse: true,
});

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  receiver: expressReceiver,
});

app.message(async ({ client, event }) => {
  // 集約チャネル内の投稿か、投稿の編集・削除の場合は除外
  if (
    event.channel == aggregateChannelId ||
    event.subtype == "message_changed" ||
    event.subtype == "message_deleted"
  ) {
    return;
  }

  try {
    // 投稿のpermalinkの取得
    const permalinkRes = await client.chat.getPermalink({
      channel: event.channel,
      message_ts: event.event_ts,
    });

    // 集約チャネルへの投稿
    await client.chat.postMessage({
      channel: aggregateChannelId,
      text: permalinkRes.permalink as string,
    });
  } catch (e) {
    console.error(e);
  }
});

export const handler = serverlessExpress({
  app: expressReceiver.app,
});

詳細は、リポジトリをご覧ください。

https://github.com/kawamataryo/times-all-bot

終わりに

以上「Slack の分報を社内 Twitter に!皆の分報を 1 つのチャネルに集約する Slack ボットを作ってみた」でした。
現職の Slack にも導入して、幸いにも好評です。この Bot 自体はただ投稿を別のチャネルにシェアするだけなので、分報の集約以外にも色々使い道はあるかなと思います。是非使ってもらえると嬉しいです。

また何か使ってみて不具合があれば気軽にコメントを下さい。

Discussion