TitaniumMobile勉強記

Web系エンジニア向けのキャリアアドバイザーやってましたが現在はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連(Node.js、Titanium)あたり

node.jsからGoogleReaderにアクセス出来ないか試してみた

GoogleReaderのAPIは公開されているわけではないのですが以前にも何度かお世話になったGoogle Reader APIの叩き方のエントリを読みながら、node.jsからGoogleReaderにアクセス出来ないか試行錯誤しています。

GoogleReaderAPIは以前よりも簡易になった?

非公式GoogleReaderAPIドキュメントの下の方のコメントに

Fixed the auth header function, had to use the auth key and not the previously used SID, also had to add the service key into the request:

ということで、以前だったらhttp ヘッダーにSIDとかトークンというものをセットしていました。

以前試したことのあるRubyのgooglebaseというgemのソースを見る限りたしかにSIDセットしているようですがためしにcurl使って

curl -k https://www.google.com/accounts/ClientLogin -d Email=xxxx@gmail.com -d Passwd=xxxxx -d service=reader

とやると

SID=XXXX(長いので省略)
LSID=XXXX(長いので省略)
Auth=XXXX(長いので省略)

みたいなレスポンスが得られるので、このAuth=の所の文字列をhttpヘッダーに

Authorization:GoogleLogin auth=XXXX(長いので省略)

セットすればOKのようです。

自分が理解したのを絵にするとこんな感じですかね
googlereader

http client的なものの準備

自分で全部作るほどのレベルではないので、GData にだってアクセスできるんだぜが参考になりそうなので、こちらをお手本にすることにしました。

とりあえず動くものは出来たので、近いうちにソース晒します

ソースはこんな感じ

/**
 * Google Account Login Client
 */

var Client = function(params){
  this.HOST = "www.google.com";
  this.http = require('http');
  this.querystring = require('querystring');
  this._httpsClient = this.http.createClient(443, this.HOST, true);
  this._httpClient = this.http.createClient(80, this.HOST, false);

};

Client.prototype= {
  login : function(email, password, service){
   if( service == undefined ){
      throw 'service parameter must be specified.';
   }
   var EventEmitter = require("events").EventEmitter;
   var event = new EventEmitter();
   var self = this;
   var params = {
      'accountType': 'HOSTED_OR_GOOGLE',
      'Email' : email,
      'Passwd' : password,
      'service' : service
   };
   var body = this.querystring.stringify(params);
   var req = this._httpsClient.request(
      'POST', '/accounts/ClientLogin',
      {
         'Content-Type': "application/x-www-form-urlencoded"
      }
   );
   req.write(body);
   req.on('response', function(res){
      var body = '';
      res.on('data', function(chunk){
         body += chunk;
      });

      res.on('end', function(){
         var obj = {};
         var lines = body.split('\n');
         for(var i in lines){
            var l  = lines[i];
            var kv = l.split('=');
            if( kv.length == 2 ){
               obj[kv[0]] = kv[1];
            }
         }
         if( res.statusCode == 200 ){
            event.emit('success');
	    //get Auth value
	    self.getFeed(self.setHeaders(self.extractAuth(body)));
         }else{
            self._authToken = undefined;
            event.emit('failure');
         }
      });
   });
   req.end();
   return event;
  },//login

  extractAuth:function(body){
    var matches = body.match(/Auth=(.*)/);
    var _result = matches[0].split('Auth=');
    return _result[1];
  },
  setHeaders:function(auth){
    var param ={};
    var _values = "GoogleLogin auth=" + auth;
    param["Authorization"]= _values;

    return param;
  },
  getFeed:function(param){
    console.log('start');
    console.log(param);
    var req = this._httpClient.request(
      'GET', '/reader/api/0/unread-count?all=true',param
    );

    req.end();

    req.on('response', function (response) {
      console.log('wait response');
      console.log('STATUS: ' + response.statusCode);

      console.log('HEADERS: ' + JSON.stringify(response.headers));

      response.setEncoding('utf8');
      response.on('data', function (chunk) {
	console.log('BODY: ' + chunk);
      });
    });
  }
};

var Google = new Client();
Google.login('yourgmailaddress,'password','reader');