AlfredでSlackの日報スレに投稿できるようにしてみた【Node.js】


前提

本記事で説明しないこと

  • AlfredのWorkflowの基本操作

基本操作は以下の記事で解説しています。
AlfredでWorkflowを作ったことない方は先にこちら参照いただくことをおすすめします。

https://zenn.dev/tomsan96/articles/91ef90b4a1c33c

環境

  • Alfred4(無料版ではworkflowの作成ができないため、有料版を用意してください)
  • Node.js 16.13.1

動機

私の勤務先ではGoogleスプレッドシートで作成している日報のURLを共有して1日の業務を終えます。
毎日botが定刻に日報報告用のメッセージを送信し、そのスレッドに各自が日報を提出するスタイルです。

  1. 日報を書く
  2. slackの報告用チャンネルを開く
  3. 報告スレッドを開く
  4. リンクを貼って投稿する

という手順が日報提出するためには必要です。
この作業(2~4)が面倒臭いを効率化したいと考えたことが動機となります。

どのように実現するか

実現したいこととしては 「Alfredで簡単に日報を提出できること」 となります。

悩みポイント①
スプレッドシートURLをどこで入力するか?
→スプレッドシートは月ごとの更新のため、環境変数に持たせて月1で環境変数を手動で変更する運用を採用しました。

悩みポイント②
botが投稿する日報報告用のメッセージをどう判定するか?
→日報報告用のメッセージは1日1回しか投稿されないという前提を踏まえ、以下の流れで日報報告用のメッセージの判定をさせることにしました。

  1. 該当チャンネル内のその日に投稿されるメッセージ履歴を取得する
  2. 取得したメッセージのうち、文言の一致を条件に日報報告用のメッセージと判定する

手順

1. Slackでアプリを作成する

Slackアプリの作り方は以下のサイトがわかりやすいです!(前回の記事同様)

https://zenn.dev/kou_pg_0131/articles/slack-api-post-message
「スコープを設定する」で必要なのはUser Token Scopeですので、Bot Token Scopesの設定はなくてOKです!
今回必要な権限は以下になります。
  • chat:write
  • channels:history
  • groups:history
  • im:history
  • mpim:history

「アプリをワークスペースにインストールする」まで実施してください。

2. Alfredでworkflowを作成する

新たなWorkflowで以下の3つを作成してください。

  • Inputs -> keyword
  • Actions -> Run Script
    • ./node_modules/.bin/run-node src/index.js "$1"
  • Outputs -> Post Notification

これらを作成した後、繋ぎ込みます。

3. スクリプトを書いて実行する

※実行コマンド等は前回の記事を参照ください
※Node.jsを使うために「Alfy」というライブラリを利用しています。

https://github.com/sindresorhus/alfy

作成したsrc/index.jsが以下になります。

import alfy from 'alfy';

// 環境変数の取得
const token = process.env.TOKEN || "";
const channel = process.env.CHANNEL || "";
const word = process.env.WORD || "";
const url = process.env.URL || "";

const now = new Date()
// 当日0時をターゲット日時に設定(ミリ秒)
const targetDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
// Unix時間(秒単位)に変換
const targetUnixTimestanp = Math.floor(targetDate.getTime() / 1000)

// oldestパラメータ:メッセージ履歴の取得開始時期を指定
const getHistoryUrl = `https://slack.com/api/conversations.history?channel=${channel}&oldest=${targetUnixTimestanp}`;
const postUrl = "https://slack.com/api/chat.postMessage";

(async() => {
    try {
        // 該当チャンネル内のその日に投稿されるメッセージ履歴を取得する(api: conversations.history)
        const response = await alfy.fetch(
            getHistoryUrl,
            {
                headers: {
                    Authorization: `Bearer ${token}`
                },
            }
        )
	// 取得したメッセージのうち、文言の一致を条件に日報報告用のメッセージと判定する
        for(let i=0; i<response.messages.length; i++) {
	    // 濁音が不一致判定されたため、normalize()で対応している
            if (word.normalize() === response.messages[i].text.normalize()) {
	        // 日報を投稿する(api: chat.postMessage)
                await alfy.fetch(
                    postUrl,
                    {
                        method: "POST",
                        headers: {
                            Authorization: `Bearer ${token}`
                        },
                        json: {
                            channel: channel,
                            thread_ts: response.messages[i].ts,
                            text: `日報です\n${url}`
                        }
                    }
                )
                console.log("投稿成功!!!")
            }
        }
    } catch {
        console.log("投稿失敗しました。。。")
    }
})();

4. 環境変数を設定する

Name Value
TOKEN xoxp-xxxxxx(作成したアプリのtoken)
CHANNEL (投稿したいチャンネルID)
URL (スプレッドシートのURL)
WORD (botが投稿している対象メッセージ文言)

成果物

結果がこちらになります。
テストということで環境変数のWORDには「リマインダー : *<!channel>* 日報スレ」、URLにYouTubeのリンクを挿入しています。

Alfredを叩いてみる

コードをいじってわざと失敗させた時

成功した結果


完成です!
これで日報の提出を楽して効率的に素早くできるようになりました!!!

参考

https://qiita.com/0ba/items/879eef81055921f845aa
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
https://api.slack.com/methods/conversations.history