LoginSignup
3
3
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

Slackでの発言を強制させたいbot

Last updated at Posted at 2024-01-16

はじめに

慶應大学 理工学部 情報工学科 B3のぽこちゃんです

今回は自分が運営に携わっている
データサイエンス系学生団体
DataCampusにて利用している
2週間、情報共有チャンネルに投稿がなかったら
本人と管理者に通知を送るbot

👇

スクリーンショット 2024-01-16 14.04.31.png

の実装を紹介します

2週間の部分は変えられるので
1日発言が無かったでも1時間動きがなかったでもなんでもできます
基礎機能ではありますが応用性は高いので是非是非

Xもやってるのでぜひフォローお願いします
フォロバします!

Slack bot

そもそもこのSlack botはGASという
Googleが提供するアプリケーション開発プラットフォームで動かしてて、JavaScriptがベースになってます。
Googleのさまざまなサービスと連携して動作を自動化でききて、スプレッドシートとかフォームとかにも対応してるのでめっちゃ便利です

👇いまにゅさんのGAS入門 参考に

bot作成の準備

  1. Slackにログインしている状態で、Slack APIへアクセスする
  2. Your Appという画面が表示されるので「 Create New App 」をクリックする
  3. App Nameにbotの名前, Select a workspaceでbotを追加したいワークスペースを選択しましょう. スクリーンショット 2024-01-16 11.23.06.png

権限の付与

  1. OAuth & Permissionsを選択スクリーンショット 2024-01-16 11.30.26.png
  2. 下に行くとScope画面が表示されるので、Bot Token Scopesの「 Add an OAuth Scope 」をクリックするスクリーンショット 2024-01-16 11.33.06.png
  3. 必要な権限を追加していく(今回は以下の通り)
calls:read
calls:write
channels:history
channels:join
channels:read
chat:write
groups:read
im:read
im:write
mpim:read
users:read
users:read.email

各権限の説明は省きますが、botが関わるところは

  • チャンネルに参加
  • チャンネルの各ユーザーの最終投稿履歴の取得
  • DMにメッセージを送信
    といった感じです

ボットをインストールする

  1. Install App をクリックするスクリーンショット 2024-01-16 11.40.09.png
  2. Install App to Workspace 」をクリックする
  3. アクセス権限リクエスト画面が表示されるので、「 許可する 」をクリック

ワークスペースから追加

Slack側で対象のワークスペースの「 アプリを追加する 」から先ほど作ったBotを選択する スクリーンショット 2024-01-16 11.44.23.png

これでbotが追加できたので次はコードの実装に移ります

GASの設定

とりあえずGASのスクリプトページまでいきましょう
スクリーンショット 2024-01-16 11.50.32.png

GASに設定するコード

いかにコードを書きますがいくつか設定する部分があります

  1. SLACK_TOKEN
    スクリーンショット 2024-01-16 11.55.17.png
    xoxoで始まる Bot User OAuth Token
  2. CHANNEL_IDスクリーンショット 2024-01-16 11.58.40.png
    適用したいチャンネルのチャンネル情報タブの下の方にあります
  3. MANAGER USER_ID
    誰が投稿していないかを管理するメンバーのメンバーIDを取得しましょうスクリーンショット 2024-01-16 12.02.20.png

他にも通知文は

postMessageToSlack(userId, '2週間、情報共有に投稿がありません!! 何でもいいので軽く投稿してみましょう!');

通知を送る閾値は
NOTIFY_THRESHOLDで設定できます(1msc単位かな?)

コード本文

const SLACK_TOKEN = 'YOUR SLACK_TOKEN';
const CHANNEL_ID = 'CANNEL_ID';
const NOTIFY_THRESHOLD = 7 * 24 * 60 * 60 * 1000 * 2; // 2週間

function getChannelMembers() {
  const url = `https://slack.com/api/conversations.members?channel=${CHANNEL_ID}`;
  const response = UrlFetchApp.fetch(url, { 
    method: 'GET' ,
    headers: {
      "Authorization": `Bearer ${SLACK_TOKEN}`
    }
    });
  const result = JSON.parse(response.getContentText());
  if (result.ok && result.members) {
    return result.members;
  } else {
    Logger.log(`Error fetching channel members. Error: ${result.error}`);
    return [];
  }
}

function checkUserLastPost() {
  const members = getChannelMembers();
  members.forEach(userId => {
    const url = `https://slack.com/api/conversations.history?channel=${CHANNEL_ID}&limit=100`; 
    const options = {
      method: 'GET',
      headers: {
        "Authorization": `Bearer ${SLACK_TOKEN}`
      }
    };
    const response = UrlFetchApp.fetch(url, options);
    const result = JSON.parse(response.getContentText());

    if (result.messages && result.messages.length > 0) {

      const userMessages = result.messages.filter(message => message.user === userId);
      if (userMessages.length > 0 ) { 
        const lastPostTime = parseFloat(userMessages[0].ts) * 1000;
        const currentTime = new Date().getTime();

        if (currentTime - lastPostTime > NOTIFY_THRESHOLD) {
          sendNotification(userId);
          Logger.log(`通知が送られました: ${userId} ${getUserName(userId)}`);
        }
      }
    } else {
      Logger.log(`Error or no messages for user: ${userId}. Error: ${result.error}`);
    }

  });
}

function sendNotification(userId) {
  const managerUserId = "MANAGER UDER_ID";

  // 通知を送るべきユーザーの名前を取得
  const userName = getUserName(userId);
  // 本人に通知を送る
  postMessageToSlack(userId, '2週間、情報共有に投稿がありません!! 何でもいいので軽く投稿してみましょう!');
  // 管理者に通知を送る
  postMessageToSlack(managerUserId, `${userName} (ID: ${userId}) は一定期間投稿がありません。`);
}


function postMessageToSlack(channelId, messageText) {
  const url = 'https://slack.com/api/chat.postMessage';
  const payload = {
    channel: channelId,
    text: messageText,
  };
  const options = {
    method: 'POST',
    headers: {
      "Authorization": `Bearer ${SLACK_TOKEN}`,
      "Content-Type": "application/json"
    },
    payload: JSON.stringify(payload)
  };

  UrlFetchApp.fetch(url, options);
}

function getUserName(userId) {
  const url = `https://slack.com/api/users.info?user=${userId}`;
  const options = {
    method: 'GET',
    headers: {
      "Authorization": `Bearer ${SLACK_TOKEN}`
    }
  };
  const response = UrlFetchApp.fetch(url, options);
  const result = JSON.parse(response.getContentText());

  if (result.ok && result.user) {
    return result.user.real_name || 'Unknown User';
  } else {
    Logger.log(`Error fetching user info. Error: ${result.error}`);
    return 'Unknown User';
  }
}

トリガー設定

最後にこのスクリプトをいつ動かすかの設定が必要になります。
GASの左側のメニューからトリガーを選択しましょう
スクリーンショット 2024-01-16 12.10.15.png

右下の青ボタン「トリガーを追加」を押して

実行する関数を「checkUesrLastPost」を選択
あとは下にある
時間ベースで1時間おきに実行とか
とか
日付ベースで毎日0時から1時の間に実行とか選びましょう!

スクリーンショット 2024-01-16 12.09.25.png

まとめ

今回は2週間、情報共有チャンネルに投稿がなかったら
本人と管理者に通知を送るbot
の作り方紹介でした

勉強したくなくて書いてただけですw
色々応用あると思うのでぜひ作ってみてください

Xもやってるのでぜひフォローお願いします

ご読了ありがとうございました!

3
3
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
3
3