(修正) Sinatra で Google Reader の共有アイテムをつぶやくアプリを作ってみた
※ 前回の記事 の続きです
アプリを使っていて時々、
"共有アイテムを追加したタイミングで、過去に追加したものがつぶやかれてしまう"
という事が起きていました。
しばらくの間、publish されてくる xml をファイルにはきだし様子を見てみたところ、以下のような事がわかりました。
- 追加したアイテムに加え、過去に追加したアイテムも含んだ xml が publish される。
- アイテムの順番は、追加した時刻でソートされておらず、バラバラに並んでいる。
こんなイメージです。
<?xml version="1.0" encoding="utf8"?>
<feed>
<entry gr:crawl-timestamp-msec="1316865492109">
...
</entry>
<entry gr:crawl-timestamp-msec="1316943113824">
...
</entry>
<entry gr:crawl-timestamp-msec="1316826628148">
...
</entry>
</feed>
entry タグの gr:crawl-timestamp-msec という属性値には、"共有アイテムに追加した時刻" が記録されています。
というわけで、publish された時刻とこの属性値の時刻を比較し、最近追加されたものだけをつぶやくように修正します。
しゅうせい!
※ 前回の "4. 新着フィードの受信" の部分の修正です。
[code lang="ruby" highlight="14,15,27,28,30,31"]
# 購読要求時の入力情報
secret = 'foofoo'
post '/sub.rb' do
# リクエストボディの取得
payload = request.body.read
# X_Hub_Signature ヘッダの値を取得
hub_sig = request.env['HTTP_X_HUB_SIGNATURE']
# HMAC-SHA1 の計算
my_sig = OpenSSL::HMAC::hexdigest(OpenSSL::Digest::SHA1.new, secret, payload)
if hub_sig.include?(my_sig) then
# 現在時刻の取得
timenow = Time.now.to_i # (*1)
# xml の解析
doc = REXML::Document.new(payload.gsub('<br>', '<br />'))
# entry 毎に処理
doc.elements.each('/feed/entry') do |ele|
title = ele.elements['title'].text
link = ele.elements['link[@rel="alternate"]'].attributes['href']
# コメントはない場合もあるので分けて処理
comment_ele = ele.elements['gr:annotation/content']
comment = comment_ele ? comment_ele.text : ''
# 追加された時刻の取得
timepub = ele.attributes['gr:crawl-timestamp-msec'].to_i / 1000 # (*2)
# 300sec 以内に追加されたものだけつぶやく
if timenow - timepub < 300 then # (*3)
t = Tweet.new
begin
t.tweet(title, link, comment)
rescue
true
end
end
end
end
# 成功を返す
status 200
end
つぶやき済みのアイテムの gr:crawl-timestamp-msec
をどこかに保持する、という方法でも良かったのですが、面倒だったので 300 秒以内ということで妥協しました。
さいごに
この修正後は過去のものがつぶやかれることはなく、快適に使えています。