LoginSignup
27
17

More than 5 years have passed since last update.

Slackで特定のスタンプ(リアクション)に反応するサーバレスボットをGASで作成してみた

Posted at

この記事は全部俺 Advent Calendar 2018の21日目の記事です。

作ったもの

2通りのことができるSlackサーバレスボットをGASを使って作成してみました。

  1. 特定のスタンプ/リアクションに反応して一瞬だけ文字を表示する

※ みなさまお忘れかもしれませんが、シュタゲネタです:)

  1. 特定のスタンプ/リアクションに反応してスタンプを追加/削除する

作成手順

GASの準備:その1

Googleスプレッドシートから、ツール → スクリプトエディタを選んでGASの編集画面に移ります。
image.png

GAS編集画面にて、以下のソースコードを貼り付けます。

function doPost(e){
  // Slackバリデーション用
  var params = JSON.parse(e.postData.getDataAsString());
  return ContentService.createTextOutput(params.challenge);
}

GAS側の設定が終わったら、これをSlack側からアクセスできるようにします。
GAS側の画面で、公開 → ウェブアプリケーションとして導入... を選択します。
アプリケーションにアクセスできるユーザー全員(匿名ユーザーを含む)を選び、プロジェクトバージョンでNewを選んで公開した後、現在のウェブ アプリケーションの URLで出てくるURLをコピーしておきます。
GAS側の設定は、一旦ここで終了です。

Slack側の準備

Slack APIにアクセスし、start buildingを押してSlack APIを新規作成します。

Create an Appから新規アプリを作成します。ここではreactorという名前で作成します。
Event SubscriptionsをOnにして、Request URLに先程のURLを貼り付けます。
すると、以下の画面のようにVerifiedと表示されるはずです。
image.png

Subscribe to Workspace Eventsにて、reaction_addedreaction_removedを追加した後、Save Changesを押します。

OAuth & Permissionsにて、Scopesで以下の画面のようになるようにPermission Scopeを追加してSave Changesを押します。
image.png

Bot Userから、Add a Bot Userを押して、ボットを追加します。名前はここではreactorとしました。

ここまで来たら、Install App to Your Teamを押してSlackに作成したAppをインストールします。
image.png

ここの下部のBot User OAuth Access Tokenを後ほど使うのでコピーしておいてください。

これから出てくるGASソースコードと全く同じ動作をさせたい方は、以下の画像のようにCustom Emojiを追加してください。
文字列についてはみんな大好き絵文字ジェネレーターを利用しました。
image.png

GAS側の準備:その2

先程のGAS画面に戻り、ソースコードを削除した後、今度は以下のソースコードを貼り付けます。

function doPost(e){
  // postMessage emoji
  const message_emojis = ["eye", "eyes"]
  // 追加/削除のトリガーとなるemoji
  const reaction_torigger_emoji = "so";
  // 追加/削除対象のemoji
  const reaction_emojis = ["re", "na"];

  // SlackApp インスタンスの取得
  var token = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN');
  var slackApp = SlackApp.create(token);

  // event parametersの取得
  var params = JSON.parse(e.postData.getDataAsString()).event;

  if (params.type === "reaction_added") {
    if (message_emojis.indexOf(params.reaction) >= 0) {
      watchYou(slackApp);
    } else if (reaction_torigger_emoji.indexOf(params.reaction) >= 0) {
      addReaction(slackApp, params.item, reaction_emojis);
    }
  } else if (reaction_torigger_emoji.indexOf(params.reaction) >= 0) {
    if (params.reaction === "so") {
      removeReaction(slackApp, params.item, reaction_emojis);
    }
  }

  // Slackバリデーション用
  var params = JSON.parse(e.postData.getDataAsString());
  return ContentService.createTextOutput(params.challenge);
}

function watchYou(slackApp){
  var options = {
    channelId: "test",              //チャンネル名
    userName: "patghqwskm@nine...", //投稿するbotの名前
    emoji: ":red_jelly:",           //iconのemoji
    message: "お前を見ているぞ",        //投稿するメッセージ
  };

  res = slackApp.postMessage(options.channelId, options.message, {username: options.userName, icon_emoji: options.emoji});
  Utilities.sleep(1000);
  slackApp.chatDelete(res.channel, res.ts);
}

function addReaction(slackApp, item, emojis){
  const url = "https://slack.com/api/reactions.add";
  const token = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN');
  const method = 'post';

  var payload = {
    'token'      : token,
    'channel'    : item.channel,
    'timestamp'  : item.ts,
  };
  var params = {
    'method' : method,
    'payload' : payload
  };

  for (var i = 0; i < emojis.length; i++) {
    Utilities.sleep(1000);
    payload.name = emojis[i];
    UrlFetchApp.fetch(url, params);
  }
}

function removeReaction(slackApp, item, emojis){
  const url = "https://slack.com/api/reactions.remove";
  const token = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN');
  const method = 'post';

  var payload = {
    'token'      : token,
    'channel'    : item.channel,
    'timestamp'  : item.ts,
  };
  var params = {
    'method' : method,
    'payload' : payload
  };

  for (var i = 0; i < emojis.length; i++) {
    Utilities.sleep(1000);
    payload.name = emojis[i];
    UrlFetchApp.fetch(url, params);
  }
}

一部処理(post.massage)はいい感じのGASライブラリをお借りしました!
スタンプ/リアクションの追加/削除を行う処理はライブラリに含まれていなかったためPOSTリクエストを自分で投げています。

ファイル → プロジェクトのプロパティから、先程コピーしたSlackのBot User OAuth Access TokenSLACK_ACCESS_TOKENとして貼り付けます。
image.png

先ほどと同様、GAS側の画面で、公開 → ウェブアプリケーションとして導入... を選択します。
アプリケーションにアクセスできるユーザー全員(匿名ユーザーを含む)を選び、プロジェクトバージョンでNewを選んで公開すると設定は完了です。
Slack画面を開いて、#testチャンネルを作成すると、一番最初の動画のような挙動をするアプリが作成できているはずです。

まとめ

GASを利用して、簡単なbotを作成してみました。
GASは手軽にサーバレス環境を試せていい感じなのでちょくちょく使用しています。
(サービスレベル的に本番環境では運用できないので、失敗しても大丈夫な趣味プロジェクトでの使用に留めたほうがいいと思います。)
今後も思いついたら手軽に試していきたいと思います。

27
17
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
27
17