TokyoRのATNDを監視してメールを送るツールを作ってみた
動機
ほぼ毎月開催されている「R勉強会@東京(#TokyoR)」は人気が高く、ATNDに参加募集があがってから2〜3日で定員を超えてしまうこともしばしばです。
twitterのタイムラインをチェックする、ハッシュタグ#TokyoRのツイートをチェックする、ATNDの検索ページをブックマークしておいてちょくちょく検索してみる、などをしていれば問題なく参加登録できますが、根が面倒くさがりなもので、「ATNDをチェックして、最新の開催情報を自分にメールする仕組み」が欲しくなりました。
「欲しいものは作れ」という声が聞こえた気がするので自分で作ってみます。
材料
- Rスクリプト(自作)
- mailgunアカウント(フリー)←自由に踏めるメールサーバーがある人は不要
- herokuアカウント(フリー)
手順
ATNDからの情報取得方法を決める
ぱっと思いついたのはATNDのAPI(http://api.atnd.org) を使うことです。
キーワード「tokyor」を含むイベントのうち最新のものは以下のクエリで取得できます。
http://api.atnd.org/events/?keyword=tokyor&count=1
なお、デフォルトでは結果はxmlで戻ってきます。formatオプションでjsonも指定できます。
http://api.atnd.org/events/?keyword=tokyor&count=1&format=json
Rスクリプト(前半)を書く
まずは手元のMacで動くRスクリプトを書いてみます。
{curl}
と{jsonlite}
を使います。
library(curl)
library(jsonlite)
con <- curl("http://api.atnd.org/events/?keyword=tokyor&count=1&format=json")
df <- fromJSON(readLines(con, warn = FALSE))$events$event
bodymessage <- paste(substr(df$started_at, 1, 10), df$title, df$event_url, sep = " ")
bodymessage
# 2015-10-10 第51回R勉強会@東京(#TokyoR) http://atnd.org/events/70522
xmlでもやってみました。
R Advent Calendar 2014の7日目にdichika氏が投稿された「R Advent Calendar 2014に記事が追加されたらメールが届くようにした(http://d.hatena.ne.jp/dichika/20141207) 」を参考に書いていきます。
html()
はdeprecatedだからread_xml()
使えと言われたりhtml_node()
もxml_node()
もdeprecatedだ{xml2}
を使えと言われたりして苦しみながらなんとか書き上げました。xmlから中身を取り出すのは初めてなので、もっとスマートなやり方があるのかもしれません。
#devtools::install_github("hadley/rvest")
library(rvest)
result <- read_xml("http://api.atnd.org/events/?keyword=tokyor&count=1") %>%
xml_children() %>%
xml_children() %>%
xml_children() %>%
xml_text()
bodymessage <- paste(substr(result[6], 1, 10), result[2], result[5], sep = " ")
今回私は{curl}
と{jsonlite}
を使う方でいきます。
Rスクリプト(後半)を書く
後半のスクリプトはほぼ先ほどのdichika氏の記事から丸ぱくりです。
ただ、私の環境ではgmailをsmtpサーバーとして使おうとすると認証がうまくいきませんでした。
そこで、send.mail()
のヘルプに出ている、認証を使わない方法
send.mail(from = "foo@gmail.com",
to = "foo+test@gmail.com",
subject = "最新TokyoR開催情報",
body = message,
smtp = list(host.name = "aspmx.l.google.com", port = 25),
authenticate = FALSE,
send = FALSE)
にしてみたところ、うまくはいきますが、gmailから「送信元偽装してるな。お前フィッシングだろ」と目をつけられます。このスクリプトを繰り返し実行していると、googleから迷惑メール送信アカウントとしてマークされてしまうかもしれません。
それはいやなので、アプリからのメール送信に使えるサービスを探したところ、mailgun (https://mailgun.com) というサービスがありました。フリーのアカウントで月間1万通まで無料でメールを送信できます。APIでの利用が推奨されていますが、smtpでの送信も可能です。登録も簡単です。mailgunやgmailに頼らなくても自由に使えるメールサーバーを持っているかたはどうぞそちらをお使いください。
#install.packages(mailR)
library(mailR) # Java6SE runtimeが無いと突然落ちるので注意
send.mail(from = "postmaster@sandboxxxxx.mailgun.org",
to = "my@address.com",
subject = "最新TokyoR開催情報",
body = bodymessage,
encoding = "utf-8",
html = FALSE,
smtp = list(host.name = "smtp.mailgun.org",
port = 465,
user.name = "postmaster@sandboxxxxx.mailgun.org",
passwd = "xxxxxx",
ssl = TRUE),
authenticate = TRUE,
send = TRUE,
debug = FALSE) # うまく動かないときはここをTRUEにする
dichika氏のソースにはlibrary(mailR)
のコメントに「Java runtimeが無いと突然落ちるので注意」と書いてありました。私のMacにはJava8のruntimeが入っているので大丈夫だろうと思ってスクリプトを実行したら、いきなり落ちました。Java6SEが必要だそうです。ちょっとだけコメントを修正しました。
Macの場合はここ(https://support.apple.com/kb/DL1572) からDLします。
herokuアプリとして登録する
heroku (https://www.heroku.com) は手軽に使えるPaaSのひとつです。rubyやpythonでの利用が普通ですが、サードパーティのbuildpackageを使うことでRでも使えます。
herokuでRを動かすためのbuildpackageはこちら(https://github.com/virtualstaticvoid/heroku-buildpack-r) です。readmeも丁寧ですしサンプルプログラムも豊富なので、使い方の説明は割愛します。
私がはまったのは1つだけ。パッケージをインストールするためのinit.rをinit.Rとしていて、それが原因でgit push heroku master
がうまくいかなかったのですが、ログからはそれが読み取れなくて悩みました。
init.r : パッケージインストール部分
install.packages("curl", repos = "http://cran.rstudio.com")
install.packages("jsonlite", repos = "http://cran.rstudio.com")
install.packages("mailR", repos = "http://cran.rstudio.com")
whenTokyoR.R:メイン
Sys.setlocale("LC_ALL", "ja_JP.UTF-8") # これを入れないと漢字が消える
library(curl)
library(jsonlite)
con <- curl("http://api.atnd.org/events/?keyword=tokyor&count=1&format=json")
df <- fromJSON(readLines(con, warn = FALSE))$events$event
bodymessage <- paste(substr(df$started_at, 1, 10), df$title, df$event_url, sep = " ")
library("mailR") # Java6SE runtimeが無いと突然落ちるので注意
send.mail(from = "postmaster@sandboxxxxxxx.mailgun.org",
to = "my@address.com",
subject = "latest TokyoR event",
body = bodymessage,
encoding = "utf-8",
html = FALSE,
smtp = list(host.name = "smtp.mailgun.org",
port = 465,
user.name = "postmaster@sandboxxxxxxx.mailgun.org",
passwd = "xxxxxxxxxxx",
ssl = TRUE),
authenticate = TRUE,
send = TRUE,
debug = FALSE) # うまく動かないときはここをTRUEにする
スクリプトを入れたフォルダーで以下を実行します。
$ git init
$ git add .
$ git commit -m 'init'
$ heroku create --stack cedar-14 --buildpack https://github.com/virtualstaticvoid/heroku-buildpack-r.git#cedar-14
$ git push heroku master
deployの際にinit.rで指定したパッケージがインストールされます。5分位待って、deployが完了したら、以下のコマンドでスクリプトを実行してみます。
$ heroku run R -f ./whenTokyoR.R --gui-none --no-save
指定したアドレス(上のサンプルではmy@address.com)あてにメールが届いたら成功です。
定期的にスクリプトを実行する
ここまででは、まだスクリプトは手動で実行する必要があり、うれしくありません。手動でスクリプトを流すんなら、ブラウザでブックマークを開いたほうが楽チンです。
幸い、herokuには定期的に処理を流すオプション(add-on)があります。
アプリの管理画面上でResourcesタブを選択し、Add-ons欄で Heroku Scheduler を追加します。
Heroku Schedulerの設定画面で R -f ./whenTokyoR.R --gui-none --no-save
をセットし、FrequencyをDaily
,Hourly
,Every 10 minutes
から選択して保存したら完了です。指定した間隔で処理が流れ、メールが飛んできます。
今後の課題
更新がないのに延々と同じ内容のメールが来るのもうざいので、前回の結果を覚えておき、更新があったときだけメールを飛ばすようにしたいです。
今日はここまで。
Enjoy!!