tumblr4r 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +5 -0
- data/Rakefile +1 -1
- data/lib/tumblr4r.rb +170 -70
- data/test/tumblr4r_dashboard_test.rb +46 -0
- data/test/tumblr4r_test.rb +15 -13
- metadata +21 -16
data/ChangeLog
CHANGED
data/Rakefile
CHANGED
data/lib/tumblr4r.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require 'net/http'
|
2
3
|
require 'rubygems'
|
3
4
|
require 'rexml/document'
|
4
|
-
|
5
|
+
begin
|
6
|
+
require 'active_support/core_ext'
|
7
|
+
require 'active_support/core_ext'
|
8
|
+
rescue
|
9
|
+
require 'activesupport'
|
10
|
+
end
|
11
|
+
|
5
12
|
require 'logger'
|
6
13
|
require 'cgi'
|
14
|
+
|
7
15
|
module Tumblr4r
|
8
|
-
VERSION = '0.
|
16
|
+
VERSION = '0.8.0'
|
9
17
|
class TumblrError < StandardError
|
18
|
+
attr_accessor :attachment
|
19
|
+
def initialize(msg, attachment=nil)
|
20
|
+
super(msg)
|
21
|
+
@attachment = attachment
|
22
|
+
end
|
10
23
|
end
|
11
24
|
|
12
25
|
module POST_TYPE
|
@@ -28,9 +41,9 @@ module Tumblr4r
|
|
28
41
|
attr_accessor :hostname, :email, :password, :name, :timezone, :title, :cname,
|
29
42
|
:description, :feeds
|
30
43
|
attr_accessor :logger
|
31
|
-
|
32
|
-
|
33
|
-
@@default_log_level = Logger::
|
44
|
+
API_READ_MAX_ALLOWED_COUNT = 50
|
45
|
+
SLEEP_SECONDS_FOR_EVERY_FETCH = 10.0 # API manual says "Requests are rate-limited to one every 10 seconds."
|
46
|
+
@@default_log_level = Logger::DEBUG
|
34
47
|
cattr_accessor :default_log_level
|
35
48
|
|
36
49
|
class << self
|
@@ -59,71 +72,127 @@ module Tumblr4r
|
|
59
72
|
self.site_info
|
60
73
|
end
|
61
74
|
|
62
|
-
# TODO: ここの再帰取得ロジックはTumblrAPIとは独立してるので
|
63
|
-
# TumblrAPIとは独立した形に切り出したり、TumblrAPIとは切り離してテストを書きたいものだ
|
64
75
|
# @param [Symbol|Integer] id_or_type :all, id
|
76
|
+
# @param [Hash] options :offset, :limit, :type, :filter, :tagged, :search,
|
65
77
|
# @return [Array<Post>|Post]
|
66
78
|
def find(id_or_type, options = { })
|
79
|
+
if id_or_type == :all
|
80
|
+
normal_find(options)
|
81
|
+
elsif id_or_type.kind_of?(Integer)
|
82
|
+
xml = @conn.get({:id => id_or_type})
|
83
|
+
posts, start, total = @parser.posts(xml)
|
84
|
+
@logger.info("size: #{posts.size}")
|
85
|
+
@logger.info("start: #{start}")
|
86
|
+
@logger.info("total: #{total}")
|
87
|
+
return posts[0]
|
88
|
+
else
|
89
|
+
raise ArgumentError.new("id_or_type must be :all or Integer, but was #{id_or_type}(<#{id_or_type.class}>)")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO: ループごとに実行して欲しい処理をblockで渡せるようにするといいかも?
|
94
|
+
# そのブロック引数にエラー情報も渡してあげれば、エラーが起きたのならretryだな、みたいな
|
95
|
+
# 指示ができない、、、、かな
|
96
|
+
def normal_find(options)
|
97
|
+
limit = options[:limit] && options[:limit].to_i
|
98
|
+
offset = options[:offset].to_i
|
99
|
+
total = self.count(options)
|
100
|
+
result = []
|
67
101
|
params = { }
|
68
|
-
return result if options[:offset] && options[:offset].to_i < 0
|
69
102
|
[:type, :filter, :tagged, :search].each do |option|
|
70
103
|
params[option] = options[option] if options[option]
|
71
104
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
options[:limit]].min
|
82
|
-
else
|
83
|
-
goal = total - params[:start]
|
105
|
+
last_fetched_at = nil
|
106
|
+
each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num|
|
107
|
+
params[:start] = offset
|
108
|
+
params[:num] = num
|
109
|
+
# APIマニュアルにはこっちのスリープ時間については明記されてないが、dashboardと同じ秒数SLEEPしとく
|
110
|
+
sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0
|
111
|
+
if sleep_secs > 0
|
112
|
+
logger.debug("sleeping #{sleep_secs} secs.")
|
113
|
+
sleep sleep_secs
|
84
114
|
end
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
115
|
+
xml = @conn.get(params)
|
116
|
+
last_fetched_at = Time.now
|
117
|
+
posts, start, total = @parser.posts(xml)
|
118
|
+
result += posts
|
119
|
+
if posts.size == 0
|
120
|
+
# Tumblr API の total で得られる値は全く信用ならない。
|
121
|
+
# 検索条件を考慮した件数を返してくれない。
|
122
|
+
# (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。
|
123
|
+
# TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する?
|
124
|
+
break
|
92
125
|
end
|
126
|
+
posts.size
|
127
|
+
end
|
128
|
+
result
|
129
|
+
end
|
93
130
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
131
|
+
#, :search,
|
132
|
+
# @param [Hash] options :offset, :limit, :type, :filter
|
133
|
+
# @return [Array<Post>]
|
134
|
+
def dashboard(options = { })
|
135
|
+
limit = options[:limit] ? options[:limit].to_i : nil
|
136
|
+
offset = options[:offset].to_i
|
137
|
+
result = []
|
138
|
+
params = {:likes => "1" }
|
139
|
+
[:type, :filter].each do |option|
|
140
|
+
params[option] = options[option] if options[option]
|
141
|
+
end
|
142
|
+
|
143
|
+
total = 1000 # 明記されてないがたぶん1000件ぐらいが上限?
|
144
|
+
last_fetched_at = nil
|
145
|
+
each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num|
|
146
|
+
params[:start] = offset
|
147
|
+
params[:num] = num
|
148
|
+
sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0
|
149
|
+
if sleep_secs > 0
|
150
|
+
logger.debug("sleeping #{sleep_secs} secs.")
|
151
|
+
sleep sleep_secs
|
116
152
|
end
|
117
|
-
|
118
|
-
|
119
|
-
xml = @conn.get({:id => id_or_type})
|
153
|
+
xml = @conn.dashboard(params)
|
154
|
+
last_fetched_at = Time.now
|
120
155
|
posts, start, total = @parser.posts(xml)
|
121
|
-
|
156
|
+
result += posts
|
157
|
+
if posts.size == 0
|
158
|
+
# Tumblr API の total で得られる値は全く信用ならない。
|
159
|
+
# 検索条件を考慮した件数を返してくれない。
|
160
|
+
# (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。
|
161
|
+
# TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する?
|
162
|
+
break
|
163
|
+
end
|
164
|
+
posts.size
|
165
|
+
end
|
166
|
+
result
|
167
|
+
end
|
168
|
+
|
169
|
+
def each_fetch(limit, offset, max_at_once, total, &block)
|
170
|
+
return if offset && offset.to_i < 0
|
171
|
+
|
172
|
+
# 取得開始位置の初期化
|
173
|
+
start = offset || 0
|
174
|
+
if limit
|
175
|
+
goal = [total - start, limit].min
|
176
|
+
else
|
177
|
+
goal = total - start
|
178
|
+
end
|
179
|
+
# 取得件数の初期化
|
180
|
+
num = [goal, max_at_once].min
|
181
|
+
if num < 0
|
182
|
+
return
|
183
|
+
end
|
184
|
+
|
185
|
+
all_fetched = 0
|
186
|
+
while all_fetched < goal
|
187
|
+
fetched_count = yield(start, num)
|
188
|
+
@logger.info("size: #{fetched_count}")
|
122
189
|
@logger.info("start: #{start}")
|
123
190
|
@logger.info("total: #{total}")
|
124
|
-
|
125
|
-
|
126
|
-
|
191
|
+
all_fetched += fetched_count
|
192
|
+
# 取得開始位置の調整
|
193
|
+
start += num
|
194
|
+
# 取得件数の調整
|
195
|
+
num = [goal - fetched_count, max_at_once].min
|
127
196
|
end
|
128
197
|
end
|
129
198
|
|
@@ -150,8 +219,17 @@ module Tumblr4r
|
|
150
219
|
return new_post
|
151
220
|
end
|
152
221
|
|
153
|
-
# @param [Integer]
|
154
|
-
def delete(
|
222
|
+
# @param [Integer|Post] post_id_or_post
|
223
|
+
def delete(post_id_or_post)
|
224
|
+
post_id = nil
|
225
|
+
case post_id_or_post
|
226
|
+
when Tumblr4r::Post
|
227
|
+
post_id = post_id_or_post.post_id
|
228
|
+
when Integer
|
229
|
+
post_id = post_id_or_post
|
230
|
+
else
|
231
|
+
raise ArgumentError.new("post_id_or_post must be Tumblr4r::Post or Integer, but was #{post_id_or_post}(<#{post_id_or_post.class}>)")
|
232
|
+
end
|
155
233
|
return @conn.delete(post_id)
|
156
234
|
end
|
157
235
|
|
@@ -173,6 +251,9 @@ module Tumblr4r
|
|
173
251
|
:private, # Integer(0|1)
|
174
252
|
:generator # String
|
175
253
|
|
254
|
+
attr_accessor :liked, # Boolean
|
255
|
+
:reblog_key # String
|
256
|
+
|
176
257
|
@@default_generator = nil
|
177
258
|
cattr_accessor :default_generator
|
178
259
|
|
@@ -293,7 +374,7 @@ module Tumblr4r
|
|
293
374
|
when Net::HTTP
|
294
375
|
@conn = http_or_hostname
|
295
376
|
else
|
296
|
-
raise ArgumentError.new("http_or_hostname must be String or Net::HTTP")
|
377
|
+
raise ArgumentError.new("http_or_hostname must be String or Net::HTTP but is #{http_or_hostname.class}")
|
297
378
|
end
|
298
379
|
@email= email
|
299
380
|
@password = password
|
@@ -321,9 +402,25 @@ module Tumblr4r
|
|
321
402
|
when Net::HTTPOK
|
322
403
|
return res.body
|
323
404
|
when Net::HTTPNotFound
|
324
|
-
raise TumblrError.new("no such site(#{@hostname})")
|
405
|
+
raise TumblrError.new("no such site(#{@hostname})", res)
|
325
406
|
else
|
326
|
-
raise TumblrError.new("unexpected response #{res.inspect}")
|
407
|
+
raise TumblrError.new("unexpected response #{res.inspect}", res)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def dashboard(options = { })
|
412
|
+
response = nil
|
413
|
+
http = Net::HTTP.new("www.tumblr.com")
|
414
|
+
params = options.merge({"email" => @email, "password" => @password, "group" => @group})
|
415
|
+
query_string = params.delete_if{|k,v| v == nil }.map{|k,v| "#{k}=#{CGI.escape(v.to_s)}" unless v.nil?}.join("&")
|
416
|
+
logger.debug("#### query_string: #{query_string}")
|
417
|
+
response = http.post('/api/dashboard', query_string)
|
418
|
+
logger.debug(response.body)
|
419
|
+
case response
|
420
|
+
when Net::HTTPSuccess
|
421
|
+
return response.body
|
422
|
+
else
|
423
|
+
raise TumblrError.new(format_error(response), response)
|
327
424
|
end
|
328
425
|
end
|
329
426
|
|
@@ -339,7 +436,7 @@ module Tumblr4r
|
|
339
436
|
when Net::HTTPOK
|
340
437
|
return true
|
341
438
|
else
|
342
|
-
raise TumblrError.new(response
|
439
|
+
raise TumblrError.new(format_error(response), response)
|
343
440
|
end
|
344
441
|
end
|
345
442
|
|
@@ -358,10 +455,7 @@ module Tumblr4r
|
|
358
455
|
when Net::HTTPSuccess
|
359
456
|
return response.body.to_i
|
360
457
|
else
|
361
|
-
|
362
|
-
response.each{|k,v| msg += "#{k}: #{v}\n"}
|
363
|
-
msg += response.body
|
364
|
-
raise TumblrError.new(msg)
|
458
|
+
raise TumblrError.new(format_error(response), response)
|
365
459
|
end
|
366
460
|
end
|
367
461
|
|
@@ -379,12 +473,16 @@ module Tumblr4r
|
|
379
473
|
logger.debug("#### response: #{response.code}: #{response.body}")
|
380
474
|
return true
|
381
475
|
else
|
382
|
-
|
383
|
-
response.each{|k,v| msg += "#{k}: #{v}\n"}
|
384
|
-
msg += response.body
|
385
|
-
raise TumblrError.new(msg)
|
476
|
+
raise TumblrError.new(format_error(response), response)
|
386
477
|
end
|
387
478
|
end
|
479
|
+
|
480
|
+
def format_error(response)
|
481
|
+
msg = response.inspect + "\n"
|
482
|
+
response.each{|k,v| msg += "#{k}: #{v}\n"}
|
483
|
+
msg += response.body
|
484
|
+
msg
|
485
|
+
end
|
388
486
|
end
|
389
487
|
|
390
488
|
# Tumblr XML API
|
@@ -446,6 +544,8 @@ module Tumblr4r
|
|
446
544
|
post.post_id = rexml_post.attributes["id"].to_i
|
447
545
|
post.url = rexml_post.attributes["url"]
|
448
546
|
post.url_with_slug = rexml_post.attributes["url-with-slug"]
|
547
|
+
post.liked = (rexml_post.attributes["liked"] == "true")
|
548
|
+
post.reblog_key = rexml_post.attributes["reblog-key"]
|
449
549
|
post.type = rexml_post.attributes["type"]
|
450
550
|
# TODO: time 関係の型をStringじゃなくTimeとかにする?
|
451
551
|
post.date_gmt = rexml_post.attributes["date-gmt"]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
require "test/unit"
|
3
|
+
require 'pit'
|
4
|
+
require 'pp'
|
5
|
+
$KCODE='u'
|
6
|
+
class Tumblr4rDashboardTest < Test::Unit::TestCase
|
7
|
+
include Tumblr4r
|
8
|
+
DASHBOARD_TEST_HOST = "tumblr4r-dashboard-test.tumblr.com"
|
9
|
+
TOTAL_COUNT = 123
|
10
|
+
REGULAR_COUNT = 6
|
11
|
+
QUOTE_COUNT = 103
|
12
|
+
PHOTO_COUNT = 2
|
13
|
+
|
14
|
+
def setup
|
15
|
+
Site.default_log_level = Logger::DEBUG
|
16
|
+
auth_info = Pit.get("tumblr4r-dashbard-test",
|
17
|
+
:require => {"email" => "required email",
|
18
|
+
"password" => "required password"})
|
19
|
+
@site = Site.new(DASHBOARD_TEST_HOST,
|
20
|
+
auth_info["email"],
|
21
|
+
auth_info["password"])
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
end
|
26
|
+
=begin
|
27
|
+
def test_find_all
|
28
|
+
posts = @site.dashboard
|
29
|
+
pp posts
|
30
|
+
assert_equal TOTAL_COUNT, posts.size
|
31
|
+
end
|
32
|
+
=end
|
33
|
+
def test_type
|
34
|
+
posts = @site.dashboard(:type => "regular")
|
35
|
+
assert_equal REGULAR_COUNT, posts.size
|
36
|
+
assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::REGULAR }
|
37
|
+
|
38
|
+
posts = @site.dashboard(:type => "quote")
|
39
|
+
assert_equal QUOTE_COUNT, posts.size
|
40
|
+
assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::QUOTE }
|
41
|
+
|
42
|
+
posts = @site.dashboard(:type => "photo")
|
43
|
+
assert_equal PHOTO_COUNT, posts.size
|
44
|
+
assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::PHOTO }
|
45
|
+
end
|
46
|
+
end
|
data/test/tumblr4r_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
3
|
require "test/unit"
|
3
4
|
require 'pit'
|
@@ -53,6 +54,7 @@ class Tumblr4rTest < Test::Unit::TestCase
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def test_find
|
57
|
+
debugger
|
56
58
|
posts = @site.find(:all)
|
57
59
|
assert_equal 9, posts.size
|
58
60
|
assert_equal Photo, posts[0].class
|
@@ -144,7 +146,7 @@ EOF
|
|
144
146
|
assert_equal false, posts[1].bookmarklet
|
145
147
|
|
146
148
|
assert_equal "", posts[1].regular_title
|
147
|
-
assert_equal "Tumblr4r
|
149
|
+
assert_equal "<p>Tumblr4rのテストです</p>", posts[1].regular_body
|
148
150
|
end
|
149
151
|
|
150
152
|
def test_find_with_type_photo
|
@@ -166,7 +168,7 @@ EOF
|
|
166
168
|
|
167
169
|
assert_equal "<p>Photoのテストです。</p>\n\n<p>ギコです。</p>", posts[1].photo_caption
|
168
170
|
assert_equal "http://www.google.co.jp/", posts[1].photo_link_url
|
169
|
-
assert_equal "http://
|
171
|
+
assert_equal "http://28.media.tumblr.com/GyEYZujUYopiula4XKmXhCgmo1_250.jpg", posts[1].photo_url
|
170
172
|
assert_equal [], posts[1].photoset
|
171
173
|
|
172
174
|
# photoset
|
@@ -182,12 +184,12 @@ EOF
|
|
182
184
|
assert_equal [], posts[0].tags
|
183
185
|
assert_equal false, posts[0].bookmarklet
|
184
186
|
|
185
|
-
assert_equal "Photoset test
|
187
|
+
assert_equal "<p>Photoset test.</p>", posts[0].photo_caption
|
186
188
|
assert_equal "", posts[0].photo_link_url
|
187
|
-
assert_equal "http://
|
188
|
-
assert_equal ["http://
|
189
|
-
"http://
|
190
|
-
"http://
|
189
|
+
assert_equal "http://25.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg", posts[0].photo_url
|
190
|
+
assert_equal ["http://25.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg",
|
191
|
+
"http://30.media.tumblr.com/tumblr_krg7btBOD21qzfaavo2_500.jpg",
|
192
|
+
"http://27.media.tumblr.com/tumblr_krg7btBOD21qzfaavo3_500.png"], posts[0].photoset
|
191
193
|
|
192
194
|
end
|
193
195
|
|
@@ -229,7 +231,7 @@ EOF
|
|
229
231
|
|
230
232
|
assert_equal "たんぶらー", posts[0].link_text
|
231
233
|
assert_equal "http://www.tumblr.com/", posts[0].link_url
|
232
|
-
assert_equal "
|
234
|
+
assert_equal "<p>ですくりぷしょん</p>", posts[0].link_description
|
233
235
|
end
|
234
236
|
|
235
237
|
def test_find_with_type_conversation
|
@@ -274,8 +276,9 @@ EOF
|
|
274
276
|
assert_equal false, posts[0].bookmarklet
|
275
277
|
|
276
278
|
assert_equal true, posts[0].audio_plays
|
277
|
-
assert_equal "tumblr4r miku", posts[0].audio_caption
|
278
|
-
assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://tumblr4rtest.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
|
279
|
+
assert_equal "<p>tumblr4r miku</p>", posts[0].audio_caption
|
280
|
+
# assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://tumblr4rtest.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
|
281
|
+
assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://assets.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
|
279
282
|
end
|
280
283
|
|
281
284
|
def test_find_with_type_video
|
@@ -293,9 +296,9 @@ EOF
|
|
293
296
|
assert_equal [], posts[0].tags
|
294
297
|
assert_equal false, posts[0].bookmarklet
|
295
298
|
|
296
|
-
assert_equal "matrix sappoloaded", posts[0].video_caption
|
299
|
+
assert_equal "<p>matrix sappoloaded</p>", posts[0].video_caption
|
297
300
|
assert_equal "http://www.youtube.com/watch?v=FavWH5RhYpw", posts[0].video_source
|
298
|
-
assert_equal "<object width=\"400\" height=\"
|
301
|
+
assert_equal "<object width=\"400\" height=\"325\"><param name=\"movie\" value=\"http://www.youtube.com/v/FavWH5RhYpw&rel=0&egm=0&showinfo=0&fs=1\"></param><param name=\"wmode\" value=\"transparent\"></param><param name=\"allowFullScreen\" value=\"true\"></param><embed src=\"http://www.youtube.com/v/FavWH5RhYpw&rel=0&egm=0&showinfo=0&fs=1\" type=\"application/x-shockwave-flash\" width=\"400\" height=\"325\" allowFullScreen=\"true\" wmode=\"transparent\"></embed></object>", posts[0].video_player
|
299
302
|
end
|
300
303
|
|
301
304
|
def test_find_with_tagged
|
@@ -402,6 +405,5 @@ EOF
|
|
402
405
|
videos = @site.find(:all, :type => Tumblr4r::POST_TYPE::VIDEO)
|
403
406
|
post = @write_site.save(videos[0])
|
404
407
|
end
|
405
|
-
|
406
408
|
end
|
407
409
|
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tumblr4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease:
|
5
|
+
version: 0.8.0
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Tomoki MAEDA
|
@@ -9,29 +10,30 @@ autorequire:
|
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
13
|
+
date: 2012-01-26 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 2.3.2
|
24
|
-
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
25
26
|
- !ruby/object:Gem::Dependency
|
26
27
|
name: pit
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
30
31
|
requirements:
|
31
32
|
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
34
|
version: 0.0.6
|
34
|
-
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
35
37
|
description: Tumblr API Wrapper for Ruby
|
36
38
|
email: tmaeda@ruby-sapporo.org
|
37
39
|
executables: []
|
@@ -46,10 +48,12 @@ files:
|
|
46
48
|
- ChangeLog
|
47
49
|
- Rakefile
|
48
50
|
- test/test_helper.rb
|
51
|
+
- test/tumblr4r_dashboard_test.rb
|
49
52
|
- test/tumblr4r_test.rb
|
50
53
|
- lib/tumblr4r.rb
|
51
|
-
has_rdoc: true
|
52
54
|
homepage: http://tumblr4r.rubyforge.org
|
55
|
+
licenses: []
|
56
|
+
|
53
57
|
post_install_message:
|
54
58
|
rdoc_options:
|
55
59
|
- --title
|
@@ -67,23 +71,24 @@ rdoc_options:
|
|
67
71
|
require_paths:
|
68
72
|
- lib
|
69
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
70
75
|
requirements:
|
71
76
|
- - ">="
|
72
77
|
- !ruby/object:Gem::Version
|
73
78
|
version: 1.8.6
|
74
|
-
version:
|
75
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
76
81
|
requirements:
|
77
82
|
- - ">="
|
78
83
|
- !ruby/object:Gem::Version
|
79
84
|
version: "0"
|
80
|
-
version:
|
81
85
|
requirements: []
|
82
86
|
|
83
87
|
rubyforge_project: tumblr4r
|
84
|
-
rubygems_version: 1.
|
88
|
+
rubygems_version: 1.8.11
|
85
89
|
signing_key:
|
86
|
-
specification_version:
|
90
|
+
specification_version: 3
|
87
91
|
summary: Tumblr API Wrapper for Ruby
|
88
92
|
test_files:
|
93
|
+
- test/tumblr4r_dashboard_test.rb
|
89
94
|
- test/tumblr4r_test.rb
|