LoginSignup
0
5

More than 1 year has passed since last update.

Slackのくじ引きbotを無料でサクッと作る - Google App Script

Last updated at Posted at 2020-12-22

この記事を見てGASが便利すぎることに気づき、色々と触りはじめました。
下記のような特徴があるため、botサーバとして利用するケースが特に便利だと思います。

  • 無料で24時間稼働してくれる
  • スプレッドシートを簡易的なDBとして利用できる
  • 関数単位で簡単にAPIのエンドポイントを作れる

hubotなどを利用する場合は、node.jsが利用できるサーバを用意してコードをデプロイして、データに変更があればJSONを修正して..など準備も運用もそれなりに大変です。
GASを使うことによって、準備・運用も簡単になるのでツールを作る際のハードルがかなり下がります。

ということで、今回はslackで「くじ引き」を行ってくれるbotを作りました。

ユースケース

次の2パターンで使えます。

  1. レビュアーや〇〇当番など、チームメンバーをランダムで選びたいとき
  2. 与えたリストからランダムで要素を選んで欲しいとき

メインは1ですが、特定のメンバー達から選んで欲しいとき・特定のメンバーを除外したいときは2が使えます。

こういう感じで動作します↓
slackのスクショ

作成手順

詰まった場合はこちらの記事を参考にしてください。

GASとSlackアプリの準備

  1. 新しくGoogle Apps Script(以下gas)とスプレッドシートを作成して、スプレッドシートのIDとURLを控えておく
    Google Drive > 左上の「新規」ボタンから作成できる
  2. gasをウェブアプリとして公開したURLを控えておく
    右上の「デプロイ」から「種類の選択:ウェブアプリ、アクセスできるユーザ:全員」にしてデプロイ
  3. slack apiからslackアプリを作成する
  4. slackアプリのVerification Tokenを控えておく
    Settings > Basic Information > App Credentials > Verification Token
  5. slackアプリに任意のslashコマンド(/member_kujiなど)とgasの公開URLを登録する
    Features > Slash Commands > Create New Command

データの準備

事前に作成したスプレッドシートをチームメンバーの情報を保存するDBとして利用します。
スクリーンショットのようにデータを入れてください。

スクリーンショット 2020-12-22 22.48.46.png

  • メンバーの情報を nickname, slack_name, icon, description の順で入力
    (今回、descriptionは使っていません)
  • シート名を members にする
  • G1に =countif(A:A, "*") - 1 という式を入れてメンバーの数をカウントした集計値が入るようにする

なお、iconにはslackで登録したカスタム絵文字を登録しています。

開発環境の準備

  • 環境構築

リポジトリには不要なコードも含まれているので、気になる場合は gas/slack_bot_kuji のディレクトリのみダウンロードしてお使いください。

$ git clone git@github.com:tkc310/gas.git
$ cd slack_bot_kuji
# npm install (node@v14.15.3が必要)
$ npm ci
  • 環境変数

.envファイルを作成して環境変数を追加しておく

$ vi .env
SLACK_VERIFICATION_TOKEN='控えたslackのVerification Token'
SPREAD_SHEET_ID='控えたスプレッドシートのID'
SPREAD_SHEET_URL='控えたスプレッドシートのURL'
  • gas用の.clasp.jsonを作成 事前に作成したgasのURLからIDを転記する
$ touch .clasp.json
$ echo '{ "scriptId": "控えたgasのID", "rootDir": "dist" }' >> .clasp.json

gasに反映

下記のコマンドでビルドされたコードがgasに反映されます。

$ npm run untest_push

slackからコマンドを打って動作確認してみてください。

# スプレッドシートのメンバーから抽出
/member_kuji
# 与えたリストからランダムに抽出
/member_kuji foo, bar, baz

gas実行時に、gasからスプレッドシートを操作するための認証などが必要になるため、
うまくgasが実行されていない場合は、スプレッドシートの認証周りを確認してください。
(gasからtest関数を実行すればスプレッドシートに認証が求められます)

コードの説明

最後にコードの説明を軽くします。

最終的なコードはこちら
claspというgasのコードをローカルで開発できるようにするツールを利用しています。
(gasにコードをpush、gasからコードをpullできる)

併せてwebpackとtypescriptが利用できるようにしています。

メイン部分のロジックが記載されている doPost.ts のコードだけ説明します。

src/doPost.ts
// 1. doPost関数はgasをウェブアプリとして公開した際、リクエスト時に実行される関数
const doPost = (e: doPostEventType): GoogleAppsScript.Content.TextOutput => {
  // 2. slackからリクエストがきた際にtokenが正しいか検証する
  if (SLACK_VERIFICATION_TOKEN != e.parameter.token) {
    throw new Error('Token Invalid');
  }

  const result = run(e.parameter);
  return ContentService.createTextOutput(
    JSON.stringify({
      // 3. slack apiのパラメータ in_channelの場合はチャンネルユーザ全てにbotのやり取りを公開
      response_type: 'in_channel',
      text: result,
    })
  ).setMimeType(ContentService.MimeType.JSON);
};

export const run = (params: doPostEventType['parameter'] | undefined): string => {
  let result = '';

  if (params && params.text) {
    // 4. foo, bar, bazのようなリストを渡された時はランダムに抽出
    const items = params.text
      .split(',')
      .map((item) => item.trim())
      .filter((item) => !!item);
    const randomIdx = getRandomNumber(0, items.length);

    result = items[randomIdx];
  } else {
    // 5. リストがない場合はスプレッドシートからチームメンバーの情報を抽出
    const spreadsheet = SpreadsheetApp.openById(SPREAD_SHEET_ID);
    const sheet = spreadsheet.getSheetByName('members');
    const length = sheet.getRange('G1').getValues()[0][0];
    const range = 'A2:D' + (parseInt(length) + 1);
    const values = sheet.getRange(range).getValues();
    const randomIdx = getRandomNumber(0, parseInt(length));
    const nickNameIdx = 0;
    const slackNameIdx = 1;
    const iconIdx = 2;
    const item = values[randomIdx];

    result = `
${item[iconIdx]} ${item[slackNameIdx]} (${item[nickNameIdx]}さん) \n
memberの編集は<${SPREAD_SHEET_URL}|こちら>
`;
  }

  // 6. gasの実行ログから確認できる
  Logger.log(result);

  return result;
};
  1. doPost関数
    gasをウェブアプリとして公開した際、リクエスト時に実行される関数になる。(gasの仕様)
  2. tokenの検証 コード上のverification tokenとslackからのリクエストのtokenが合致しているか確認している
  3. slack apiパラメータ
    botとのやり取りをチャンネルのメンバーに公開するかのオプション。他にも色々ある
  4. slackのコマンド入力時にリストを渡された時の処理
    リストからランダムに要素を抽出して返している
  5. slackのコマンド入力時にリストを渡されなかった時の処理
    スプレッドシートからチームメンバーの情報を取得している
  6. gasの管理画面から実行ログを確認することができる

以上です。

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