GoogleAppsScriptでRSS2.0フィードを作成・出力する

以前、GoogleAppsScript (以降、GAS) にてXMLを扱ったことがありました*1


そんな中、先日GASのリリースノートが更新され、今までのXMLがDeprecatedとなり、今後はXML Serviceというものを使うことになりました。また、公式Blogにも記事がアップされています。


そこで新しいXML Serviceを使って何か作ろうと考えたところ、RSSフィードXMLの一つということを思い出し、GASでRSSフィードを作成・出力してみることにしました。
なお、XML Serviceの基本的な使い方については公式ブログに記載があったため、そちらを参考に作りました。



■悩んだところなど

出力フィードのタイプ

以下のサイトを見たところ、4つのXMLが書かれていました。


どのフィードを使おうかと考えましたが、

ということで、RSS2.0のフィードを使うことにしました。



pubDateをRFC2822形式で設定する方法

GASのUtilitiesクラスにformatDate()メソッドがあり、扱いやすそうだったため、それを利用しました。

デフォルトパラメータの設定

pubDateのタイムゾーンについて、基本的には「JST」でいいけれど他のタイムゾーンも使えるようにしようと考えました。
JavaScriptのデフォルトパラメータについて調べたところ、ES6から実装されるとのことでした。


では、GASはどのJavaScriptをベースにしているのかを調べたところ、JavaScript1.8ということで残念ながら使えないようでした。


そのため、以下を参考にデフォルトパラメータを設定しました。

if (typeof timezone === 'undefined') timezone = "JST" ;
エラーチェックについて

簡単に作ったためエラーチェックについては、ほとんどしていません。
以下を参考にして、pubDateがDate型かどうかをチェックしているくらいです。

if (!(pubDate instanceof Date)) throw 'pubDateは日付型';
ファイルの分離について

WebからのGETにレスポンスを返す「example.gs」と、RSS2.0フィードを作成するライブラリの「rss20feed.gs」に分けました。
「rss20feed.gs」はいわゆるモジュールパターンで作りましたが、JavaScriptのライブラリはどんな感じで作るのが一番良いのかは、まだよくわかっていません...

Webサービスとして公開する方法

久しぶりなので忘れていましたが、過去の自分のメモが役に立ちました。バージョン管理して、Webサービスとして公開する、と。

■ソース

以下のとおりですが、一応feedlyにも取り込めましたので、問題ないかと思います。
JavaScriptに慣れていないので、書き方などで問題があれば、ご指摘ください。


example.gs

function doGet() {
  var rss = makeRss();
  
  rss.addTitle('RSS 2.0 test');
  rss.addLink('http://example.com');
  rss.addDescription('RSS 2.0のテスト');
  rss.addLanguage('ja');
  
  for (var i = 1; i < 3; i++){
    rss.addItem('ページ:' + i,
                'http://example.com/' + i,
                i + 'つ目のページ',
                new Date()
               )
  }
  
  return ContentService.createTextOutput(rss.toString())
         .setMimeType(ContentService.MimeType.RSS);
}


rss20feed.gs

var makeRss = function(){
  var channel = XmlService.createElement('channel');
  var root = XmlService.createElement('rss')
                       .setAttribute('version', "2.0")
                       .addContent(channel);
  
  var createElement = function(element, text){
    return XmlService.createElement(element).setText(text);
  };

  
  return {
    addTitle: function(title){
      channel.addContent(createElement('title', title));
    },
    
    addLink: function(link){
      channel.addContent(createElement('link', link));
    },
    
    addDescription: function(description){
      channel.addContent(createElement('description', description));
    },
    
    addLanguage: function(language){
      channel.addContent(createElement('language', language));
    },
    
    addItem: function(title, link, description, pubDate, timezone){
      if (typeof timezone === 'undefined') timezone = "JST" ;
      if (!(pubDate instanceof Date)) throw 'pubDateは日付型';
      
      var item = XmlService.createElement('item');
      
      item.addContent(createElement('title', title));
      item.addContent(createElement('link', link));
      item.addContent(createElement('description', description));
      
      var dateRfc2822 = Utilities.formatDate(pubDate, timezone, "EEE, dd MMM yyyy HH:mm:ss Z");
      item.addContent(createElement('pubDate', dateRfc2822));
      
      channel.addContent(item);
    },
    
    toString: function(){
      var document = XmlService.createDocument(root);
      var xml = XmlService.getPrettyFormat().format(document);
      
      return xml;
    }
  };
};


また、gistにも上げました(使う時は、.jsを.gsに変えます)。

*1:現在エラーで正しく動作していませんが、そのうち直さないと...