class Tumblr4r::Site
ConnectionオブジェクトとParserオブジェクトを組み合わせて、 TumblrAPIとRubyオブジェクトの相互変換を行う TODO: private な post だけを取得する API が無いのだなぁ
-
Webから更新したものがAPIで取得できるデータに反映されるには少しタイムラグがあるようだ
-
Webから更新しちゃうと、POST日時の秒が丸められてしまう
Constants
- API_READ_MAX_ALLOWED_COUNT
- SLEEP_SECONDS_FOR_EVERY_FETCH
Attributes
cname[RW]
description[RW]
email[RW]
feeds[RW]
hostname[RW]
logger[RW]
name[RW]
password[RW]
timezone[RW]
title[RW]
Public Class Methods
find(hostname, email=nil, password=nil, http=nil) { |post| ... }
click to toggle source
TODO: unit test
# File lib/tumblr4r.rb, line 50 def find(hostname, email=nil, password=nil, http=nil, &block) site = self.new(hostname, email, password, http) result = site.find(:all) if block_given? result.each do |post| yield post end else return result end end
new(hostname, email=nil, password=nil, http = nil, logger = nil)
click to toggle source
# File lib/tumblr4r.rb, line 63 def initialize(hostname, email=nil, password=nil, http = nil, logger = nil) @hostname = hostname @email = email @password = password @logger = logger || Logger.new(STDERR) @logger.level = @@default_log_level @conn = XMLConnection.new(http || @hostname, email, password, @logger) @parser = XMLParser.new self.site_info end
Public Instance Methods
count(options = { })
click to toggle source
# File lib/tumblr4r.rb, line 198 def count(options = { }) params = { } [:id, :type, :filter, :tagged, :search].each do |option| params[option] = options[option] if options[option] end params[:num] = 1 params[:start] = 0 xml = @conn.get(params) posts, start, total = @parser.posts(xml) return total end
dashboard(options = { })
click to toggle source
, :search,
@param [Hash] options :offset, :limit, :type, :filter @return [Array<Post>]
# File lib/tumblr4r.rb, line 133 def dashboard(options = { }) limit = options[:limit] ? options[:limit].to_i : nil offset = options[:offset].to_i result = [] params = {:likes => "1" } [:type, :filter].each do |option| params[option] = options[option] if options[option] end total = 1000 # 明記されてないがたぶん1000件ぐらいが上限? last_fetched_at = nil each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num| params[:start] = offset params[:num] = num sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0 if sleep_secs > 0 logger.debug("sleeping #{sleep_secs} secs.") sleep sleep_secs end xml = @conn.dashboard(params) last_fetched_at = Time.now posts, start, total = @parser.posts(xml) result += posts if posts.size == 0 # Tumblr API の total で得られる値は全く信用ならない。 # 検索条件を考慮した件数を返してくれない。 # (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。 # TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する? break end posts.size end result end
delete(post_id_or_post)
click to toggle source
@param [Integer|Post] post_id_or_post
# File lib/tumblr4r.rb, line 222 def delete(post_id_or_post) post_id = nil case post_id_or_post when Tumblr4r::Post post_id = post_id_or_post.post_id when Integer post_id = post_id_or_post else raise ArgumentError.new("post_id_or_post must be Tumblr4r::Post or Integer, but was #{post_id_or_post}(<#{post_id_or_post.class}>)") end return @conn.delete(post_id) end
each_fetch(limit, offset, max_at_once, total) { |start, num| ... }
click to toggle source
# File lib/tumblr4r.rb, line 168 def each_fetch(limit, offset, max_at_once, total, &block) return if offset && offset.to_i < 0 # 取得開始位置の初期化 start = offset || 0 if limit goal = [total - start, limit].min else goal = total - start end # 取得件数の初期化 num = [goal, max_at_once].min if num < 0 return end all_fetched = 0 while all_fetched < goal fetched_count = yield(start, num) @logger.info("size: #{fetched_count}") @logger.info("start: #{start}") @logger.info("total: #{total}") all_fetched += fetched_count # 取得開始位置の調整 start += num # 取得件数の調整 num = [goal - fetched_count, max_at_once].min end end
find(id_or_type, options = { })
click to toggle source
@param [Symbol|Integer] id_or_type :all, id @param [Hash] options :offset, :limit, :type, :filter, :tagged, :search, @return [Array<Post>|Post]
# File lib/tumblr4r.rb, line 77 def find(id_or_type, options = { }) if id_or_type == :all normal_find(options) elsif id_or_type.kind_of?(Integer) xml = @conn.get({:id => id_or_type}) posts, start, total = @parser.posts(xml) @logger.info("size: #{posts.size}") @logger.info("start: #{start}") @logger.info("total: #{total}") return posts[0] else raise ArgumentError.new("id_or_type must be :all or Integer, but was #{id_or_type}(<#{id_or_type.class}>)") end end
normal_find(options)
click to toggle source
TODO: ループごとに実行して欲しい処理をblockで渡せるようにするといいかも? そのブロック引数にエラー情報も渡してあげれば、エラーが起きたのならretryだな、みたいな 指示ができない、、、、かな
# File lib/tumblr4r.rb, line 95 def normal_find(options) limit = options[:limit] && options[:limit].to_i offset = options[:offset].to_i total = self.count(options) result = [] params = { } [:type, :filter, :tagged, :search].each do |option| params[option] = options[option] if options[option] end last_fetched_at = nil each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num| params[:start] = offset params[:num] = num # APIマニュアルにはこっちのスリープ時間については明記されてないが、dashboardと同じ秒数SLEEPしとく sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0 if sleep_secs > 0 logger.debug("sleeping #{sleep_secs} secs.") sleep sleep_secs end xml = @conn.get(params) last_fetched_at = Time.now posts, start, total = @parser.posts(xml) result += posts if posts.size == 0 # Tumblr API の total で得られる値は全く信用ならない。 # 検索条件を考慮した件数を返してくれない。 # (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。 # TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する? break end posts.size end result end
save(post)
click to toggle source
# File lib/tumblr4r.rb, line 215 def save(post) post_id = @conn.write(post.params) new_post = self.find(post_id) return new_post end
site_info()
click to toggle source
# File lib/tumblr4r.rb, line 210 def site_info xml = @conn.get(:num => 1) @parser.siteinfo(self, xml) end