5
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?

More than 3 years have passed since last update.

Bolt + Serverless Framework でお手軽 Slack アプリ開発

Last updated at Posted at 2022-05-20
Page 1 of 21

作るもの


背景

  • とあるチームで、「週に1件以上ビジネスアイデアを Slack に投稿しよう!」という取り組みを作った
  • しばらくは真面目に投稿していたが、忙しさにかまけて徐々に投稿が減る事態に・・・
  • 「ボットに催促してもらおう!」ということに

機能&構成

  • アイデアの投稿があれば褒めてくれる
  • 週に1度のアイデア投稿がなければ催促する
    image.png

image.png


手順

Slack アプリの準備

基本的には、Bolt 入門ガイド に従って準備しますが、いくつか記載のない手順も必要だったので、改めてまとめておきます😃


1. アプリを作成する

slack api ダッシュボードの Your AppsCreate New App をクリックします。
画像のようなダイアログが開くので、ここでは From scratch を選択しておきましょう。
image.png

アプリ名を入力し、テストに使うワークスペースを選択します。
アプリ名は後から変更可能なので、適当に入力しておきましょう。
image.png


2. トークンとアプリのインストール

トークンには ユーザートークン ボットトークン アプリレベルトークン の3種類が存在するようですが、今回はボットを作りたいのでボットトークンを作成します。


2-1. ボット名の設定

作成したアプリの管理画面サイドメニューの Features > App Home にある Your App’s Presence in Slack 欄の Edit をクリックします。
アプリ名とは別にボットの表示名とユーザー名が必要なようなので、設定しておきます。
この手順を抜かすと、後続手順のワークスペース追加ができませんでした。
image.png


2-2. Slash コマンドの作成

メニューの Features > Slash Commands から、 Create New Command を押してコマンド登録します。
デプロイ前でまだ URL が決まっていないので、 Request URL は example.com にしておきました。
image.png


2-3. 権限設定

サイドメニューの Features > OAuth & Permissions から必要な権限を追加します。
2-2の手順でで commands は登録されていたので、 chat:write を追加しておきました。
image.png

最後に、同じ画面上部の Install to Workspace をクリックして、ワークスペース側からアプリへの認可を与えます。
image.png


3. Bolt on Serverless Framework の環境作り

以下の手順で構築しましたが、利用したテンプレートの依存バージョンが古く、解決するのに苦労しました。。

諸々解決した状態でシンプルなサンプルアプリを公開しているで、面倒な人はよろしければ→bolt-serverless-node-example をクローンして使ってください。
(これもいずれ古くなると思いますが😅)


3-1. テンプレートから Serverless アプリを新規作成する

npm i -g serverless

# Serveless 用のテンプレートを利用して新規作成(色々と古いので要注意)
serverless create \
  --template-url https://github.com/seratch/serverless-slack-bolt-aws/tree/master \
  --path idea-reminder

その後、諸々のパッケージのバージョンを上げ、結果としてエラーになった箇所を修正したり、 TypeScript を入れたり `Serverless Offline が使えるようにしました。(詳細略)


3-2. Slash コマンドをとりあえず動かしてみる

2-2 で登録したコマンドの Edit を押し、 Request URL を ngrok で公開した以下の内容に変更します。

https://xxxxxxxx.ngrok.io/dev/slack/events

app を追加したチャンネルで /idea ほげほげ と打つと、 ボットが ほげほげ と返してくれるやまびこアプリができました。


3-3. イベント購読設定

チャンネルにメッセージが投稿されたら受け取れるようにしておきます。
サイドメニューの Event Subscription > Enable Events を On にし、 Request URLhttps://<ngrok のドメイン>/dev/slack/events を設定します。
image.png

Subscribe to bot eventsmessage.channels を追加します。
image.png


4. 機能を実装

4-1. 特定の文字列が含まれるメッセージに対して返信をする

「【アイデア】」という文字列が含まれる投稿を受信し、スレッドでリプライします。
(TS の型エラーが出てしまうので、本来はよくない書き方なのかもしれない・・・)

handler.ts
boltApp.message('【アイデア】', async ({
  message, logger, say,
}) => {
  try {
    // @ts-ignore
    await say({ text: `<@${message.user}>さん、 アイデアの投稿ありがとう!`, thread_ts: message.ts });
  } catch (e) {
    logger.error(e);
  }
});

4-2. 今週のアイデア投稿をカウントする

/idea というスラッシュコマンドを入力したら、そのユーザーの「【アイデア】」という文字列が含まれる今週の投稿をカウントします。
TS の型推論が効かない箇所を補いつつ。

handler.ts
boltApp.command('/idea', async ({
  command, logger, ack, say,
}) => {
  const thisMonday = dayjs().day(1).startOf('day');
  try {
    const res = await boltApp.client.conversations.history({
      token: process.env.SLACK_BOT_TOKEN,
      channel: command.channel_id,
      oldest: `${String(thisMonday.unix())}.000000`,
      limit: 100, // 週に100件を超えるアイデアがない前提
    });
    const messages = res.messages as { [key: string]: unknown }[];
    const count = messages
      .filter((message) => message.user === command.user_id)
      .filter((message) => (message.text as string).includes('【アイデア】'))
      .length;
    let text = `<@${command.user_id}>さんの今週のアイデアはまだ投稿されていません。`
      + `${thisMonday.add(6, 'day').format('M月D日(日)')}までに1件のアイデアを投稿しましょう!`;
    if (count > 0) {
      text = `<@${command.user_id}>さんは、${thisMonday.format('M月D日(月)')}から今日までの間に${count}件のアイデアを投稿しました!この調子!`;
    }
    await say(text);
    await ack();
  } catch (e) {
    logger.error(e);
    await ack(`:x: Failed to post a message (error: ${e})`);
  }
});

/idea を送ると以下のようにメッセージが返ってくるようになりました。

image.png


5. AWS にデプロイ

5-1. デプロイ

  • AWS のダッシュボードから、デプロイ用の IAM ユーザーを作成し、 AdministratorAccess 権限を付与します
  • ~/.aws/credentials に上記の IAM ユーザーを設定します
  [servelessUser]
  aws_access_key_id=AKIAXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ひとまず dev stage にデプロイしてみます

sls deploy --verbose --stage dev --aws-profile serverlessUser

デプロイが成功すると以下のようなログが表示され、自動的に生成された API Gateway 上のエンドポイントも表示されます

✔ Service deployed to stack idea-reminder-dev (164s)

endpoint: POST - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/slack/events
functions:
  app: idea-reminder-dev-app (3.5 MB)

5-2. エンドポイントを変更

  • 先ほど一時的に設定していた ngrok のエンドポイントを、5-1. で表示された URL に変更しておきます
    • Slash コマンドの Request URL
    • Event Subscriptions の Request URL

まとめ

  • 後で書く
5
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
5
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?