slack API + GASでリアクションがあったら指定チャンネルにメンション通知する

まえがき

Slackでリアクションされたら、メンション&リアクションに一覧表示されますが、リアルタイムでリアクションに気づきたくて通知されるようにSlack API+GASで実装してみました。

というのも夫婦間でSlackを使っていて、家事育児をしていると仕事中のように常にSlackを開いているわけではないのでリアクション通知があったらいいなという気持ちで作ってみました。

こんな通知がくるようにしました。

通知イメージ

ちなみにメンバーが多いと通知がきまくってうざいので、メンバー2人ならではの機能だとは思います。

構成

構成図

  • Slackのリアクションイベントをトリガー
  • GASでPOSTリクエストを受け取って処理
  • GASからIncoming WebhooksでSlackの対象チャンネルにメッセージ投稿

*GASとGitHub連携はGoogle Apps Script GitHub アシスタントを使っています。

実装

GAS作成(公開)

サーバ側はGASで用意しました。 「ウェブアプリ」としてデプロイして、公開URLをメモしておきます。

Promise.allを使ってチャンネル名とユーザIDを取得しておいて、Webhookで「リアクション+メンション+メッセージURL」を対象チャンネルに投稿するようにしています。

const props = PropertiesService.getScriptProperties().getProperties();
const oAuthAccessToken = props.OAUTH_ACCESS_TOKEN;
const slackApiBase = 'https://slack.com/api/';

function doPost(e){
  const json = JSON.parse(e.postData.getDataAsString());
  const itemChannel = json.event.item.channel;
  const itemTs = json.event.item.ts;
  const reaction = json.event.reaction;

  Promise.all([
    fetchChannel(itemChannel),
    fetchMessage(itemChannel, itemTs)
  ])
  .then(function(data) {
    const [channelName, messageData] = data;
    const message = "<@" + messageData["userId"] + ">" + "[" + channelName + "]にリアクションがつきました。\n\n" + messageData["linkUrl"];
    const jsonData = { "text": ":" +reaction + ":" + message };
    const payload = JSON.stringify(jsonData);
    const options = {
      "method" : "post",
      "contentType" : "application/json",
      "payload" : payload
    };

    UrlFetchApp.fetch(props.WEBHOOK_URL, options);
  })
  .then(() => {
    return ContentService.createTextOutput(params.challenge);
  })
}

// チャンネルリストを取得してチャンネルIDから対象のチャンネル名を取得
function fetchChannel(channelId) {
  return new Promise((resolve) => {
    const channelsUrl = slackApiBase + 'conversations.list?token=' + oAuthAccessToken + '&exclude_archived=1&pretty=1';
    const channels = JSON.parse(UrlFetchApp.fetch(channelsUrl)).channels;
    const targetChannel = channels.find(channel => channel.id === channelId);
    const channelName = (targetChannel !== undefined) ? targetChannel.name : "チャンネル以外";
    resolve(channelName);
  })
}

// メンション用に対象メッセージ投稿者のユーザIDを取得
function fetchMessage(channel, ts) {
  return new Promise((resolve) => {
    const url = slackApiBase + "conversations.replies?token=" + oAuthAccessToken + "&channel=" + channel + "&ts=" + ts + "&latest=" + ts + "&limit=1&inclusive=true" 
    const replies = JSON.parse(UrlFetchApp.fetch(url));
    const targetMessage = replies.messages[0];
    const isThread = (targetMessage.thread_ts !== undefined && targetMessage.ts !== targetMessage.thread_ts);
    let linkUrl = props.SLACK_WORKSPACE_URL + "archives/" + channel +"/p" + String(targetMessage.ts).replace(/\./g, '');
    // スレッドの場合
    if(isThread) {
      linkUrl += "?thread_ts=" + String(targetMessage.thread_ts).replace(/\./g, '') + "&cid=" + channel;
    }
    resolve({linkUrl: linkUrl, userId: targetMessage.user});
  })
}

参考

qiita.com

環境変数

GASのプロパティストアを利用。

  • OAUTH_ACCESS_TOKENはSlackアプリ作成時のOAuth & Permissions > Scopes設定後に表示されるものを定義します。

  • WEBHOOK_URLはSlackアプリ作成時にIncoming WebhooksONにしてURLを取得します。投稿先は#reactionチャンネルを作成して設定しました。

IDEではなぜかプロパティ編集画面がなくなっていてかなりつまづきました。 仕方ないのでプロパティストアの設定時だけ旧IDEに戻して設定後にまた新IDEに戻しました。

プロパティストア

ちなみに旧IDEに戻す際に以下のようなアンケートが出たのでMissing script property editingにチェックしておきましたw

f:id:mashym91:20210220175144p:plain:w300

Slackアプリ作成

Slackアプリの作成はこちらを参考にさせていただきました。

www.pnkts.net

適当にリアクション通知という名前で作成。 Slackアプリ作成

Event Subscriptions>Enable Eventsを有効にして先ほどメモしておいたGASのURLを貼り付けてVerified表示されることを確認します。

Event Subscriptions

Subscribe to events on behalf of usersreaction_addedを追加します。

Subscribe to events on behalf of users

OAuth & Permissions>Scopesで以下を設定してアプリをインストール。(App Installから)表示されるOAuth Access TokenをGASのプロパティ(OAUTH_ACCESS_TOKEN)に定義します。

User Token Scopes

参考

www.lancard.com

Incoming Webhooks設定

GASからメッセージ投稿するためにIncoming Webhooks>Activate Incoming Webhooks を有効にします。

Webhook URLs for Your Workspaceワークスペースのチャンネル(作成した#reaction)に追加します。

*以前はicon_emojiも投稿できたみたいですが、できなくなったようなのでtextに絵文字リアクションを追加して投稿する実装にしています。

Reference: Message payloads | Slack

Slack での Incoming Webhook の利用 | Slack

つまづいた点

スレッド対応

元メッセージURLの生成とユーザID取得用にslack APIconversations.historyを使っていましたが、スレッドの場合thread_tsも必要だったのでそれがが取れるconversations.repliesを使うように変更しました。 スレッド時のURL構成やAPIのresponseなどドキュメントを調べたりけっこう時間かかりました。

conversations.replies method | Slack

非同期処理の制御(Promise→Promise.all)

そのままだとAPIでのデータ取得前にWebhook処理が走ってしまうので、Promiseを使って順次処理していましたが、APIでのデータ取得は順番を気にしなくていいのでPromise.allを使うようにリファクタリングしました。

Promise.allでコードがかなりスッキリしたと思います。

参考

qiita.com

google github アシスタントの連携

Chrome拡張機能をインストールしてもGASの画面に全然反映されず困りましたが、こちらにある「v4.0.7を手動でインストール」で解決しました。

Google Apps Script GitHub アシスタントが表示されない&Google認証でエラー This app is blocked - Qiita

Google Apps Script GitHub アシスタント - Chrome ウェブストア

運用

最初に書いたとおり夫婦間用Slackでメンバーは2人なのでメッセージにメンションはつけず通知設定をすべての新しいメッセージにしていて、#reactionチャンネルだけメンションのみ設定で自分の投稿に対するリアクションだけ通知がくるようにしています。

最後に

実装から記事をまとめるまでちょっと時間が空いているので設定の流れなど違ってる部分があるかもしれませんm(__)m

#reactionチャンネルに常にすべてのリアクション情報が投稿される点はかなり微妙ですが、Slack APIもGASも初めて触ったのでいろいろ勉強になりました。

何より、今までは「了解」などの返事 をいちいちメッセージでスタンプ投稿していたのが、リアクションでいけるようになったのは個人的にかなり良かったです。

追記(2021/2/22)

昨日から夫のAndroidにSlackのリアクション通知がくるようになったらしく...。iPhoneには来ていないのでAndroid版のみ実装されたのか、ベータ版で一部ユーザに公開されているのか、どちらにしてもリアクション通知が公式で導入されたらアプリ不要ですw

【React】ドット(ピリオド)3つの意味

Reactでたまに出てくるドット3つの記法とは何か調べてみた。

JavaScriptでのスプレッド構文

ちなみにReactのPropsの受け渡し時に使われる{...props}Spread Attributesと呼ばれるもの。

オブジェクトや配列の前に記述することで、それらの要素を展開することができる。

// オブジェクトの展開
const colors = {
  red: "赤",
  blue: "青",
  yellow: "黄"
};
console.log({...colors, green: "緑", black: "黒"});
/*
 {red: "赤", blue: "青", yellow: "黄", green: "緑", black: "黒"}
*/

// 配列の展開
const colors = ["赤", "青", "黄"];
console.log(...colors, "緑", "黒");
// ["赤", "青", "黄", "緑", "黒"]

propsの受け渡し

const props = { foo: "a", bar: "b" };
render() {
  return <Child foo={props.a} bar={props.b} />
}

// Spread Attributeを使って書くと簡潔
const props = { foo: "a", bar: "b" };
render() {
  return <Child {...props} />
}

参考

スプレッド構文 - JavaScript | MDN

夫婦のコミュニケーションツール紹介 -slack・Todoアプリ他-

こんにちは。

現在育休中で一児の母です。

結婚や出産を機にさまざまなツールを取り入れて、育児や夫婦間コミュニケーションが割とうまくいっている気がするのでご紹介します。

導入にあたって

私は仕事でSlackなど各種ツールを使っているせいか私生活にも活かしたいという気持ちがあり、夫はそれに付き合ってくれるタイプの人で、新しいツールを試してみたいと提案すると比較的前向きに考えてくれます。

ですが普通の家庭ではなかなかそうはいかないのが現状かなと思います。「めんどくさい」と一蹴されたり、そもそも導入自体のハードルが高いかもしれません。。 私は提案材料として最低限以下のことを事前に調べてから夫に説明し、承諾してもらうようにしています。

事前にチェックしていること

チェック項目 チェック箇所
日本語対応の有無 英語のみの場合でも使えそうかどうか
有料/無料 有料プランがある場合は無料プランで事足りるか
メリット/デリット デメリットもチェックして自分たちの生活にマッチしそうかどうか
導入事例 使用感をイメージ

時間をかけてアカウントを作ったのに英語だらけで全くわからなかったり、途中で課金が必要になったり、致命的なデメリットがあったりしたらせっかくの労力が水の泡なので、この辺は入念にチェックします。

ツール紹介

それぞれどのような用途で使っていて、メリットがあるのかご紹介していきます。 各種導入方法や細かい使い方は省略します。興味があれば調べてみてください。

コミュニケーション用

Slack

IT企業ならほぼ導入しているチャットツールです。チャットツールというとLINEが主流ですがLINEと異なるのはチャンネル分け(LINEで言うところのグループ作成)をして使う点です。

夫婦間で使う場合メンバーは2人なので、なぜチャンネル分けをする必要があるのかと思うかもしれませんが、日常会話の代用と考えると良さがわかるかもしれません。

1つのチャンネルで会話するということは、例えば育児の話をしている途中に「今日は何時に帰ってくるの?」「夕飯は○○でいいかな?」「今度の休みにさ...」といったちょっとしたスケジュール確認や雑談を五月雨式に相手に投げることになります。それを受け取った相手はどう感じるでしょう。回答がめんどうになったり、未回答の質問がわからなくなったり、夕飯の話に脱線して最初の育児の話に戻れなくなることもあるでしょう。

Slackのチャンネル分けをするということはカテゴリ分けをして会話ができ、あとで見返したときにもそれぞれの会話の流れがわかりやすいというのが最大のメリットです。 ちなみに我が家で使っている主なチャンネルは以下のような感じです。

  • 連絡事項
  • 雑談
  • スケジュール
  • ご飯
  • マネー
  • 育児
  • 掃除_洗濯
  • 買い物

現在は「雑談」チャンネルが一番アクティブだったりします。面白い記事や小ネタなどを共有して帰宅後にその話でまた盛り上がったりもします。

デメリット

無料プランで使っているので直近の1万メッセージ以外は検索や閲覧対象外になりますが、記録的に残したいやりとりというよりは日常会話をSlack上でやっているイメージなので今のところ問題ありません。

また不具合なのかたまにですが通知が来ないことがあります。仕事用ではそんなことはないので無料プランのせいなのでしょうか。。

LINE

普通にLINEも使います。主に通話ですが急用で既読確認をしたい場合などはこちらが確実です。 ただSlackを導入してからはほとんどメッセージのやりとりはなくなりました(笑)

スケジュール管理

Googleカレンダー

お互いの予定をそれぞれGoogleカレンダーで共有しています。Googleのファミリー設定をしているので家族の予定は別途登録していて、「私の予定」「夫の予定」「家族の予定」の3つに色分け表示されて見やすいです。

我が家は夫の休みが土日でないことが多いのでいちいち予定を聞かなくて済むのはだいぶ楽です。そしてスケジュール共有不足による喧嘩やストレスがほとんど無いのでとてもオススメです。

買い物リスト管理

Microsoft To Doアプリ

一般的な夫婦は生活用品や食材の買い物リストの共有ってどうしてるんでしょうか。 いちいち確認するのは面倒すぎるのでアプリで買い物リストに追加しておいて、買える方がまとめて購入するという感じです。家にいても外出していても思いついた時にリストに書き込むだけでいいので買い忘れがなくて済みます。

買い物リストがメインですが、結婚や妊娠・出産した際は事務手続きなどのTodoリストを作って共有していました。

育児用

ぴよログアプリ

出産後に夫が育休を取得してくれたこともあり、ありがたいことに夫は90%以上の育児ができる状態です。その手助けとなったのがリアルタイムに共有ができる育児記録アプリの「ぴよログ」です。

おむつを替えたとかミルクをあげたとかをお互いに記録していちいち確認しなくても次のミルク時間の目安がわかるので、育児のバトンタッチがとてもスムーズにできます。

記録したものをPDF化できたり、有料ですが製本もできるのでいずれ形にして残そうと思っています。

みてねアプリ

子どもの成長を家族間で共有できるアプリです。節目でアルバムを作って実家に送ったりもしています。 コロナもあって私の両親にはまだ会わせられていないのですが、このアプリで子供の日々の成長を見せられているのは救いです。

その他

Googleスプレッドシート

Google版エクセルです。表が向いているような共有事項がある際にシートを共有してちょこちょこ活用しています。

  • 結婚/出産祝いの金額や内祝い品の管理
  • 年賀状用の住所リスト

Googleフォト

誕生日や旅行のアルバムを作る際に共有アルバムを使っています。 無制限アップロードできていたのが2021年6月から容量制限がかかるのでGoogleフォト自体どうしようかと思っているところですがw

Evernote

メモツールとして旅行計画などをノート共有して使っていましたが、最近は私が「Notion」に移行したこともあって今後は旅行などの機会があればそちらを使うかもしれません。

Nature Remo

いわゆるスマート赤外線リモコンで家電をスマホから操作できます。 我が家ではリビングのエアコンとテレビ用に使っていて、スマホを持っていればお互いにどこからでも(外からでも)操作できるので重宝しています。

子育てをしていると授乳中や手が離せない場面が多いので、ちょっとエアコンの温度を調整したり、朝目覚めて寝室からリビングのエアコンをつけて部屋を温めておけるのはかなり良いです。

Spotify

共有とはちょっと違いますが...お互い音楽をよく聞くのでストリーミングサービスを家族プランで利用しています。「Family Mix」(家族がよく聴く音楽を組み合わせて作るプレイリスト)は使ってないですが、家族間で共有したい場合はいいかもしれません。

まとめ

導入が簡単なものもあれば、少しハードルの高いツールもあると思うので、自分にあったものを比較検討してみるのがいいかと思います。

夫婦間で共有することの一番のメリットはいちいち確認しなくてもいいということですね。仕事と同じで無駄な口頭確認に時間を割かずに、ツールを活用することによって夫婦の貴重な時間をもっと大事な会話や子どもとの時間に費やせていると思います。

育児用の電動アシスト自転車〜ギュット・クルームR・DXの購入までとレビュー

こんにちは。

現在育休中で11ヶ月になる娘を育てております。

今回は育児関連の記事として最近購入した電動アシスト自転車について書きたいと思います。

購入目的

4月から娘を家から少し離れた保育園に通わせるため、その送り迎えの手段として。

比較検討〜選定

結論から言うと私はギュット・クルームR・DXを購入しました。

ギュット・クルームR・DX
ギュット・クルームR・DX(届いた直後でカゴに書類が入ってますw)

完結な理由は以下です。

  • 長く乗せられる後ろ乗せにしたかったから。
  • パナソニックはアシスト力に定評があり、中でもクルームモデルはcombiとコラボしたチャイルドシートを採用しているから。
  • カゴが小さい物を入れても落ちないのと、外から見えにくい仕様だから。

購入までの経緯はこれからお話しますが、まず電動アシスト自転車についての知識はほぼゼロの状態だったためググりまくりました。特徴やメリット・デメリット、比較記事などたくさんあるのでいくつか読めばだいたいイメージはつかめますが、ざっくりだとこんな感じでしょうか。

3大メーカーの独占市場

電動アシスト自転車パナソニックブリジストンヤマハの3メーカーがほぼ市場を独占しています。 家電量販店の販売員の方の話を参考にさせてもらうと以下のような特徴かなと。

メーカー 特徴
パナソニック アシスト力が強い。
ブリジストン 両輪駆動型なので3人乗せになったときに強い。走行中に自動充電できる。
ヤマハ 前乗せタイプの中ではホールド感があり一番おすすめ。

前乗せと後ろ乗せの違い

こちらも調べればより詳細な情報が出てきますが、ざっくり以下のような感じです。

メリット デメリット
前乗せ 子どもが目の届く位置にいる。 4歳くらいまでしか乗せられない。
後ろ乗せ 6歳くらいまで乗せられる。安定感がある。 子どもの様子がわからない。2歳くらいからでないと安定して乗せられない

ギュット・クルームR・DXを選んだ理由

とりあえず一通りの情報を入れてからヤマダ電機に行きました。ネットや近くの自転車屋さんで購入という手もありますがヤマダ電機のポイントを使って購入したかったので。

乗り始めが1歳ちょっとということもあり最初は「前乗せ」を選ぼうとしていました。そうなると比較記事などでもおすすめの「ヤマハ」一択かなと思っていたのですが、たまたま店舗在庫に好みの色がなく、且つお正月だったためメーカ問い合わせもできない時期で一旦保留としました。

一度冷静にイチから検討し出してみると、半年〜1年フロントチャイルドシートを取り付ければ、長く乗せられる「後ろ乗せ」を買った方がいいのではという気持ちになってきました。カゴもデフォルトでついてますし。

後ろ乗せは2歳から推奨とはありますが、一応1歳〜対象と記載されているので1歳後半くらいになれば乗れるのではと(もちろん体格によると思いますが)。娘は現在9.5kgほどで11ヶ月にしてはなかなかある方ですし(笑)

(↑と思いましたが、やはり安全面を考えて後付けのフロントチャイルドシートを別途買う予定です。)

ビックカメラの店員さんの話がとてもわかりやすく、ここでギュットクルームR•DXに決めることになります。

店員さんも娘を見て一歳半過ぎれば乗れるかもと言っていたので、ここで「後ろ乗せ」に完全に方向転換しました。 あとは上の表の特徴を聞いて、まずヤマハは後ろ乗せは無しかなと。(修理時の部品取り寄せなどに時間がかかることもあるという話もあり…)

そうなるとパナソニックブリヂストンになるのですが、パナソニックのCombiのチャイルドシートとコラボしたギュットクルームモデルはなかなか魅力的だなと。 Combi社のベビーカーに使用されている独自の衝撃吸収素材、「エッグショック」を採用しているので乗り心地もいいのかなという予想です。(乗る側の気持ちはわかりませんがw)

アシスト力も申し分ないということだったのでパナソニックのギュットクルームRが確定的となりました。 あとはラクイックという自動解錠搭載の場合はEX、無しの場合はDXなのですが、二万弱かけてまでじゃないなという判断で無しのDXにする事にしました。

色選び

カラーバリエーションの中からだと第一印象ではマットオリーブかマットキャメルがいいなと思っていたのですが、在庫確認してもらったところ、現在マットオリーブが入荷未定状態ということで断念。キャメルかなと思いましたが、マットキャメルはチャイルドシートが白の仕様で色褪せなど変色する可能性があるかなと重い、こちらも却下。 そうなるとマットネイビーかマットチャコールブラックの2択になったんですが、黒じゃちょっと面白くないかなと思ったのと、旦那さんがマットネイビー推しだったので「マットネイビー」に決定しました。

余談

ちなみに店員さん談ですが、ブリジストンは両輪駆動なので走り出しがスムーズで初心者の方にはおすすめだそうです。アシスト力ではパナソニックに軍配で過去にパナソニックに乗ったことがある人にはあまりおすすめしないということでした。

乗り心地・感想

一度だけ一人で試し乗りしただけなんですが...。 電動アシスト自転車初心者ということもあり、走り出しのアシストのパワーにかなりビックリしました。ひとこぎですごい体持ってかれます!ブリジストンの両輪駆動だと前輪もアシストされるので持ってかれる感が少ないのかなーという予想です。 あと全然漕いでる感じがしない!(←そういうものですよねw)

色はマットオリーブが良かったですが、マットネイビーは落ち着いた色合いでこれはこれですごくかっこいいので良かったです。

最後に

今回私はまったく試乗せずに店員さんの話やネット情報をもとに決めましたが、時間があったり乗り心地をちゃんと確認したい方は近くの自転車屋さんなどで試乗してから買ったほうがいいと思います。

レインカバーやフロントチャイルドシートも購入しないとですが、そちらはまだ比較検討中です。 また進展あれば更新します!