2013年4月3日水曜日

RSS Mailer by Google Apps Script

とあるサイトのRSSをメールで通知する仕組みが欲しくて、Google Apps ScriptでRSSメーラーを作りました。

結構新しい記事がリリースされても気づいていない方が多いので、メール通知してみようかと。
デジタル世代ではない方々にRSSリーダーは習慣付きにくそうですし、一つのサイトしか購読しないのだったら、RSSリーダー開くより直接そのサイトを見るほうがいい。
でも、毎日サイト開くのも手間だし、使い慣れてる携帯にメール通知してあげたほうがよっぽど現実的、というわけです。

以前はRSSを取得してメールで通知する無料サービスが結構あったように思いますが、最近は見かけません。
収益化がうまくいかなかったんでしょう。
Hyper-Vの上でUbuntu Server動かして、Rubyでやろうかな、と思っていたところ、Google Apps Scriptで実現できそうな情報を見つけました。

やってみたところ非常に簡単、かつ高機能でビックリ。
動作もなかなか早いように思います。
サーバの構築、運用が不要で、定期的にジョブを実行できる。素晴らしい。
Herokuだとローカルにテスト環境を構築したりするのが面倒ですが、これならブラウザからオンラインですべて済ませられる。
これからはcron的な仕組みを作りたい時は、まずGoogle Apps Scriptを検討しようと思った次第です。
(勝手な印象ですが、Webサービスを作るのには向いてないようです)

3ヶ月ほど運用して問題なく動作しているので、プログラムを公開してみようと思います。
今回書いたプログラムは下記のような感じです。
 
var FEED_URL = 'http://www.jw.org/ja/%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9/rss/LatestNewsList/feed.xml';
var SENDER = '[email protected]';
var RECIPIENTS = [
  '[email protected]',
  '[email protected]'
];
var TITLE_PREFIX = '[jw.org]';
var PROPKEY_LAST_FETCHED = 'Last fetched';



function main(){
  // Fetch
  var rssText = UrlFetchApp.fetch(FEED_URL).getContentText();
  
  // Parse
  var rss = Xml.parse(rssText);
  var items = rss.getElement().getElement("channel").getElements("item");
  
  // Check property
  var lastFetched = ScriptProperties.getProperty(PROPKEY_LAST_FETCHED);
  if(lastFetched != null){
    
    // Check new item
    var news = [];
    for each(var item in items){
      if(lastFetched.indexOf(item.getElement("guid").getText()) < 0){
        news.push(item);
      }
    }
    
    // Send mail
    for each(var item in news){
      var title = item.getElement("title").getText();
      var subject = (TITLE_PREFIX + title).substr(0, 70);
      var body = title + '\n' + item.getElement("link").getText();
      MailApp.sendEmail(SENDER, subject, body, {bcc: RECIPIENTS.join(', ')});
    }
  }
  
  // Record
  var guids = [];
  for each(var item in items){
    guids.push(item.getElement("guid").getText());
  }
  ScriptProperties.setProperty(PROPKEY_LAST_FETCHED, guids.join(','));
}



function testDeleteProperty(){
  ScriptProperties.deleteProperty(PROPKEY_LAST_FETCHED);
}



function testShiftLastFetched(){
  var lastFetched = ScriptProperties.getProperty(PROPKEY_LAST_FETCHED);
  lastFetched = lastFetched.split(',').slice(1).join(',');
  ScriptProperties.setProperty(PROPKEY_LAST_FETCHED, lastFetched);
}
簡単なアルゴリズムにしているので、下記の弱点があります。

  • 過去の記事が再度RSSに出てきたりしても、気づかず配信する(あまり無いとは思いますが)
  • subjectをUTF-8を意識せずにsubstrでぶった切っているので、タイトルが長い時にsubjectの最後が文字化けしそう

それにしてもこんな短くて手軽なスクリプトでRSS Mailerが実現できるなんて感動ものです。

実際の導入方法としては、

  1. Googleドライブに新規スクリプトを作成
  2. 上記コードを記入
  3. 冒頭の定数部分を適宜変更
  4. 毎日1回走るトリガーを設定

という感じです。

なんとお手軽なんでしょう。
これがパラダイム・シフトってやつでしょうか。
これを活用しない手はありません。
お勧めです!


Google Readerが終了する、ということで、このスクリプトで自分宛にRSSをメールで送れば、簡易なRSSリーダーにもなりますね。


下記の方々の情報を参考にさせて頂きました。感謝です!

cles::blog - Google Apps Scriptで超簡易版RSSリーダーを書いてみた

bmoo.net - 逆引きGoogle Apps Scriptリファレンス