多分現在主流のRSSリーダーであるFeedlyが少し前にようやくAPIを公開してくれたので、オレオレリーダーを作る為の下調べをしてみた。最初戸惑ったが色々API叩いてるうちに大体わかってきたのでメモる。
APIドキュメント: http://developer.feedly.com/v3/
#IDの種類と形式
- userId -
user/:userId
- feedId -
feed/:feedUri
- categoryId -
:userId/category/:categoryName
- 特殊カテゴリ:
global.all
,global.uncategorized
- 特殊カテゴリ:
- tagId -
:userId/tag/:tagName
- 特殊タグ:
global.saved
- 特殊タグ:
#認証手順
- 普通のOAuth2.0だが現在は
redirect_uri
が制限されているためサイト間認証は使えない。 -
http://localhost
やurn:ietf:wg:oauth:2.0:oob
は許可されてるのでローカルアプリで使う分にはとりあえず問題ない。 - OAuthのプロセス中に出てくるclient_idだのclient_secretだのは全部Sandbox用の固定値を使えばとりあえず自分のアクセストークンを取る分には問題ない。
やってみる
-
https://cloud.feedly.com/v3/auth/auth?client_id=feedly&redirect_uri=http://localhost&scope=https://cloud.feedly.com/subscriptions&response_type=code&provider=google&migrate=false
をブラウザで開く。(パラメータは全部固定でOK) -
認証後
http://localhost/?code=XXX&state=
に飛ばされるのでアドレスバーからXXX
の部分をコピーする。 -
https://cloud.feedly.com/v3/auth/token へ
client_id=feedly&client_secret=0XP4XQ07VVMDWBKUHTJM4WUQ&grant_type=authorization_code&redirect_uri=http%3A%2F%2Fwww.feedly.com%2Ffeedly.html&code=XXX
の最後のXXX部分を先ほど取得したcodeの値で置き換えたものをPOSTする。こんな感じ>$ curl -s -d 'client_id=feedly&client_secret=0XP4XQ07VVMDWBKUHTJM4WUQ&grant_type=authorization_code&redirect_uri=http%3A%2F%2Fwww.feedly.com%2Ffeedly.html&code=XXX' https://cloud.feedly.com/v3/auth/token
-
おなじみのaccess_tokenとrefresh_tokenがとれるので以降のAPIリクエストにはここで取得した
access_foken
の値をヘッダに付けて行うようにする。 -
使用例はこんな感じ>
$ curl -s -H 'Authorization: Bearer ACCESS_TOKEN' https://cloud.feedly.com/v3/profile
(ACCESS_TOKENには3で取得したaccess_tokenの値で置き換え)
#Profile
- ユーザプロファイルを取得する
{
"fullName": "Yoshiaki Kawazu",
"locale": "ja",
"picture": "https://lh3.googleusercontent.com/-ECJgMVZ8twg/AAAAAAAAAAI/AAAAAAAAAVM/vdZM4-BFTMs/photo.jpg",
"gender": "male",
"email": "kawazzz@gmail.com",
"google": "107778016735353586604",
"givenName": "Yoshiaki",
"familyName": "Kawazu",
"client": "feedly",
"id": "43d020e7-87a7-4e7f-a8e9-cacb54acd1b5",
"wave": "2013.11",
"windowsLiveConnected": false,
"wordPressConnected": false,
"facebookConnected": false,
"reader": "01581900768824391990",
"evernoteConnected": false,
"pocketConnected": false,
"twitterConnected": false
}
#Markers
##markers/counts
- フィードの未読数が取得できる
- 登録してるfeedが全て取得できるっぽい
- フィードカテゴリやALLなどの特殊なidのやつも返ってくる
{
"unreadcounts": [
{
"updated": 1394598427423,
"count": 18,
"id": "feed/http://feedproxy.google.com/hatena/b/hotentry"
},
{
"updated": 1394137265230,
"count": 0,
"id": "feed/http://aws.amazon.com/rss/whats-new.rss"
},
{
"updated": 1394599287257,
"count": 24,
"id": "user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/global.all"
},
{
"updated": 1394599287257,
"count": 0,
"id": "user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/知り合い"
},
{
"updated": 1394582230100,
"count": 0,
"id": "user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/エロ"
},
{
"updated": 1394599287257,
"count": 24,
"id": "user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/global.uncategorized"
}
]
}
Stream
streams/ids
- ストリームIDにぶら下がったエントリのID一覧を取得する。
- 取得済みエントリIDはキャッシュしておき新着チェックに使うのが目的のAPIと思われ。
- コンテンツまで一発で取得したい場合は
streams/contents
を使えば良い。 - エントリIDからコンテンツを取得するには
entries/:entryId
もしくはentries/.mget
を使う。 - streamIdに指定できるのは
categoryId
feedId
tagId
のどれか。 -
streams/:streamId/ids
というURLも使えるとドキュメントにあったがクエリで渡しても良い。-
:streamId
の部分に埋める場合は必ず、ID中の/
も含めてURLエンコードしておく必要がある。
-
https://cloud.feedly.com/v3/streams/ids?streamId=user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/global.all&count=5
または
https://cloud.feedly.com/v3/streams/user%2F43d020e7-87a7-4e7f-a8e9-cacb54acd1b5%2Fcategory%2Fglobal.all/ids?count=5
{
"ids": [
"vd6/vZ0gPFJR0iUi25Q38MITxKq1RRhf/pxYrAJpSMQ=_144b479e861:7f050e:5f76ba1",
"RkLxQmvOp/nc7DIgnc7qmGmho0aOcNwtk5qewRZKloo=_144b47765db:78700b:57158c7e",
"SzCknK5yCfKi0NrRCLzY3clkPWypMPSgdsVAzzPiIEk=_144b472c945:1f479:3a1395db",
"gHDibUzBXqLZr4i7DfbTJIWTMbq4x72ysmvnyHLsh54=_144b46fc344:768b12:57158c7e",
"gHDibUzBXqLZr4i7DfbTJIWTMbq4x72ysmvnyHLsh54=_144b46fc344:768b11:57158c7e"
],
"continuation": "144b46fc344:768b11:57158c7e"
}
streams/contents
- ストリームIDにぶら下がったエントリのコンテンツ一覧を取得する。
- streamIdに指定できるのは
categoryId
feedId
tagId
のどれか。 -
streams/:streamId/contents
というURLも使えるとドキュメントにあったがクエリで渡しても良い。-
:streamId
の部分に埋める場合は必ず、ID中の/
も含めてURLエンコードしておく必要がある。
-
https://cloud.feedly.com/v3/streams/contents?streamId=user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/global.all&count=2
または
https://cloud.feedly.com/v3/streams/user%2F43d020e7-87a7-4e7f-a8e9-cacb54acd1b5%2Fcategory%2Fglobal.all/contents?count=2
{
"items": [
{
"engagementRate": 0.36,
"engagement": 5,
"crawled": 1394598626006,
"author": "jniino",
"summary": {
"direction": "ltr",
"content": "光ネットワークや無線ネットワーク、パケット通信など種類の異なる複数のネットワーク..."
},
"content": {
"direction": "ltr",
"content": "光ネットワークや無線ネットワーク、パケット通信など種類の異なる複数のネットワークの情報を統一的に定義し、上位レイヤから簡単に扱えるようにしたSoftware-Defined Networkingの技術を、NTT、NTTコム、富士通、日立、NECが共同で発表しました。 これにより通信事業者などが広域にわたる複数のネットワークを柔軟に組み合わせて仮想ネットワークを構築しつつ、全体の状況を把握したり、各レイヤのネットワーク装置を連係させることで、要求に応じたネットワークの設計、構築……"
},
"id": "/4r8BU2nbsgJrgfRKK3amXnaOxpprjCJvWjoCKjAPwY=_144b48e42d6:852591:5f76ba1",
"originId": "tag:www.publickey1.jp,2014://2.2804",
"keywords": [
"blog",
"Software-Defined Network",
"ネットワーク"
],
"fingerprint": "9703a9db",
"alternate": [
{
"type": "text/html",
"href": "http://www.publickey1.jp/blog/14/software-defined_networkingnttnttnec.html"
}
],
"title": "Software-Defined Networkingで広域ネットワークを総合的に扱う基本技術を確立。NTT、NTTコム、富士通、日立、NECが共同で発表",
"updated": 1394597056000,
"published": 1394596984000,
"origin": {
"streamId": "feed/http://www.publickey1.jp/atom.xml",
"title": "Publickey",
"htmlUrl": "http://www.publickey1.jp/"
},
"sid": "+d0QLpjFyPQ0+bv2Zs0tZe8M5+yaZXD0xyM5xDZrw6I=",
"visual": {
"url": "none"
},
"unread": true
},
{
"unread": true,
"visual": {
"url": "none"
},
"origin": {
"streamId": "feed/http://kernel.org/kdist/rss.xml",
"title": "Latest Linux Kernel Versions",
"htmlUrl": "http://www.kernel.org"
},
"fingerprint": "1870aafa",
"originId": "kernel.org,linux-next,next-20140311,2014-03-12",
"id": "3n4rP10OBRjEEdn8ddzpt3a6rmsfO/6fqgXkJR2bJ5s=_144b48dda3b:850d01:5f76ba1",
"summary": {
"direction": "ltr",
"content": "<table>\n<tr><th align=\"right\">Version:</th><td><strong>next-20140311</strong> (linux-next)</td></tr>\n<tr><th align=\"right\">Released:</th><td>2014-03-12</td></tr>\n</table>"
},
"crawled": 1394598599227,
"alternate": [
{
"type": "text/html",
"href": "http://www.kernel.org/"
}
],
"title": "next-20140311: linux-next",
"published": 1394595471000
},
],
"continuation": "144b48b3b1f:8441c8:5f76ba1",
"updated": 1394598626006,
"id": "user/43d020e7-87a7-4e7f-a8e9-cacb54acd1b5/category/global.all"
}
まとめ
↑とりあえずこれだけ例を上げとけば普通のRSSリーダは作れそうだな。
最初ALLの内容をどうやって取るのかが分からんくて非常に悩んだ。global.allカテゴリのコンテンツをEntryかStreamから取れば良いまで分かれば後はどうとでもなる。
あとは既読マークとかは Markers に適当にPOSTしとけば良い。