4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GASでSlackのDMをBotから社員(有料)ユーザーだけに送る

Last updated at Posted at 2023-11-30

この記事は、リンクバルアドベントカレンダー2023の1日目の記事です。

はじめに

Slackで同じ内容のDMを複数のユーザーに送りたいことってありますよね?
30人程度までなら手動でもいいですが、それ以上だとめんどうなので、GAS(Google Apps Script)を使って送る方法を紹介します。

GASでDMを送る方法は検索したりChatGPTに聞けばいろいろ出てきます。
が、今回は以下の要件があったので、少しスプレッドシートで工夫します。

  • 社員ユーザーにだけ送りたい
    • 取引先のユーザーなどには送らない
  • その他記事の本筋からずれる要件
    • スプレッドシートにメッセージのテキストを用意したい
    • 用意したテキストをランダムに送りたい
    • 定期的に送りたい

コードだけ知りたい方はこちらまで飛んでください!

準備

1 Slack Appの作成

https://api.slack.com/apps の 右上の Create New App ボタン から作成できます。

詳細は公式のヘルプや、以下のような記事を参考にしてください!

参考記事

botに必要なスコープ

  • chat:write
  • im:write

あとはtokenが必要なので、控えておいてください。

2 DM送信対象者のUser IDの取得

botからDMを送るには、送信対象ユーザーのSlackのUser IDが必要です。
Slackの画面から個別に取得することもできますが、人数が多いとしんどすぎるので、Analytics画面からCSVを取得します。

1 Analytics画面のMembersを開く

https://linkbal.slack.com/stats#members です。

2 Edit Columns で、必要な項目をチェックする&不要な項目のチェックを外す

Screenshot 2023-11-24 at 13.03.21.png

最低限 User ID さえあれば送信できます
今回は管理と社員だけに送るために、画像のようにチェックしています。

Screenshot 2023-11-24 at 13.04.28.png

Included in bill は、有料ユーザーがどうかです。当社の場合は、社員以外は基本的に有料ユーザーがいないので、このデータで社員判定をします。

もし社員以外にも有料ユーザーがいたり、有料ユーザーだけど社員でない人がいる場合などは、例えばスプレッドシートで特定のドメインがEmail列に含まれているか、など工夫しましょう。

3 Export CSV でCSVをダウンロードする

データ量次第ですが、早ければ1,2秒でSlack BotからDMで送られます

Screenshot 2023-11-24 at 13.03.21 copy.png

3 スプレッドシートとGASの作成

なんでもいいのでスプレッドシートを1つ準備してください。

1 先ほどのCSVをアップロードする

メニューの ファイル > インポート > アップロード でできます。

Screenshot 2023-11-24 at 13.14.46.png

画像のモーダルが出るので、操作した状況に合わせて適切なものを選択してください。
基本的に 新しいシートを挿入する現在のシートを置換する のどちらかになります。

Screenshot 2023-11-24 at 13.09.07.png

2 社員ユーザーだけに対象を絞る

CSVをインポートしたシートの名前が Slackインポート用 だとします。

1つシートを追加して、A1に以下の関数を入れます。

=QUERY(
'Slackインポート用'!B:G,
"select
  C
where
  G = 1",
1
)

Screenshot 2023-11-24 at 13.23.20.png

やってることは単純で、QUERY関数で、CSVデータからG列が1の行のC列を抽出しているだけです。
最後の1は、ヘッダー行があることを表しています。

今回のCSVは、C列がUser IDで、G列が Included in bill です。

コメントをつけるとこんな感じです。

=QUERY(
'Slackインポート用'!B:G, // 対象範囲
"select
  C // 取得する列
where
  G = 1", // 取得する行の条件。G列が1の行
1 // ヘッダー行があることを明示
)

QUERY関数の公式ドキュメント
https://support.google.com/docs/answer/3093343?hl=ja

2 シートと紐づくGASのプロジェクトを作成する
メニューの 拡張機能 > Apps Script で、スプレッドシートに紐づいたGASのプロジェクトを作成しましょう。

Screenshot 2023-11-24 at 13.14.56.png

GASの作成

記事の主題からはそれますが、、、
前提として、画像のようなデータから、分類をランダムで選び、その分類のテキストからランダムに送るようになっています。

Screenshot 2023-11-24 at 13.18.37.png

やること

  1. GASのエディタに以下のコードを貼り付ける
    • 最初からある myFunctio などの3行のコードは不要なので消してOKです
  2. ショートカットのctrl+sやcmd+sか、フロッピーディスクのアイコンで保存する

コード

コメントで説明しています。

// 特定ユーザーだけにしたテスト実行用
function doTest() {
  main('テスト用Slack_UserID抽出'); // 名前は実際のシートに合わせる
}

function main(targetSheetName) {
  const spreadsheet = SpreadsheetApp.getActive(); // スプレッドシートからスクリプト作成した前提

  const slackUserSheet = spreadsheet.getSheetByName(targetSheetName); // SlackのUserID記載のシート名を指定
  const targetUserIds = slackUserSheet.getDataRange().getValues().slice(1); // ヘッダー行を対象から外す

  // ========== ここから:ランダムにテキストを送るための実装 ==========
  // スプレッドシートからテキストデータを取得
  const textSheet = spreadsheet.getSheetByName('テキストシート名'); // 名前は実際のシートに合わせる
  const textRange = textSheet.getDataRange().getValues().slice(1); // ヘッダー行を対象から外す
  
  // 大分類ごとにテキストをグループ化
  const classifiedTextObjects = createClassifiedTextObjects(textRange);
  // ========== ここまで:ランダムにテキストを送るための実装 ==========

  targetUserIds.forEach(function(row) {
    const targetUserId = row[0];
    if (!targetUserId) return; // 空のセルは無視

    sendSlackDM(targetUserId, getSlackMessage(classifiedTextObjects)); // 定型文を送るだけなら、この第二引数に文字列をそのまま渡せばOK
  });
}

// メンバーにDMを送信する
function sendSlackDM(targetUserId, message) {
  const payload = {
    token: 'xxxxx', // 作成したAPIのtokne
    channel: targetUserId,
    text: message
  }

  const slackEndPoint = 'https://slack.com/api/chat.postMessage'
  const option = {
    "method" : "post",
    "payload" : payload
  }

  const response = UrlFetchApp.fetch(slackEndPoint, option)
  // Logger.log(response) // デバッグ
}

// 全UserID 誤って実行しないよう注意!!!!!
function doProd() {
  main('Slack_UserID抽出'); // 名前は実際のシートに合わせる
}


// ========== 以下はランダムにテキストを送るための実装 ==========

// テキストの種類とテキストそのもののオブジェクトを作成する
function createClassifiedTextObjects(range) {
  const classifiedTextObjects = {};

  range.forEach(function(row) {
    const textType = row[0];
    const textSentence = row[1];

    if (!classifiedTextObjects[textType]) {
      classifiedTextObjects[textType] = [];
    }
    classifiedTextObjects[textType].push(textSentence);
  });
  return classifiedTextObjects;
}

// テキストをランダムに返す
function getRandomTextType(classifiedTextObjects) {
  const textTypes = Object.keys(classifiedTextObjects);
  return textTypes[Math.floor(Math.random() * textTypes.length)];
}

// textType のテキストをランダムに返す
function getRandomTextSentence(classifiedTextObjects, textType) {
  const textSentences = classifiedTextObjects[textType];
  return textSentences[Math.floor(Math.random() * textSentences.length)];
}

function getSlackMessage(classifiedTextObjects) {
  const randomTextType = getRandomTextType(classifiedTextObjects);
  const randomTextSentence = getRandomTextSentence(classifiedTextObjects, randomTextType);

  const message = `定型文
${randomTextType}
${randomTextSentence}
定型文`;
  // Logger.log(message); デバッグ

  return message;
}

テスト実行

doTest というテスト用の関数を作っています。

私は誤って2回テストのメッセージを全員に送ってしまったので、上記作成しました。
doTest のシートのA2とA3に、自分のSlackのUser IDを入れておきましょう。
2行入れておけば、DMが2通来たらテスト実行だとわかります。1通しか来なかったらミスってます...

画像の部分が doTest になっていることを確認したら、実行 ボタンを押しましょう。

Screenshot 2023-11-24 at 13.32.32.png

作成したSlack Appから、自分にDMが2つ来るはずです!

来ない場合は、以下を確認しましょう。

  • シートの作り
  • Slack Appの権限が足りているか
  • Slack AppのTokneがGASに設定されたいるか
  • GASでエラーが出ていないか

GAS初見だったりプログラミング未経験の方はトラブルシューティングが難しいので、どうしてもわからないときはプロフィール記載のSMSにメッセージなり送っていただければ、(多分)回答します!

本番実行(定期実行)

サイドメニューの トリガー > 右下の トリガーを追加 > 画像のように設定して 保存

Screenshot 2023-11-24 at 13.36.51.png

Screenshot 2023-11-24 at 13.37.14.png

重要なポイント

  • 実行する関数doProd を選択すること
  • イベントのソースを選択 やそれ以降の設定は、適切なものを選択すること

こうすれば、設定した内容で定期実行されます。

おわりに

おつかれさまでした!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?