slainer68_youtube_it 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/Gemfile +10 -0
  2. data/Gemfile.lock +27 -0
  3. data/Manifest.txt +37 -0
  4. data/README.rdoc +270 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/lib/youtube_it/chain_io.rb +76 -0
  8. data/lib/youtube_it/client.rb +447 -0
  9. data/lib/youtube_it/middleware/faraday_authheader.rb +24 -0
  10. data/lib/youtube_it/middleware/faraday_oauth.rb +21 -0
  11. data/lib/youtube_it/middleware/faraday_oauth2.rb +13 -0
  12. data/lib/youtube_it/middleware/faraday_youtubeit.rb +30 -0
  13. data/lib/youtube_it/model/activity.rb +17 -0
  14. data/lib/youtube_it/model/author.rb +13 -0
  15. data/lib/youtube_it/model/category.rb +11 -0
  16. data/lib/youtube_it/model/comment.rb +16 -0
  17. data/lib/youtube_it/model/contact.rb +19 -0
  18. data/lib/youtube_it/model/content.rb +18 -0
  19. data/lib/youtube_it/model/message.rb +12 -0
  20. data/lib/youtube_it/model/playlist.rb +11 -0
  21. data/lib/youtube_it/model/rating.rb +23 -0
  22. data/lib/youtube_it/model/subscription.rb +7 -0
  23. data/lib/youtube_it/model/thumbnail.rb +17 -0
  24. data/lib/youtube_it/model/user.rb +27 -0
  25. data/lib/youtube_it/model/video.rb +239 -0
  26. data/lib/youtube_it/parser.rb +534 -0
  27. data/lib/youtube_it/record.rb +12 -0
  28. data/lib/youtube_it/request/base_search.rb +72 -0
  29. data/lib/youtube_it/request/error.rb +15 -0
  30. data/lib/youtube_it/request/standard_search.rb +43 -0
  31. data/lib/youtube_it/request/user_search.rb +47 -0
  32. data/lib/youtube_it/request/video_search.rb +102 -0
  33. data/lib/youtube_it/request/video_upload.rb +538 -0
  34. data/lib/youtube_it/response/video_search.rb +41 -0
  35. data/lib/youtube_it/version.rb +4 -0
  36. data/lib/youtube_it.rb +83 -0
  37. data/slainer68_youtube_it.gemspec +102 -0
  38. data/test/files/recorded_response.xml +1 -0
  39. data/test/files/youtube_video_response.xml +53 -0
  40. data/test/helper.rb +9 -0
  41. data/test/test.mov +0 -0
  42. data/test/test_chain_io.rb +63 -0
  43. data/test/test_client.rb +435 -0
  44. data/test/test_field_search.rb +48 -0
  45. data/test/test_video.rb +48 -0
  46. data/test/test_video_feed_parser.rb +271 -0
  47. data/test/test_video_search.rb +141 -0
  48. metadata +172 -0
@@ -0,0 +1,447 @@
1
+ class YouTubeIt
2
+ class Client
3
+ include YouTubeIt::Logging
4
+ # Previously this was a logger instance but we now do it globally
5
+
6
+ def initialize *params
7
+ if params.first.is_a?(Hash)
8
+ hash_options = params.first
9
+ @user = hash_options[:username]
10
+ @pass = hash_options[:password]
11
+ @dev_key = hash_options[:dev_key]
12
+ @client_id = hash_options[:client_id] || "youtube_it"
13
+ @legacy_debug_flag = hash_options[:debug]
14
+ elsif params.first
15
+ puts "* warning: the method YouTubeIt::Client.new(user, passwd, dev_key) is deprecated, use YouTubeIt::Client.new(:username => 'user', :password => 'passwd', :dev_key => 'dev_key')"
16
+ @user = params.shift
17
+ @pass = params.shift
18
+ @dev_key = params.shift
19
+ @client_id = params.shift || "youtube_it"
20
+ @legacy_debug_flag = params.shift
21
+ end
22
+ end
23
+
24
+ # Retrieves an array of standard feed, custom query, or user videos.
25
+ #
26
+ # === Parameters
27
+ # If fetching videos for a standard feed:
28
+ # params<Symbol>:: Accepts a symbol of :top_rated, :top_favorites, :most_viewed,
29
+ # :most_popular, :most_recent, :most_discussed, :most_linked,
30
+ # :most_responded, :recently_featured, and :watch_on_mobile.
31
+ #
32
+ # You can find out more specific information about what each standard feed provides
33
+ # by visiting: http://code.google.com/apis/youtube/reference.html#Standard_feeds
34
+ #
35
+ # options<Hash> (optional):: Accepts the options of :time, :page (default is 1),
36
+ # and :per_page (default is 25). :offset and :max_results
37
+ # can also be passed for a custom offset.
38
+ #
39
+ # If fetching videos by tags, categories, query:
40
+ # params<Hash>:: Accepts the keys :tags, :categories, :query, :order_by,
41
+ # :author, :racy, :response_format, :video_format, :page (default is 1),
42
+ # and :per_page(default is 25)
43
+ #
44
+ # options<Hash>:: Not used. (Optional)
45
+ #
46
+ # If fetching videos for a particular user:
47
+ # params<Hash>:: Key of :user with a value of the username.
48
+ # options<Hash>:: Not used. (Optional)
49
+ # === Returns
50
+ # YouTubeIt::Response::VideoSearch
51
+ def videos_by(params, options={})
52
+ request_params = params.respond_to?(:to_hash) ? params : options
53
+ request_params[:page] = integer_or_default(request_params[:page], 1)
54
+
55
+ request_params[:dev_key] = @dev_key if @dev_key
56
+
57
+ unless request_params[:max_results]
58
+ request_params[:max_results] = integer_or_default(request_params[:per_page], 25)
59
+ end
60
+
61
+ unless request_params[:offset]
62
+ request_params[:offset] = calculate_offset(request_params[:page], request_params[:max_results] )
63
+ end
64
+
65
+ if params.respond_to?(:to_hash) and not params[:user]
66
+ request = YouTubeIt::Request::VideoSearch.new(request_params)
67
+ elsif (params.respond_to?(:to_hash) && params[:user]) || (params == :favorites)
68
+ request = YouTubeIt::Request::UserSearch.new(params, request_params)
69
+ else
70
+ request = YouTubeIt::Request::StandardSearch.new(params, request_params)
71
+ end
72
+
73
+ logger.debug "Submitting request [url=#{request.url}]." if @legacy_debug_flag
74
+ parser = YouTubeIt::Parser::VideosFeedParser.new(request.url)
75
+ parser.parse
76
+ end
77
+
78
+ # Retrieves a single YouTube video.
79
+ #
80
+ # === Parameters
81
+ # vid<String>:: The ID or URL of the video that you'd like to retrieve.
82
+ # user<String>:: The user that uploaded the video that you'd like to retrieve.
83
+ #
84
+ # === Returns
85
+ # YouTubeIt::Model::Video
86
+ def video_by(video)
87
+ vid = nil
88
+ vid_regex = /(?:youtube.com|youtu.be).*(?:\/|v=)(\w+)/
89
+ if video =~ vid_regex
90
+ vid = $1
91
+ else
92
+ vid = video
93
+ end
94
+ video_id ="http://gdata.youtube.com/feeds/api/videos/#{vid}?v=2#{@dev_key ? '&key='+@dev_key : ''}"
95
+ parser = YouTubeIt::Parser::VideoFeedParser.new(video_id)
96
+ parser.parse
97
+ end
98
+
99
+ def video_by_user(user, vid)
100
+ video_id = "http://gdata.youtube.com/feeds/api/users/#{user}/uploads/#{vid}?v=2#{@dev_key ? '&key='+@dev_key : ''}"
101
+ parser = YouTubeIt::Parser::VideoFeedParser.new(video_id)
102
+ parser.parse
103
+ end
104
+
105
+ def video_upload(data, opts = {})
106
+ client.upload(data, opts)
107
+ end
108
+
109
+ def video_update(video_id, opts = {})
110
+ client.update(video_id, opts)
111
+ end
112
+
113
+ def video_delete(video_id)
114
+ client.delete(video_id)
115
+ end
116
+
117
+ def message_delete(message_id)
118
+ client.delete_message(message_id)
119
+ end
120
+
121
+ def upload_token(options, nexturl = "http://www.youtube.com/my_videos")
122
+ client.get_upload_token(options, nexturl)
123
+ end
124
+
125
+ def add_comment(video_id, comment)
126
+ client.add_comment(video_id, comment)
127
+ end
128
+
129
+ # opts is converted to get params and appended to comments gdata api url
130
+ # eg opts = { 'max-results' => 10, 'start-index' => 20 }
131
+ # hash does _not_ play nice with symbols
132
+ def comments(video_id, opts = {})
133
+ client.comments(video_id, opts)
134
+ end
135
+
136
+ def add_favorite(video_id)
137
+ client.add_favorite(video_id)
138
+ end
139
+
140
+ def delete_favorite(video_id)
141
+ client.delete_favorite(video_id)
142
+ end
143
+
144
+ def favorites(user = nil, opts = {})
145
+ client.favorites(user, opts)
146
+ end
147
+
148
+ def profile(user = nil)
149
+ client.profile(user)
150
+ end
151
+
152
+ # Fetches a user's activity feed.
153
+ def activity(user = nil, opts = {})
154
+ client.get_activity(user, opts)
155
+ end
156
+
157
+ def playlist(playlist_id)
158
+ client.playlist playlist_id
159
+ end
160
+
161
+ def playlists(user = nil)
162
+ client.playlists(user)
163
+ end
164
+
165
+ def add_playlist(options)
166
+ client.add_playlist(options)
167
+ end
168
+
169
+ def update_playlist(playlist_id, options)
170
+ client.update_playlist(playlist_id, options)
171
+ end
172
+
173
+ def add_video_to_playlist(playlist_id, video_id)
174
+ client.add_video_to_playlist(playlist_id, video_id)
175
+ end
176
+
177
+ def delete_video_from_playlist(playlist_id, playlist_entry_id)
178
+ client.delete_video_from_playlist(playlist_id, playlist_entry_id)
179
+ end
180
+
181
+ def delete_playlist(playlist_id)
182
+ client.delete_playlist(playlist_id)
183
+ end
184
+
185
+ def like_video(video_id)
186
+ client.rate_video(video_id, 'like')
187
+ end
188
+
189
+ def dislike_video(video_id)
190
+ client.rate_video(video_id, 'dislike')
191
+ end
192
+
193
+ def subscribe_channel(channel_name)
194
+ client.subscribe_channel(channel_name)
195
+ end
196
+
197
+ def unsubscribe_channel(subscription_id)
198
+ client.unsubscribe_channel(subscription_id)
199
+ end
200
+
201
+ def subscriptions(user_id = nil)
202
+ client.subscriptions(user_id)
203
+ end
204
+
205
+ def enable_http_debugging
206
+ client.enable_http_debugging
207
+ end
208
+
209
+ def add_response(original_video_id, response_video_id)
210
+ client.add_response(original_video_id, response_video_id)
211
+ end
212
+
213
+ def delete_response(original_video_id, response_video_id)
214
+ client.delete_response(original_video_id, response_video_id)
215
+ end
216
+
217
+ def current_user
218
+ client.get_current_user
219
+ end
220
+
221
+ # Gets the authenticated users video with the given ID. It may be private.
222
+ def my_video(video_id)
223
+ client.get_my_video(video_id)
224
+ end
225
+
226
+ # Gets all videos
227
+ def my_videos(opts = {})
228
+ client.get_my_videos(opts)
229
+ end
230
+
231
+ # Get's all of the user's contacts/friends.
232
+ def my_contacts(opts = {})
233
+ client.get_my_contacts(opts)
234
+ end
235
+
236
+ # Send vedio message
237
+ def send_message(opts = {})
238
+ client.send_message(opts)
239
+ end
240
+
241
+ # Get's all of the user's messages/inbox.
242
+ def my_messages(opts = {})
243
+ client.get_my_messages(opts)
244
+ end
245
+
246
+ private
247
+
248
+ def client
249
+ @client ||= YouTubeIt::Upload::VideoUpload.new(:username => @user, :password => @pass, :dev_key => @dev_key)
250
+ end
251
+
252
+ def calculate_offset(page, per_page)
253
+ page == 1 ? 1 : ((per_page * page) - per_page + 1)
254
+ end
255
+
256
+ def integer_or_default(value, default)
257
+ value = value.to_i
258
+ value > 0 ? value : default
259
+ end
260
+ end
261
+
262
+ class AuthSubClient < Client
263
+ def initialize *params
264
+ if params.first.is_a?(Hash)
265
+ hash_options = params.first
266
+ @authsub_token = hash_options[:token]
267
+ @dev_key = hash_options[:dev_key]
268
+ @client_id = hash_options[:client_id] || "youtube_it"
269
+ @legacy_debug_flag = hash_options[:debug]
270
+ else
271
+ puts "* warning: the method YouTubeIt::AuthSubClient.new(token, dev_key) is depricated, use YouTubeIt::AuthSubClient.new(:token => 'token', :dev_key => 'dev_key')"
272
+ @authsub_token = params.shift
273
+ @dev_key = params.shift
274
+ @client_id = params.shift || "youtube_it"
275
+ @legacy_debug_flag = params.shift
276
+ end
277
+ end
278
+
279
+ def create_session_token
280
+ response = nil
281
+ session_token_url = "/accounts/AuthSubSessionToken"
282
+
283
+ http_connection do |session|
284
+ response = session.get2('https://%s' % session_token_url,session_token_header).body
285
+ end
286
+ @authsub_token = response.sub('Token=','')
287
+ end
288
+
289
+ def revoke_session_token
290
+ response = nil
291
+ session_token_url = "/accounts/AuthSubRevokeToken"
292
+
293
+ http_connection do |session|
294
+ response = session.get2('https://%s' % session_token_url,session_token_header).code
295
+ end
296
+ response.to_s == '200' ? true : false
297
+ end
298
+
299
+ def session_token_info
300
+ response = nil
301
+ session_token_url = "/accounts/AuthSubTokenInfo"
302
+
303
+ http_connection do |session|
304
+ response = session.get2('https://%s' % session_token_url,session_token_header)
305
+ end
306
+ {:code => response.code, :body => response.body }
307
+ end
308
+
309
+ private
310
+ def client
311
+ @client ||= YouTubeIt::Upload::VideoUpload.new(:dev_key => @dev_key, :authsub_token => @authsub_token)
312
+ end
313
+
314
+ def session_token_header
315
+ {
316
+ "Content-Type" => "application/x-www-form-urlencoded",
317
+ "Authorization" => "AuthSub token=#{@authsub_token}"
318
+ }
319
+ end
320
+
321
+ def http_connection
322
+ http = Net::HTTP.new("www.google.com")
323
+ http.set_debug_output(logger) if @http_debugging
324
+ http.start do |session|
325
+ yield(session)
326
+ end
327
+ end
328
+ end
329
+
330
+ class OAuthClient < Client
331
+ def initialize *params
332
+ if params.first.is_a?(Hash)
333
+ hash_options = params.first
334
+ @consumer_key = hash_options[:consumer_key]
335
+ @consumer_secret = hash_options[:consumer_secret]
336
+ @user = hash_options[:username]
337
+ @dev_key = hash_options[:dev_key]
338
+ @client_id = hash_options[:client_id] || "youtube_it"
339
+ @legacy_debug_flag = hash_options[:debug]
340
+ else
341
+ puts "* warning: the method YouTubeIt::OAuthClient.new(consumer_key, consumer_secrect, dev_key) is depricated, use YouTubeIt::OAuthClient.new(:consumer_key => 'consumer key', :consumer_secret => 'consumer secret', :dev_key => 'dev_key')"
342
+ @consumer_key = params.shift
343
+ @consumer_secret = params.shift
344
+ @dev_key = params.shift
345
+ @user = params.shift
346
+ @client_id = params.shift || "youtube_it"
347
+ @legacy_debug_flag = params.shift
348
+ end
349
+ end
350
+
351
+ def consumer
352
+ @consumer ||= ::OAuth::Consumer.new(@consumer_key,@consumer_secret,{
353
+ :site=>"https://www.google.com",
354
+ :request_token_path=>"/accounts/OAuthGetRequestToken",
355
+ :authorize_path=>"/accounts/OAuthAuthorizeToken",
356
+ :access_token_path=>"/accounts/OAuthGetAccessToken"})
357
+ end
358
+
359
+ def request_token(callback)
360
+ @request_token = consumer.get_request_token({:oauth_callback => callback},{:scope => "http://gdata.youtube.com"})
361
+ end
362
+
363
+ def access_token
364
+ @access_token = ::OAuth::AccessToken.new(consumer, @atoken, @asecret)
365
+ end
366
+
367
+ def config_token
368
+ {
369
+ :consumer_key => @consumer_key,
370
+ :consumer_secret => @consumer_secret,
371
+ :token => @atoken,
372
+ :token_secret => @asecret
373
+ }
374
+ end
375
+
376
+ def authorize_from_request(rtoken,rsecret,verifier)
377
+ request_token = ::OAuth::RequestToken.new(consumer,rtoken,rsecret)
378
+ access_token = request_token.get_access_token({:oauth_verifier => verifier})
379
+ @atoken,@asecret = access_token.token, access_token.secret
380
+ end
381
+
382
+ def authorize_from_access(atoken,asecret)
383
+ @atoken,@asecret = atoken, asecret
384
+ end
385
+
386
+ def current_user
387
+ profile = access_token.get("http://gdata.youtube.com/feeds/api/users/default")
388
+ response_code = profile.code.to_i
389
+
390
+ if response_code/10 == 20 # success
391
+ REXML::Document.new(profile.body).elements["entry"].elements['author'].elements['name'].text
392
+ elsif response_code == 403 || response_code == 401 # auth failure
393
+ raise YouTubeIt::Upload::AuthenticationError.new(profile.inspect, response_code)
394
+ else
395
+ raise YouTubeIt::Upload::UploadError.new(profile.inspect, response_code)
396
+ end
397
+ end
398
+
399
+ private
400
+
401
+ def client
402
+ # IMPORTANT: make sure authorize_from_access is called before client is fetched
403
+ @client ||= YouTubeIt::Upload::VideoUpload.new(:username => current_user, :dev_key => @dev_key, :access_token => access_token, :config_token => config_token)
404
+ end
405
+
406
+ end
407
+
408
+ class OAuth2Client < YouTubeIt::Client
409
+ def initialize(options)
410
+ @client_id = options[:client_id]
411
+ @client_secret = options[:client_secret]
412
+ @client_access_token = options[:client_access_token]
413
+ @client_refresh_token = options[:client_refresh_token]
414
+ @dev_key = options[:dev_key]
415
+ end
416
+
417
+ def oauth_client
418
+ @oauth_client ||= ::OAuth2::Client.new(@client_id, @client_secret,
419
+ :site => "https://accounts.google.com",
420
+ :authorize_url => '/o/oauth2/auth',
421
+ :token_url => '/o/oauth2/token')
422
+ end
423
+
424
+ def access_token
425
+ @access_token ||= ::OAuth2::AccessToken.new(oauth_client, @client_access_token, :refresh_token => @client_refresh_token)
426
+ end
427
+
428
+ def current_user
429
+ profile = access_token.get("http://gdata.youtube.com/feeds/api/users/default")
430
+ response_code = profile.status
431
+
432
+ if response_code/10 == 20 # success
433
+ REXML::Document.new(profile.body).elements["entry"].elements['author'].elements['name'].text
434
+ elsif response_code == 403 || response_code == 401 # auth failure
435
+ raise YouTubeIt::Upload::AuthenticationError.new(profile.inspect, response_code)
436
+ else
437
+ raise YouTubeIt::Upload::UploadError.new(profile.inspect, response_code)
438
+ end
439
+ end
440
+
441
+ private
442
+
443
+ def client
444
+ @client ||= YouTubeIt::Upload::VideoUpload.new(:username => current_user, :access_token => access_token, :dev_key => @dev_key)
445
+ end
446
+ end
447
+ end
@@ -0,0 +1,24 @@
1
+ module Faraday
2
+ class Request::AuthHeader < Faraday::Middleware
3
+
4
+ def call(env)
5
+ req_headers = env[:request_headers]
6
+ req_headers.merge!(@headers)
7
+ unless req_headers.include?("GData-Version")
8
+ req_headers.merge!("GData-Version" => "2")
9
+ end
10
+ unless req_headers.include?("Content-Type")
11
+ req_headers.merge!("Content-Type" => "application/atom+xml; charset=UTF-8")
12
+ end
13
+ unless req_headers.include?("Content-Length")
14
+ req_headers.merge!("Content-Length" => env[:body] ? "#{env[:body].length}" : "0")
15
+ end
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def initialize(app, headers)
21
+ @app, @headers = app, headers
22
+ end
23
+ end
24
+ end