Google App Scriptで学習記録を自動化してみる
かなり迷走気味なこのブログですが、リモートワークで通勤時間が消滅した分、いろいろな事が試せるのはいいですね。いっそのこと、このままリモートワークがスタンダードになってくれと心から願う今日この頃です。
以前の記事で、オンライン英会話を始めた話を書きましたが、習慣化するために進捗を記録化して、何ならTwitterでつぶやいてしまおうというのを考えていたところ、Google App Scriptを使うのが良さげで、一気に実装してみたというのが、今回のお話です。
↓エンジニアは英語が話せてナンボ。お試しあれw
cambly.com
やりたいこと(やったこと)
今回実装したイメージを図にするとこんな感じです。
Google Sheetsで履歴を溜めるのが目的なのか、Botで呟かせるのが目的なのか微妙なところですね。図ではCamblyとNativeCampが載っていますが、長くなりそうなので今回はCamblyをメインに書き残しておこうと思います。
Camblyでは
上の図では2つのオンライン英会話が載っていますが、まずはCamblyから始めました。Camblyでは、セッションが終わると、こんな感じでSession Summaryというメールが届きます。
これの中に、何分間のセッションだったのかとか、講師は誰だったのかみたいな情報があるので、これらをもとに学習記録を残すことが出来そうです。
履歴だけならWebサイトで見れるんだけどね…
それはともかく、レッスンが終わるたびにTwiterにこれまでの達成度合いをつぶやくBotを作るところまでやりたい。
こんな感じ。
実装方法を考える
最初は、Twitterにつぶやくことをメインに考えて、Bot専用のサービスなども見たのですが、データの加工がどうしても必要だろうというところで、Google大先生に頼ってみたところ、Google App Script(GAS)を使えば、Googleの中で完結したモノが作れそうだということでトライしてみることにしました。
他にもやり方はたくさんあるのですが、メール、記録をつけるスプレッドシートなど、Googleのエコシステムの中に必要なモノがそろっているのが大きかったですね。もちろん、GASからツイートする方法についても、問題なくできそうだということが確認できました。ひとつ気がかりなのは、これまでJavaScriptを触ったことがないので、そこの学習コスト(時間の事ね)も気になったものの、ここは「迷わず行けよ、行けば分かるさ」という感じで、一気に作ってしまうことに。
実装のステップ
結論から言うと、本当に何とかなりました。JavaScriptや正規表現などはTry & Errorの繰り返しとなったものの、これは他の手慣れた言語でも同じです。{}やら行末の;が気持ち悪いなと思っていたのも最初だけで、こんなお作法なのねと慣れてしまえば大した問題にならず、GASからSheetsなどを動かすのも、Microsoft OfficeでExcel VBAを触ったことがあったので、こちらも没問題(メイウェンティ)。いかに順を追って見ていきたいと思います。
GmailからSession Summaryメールを抜き出す
自分のGmailアドレス宛に届いたメールの中から、CamblyのSession Summaryメールを抽出するための条件を考えます。難しく考えないで、Gmailの検索ボックスにいろいろ入れてみて、狙ったメールが検索結果として表示されればOKです。
この画面の例だと、メールの件名に"Session summary"を含んでおり、1日以内に受信した(newer_than:1d)メールという条件で、1件ヒットしている事が分かります。この条件だけだと、同じタイトルのメールが別の会社や組織などから届く可能性もあるので、自分の場合も発信者を条件に追加しています。最終的にコレだ!と決めた検索条件は、コーディングの時に使うのでメモ帳などに貼り付けておきます。
メールの中から保存したい情報を抜き出す
次にメールから欲しい情報を決めます。下は実際に届いたメールですが、黒塗りでわかりにくいですね。
例えば、こんな情報とか。
- 件名から日付(ただし月、日、曜日のみ)
- 本文からセッションの長さ
- 本文から講師の名前
Camblyからのメールは、結構シンプルなので使える情報が限られます。例えば、1日に2回以上セッションを受けた場合、上の情報だけでは完全に判別できない可能性があります。そこで、メールがセッションの直後に送られる前提で(遅延が出たらアウトですが)、メールの受信日時とセッションの長さの情報を組み合わせて、セッションが開始された時間帯を推測してみようだとか、同じメールを2回カウントしないようにGmailの個別のメールに必ず付いてるMail IDを拾っておこう、みたいなアイディアを出しておきます。
情報を貯める場所を用意する
メールから拾った情報を貯めておくためのSpread sheetをGoogle Sheetsの中に用意します。
作りながら、GASにどうやって更新させるかなどをイメージしながら作ります。自分の例だと、最新のレコードが常に先頭に来るようにすること、あとはこれまでの通算回数や合計セッション時間などが分かるようにしたかったので、それらを入れるための項目を用意しています。新しいセッション履歴が、常に8行目にインサートされる感じで、上の方の統計は数式で計算させればいいや、という感じで割り切っています。あと、作成したSpread sheetのURLがコーディングの時に必要になるので、こちらもメモ帳などに残しておきます。
とりあえずコーディングをはじめてみる
まだTwitterと連携するところまで見ていませんが、いきなりコーディングをはじめて見ます。Gmailから情報を抜き出して、Spreadsheetに記録するGASのスクリプトは、ググると結構な数が見つかりますが、私の場合は、主にこちらを参考にさせてもらいました。
自分のように、多少Excel VBAの経験がある人だと、Spreadsheet側の更新よりも、メールからピンポイントで情報を抜くところの方が苦労しました。といっても、Pythonで正規表現はなんとなく触ったことがあったので、こちらのサイトを使いながら、正規表現を少しずついじってコードに反映させて行きました。
1つだけ注意点を挙げるとすると、正規表現にハマりすぎると、何でもかんでも正規表現できれいに一発で抜き出したいという気持ちが頭をもたげると思います。でも、例えばPostive backbehind(?<=x)など、GASの中で対応していないモノもあるので、実際には、結構泥臭くreplace文などを駆使して実装しています。特にメールの中から情報を抜き出す部分は、一般化が難しいので、CamblyならCamblyに特化したメールの内容をparseするfunctionを分けておくと、あとで使い回しが楽になります。
Twitter連携
自分の場合は、GmailからSpreadsheetに更新するところと、Spreadsheetから最新のエントリをTwitterに呟くBotの部分を分けて作りました。理由はいくつかあるのですが、例えば初めて動かすときに、すでに20何回ものSession Summaryのメールがあるわけで、それを追加するたびに呟かれたのでは、いくらBotとは言え感じが悪いですよね。あとは、Twitterに呟くところを分けておけば、トラブってTwitterに投げられなかった場合でも、そこだけ単体で実行すればリカバリできます。
前置きが長くなりましたが、こちらも先人の知恵をお借りする感じで、こちらの2つを主に参考にさせていただきました。
qiita.com
moripro.net
Tweetの文面は、自分で好きなように考えるとして、これまでの実績だとか、セッションの長さなどはSpreadsheetから拾ってくるようにしてあります。あとは自分用のハッシュタグなんかもつけてあげれば、それらしくなりますよね。
自分の場合は、Botのあとに感想をReplyでつけています。あ、Replyの部分はBotではありません。
最後にスケジューリング
一通り、動かしてみて良さげだったら、最後にスクリプトが1時間に1回動くように設定してあげます。
コーディングのところで書きませんでしたが、キモになりやすいところには、Logger.log()を使ってログを吐くようにしておくと、仮にエラーになったときの原因特定が楽になると思います。ログは「実行数」というところで確認できます。