🍣

GASでSlackAPIを使ってメッセージ投稿してセルフリアクションする

2023/03/12に公開

GASでSlackメッセージを投稿してリアクションまで自動でつけたいと思いました。

理由は、例えば「ランチbot」みたいなやつがいたとして、こんなメッセージを送ったとします

こんなときに、ファーストリアクションをするユーザーは :ramen: や :sushi: を自分で探してリアクションしなければならないため、ユーザーフレンドリーとは言えません。

なので、メッセージ投稿と同時に

このようにリアクションをつけてあげると、続く人がリアクションをつけやすくなります。

これをしたいと思いました。

与件

以下はスクリプトにベタ書きや別のスプレッドシートに記載するのではなくプロパティストアを利用して作る

  • Slack API Token
  • 投稿するChannel ID
  • リアクション(複数も可能)

TypeScriptで開発(clasp利用する)

まずはSlackBotのscope周りを設定しましょう

ここでは詳細には触れませんが、


OAuth&Permissionsの項目から

  • chat:write
  • reactions:write
    の権限を付けてAPI Tokenをゲットしましょう。
    (いつもSlack Botの権限周りは迷いますね)

開発

大きく分けて、

  1. プロパティストアからプロパティ取得
  2. SlackAPIを用いてメッセージ投稿
  3. SlackAPIを用いてリアクション
    という感じになります。

すべてTypeScriptで書きます。

プロパティストアからプロパティを取得

細かいバリデーションはしません。
入力するのは自分だからです。
リアクションは複数リアクションをつけたければカンマで区切って入力します

const properties = PropertiesService.getScriptProperties();

const slackToken:string = properties.getProperty("SLACK_TOKEN");
const channelId:string = properties.getProperty("CHANNEL_ID");
const reactions:string[] = (properties.getProperty("REACTIONS").split(",");

SlackAPIを用いてメッセージ投稿

戻り値はリアクション投稿に利用するため、chat.postMessageのレスポンスに含まれているts(タイムスタンプ)を返します。(リクエスト失敗したら空文字列が返ります)

関数の引数はチャンネルID投稿するテキストです。

function sendMessage(channelId:string, text:string) :string {
    const options:URLFetchRequestOptions = {
        "method": "post",
        "contentType": "application/x-www-form-urlencoded",
        "payload": {
            "token": slackToken,
            "channel": channelId,
            "text": text
        }
    };
    const url = 'https://slack.com/api/chat.postMessage';
    const response = UrlFetchApp.fetch(url, options);
    if (response.getResponseCode() == 200) {
        const res = JSON.parse(response.getContentText());
        if (res.ok) {
            return res.ts;
        }
    }
    return "";
}

SlackAPIを用いてリアクション

SlackAPIのreactions.addを用いてメッセージにリアクションする関数です。
戻り値は成功失敗をbooleanで返しています。

関数の引数はチャンネルIDリアクションしたいメッセージのタイムスタンプつけたいリアクション(1つ)です。

function addReaction(channelId:string, timestamp:string, reaction:string):boolean {
    const options:URLFetchRequestOptions = {
        "method": "post",
        "contentType": "application/x-www-form-urlencoded",
        "payload": {
            "token": slackToken,
            "channel": channelId,
            "timestamp": timestamp,
            "name": reaction
        }
    };
    const url = 'https://slack.com/api/reactions.add';
    const response = UrlFetchApp.fetch(url, options);
    if (response.getResponseCode() == 200) {
        const res = JSON.parse(response.getContentText());
        if (res.ok) {
            return true;
        }
    }
    return false;
}

できたもの

上記で作った関数たちをこんな感じで呼んでいきます。
reactionは1APIコールに付き1つのリアクションしかつけれない模様なので、何度か呼ぶようにしています。(1コールで複数つけられる方法があれば教えて下さい・・・)

function main() {
    const msg: string = "{{MESSAGE}}";
    const ts = sendMessage(channelId, msg);

    if (ts === "") return;
    if (reactions == [""]) return;

    reactions.forEach((reaction)=>{
        addReaction(channelId, ts, reaction);
    });
}

こんな感じclaspにPushして終了。
無事に自動投稿&セルフリアクションできるようになりました!

参考になれば嬉しいです。

Discussion