Slack→GAS→NotionでTODOリスト化を少し便利にする
これは 🎅GMOペパボエンジニア Advent Calendar 2022 の9日目の記事です。
🎄GMOペパボエンジニア Advent Calendar 2022もありますのでぜひご覧ください!!
昨日は yana-gi さんによる 中学生以来の電子工作をして meishi2 を組み立てたでした。自分でキーボードを組み立てて、しかも好きなマクロを登録できるって楽しそうですね!私も記事内で紹介されていた「自作キーボードを作る会」に参加していて、これからキーボード作りに取り組むのが楽しみです😋
追記
- 2022/12/09 00:38追記 リプライを取得できないことを確認したので修正中です。
- 2022/12/09 01:14追記 コードの修正が完了しました。
タスク管理の悩みごと
みなさんは仕事などにおけるタスク管理をどのように行われているでしょうか?私はNotionのデータベースを使用して管理しています!優先度や関連するURL、進行具合などをすぐに確認できるようにしています。
ここで一点悩みが……
タスク管理をする際に、自分用のTODOリストとチーム用のカンバンと2箇所で管理をしています。両方のデータベースに登録する際に、片方だけ登録してもう片方に登録し忘れるということが頻発してしまうのです。
「一方だけに登録すればいいのでは?」とも思うのですが…チームにも自分にも関することは両方に登録したいですし、どちらか一方だけ登録できればOKという場合もあって悩んでいました。あと、普段のやり取りをSlackでするのにタスク管理のためにNotionに移動するのが面倒ですからね…
…つい本音が漏れてしまいました
ということで今回は
- タスク管理したいSlackのメッセージに特定のemojiをリアクション
- Notionの指定したデータベースにページを作成し、メッセージの内容を名前として登録する
の流れを自動化してみました。
Notionの準備
データベースの準備
まずはタスクを登録するデータベースが必要です。今回は仮想のデータベースを二つ作成しました。
インテグレーションの準備
Notionのページ作成をAPIから実行できるようにするためインテグレーションを作成します。
今回はページの作成ができれば十分なので「コンテンツを挿入」だけ設定します。
Google Apps Script の準備
Slack AppとNotionの仲介役にサーバーが必要です。今回は、GASを使ってリクエストを処理するようにします。
見本のシートを作成したので、自分のGoogleドライブに保存して使用してください。 これから保存していただいたシートに情報を書き込むのですが、トークンなどがバレないようにリンクの漏洩などには十分にご注意ください。
この先、Slack AppがGASを認証できるように設定を行います。「拡張機能」から「Apps Script」を開いて
以下のコードをコピペします。ペーストしたら、2行目の GoogleスプレッドシートのIDを置き換える
をスプレッドシートのIDに置き換えてください。IDは https://docs.google.com/spreadsheets/d/xxxxxxxxxxxx/edit......
の xxxxxxxxxxxx
の部分です。
function doPost(e) { const sheet = SpreadsheetApp.openById("GoogleスプレッドシートのIDを置き換える"); const notionToken = sheet.getRange("F2").getValue(); const slackToken = sheet.getRange("H2").getValue(); const lastRow = sheet.getLastRow(); const params = JSON.parse(e.postData.getDataAsString()); if (params.type == 'url_verification') { return ContentService.createTextOutput(params.challenge); } else { const slackEvent = params.event; const targetEmoji = slackEvent.reaction; const ts = slackEvent.item.ts; const channel = slackEvent.item.channel; const title = getSlackMessage(slackToken, channel, ts) let settingCells; let databaseId, emoji; let destinations = {}; for(let i = 2; i <= lastRow; i++){ settingCells = sheet.getRange(`A${i}:C${i}`).getValues(); [, databaseId, emoji] = settingCells[0]; if (!Object.keys(destinations).includes(emoji)) { destinations[emoji] = []; } destinations[emoji].push(databaseId); } Object.keys(destinations).forEach(key => { if(targetEmoji == key) { destinations[key].forEach(destination => { postToNotion(notionToken, destination, title); }) } }) } } function getSlackMessage(slackToken, channel, ts) { const options = { "headers": { "Authorization": `Bearer ${slackToken}`, }, "payload": { "channel": channel, "latest" : ts, "inclusive": "true", "limit": "1", "ts": ts } } let res = UrlFetchApp.fetch("https://slack.com/api/conversations.replies", options) return JSON.parse(res.getContentText()).messages[0].text; } function postToNotion(notionToken, databaseId, title) { const payload = { "parent": { "database_id": databaseId }, "properties" : { "title": { "title": [ { "text": { "content": title } } ] } } } const options = { "headers": { "Authorization": `Bearer ${notionToken}`, "Notion-Version": "2022-06-28" }, "contentType": "application/json", "method": "post", "muteHttpExceptions": true, "payload": JSON.stringify(payload) } UrlFetchApp.fetch("https://api.notion.com/v1/pages", options) };
コピペしたら右上の「デプロイ」からWebアプリとしてデプロイします。Slack Appからのリクエストを受け付けるように「アクセスできるユーザー」は「全員」に設定します。
「アクセスを承認」のボタンが出てきたら、自分のアカウントを選択→「Advanced」→Go to (GASのプロジェクト名)…と作成したGASを承認してください。
無事デプロイが完了したら、作成したGASのWebアプリのURLが表示されるのでコピーします。
Slackの準備
ワークスペースやチャンネルの作成の説明については省略します。
Slack Appの作成
以下のリンクにアクセスし「Create an app」→「from scratch」で新しくSlack Appを作成しましょう。
Slack Appの名前と対象のワークスペースを決定したら、「Basic Information」が開くので「Event Subscriptions」に移動します。
ここで先ほどコピーしたGASのWebアプリのURLを「Request URL」に登録してサーバーの認証を行います。認証ができると「Request URL Verified ✅」が表示されます。
そのままページ下部に移動すると「Subscribe to bot events」という項目があるので、emojiを押したことをAppが検知できるように「Add Bot User Event」から「reaction_added」を追加します。
右下の「Save Changes」を押して忘れずに変更を保存しましょう。
Slack Appの権限設定
このあと作成するAPIのために「OAuth & Permissions」から権限を設定します。「Scopes」の「User Token Scopes」に以下の4つを追加しましょう。「Bot Token Scopes」のreactions:read
は先ほど「Subscribe to bot events」を設定したときに適用されています。
channels:history
groups:history
im:history
mpim:history
Slack Appの名前を設定する
「App Home」からSlack Appの名前を設定します。これを設定しないと、「インストールするボットユーザーがありません」というエラーが出てAppをインストールできません。
登録に成功すると「Bot user added!」と表示されます。
Slack Appのインストール
「Basic Information」に移動すると「Install your app」という項目があるので、「Install to Workspace」からAppをインストールしましょう。
右下の「許可する」でインストールしましょう。
チャンネルへの追加
Appを使用したいチャンネルへ追加します。
チャンネル詳細を開き、「インテグレーション」の「App」から「アプリを追加する」を選択します。追加できるアプリの一覧が表示されるので、先ほど作成したアプリを追加しましょう。
Notionデータベースとスプレッドシートの準備
AとB、二つのデータベースを作成したので、「Aのデータベースに登録するときはAのemoji」「Bのデータベースに登録するときはBのemoji」「両方に登録するときにはOKのemoji」を使うことにしました。
Notionのデータベースの右上、メニューを開いて「ビューのリンクをコピー」を押します。
すると https://www.notion.so/aaaaaaaaaaaaa?v=.........
のようなリンクを取得できるので aaaaaaaaaaaaa
をスプレッドシートに貼りましょう。もう片方のデータベースについても同様に取得と貼り付けをします。また、どのemojiを押したときにページ作成を行うか設定もしておきましょう。
コネクトの追加
Notionのインテグレーションを導入するためにページ右上のコネクトから、自分が作成したインテグレーションを選択します。
tokenをスプレッドシートに貼り付け
長かった工程もこれが最後です!
冒頭で準備したNotionのインテグレーションのシークレットトークンをスプレッドシートのF2セルにコピペします。
また、上記画像のようにSlack Appの「User OAuth Token」も「Installed App Settings」から取得してH2セルにペーストします。
動作確認
Slackでメッセージを送ってemojiでreactionしてみましょう。
するとNotionのデータベースにページが自動で作成されます。
これで少しだけ便利にできるSlack・GAS・Notion連携の完成です!
最後に
今回はemojiを判定して対応させたいデータベースへの登録を行いました。Slack AppやGAS、Notion APIを使うことで少しだけ便利にすることができたました!これからもっと発展させてURLを自動登録したり、他のプロパティも登録できるようなアプリケーションに進化させていきたいです。
参考にした情報
この記事・アプリを作成するにあたってたくさんの情報を参考にさせていただきました。情報を発信してくださった方々に感謝いたします。
- Reference overview | Apps Script | Google Developers
- Using Slack APIs | Slack
- Notion API
- JavaScript リファレンス - JavaScript | MDN
- Google AppScriptでHTTP POST(doPost)を受け付ける最小コード (2022年夏) - Qiita
- 【GAS】UrlFetchApp.fetchの使い方
- Slackの特定チャンネルのメッセージをクロールする方法 - Qiita
- Slack Appの作り方を丁寧に残す【BotとEvent APIの設定編】
- ID からスプレッドシートを開く:openById(id)【GAS】 | G Suite ガイド - G Suite ガイド:G Suite の導入方法や使い方を徹底解説!
- GAS:Slackでemojiが押されたら対象のスレッドをスプレッドシートにコピーしてSlackに通知する-1/3
- Slack のメッセージ履歴を取得する | DevelopersIO
明日の🎅GMOペパボエンジニア Advent Calendar 2022は、我らがCTOのあんちぽさんです!🙌