youtube_it 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
1
+ class YouTubeIt
2
+ module Response
3
+ class VideoSearch < YouTubeIt::Record
4
+ # *String*:: Unique feed identifying url.
5
+ attr_reader :feed_id
6
+
7
+ # *Fixnum*:: Number of results per page.
8
+ attr_reader :max_result_count
9
+
10
+ # *Fixnum*:: 1-based offset index into the full result set.
11
+ attr_reader :offset
12
+
13
+ # *Fixnum*:: Total number of results available for the original request.
14
+ attr_reader :total_result_count
15
+
16
+ # *Time*:: Date and time at which the feed was last updated
17
+ attr_reader :updated_at
18
+
19
+ # *Array*:: Array of YouTubeIt::Model::Video records
20
+ attr_reader :videos
21
+
22
+ def current_page
23
+ ((offset - 1) / max_result_count) + 1
24
+ end
25
+
26
+ # current_page + 1 or nil if there is no next page
27
+ def next_page
28
+ current_page < total_pages ? (current_page + 1) : nil
29
+ end
30
+
31
+ # current_page - 1 or nil if there is no previous page
32
+ def previous_page
33
+ current_page > 1 ? (current_page - 1) : nil
34
+ end
35
+
36
+ def total_pages
37
+ (total_result_count / max_result_count.to_f).ceil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,4 @@
1
+ class YouTubeIt
2
+ VERSION = '0.0.1'
3
+ end
4
+
Binary file
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'pp'
4
+ require File.dirname(__FILE__) + '/../lib/youtube_it'
5
+
6
+ YouTubeIt.logger.level = Logger::ERROR
data/test/test.mov ADDED
Binary file
@@ -0,0 +1,63 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestChainIO < Test::Unit::TestCase
4
+ def setup
5
+ @klass = YouTubeIt::ChainIO # save typing
6
+ end
7
+
8
+ def test_should_support_read_from_one_io
9
+ io = @klass.new "abcd"
10
+ assert io.respond_to?(:read)
11
+ assert_equal "ab", io.read(2)
12
+ assert_equal "cd", io.read(2)
13
+ assert_equal false, io.read(2)
14
+ end
15
+
16
+ def test_should_skip_over_depleted_streams
17
+ io = @klass.new '', '', '', '', 'ab'
18
+ assert_equal 'ab', io.read(2)
19
+ end
20
+
21
+ def test_should_read_across_nultiple_streams_with_large_offset
22
+ io = @klass.new 'abc', '', 'def', '', 'ghij'
23
+ assert_equal 'abcdefgh', io.read(8)
24
+ end
25
+
26
+ def test_should_return_false_for_empty_items
27
+ io = @klass.new '', '', '', '', ''
28
+ assert_equal false, io.read(8)
29
+ end
30
+
31
+ def test_should_support_overzealous_read
32
+ io = @klass.new "ab"
33
+ assert_equal "ab", io.read(5000)
34
+ end
35
+
36
+ def test_should_predict_expected_length
37
+ io = @klass.new "ab", "cde"
38
+ assert_equal 5, io.expected_length
39
+ end
40
+
41
+ def test_should_predict_expected_length_with_prepositioned_io
42
+ first_buf = StringIO.new("ab")
43
+ first_buf.read(1)
44
+
45
+ io = @klass.new first_buf, "cde"
46
+ assert_equal 4, io.expected_length
47
+ end
48
+
49
+ def test_should_predict_expected_length_with_file_handle
50
+ test_size = File.size(__FILE__)
51
+ first_buf = StringIO.new("ab")
52
+ first_buf.read(1)
53
+
54
+ io = @klass.new File.open(__FILE__), first_buf
55
+ assert_equal test_size + 1, io.expected_length
56
+ end
57
+
58
+ def test_greedy
59
+ io = YouTubeIt::GreedyChainIO.new("a" * (1024 * 513))
60
+ chunk = io.read(123)
61
+ assert_equal 1024 * 512, chunk.length, "Should have read the first 512 KB chunk at once instead"
62
+ end
63
+ end
@@ -0,0 +1,301 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestClient < Test::Unit::TestCase
4
+
5
+ OPTIONS = {:title => "test title",
6
+ :description => "test description",
7
+ :category => 'People',
8
+ :keywords => %w[test]}
9
+ ACCOUNT = {:user => "tubeit20101", :passwd => "youtube_it", :dev_key => "AI39si411VBmO4Im9l0rfRsORXDI6F5AX5NlTIA4uHSWqa-Cgf-jUQG-6osUBB3PTLawLHlkKXPLr3B0pNcGU9wkNd11gIgdPg" }
10
+ RAILS_ENV = "test"
11
+
12
+ def setup
13
+ @client = YouTubeIt::Client.new(ACCOUNT[:user], ACCOUNT[:passwd] , ACCOUNT[:dev_key])
14
+ end
15
+
16
+ def test_should_respond_to_a_basic_query
17
+ response = @client.videos_by(:query => "penguin")
18
+
19
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
20
+ assert_equal 25, response.max_result_count
21
+ assert_equal 25, response.videos.length
22
+ assert_equal 1, response.offset
23
+ assert(response.total_result_count > 100)
24
+ assert_instance_of Time, response.updated_at
25
+
26
+ response.videos.each { |v| assert_valid_video v }
27
+ end
28
+
29
+ def test_should_respond_to_a_basic_query_with_offset_and_max_results
30
+ response = @client.videos_by(:query => "penguin", :offset => 15, :max_results => 30)
31
+
32
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
33
+ assert_equal 30, response.max_result_count
34
+ assert_equal 30, response.videos.length
35
+ assert_equal 15, response.offset
36
+ assert(response.total_result_count > 100)
37
+ assert_instance_of Time, response.updated_at
38
+
39
+ response.videos.each { |v| assert_valid_video v }
40
+ end
41
+
42
+ def test_should_respond_to_a_basic_query_with_paging
43
+ response = @client.videos_by(:query => "penguin")
44
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
45
+ assert_equal 25, response.max_result_count
46
+ assert_equal 1, response.offset
47
+
48
+ response = @client.videos_by(:query => "penguin", :page => 2)
49
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
50
+ assert_equal 25, response.max_result_count
51
+ assert_equal 26, response.offset
52
+
53
+ response2 = @client.videos_by(:query => "penguin", :page => 3)
54
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response2.feed_id
55
+ assert_equal 25, response2.max_result_count
56
+ assert_equal 51, response2.offset
57
+ end
58
+
59
+ def test_should_get_videos_for_multiword_metasearch_query
60
+ response = @client.videos_by(:query => 'christina ricci')
61
+
62
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
63
+ assert_equal 25, response.max_result_count
64
+ assert_equal 25, response.videos.length
65
+ assert_equal 1, response.offset
66
+ assert(response.total_result_count > 100)
67
+ assert_instance_of Time, response.updated_at
68
+
69
+ response.videos.each { |v| assert_valid_video v }
70
+ end
71
+
72
+ def test_should_handle_video_not_yet_viewed
73
+ response = @client.videos_by(:query => "YnqHZDh_t2Q")
74
+
75
+ assert_equal 1, response.videos.length
76
+ response.videos.each { |v| assert_valid_video v }
77
+ end
78
+
79
+ # TODO: this doesn't work because the returned feed is in an unknown format
80
+ # def test_should_get_video_for_search_by_video_id
81
+ # response = @client.videos_by(:video_id => "T7YazwP8GtY")
82
+ # response.videos.each { |v| assert_valid_video v }
83
+ # end
84
+
85
+ def test_should_get_videos_for_one_tag
86
+ response = @client.videos_by(:tags => ['panther'])
87
+ response.videos.each { |v| assert_valid_video v }
88
+ end
89
+
90
+ def test_should_get_videos_for_multiple_tags
91
+ response = @client.videos_by(:tags => ['tiger', 'leopard'])
92
+ response.videos.each { |v| assert_valid_video v }
93
+ end
94
+
95
+ def test_should_get_videos_for_one_category
96
+ response = @client.videos_by(:categories => [:news])
97
+ response.videos.each { |v| assert_valid_video v }
98
+ end
99
+
100
+ def test_should_get_videos_for_multiple_categories
101
+ response = @client.videos_by(:categories => [:news, :sports])
102
+ response.videos.each { |v| assert_valid_video v }
103
+ end
104
+
105
+ # TODO: Need to do more specific checking in these tests
106
+ # Currently, if a URL is valid, and videos are found, the test passes regardless of search criteria
107
+ def test_should_get_videos_for_categories_and_tags
108
+ response = @client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
109
+ response.videos.each { |v| assert_valid_video v }
110
+ end
111
+
112
+ def test_should_get_most_viewed_videos
113
+ response = @client.videos_by(:most_viewed)
114
+ response.videos.each { |v| assert_valid_video v }
115
+ end
116
+
117
+ def test_should_get_top_rated_videos_for_today
118
+ response = @client.videos_by(:top_rated, :time => :today)
119
+ response.videos.each { |v| assert_valid_video v }
120
+ end
121
+
122
+ def test_should_get_videos_for_categories_and_tags_with_category_boolean_operators
123
+ response = @client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
124
+ :tags => { :include => ['football'], :exclude => ['soccer'] })
125
+ response.videos.each { |v| assert_valid_video v }
126
+ end
127
+
128
+ def test_should_get_videos_for_categories_and_tags_with_tag_boolean_operators
129
+ response = @client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
130
+ :tags => { :either => ['football', 'soccer', 'polo'] })
131
+ response.videos.each { |v| assert_valid_video v }
132
+ end
133
+
134
+ def test_should_get_videos_by_user
135
+ response = @client.videos_by(:user => 'liz')
136
+ response.videos.each { |v| assert_valid_video v }
137
+ end
138
+
139
+ def test_should_get_videos_by_user_with_pagination_and_ordering
140
+ response = @client.videos_by(:user => 'liz', :page => 2, :per_page => '2', :order_by => 'published')
141
+ response.videos.each { |v| assert_valid_video v }
142
+ assert_equal 3, response.offset
143
+ assert_equal 2, response.max_result_count
144
+ end
145
+
146
+ def test_should_get_favorite_videos_by_user
147
+ response = @client.videos_by(:favorites, :user => 'drnicwilliams')
148
+ assert_equal "http://gdata.youtube.com/feeds/api/users/drnicwilliams/favorites", response.feed_id
149
+ response.videos.each { |v| assert_valid_video v }
150
+ end
151
+
152
+ def test_should_get_videos_for_query_search_with_categories_excluded
153
+ video = @client.video_by("EkF4JD2rO3Q")
154
+ assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/EkF4JD2rO3Q&feature=youtube_gdata\"></param>\n <param name=\"wmode\" value=\"transparent\"></param>\n <embed src=\"http://www.youtube.com/v/EkF4JD2rO3Q&feature=youtube_gdata\" type=\"application/x-shockwave-flash\" \n wmode=\"transparent\" width=\"425\" height=\"350\"></embed>\n</object>\n", video.embed_html
155
+ assert_valid_video video
156
+ end
157
+
158
+ def test_should_get_video_from_user
159
+ video = @client.video_by_user("chebyte","FQK1URcxmb4")
160
+ assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/FQK1URcxmb4&feature=youtube_gdata\"></param>\n <param name=\"wmode\" value=\"transparent\"></param>\n <embed src=\"http://www.youtube.com/v/FQK1URcxmb4&feature=youtube_gdata\" type=\"application/x-shockwave-flash\" \n wmode=\"transparent\" width=\"425\" height=\"350\"></embed>\n</object>\n", video.embed_html
161
+ assert_valid_video video
162
+ end
163
+
164
+
165
+ def test_should_always_return_a_logger
166
+ @client = YouTubeIt::Client.new
167
+ assert_not_nil @client.logger
168
+ end
169
+
170
+ def test_should_not_bail_if_debug_is_true
171
+ assert_nothing_raised { YouTubeIt::Client.new(true) }
172
+ end
173
+
174
+ def test_should_determine_if_nonembeddable_video_is_embeddable
175
+ response = @client.videos_by(:query => "avril lavigne girlfriend")
176
+
177
+ video = response.videos.first
178
+ assert !video.embeddable?
179
+ end
180
+
181
+ def test_should_determine_if_embeddable_video_is_embeddable
182
+ response = @client.videos_by(:query => "strongbad")
183
+
184
+ video = response.videos.first
185
+ assert video.embeddable?
186
+ end
187
+
188
+ def test_should_retrieve_video_by_id
189
+ video = @client.video_by("http://gdata.youtube.com/feeds/videos/EkF4JD2rO3Q")
190
+ assert_valid_video video
191
+
192
+ video = @client.video_by("EkF4JD2rO3Q")
193
+ assert_valid_video video
194
+ end
195
+
196
+ def test_return_upload_info_for_upload_from_browser
197
+ response = @client.upload_token(OPTIONS)
198
+ assert response.kind_of?(Hash)
199
+ assert response.size, 2
200
+ response.each do |k,v|
201
+ assert v
202
+ end
203
+ end
204
+
205
+ def test_should_upload_a_video
206
+ video_id = @client.video_upload(File.open("test/test.mov"), OPTIONS)
207
+ video = @client.video_by_user(ACCOUNT[:user], video_id)
208
+ assert_valid_video video
209
+ @client.video_delete(video_id)
210
+ end
211
+
212
+ def test_should_update_a_video
213
+ OPTIONS[:title] = "title changed"
214
+ video_id = @client.video_upload(File.open("test/test.mov"), OPTIONS)
215
+ @client.video_update(video_id, OPTIONS)
216
+ video = @client.video_by_user(ACCOUNT[:user], video_id)
217
+ assert_valid_video video
218
+ assert video.title == "title changed"
219
+ @client.video_delete(video_id)
220
+ end
221
+
222
+ def test_should_delete_video
223
+ video_id = @client.video_upload(File.open("test/test.mov"), OPTIONS)
224
+ video = @client.video_by_user(ACCOUNT[:user], video_id)
225
+ assert_valid_video video
226
+ assert @client.video_delete(video_id)
227
+ end
228
+
229
+ private
230
+
231
+ def assert_valid_video (video)
232
+ # check general attributes
233
+ assert_instance_of YouTubeIt::Model::Video, video
234
+ assert_instance_of Fixnum, video.duration
235
+ assert_instance_of String, video.html_content if video.html_content
236
+
237
+ # validate media content records
238
+ video.media_content.each do |media_content|
239
+ assert_valid_url media_content.url
240
+ assert_instance_of YouTubeIt::Model::Video::Format, media_content.format
241
+ assert_instance_of String, media_content.mime_type
242
+ assert_match(/^[^\/]+\/[^\/]+$/, media_content.mime_type)
243
+ end
244
+
245
+ default_content = video.default_media_content
246
+ if default_content
247
+ assert_instance_of YouTubeIt::Model::Content, default_content
248
+ assert default_content.is_default?
249
+ end
250
+
251
+ # validate keywords
252
+ video.keywords.each { |kw| assert_instance_of(String, kw) }
253
+
254
+ # http://www.youtube.com/watch?v=IHVaXG1thXM
255
+ assert_valid_url video.player_url
256
+ assert_instance_of Time, video.published_at
257
+
258
+ # validate optionally-present rating
259
+ if video.rating
260
+ assert_instance_of YouTubeIt::Model::Rating, video.rating
261
+ assert_instance_of Float, video.rating.average
262
+ assert_instance_of Fixnum, video.rating.max
263
+ assert_instance_of Fixnum, video.rating.min
264
+ assert_instance_of Fixnum, video.rating.rater_count
265
+ end
266
+
267
+ # validate thumbnails
268
+ assert(video.thumbnails.size > 0)
269
+
270
+ assert_not_nil video.title
271
+ assert_instance_of String, video.title
272
+ assert(video.title.length > 0)
273
+
274
+ assert_instance_of Time, video.updated_at
275
+ # http://gdata.youtube.com/feeds/videos/IHVaXG1thXM
276
+ assert_valid_url video.video_id
277
+ assert_instance_of Fixnum, video.view_count
278
+ assert_instance_of Fixnum, video.favorite_count
279
+
280
+ # validate author
281
+ assert_instance_of YouTubeIt::Model::Author, video.author
282
+ assert_instance_of String, video.author.name
283
+ assert(video.author.name.length > 0)
284
+ assert_valid_url video.author.uri
285
+
286
+ # validate categories
287
+ video.categories.each do |cat|
288
+ assert_instance_of YouTubeIt::Model::Category, cat
289
+ assert_instance_of String, cat.label
290
+ assert_instance_of String, cat.term
291
+ end
292
+ end
293
+
294
+ def assert_valid_url (url)
295
+ URI::parse(url)
296
+ return true
297
+ rescue
298
+ return false
299
+ end
300
+ end
301
+
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestVideo < Test::Unit::TestCase
4
+ def test_should_extract_unique_id_from_video_id
5
+ video = YouTubeIt::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/ZTUVgYoeN_o")
6
+ assert_equal "ZTUVgYoeN_o", video.unique_id
7
+ end
8
+
9
+ def test_should_extract_unique_id_with_hypen_from_video_id
10
+ video = YouTubeIt::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
11
+ assert_equal "BDqs-OZWw9o", video.unique_id
12
+ end
13
+
14
+ def test_should_have_related_videos
15
+ video = YouTubeIt::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
16
+ response = video.related
17
+
18
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/BDqs-OZWw9o/related", response.feed_id
19
+ assert_equal 25, response.max_result_count
20
+ assert_equal 25, response.videos.length
21
+ assert_equal 1, response.offset
22
+ assert(response.total_result_count > 0)
23
+ assert_instance_of Time, response.updated_at
24
+ end
25
+
26
+ def test_should_have_response_videos
27
+ video = YouTubeIt::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
28
+ response = video.responses
29
+
30
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/BDqs-OZWw9o/responses", response.feed_id
31
+ assert_equal 25, response.max_result_count
32
+ assert_equal 25, response.videos.length
33
+ assert_equal 1, response.offset
34
+ assert(response.total_result_count > 0)
35
+ assert_instance_of Time, response.updated_at
36
+ end
37
+
38
+ end