stefafafan の fa は3つです

"すてにゃん" こと id:stefafafan のブログです

Google Apps Script + clasp でSlack bot作った時にわかった小ネタ100連発

最近チーム用にGASとclasp (CLIで操作できるようになるツール) で Slack bot を作りました。今回そのbotの話はしませんが、bot作ってわかった細々としたことを軽くまとめて共有します。

Google Apps Script

毎日分単位で特定の時刻に発火してほしい場合はスクリプトからトリガーをセットすると良い

GASの画面を見ると、トリガーをWeb UIで設定できるようになっています。「時間主導型」だと以下のような設定ができます。

  • 特定の日時 (1回)
  • 分ベース (1分置き、5分置き、10分置き、15分置き、30分置き)
  • 時間ベース (1時間置き、2時間置き、4時間置き、6時間置き、8時間置き、12時間置き)
  • 日付ベース (毎日0時-1時、1時-2時、2時-3時、etc.)
  • 週ベース (毎週月曜 0時-1時、1時-2時、2時-3時、etc.、毎週火曜 0時-1時、1時-2時、2時-3時、etc.)
  • 月ベース (毎月1日 0時-1時、1時-2時、2時-3時、etc.、毎月2日 0時-1時、1時-2時、2時-3時、etc.、)

これらでも一見十分にも思えますが、自分のユースケースでは「毎朝10:15にSlackに投稿」がやりたかったため足りませんでした。一番近いのが「日付ベース」で毎日10-11時ですが、これだと10:01に実行されるかもしれないですし、10:59に実行されるかもしれません。

こういう場合はスクリプトの中からでも newTrigger できるので、1度実行するたびに翌朝10:15のトリガーをセットするというのをやりつづけることによって(つまり特定の日時 (1回)のケースをスクリプト実行のたびにセットしてあげる)、このユースケースに対応できます。

以下のようなコードを発火のたびに実行すると、翌朝10:15に再び doPost 関数を実行してね、という風にできます。

let setTime = new Date();
setTime.setDate(setTime.getDate() + 1);
setTime.setHours(10);
setTime.setMinutes(15);
ScriptApp.newTrigger("doPost").timeBased().at(setTime).create();

developers.google.com

日本の祝日は動かないようにしたい場合は祝日カレンダーを使うと良い

自分のSlack botは平日仕事があるときだけ動いてほしかったので、どうにかできないかと調べたら祝日カレンダーが使えました。

Google Calendar使っている場合、「関心のあるカレンダーを探す」から「日本の祝日」を追加しておきます(他の国のやつでも好きに追加する)。
f:id:stefafafan:20220404220348p:plain
f:id:stefafafan:20220404220401p:plain

追加した「日本の祝日」を選択するとカレンダーIDがゲットできて、 ja.japanese#holiday@group.v.calendar.google.com であることがわかる。
f:id:stefafafan:20220404220411p:plain

あとはGAS中でこのカレンダーを使って判定のコードを書けば完成という感じです。

const today = new Date();
const calendarId = "ja.japanese#holiday@group.v.calendar.google.com";
const calendar = CalendarApp.getCalendarById(calendarId);
const todayEvents = calendar.getEventsForDay(today);

clasp

変更を素朴にデプロイし続けるだけでは足りず、バージョンの切り替えも必要

clasp で手元で書いたコードをGASに反映してデプロイするときは基本的に clasp push してから、 clasp deploy します。pushするだけだとコードが書き変わるだけで、今まさに動いているアプリは変わらないのでdeployも必要なのですが、 clasp deploy とだけ打つと「新しいバージョンはデプロイされているが、古いバージョンが動き続けている」になりがちです。

これわかりづらくて、リポジトリにもissueが立っています。
github.com

結局どうすると良いのかというと、clasp push && clasp deploy -i DEPLOYMENT_ID をデプロイのときに毎回叩いています。 -i オプションはドキュメントにも書いてありますが redeploy したいときに指定するもので、イマイチdeploymentIdとversionの関係性がむずかしいという感じだけどこれで再デプロイするとバージョンは新しく作られる上にそのバージョンにも切り替わってくれています。難しい。ちなみにdeploymentId を知りたい場合は clasp deployments から取得できます。

clasprc.json のcredentialsをGitHubのRepository Secretsに登録しておけば、mainブランチにマージ = デプロイを実現できる

普段の開発で git push、merge、clasp push、clasp deploy とやってると何だかGitHubとGASの二箇所に対して同じことをやっていてだるい気持ちになってきます。

clasprc.jsonあたりにデプロイに必要なcredentialsが入ってるので、それをそのままGitHubのRepository Secretsに登録してしまうと、GitHub Actionsの設定もちょっと書けば、mainブランチにマージ = デプロイにできます。何となくcredentialsをRepository Secretsに入れるの抵抗がある気もしますが、自分の場合Internal Repositoryだしいいかという感じでやっています。

dev.classmethod.jp

Slack

ユーザに対してメンションを送りたい場合はSlackのMember IDが必須

結構前からある話題だと思いますが、Slack botから素朴にWebhookで こんにちは @stefafafan というテキストを送っても @stefafafan はメンションになりません。メンションにしたい場合は こんにちは <@U123> みたいな感じに、そのユーザのSlack Member IDを使ってメンションを送る必要があります。

これは2017年の記事ですが、もうこの時に非推奨になっていますね。
api.slack.com

メンションを送る相手が固定の場合は、Slackアプリのユーザの詳細から Copy member ID みたいなボタンがあるのでそこから取得して使うことができます。
f:id:stefafafan:20220404223310p:plain

Layout blocks を使うと綺麗に文章をフォーマットできる

Slack botによる発言を綺麗にフォーマットしたい場合はLayout blocksを使うのがおすすめです。textフィールドの中で試行錯誤するより綺麗になります。

api.slack.com

以下のBlock Kit Builderを使うとブラウザ上で色々試せるのでかなり便利です。色々試してみましょう
https://app.slack.com/block-kit-builder

f:id:stefafafan:20220404224209p:plain

以上です

いかがでしたか?ちょっとしたことを色々書いてたら意外と分量のある記事になってしまったけど、GAS+claspかなり便利なのでおすすめです。