【ライフログ】Kindleの購入履歴を管理する
私は、ライフログをGoogleカレンダーに集めるようにしている。そこにKindleで買った本も登録している。
なぜGoogleカレンダーに?
カレンダー形式で、いつなのかわかりやすいし、検索もできるから。
以前はEvernoteに1日1ページでライフログノートを作っていたが、Kindleというキーワードで検索したときに、それが含まれるノートは表示されるものの、ノートの中身までは、表示されない。だから、Kindleで買った本を一覧で表示したいなどのニーズには応えられなかった。そういった経緯もあり、今はGoogleカレンダーにライフログとして残している。
どうやって実現しているか
Kindleにライフログとして残していく上で、私がすることは、Kindleで本を買うことだけだ。すると、自動的にライフログカレンダーに登録してくれる。図でも示しているが、流れとしては
- アマゾンから、購入確認のメールが届く
- 毎日1回、Google Apps Script(以下GASと表現)で、購入メールを探す
- 購入メールが昨日のメールだったら、カレンダーに登録する
となっている。
GAS
まずは全貌
これらを実現しているコードは、以下に示す。
function kindle() { var query = 'newer_than:3d from:digital-no-reply@amazon.co.jp ご購入ありがとうございます。 Kindle'; var threads = GmailApp.search(query,0,50); var messages = GmailApp.getMessagesForThreads(threads); for(var i=messages.length-1; i>=0 ; i--) { for(var j=messages[i].length-1;j>=0; j--) { if(yesterday_decision(messages[i][j].getDate())){ var body = messages[i][j].getBody(); body = body.replace(/\r?\n/g,""); var title = body.match(/title=".*?"/g)[1]; if(title !== undefined) title = title.match(/title="(.*?)"/)[1]; makeCalender(messages[i][j].getDate(),title+"を購入","購入メール\n"+threads[i].getPermalink()+"\n\n買った本\nhttps://www.amazon.co.jp/hz/mycd/myx#/home/content/booksAll/dateDsc/",10); } } } } function yesterday_decision(date1) { var year1 = date1.getFullYear(); var month1 = date1.getMonth() + 1; var day1 = date1.getDate(); var date2 = new Date(); date2.setDate(date2.getDate()-1); var year2 = date2.getFullYear(); var month2= date2.getMonth() + 1; var day2 = date2.getDate(); if (year1 == year2){ if (month1 == month2){ return day1 == day2; } } return false; } function makeCalender(date_str,title,text,color){ if(date_str==="yesterday"){ var date2 = new Date(); date2.setDate(date2.getDate()-1); date_str=date2; } var calender = CalendarApp.getCalendarById('abcde@group.calendar.google.com'); var event = calender.createAllDayEvent(title,new Date(date_str),{description: text}); event.setColor(color); event.removeAllReminders(); }
それぞれの関数ごとに解説していく。
function kindle
これが、1日1回、自動的に実行される関数だ。
//ここで、まず、検索する条件を設定する。 var query = 'newer_than:3d lfrom:digital-no-reply@amazon.co.jp ご購入ありがとうございます。 Kindle'; //該当するスレッドを取得する var threads = GmailApp.search(query,0,50); //スレッドからメールを取得する var messages = GmailApp.getMessagesForThreads(threads);
検索の条件は、"3日以内に、[digital-no-reply@amazon.co.jp]から届いた、「ご購入ありがとうございます。」と「Kindle」というキーワードを含むメール"である。ここの条件は、Gmailの検索と同等のことができるので、調べながら適当に設定してほしい。条件として、3日以内じゃなくて、昨日で検索もできるのだが、そうすると、一部検索から漏れてしまうメールがあったため、過去3日分取得して、そこから昨日かどうか判定するようにした。
スレッドを取得するには、GmailApp.search(query,start,max)
を使う。これは、第1引数に検索の条件、第2引数で、何件目から取得するかを、第3引数で、何件取得するかを指定する。ここでは50件としている。まあ、50件もあれば、昨日のアマゾンからのメールはすべて取得できるでしょ、という適当な考えに基づく。
スレッドとメール
スレッドは、複数のメールの集まり。受信したメールに返信したりすると、それらのメールは、一つのスレッドとして、認識される。
次に、それぞれのメールに対する処理をみていく。
for(var i=messages.length-1; i>=0 ; i--) { for(var j=messages[i].length-1;j>=0; j--) { if(yesterday_decision(messages[i][j].getDate())){ var body = messages[i][j].getBody(); body = body.replace(/\r?\n/g,""); var title = body.match(/title=".*?"/g)[1]; if(title !== undefined) title = title.match(/title="(.*?)"/)[1]; makeCalender(messages[i][j].getDate(),title+"を購入","購入メール\n"+threads[i].getPermalink()+"\n\n買った本\nhttps://www.amazon.co.jp/hz/mycd/myx#/home/content/booksAll/dateDsc/",10); } } }
messagesは二次元配列になっていて、messages[スレッドのindex][メールのindex]
となっている。forでスレッドを逆から回し、その中でforでメールを逆から回している。
なんで逆に回しているかというと、最新のメールがmessagesの最初にきているから。過去のメールから順番にカレンダーに登録したかったため。
messages[i][j].getDate()
で、そのメールを受信した時間を取得できる。そこから、昨日受信したメールかを調べている。yesterday_decision(何らかの日付データ)
という関数を呼び出すと、日付が昨日だったらTrue、違ったらFalseが帰ってくる。
日付が昨日かどうか判定するには、以下のページを参照してみてほしい。
seisyo58.hatenablog.com
getBody
でメールの本文が取得できるので、そこから本のタイトルを取得している。
makeCalender
関数で、カレンダーに登録している。
function makeCalender
function makeCalender(date_str,title,text,color){ //登録するカレンダーをIDで指定 var calender = CalendarApp.getCalendarById('abcde@group.calendar.google.com'); //新しいイベントを登録 var event = calender.createAllDayEvent(title,new Date(date_str),{description: text}); //イベントの色を指定 event.setColor(color); //イベントの通知をすべて消す event.removeAllReminders(); }
解説はコメントを見てほしい。
イベントの色は、このページを参考にしてほしい。
Enum EventColor | Apps Script | Google Developers
ライフログカレンダーには、過去のデータしかないので、通知は必要ないし、表示がごちゃごちゃになると思ったので、削除している。
毎日実行させるために登録
トリガーをこのように設定することで、毎日実行される。毎日実行され、昨日買った本が、カレンダーに登録される。
まとめ
自動的にライフログが蓄積されていくため、3日坊主などにならない。自動化って素晴らしい。