youtube_it 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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