youtube_it 2.1.7 → 2.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -0
- data/lib/youtube_it.rb +1 -0
- data/lib/youtube_it/client.rb +120 -103
- data/lib/youtube_it/middleware/faraday_youtubeit.rb +2 -2
- data/lib/youtube_it/model/caption.rb +7 -0
- data/lib/youtube_it/model/thumbnail.rb +3 -0
- data/lib/youtube_it/model/video.rb +18 -1
- data/lib/youtube_it/parser.rb +22 -2
- data/lib/youtube_it/request/video_upload.rb +33 -16
- data/lib/youtube_it/version.rb +1 -1
- metadata +132 -124
data/README.rdoc
CHANGED
@@ -118,6 +118,10 @@ Fields Parameter(experimental features):
|
|
118
118
|
$ client.videos_by(:fields => {:published => ((Date.today - 30)..(Date.today))})
|
119
119
|
$ client.videos_by(:fields => {:recorded => ((Date.today - 30)..(Date.today))})
|
120
120
|
|
121
|
+
Note: These queries do not find private videos! Use these methods instead:
|
122
|
+
$ client.get_my_video("FQK1URcxmb4")
|
123
|
+
$ client.get_my_videos(:query => "penguin")
|
124
|
+
|
121
125
|
== VIDEO MANAGEMENT
|
122
126
|
|
123
127
|
Note: YouTube account, OAuth or AuthSub enables video management.
|
data/lib/youtube_it.rb
CHANGED
data/lib/youtube_it/client.rb
CHANGED
@@ -6,18 +6,18 @@ class YouTubeIt
|
|
6
6
|
def initialize *params
|
7
7
|
if params.first.is_a?(Hash)
|
8
8
|
hash_options = params.first
|
9
|
-
@user
|
10
|
-
@pass
|
11
|
-
@dev_key
|
12
|
-
@client_id
|
13
|
-
@legacy_debug_flag
|
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
14
|
elsif params.first
|
15
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
|
17
|
-
@pass
|
18
|
-
@dev_key
|
19
|
-
@client_id
|
20
|
-
@legacy_debug_flag
|
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
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -59,7 +59,7 @@ class YouTubeIt
|
|
59
59
|
end
|
60
60
|
|
61
61
|
unless request_params[:offset]
|
62
|
-
request_params[:offset] = calculate_offset(request_params[:page], request_params[:max_results]
|
62
|
+
request_params[:offset] = calculate_offset(request_params[:page], request_params[:max_results])
|
63
63
|
end
|
64
64
|
|
65
65
|
if params.respond_to?(:to_hash) and not params[:user]
|
@@ -110,10 +110,14 @@ class YouTubeIt
|
|
110
110
|
client.update(video_id, opts)
|
111
111
|
end
|
112
112
|
|
113
|
+
def captions_update(video_id, data, opts = {})
|
114
|
+
client.captions_update(video_id, data, opts)
|
115
|
+
end
|
116
|
+
|
113
117
|
def video_delete(video_id)
|
114
118
|
client.delete(video_id)
|
115
119
|
end
|
116
|
-
|
120
|
+
|
117
121
|
def message_delete(message_id)
|
118
122
|
client.delete_message(message_id)
|
119
123
|
end
|
@@ -156,7 +160,7 @@ class YouTubeIt
|
|
156
160
|
def profiles(*users)
|
157
161
|
client.profiles(*users)
|
158
162
|
end
|
159
|
-
|
163
|
+
|
160
164
|
# Fetches a user's activity feed.
|
161
165
|
def activity(user = nil, opts = {})
|
162
166
|
client.get_activity(user, opts)
|
@@ -165,7 +169,7 @@ class YouTubeIt
|
|
165
169
|
def watchlater(user = nil)
|
166
170
|
client.watchlater(user)
|
167
171
|
end
|
168
|
-
|
172
|
+
|
169
173
|
def add_video_to_watchlater(video_id)
|
170
174
|
client.add_video_to_watchlater(video_id)
|
171
175
|
end
|
@@ -178,8 +182,24 @@ class YouTubeIt
|
|
178
182
|
client.playlist(playlist_id, order_by)
|
179
183
|
end
|
180
184
|
|
181
|
-
def playlists(user = nil)
|
182
|
-
client.playlists(user)
|
185
|
+
def playlists(user = nil, opts = nil)
|
186
|
+
client.playlists(user, opts)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Fetches all playlists for a given user by repeatedly making requests for
|
190
|
+
# as many pages of playlists as the user has. Note that this can take a
|
191
|
+
# long time if the user has many playlists.
|
192
|
+
def all_playlists(user = nil)
|
193
|
+
newest_playlists, all_playlists_for_user = [], []
|
194
|
+
start_index, page_size = 1, 25
|
195
|
+
|
196
|
+
begin
|
197
|
+
newest_playlists = playlists(user, {'start-index' => start_index, 'max-results' => page_size})
|
198
|
+
all_playlists_for_user += newest_playlists
|
199
|
+
start_index += page_size
|
200
|
+
end while newest_playlists && newest_playlists.size == page_size
|
201
|
+
|
202
|
+
all_playlists_for_user
|
183
203
|
end
|
184
204
|
|
185
205
|
def add_playlist(options)
|
@@ -209,7 +229,7 @@ class YouTubeIt
|
|
209
229
|
def dislike_video(video_id)
|
210
230
|
client.rate_video(video_id, 'dislike')
|
211
231
|
end
|
212
|
-
|
232
|
+
|
213
233
|
def subscribe_channel(channel_name)
|
214
234
|
client.subscribe_channel(channel_name)
|
215
235
|
end
|
@@ -217,7 +237,7 @@ class YouTubeIt
|
|
217
237
|
def unsubscribe_channel(subscription_id)
|
218
238
|
client.unsubscribe_channel(subscription_id)
|
219
239
|
end
|
220
|
-
|
240
|
+
|
221
241
|
def subscriptions(user_id = nil)
|
222
242
|
client.subscriptions(user_id)
|
223
243
|
end
|
@@ -225,7 +245,7 @@ class YouTubeIt
|
|
225
245
|
def enable_http_debugging
|
226
246
|
client.enable_http_debugging
|
227
247
|
end
|
228
|
-
|
248
|
+
|
229
249
|
def add_response(original_video_id, response_video_id)
|
230
250
|
client.add_response(original_video_id, response_video_id)
|
231
251
|
end
|
@@ -237,7 +257,7 @@ class YouTubeIt
|
|
237
257
|
def current_user
|
238
258
|
client.get_current_user
|
239
259
|
end
|
240
|
-
|
260
|
+
|
241
261
|
# Gets the authenticated users video with the given ID. It may be private.
|
242
262
|
def my_video(video_id)
|
243
263
|
client.get_my_video(video_id)
|
@@ -247,27 +267,27 @@ class YouTubeIt
|
|
247
267
|
def my_videos(opts = {})
|
248
268
|
client.get_my_videos(opts)
|
249
269
|
end
|
250
|
-
|
270
|
+
|
251
271
|
# Gets all of the user's contacts/friends.
|
252
272
|
def my_contacts(opts = {})
|
253
273
|
client.get_my_contacts(opts)
|
254
274
|
end
|
255
|
-
|
275
|
+
|
256
276
|
# Send video message
|
257
277
|
def send_message(opts = {})
|
258
278
|
client.send_message(opts)
|
259
279
|
end
|
260
|
-
|
280
|
+
|
261
281
|
# Gets all of the user's messages/inbox.
|
262
282
|
def my_messages(opts = {})
|
263
283
|
client.get_my_messages(opts)
|
264
284
|
end
|
265
|
-
|
285
|
+
|
266
286
|
# Gets the user's watch history
|
267
287
|
def watch_history
|
268
288
|
client.get_watch_history
|
269
289
|
end
|
270
|
-
|
290
|
+
|
271
291
|
# Gets new subscription videos
|
272
292
|
def new_subscription_videos(user_id = nil)
|
273
293
|
client.new_subscription_videos(user_id)
|
@@ -294,12 +314,12 @@ class YouTubeIt
|
|
294
314
|
puts "* AuthSubClient will be deprecated. Use OAuth2 Client."
|
295
315
|
if params.first.is_a?(Hash)
|
296
316
|
hash_options = params.first
|
297
|
-
@authsub_token
|
298
|
-
@dev_key
|
299
|
-
@client_id
|
300
|
-
@legacy_debug_flag
|
317
|
+
@authsub_token = hash_options[:token]
|
318
|
+
@dev_key = hash_options[:dev_key]
|
319
|
+
@client_id = hash_options[:client_id] || "youtube_it"
|
320
|
+
@legacy_debug_flag = hash_options[:debug]
|
301
321
|
else
|
302
|
-
puts "* warning: the method YouTubeIt::AuthSubClient.new(token, dev_key) is
|
322
|
+
puts "* warning: the method YouTubeIt::AuthSubClient.new(token, dev_key) is deprecated, use YouTubeIt::AuthSubClient.new(:token => 'token', :dev_key => 'dev_key')"
|
303
323
|
@authsub_token = params.shift
|
304
324
|
@dev_key = params.shift
|
305
325
|
@client_id = params.shift || "youtube_it"
|
@@ -311,23 +331,19 @@ class YouTubeIt
|
|
311
331
|
response = nil
|
312
332
|
session_token_url = "/accounts/AuthSubSessionToken"
|
313
333
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
@authsub_token = response.sub('Token=','')
|
334
|
+
http_connection do |session|
|
335
|
+
response = session.get2('https://%s' % session_token_url, session_token_header).body
|
336
|
+
end
|
337
|
+
@authsub_token = response.sub('Token=', '')
|
320
338
|
end
|
321
339
|
|
322
340
|
def revoke_session_token
|
323
341
|
response = nil
|
324
342
|
session_token_url = "/accounts/AuthSubRevokeToken"
|
325
343
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
end.status
|
330
|
-
|
344
|
+
http_connection do |session|
|
345
|
+
response = session.get2('https://%s' % session_token_url, session_token_header).code
|
346
|
+
end
|
331
347
|
response.to_s == '200' ? true : false
|
332
348
|
end
|
333
349
|
|
@@ -335,34 +351,31 @@ class YouTubeIt
|
|
335
351
|
response = nil
|
336
352
|
session_token_url = "/accounts/AuthSubTokenInfo"
|
337
353
|
|
338
|
-
|
339
|
-
|
340
|
-
req.headers = session_token_header
|
354
|
+
http_connection do |session|
|
355
|
+
response = session.get2('https://%s' % session_token_url, session_token_header)
|
341
356
|
end
|
342
|
-
|
343
|
-
{:code => response.status, :body => response.body }
|
357
|
+
{:code => response.code, :body => response.body}
|
344
358
|
end
|
345
359
|
|
346
360
|
private
|
347
|
-
|
348
|
-
|
349
|
-
|
361
|
+
def client
|
362
|
+
@client ||= YouTubeIt::Upload::VideoUpload.new(:dev_key => @dev_key, :authsub_token => @authsub_token)
|
363
|
+
end
|
350
364
|
|
351
|
-
|
352
|
-
|
353
|
-
"Content-Type"
|
354
|
-
"Authorization"
|
355
|
-
|
356
|
-
|
365
|
+
def session_token_header
|
366
|
+
{
|
367
|
+
"Content-Type" => "application/x-www-form-urlencoded",
|
368
|
+
"Authorization" => "AuthSub token=#{@authsub_token}"
|
369
|
+
}
|
370
|
+
end
|
357
371
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
end
|
372
|
+
def http_connection
|
373
|
+
http = Net::HTTP.new("www.google.com")
|
374
|
+
http.set_debug_output(logger) if @http_debugging
|
375
|
+
http.start do |session|
|
376
|
+
yield(session)
|
364
377
|
end
|
365
|
-
|
378
|
+
end
|
366
379
|
end
|
367
380
|
|
368
381
|
class OAuthClient < Client
|
@@ -370,33 +383,33 @@ class YouTubeIt
|
|
370
383
|
puts "* OAuth 1.0 Client will be deprecated. Use OAuth2 Client."
|
371
384
|
if params.first.is_a?(Hash)
|
372
385
|
hash_options = params.first
|
373
|
-
@consumer_key
|
374
|
-
@consumer_secret
|
375
|
-
@user
|
376
|
-
@dev_key
|
377
|
-
@client_id
|
378
|
-
@legacy_debug_flag
|
386
|
+
@consumer_key = hash_options[:consumer_key]
|
387
|
+
@consumer_secret = hash_options[:consumer_secret]
|
388
|
+
@user = hash_options[:username]
|
389
|
+
@dev_key = hash_options[:dev_key]
|
390
|
+
@client_id = hash_options[:client_id] || "youtube_it"
|
391
|
+
@legacy_debug_flag = hash_options[:debug]
|
379
392
|
else
|
380
393
|
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')"
|
381
|
-
@consumer_key
|
382
|
-
@consumer_secret
|
383
|
-
@dev_key
|
384
|
-
@user
|
385
|
-
@client_id
|
386
|
-
@legacy_debug_flag
|
394
|
+
@consumer_key = params.shift
|
395
|
+
@consumer_secret = params.shift
|
396
|
+
@dev_key = params.shift
|
397
|
+
@user = params.shift
|
398
|
+
@client_id = params.shift || "youtube_it"
|
399
|
+
@legacy_debug_flag = params.shift
|
387
400
|
end
|
388
401
|
end
|
389
402
|
|
390
403
|
def consumer
|
391
|
-
@consumer ||= ::OAuth::Consumer.new(@consumer_key
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
404
|
+
@consumer ||= ::OAuth::Consumer.new(@consumer_key, @consumer_secret, {
|
405
|
+
:site => "https://www.google.com",
|
406
|
+
:request_token_path => "/accounts/OAuthGetRequestToken",
|
407
|
+
:authorize_path => "/accounts/OAuthAuthorizeToken",
|
408
|
+
:access_token_path => "/accounts/OAuthGetAccessToken"})
|
396
409
|
end
|
397
410
|
|
398
411
|
def request_token(callback)
|
399
|
-
@request_token = consumer.get_request_token({:oauth_callback => callback},{:scope => "http://gdata.youtube.com"})
|
412
|
+
@request_token = consumer.get_request_token({:oauth_callback => callback}, {:scope => "http://gdata.youtube.com"})
|
400
413
|
end
|
401
414
|
|
402
415
|
def access_token
|
@@ -405,29 +418,29 @@ class YouTubeIt
|
|
405
418
|
|
406
419
|
def config_token
|
407
420
|
{
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
421
|
+
:consumer_key => @consumer_key,
|
422
|
+
:consumer_secret => @consumer_secret,
|
423
|
+
:token => @atoken,
|
424
|
+
:token_secret => @asecret
|
425
|
+
}
|
413
426
|
end
|
414
427
|
|
415
|
-
def authorize_from_request(rtoken,rsecret,verifier)
|
416
|
-
request_token = ::OAuth::RequestToken.new(consumer,rtoken,rsecret)
|
428
|
+
def authorize_from_request(rtoken, rsecret, verifier)
|
429
|
+
request_token = ::OAuth::RequestToken.new(consumer, rtoken, rsecret)
|
417
430
|
access_token = request_token.get_access_token({:oauth_verifier => verifier})
|
418
|
-
@atoken
|
431
|
+
@atoken, @asecret = access_token.token, access_token.secret
|
419
432
|
end
|
420
433
|
|
421
|
-
def authorize_from_access(atoken,asecret)
|
422
|
-
@atoken
|
434
|
+
def authorize_from_access(atoken, asecret)
|
435
|
+
@atoken, @asecret = atoken, asecret
|
423
436
|
end
|
424
437
|
|
425
438
|
def current_user
|
426
439
|
profile = access_token.get("http://gdata.youtube.com/feeds/api/users/default")
|
427
440
|
response_code = profile.code.to_i
|
428
441
|
|
429
|
-
if response_code/10 == 20 # success
|
430
|
-
Nokogiri::XML(profile.body).at("
|
442
|
+
if (response_code / 10).to_i == 20 # success
|
443
|
+
Nokogiri::XML(profile.body).at("//yt:username").text
|
431
444
|
elsif response_code == 403 || response_code == 401 # auth failure
|
432
445
|
raise YouTubeIt::Upload::AuthenticationError.new(profile.inspect, response_code)
|
433
446
|
else
|
@@ -446,14 +459,13 @@ class YouTubeIt
|
|
446
459
|
|
447
460
|
class OAuth2Client < YouTubeIt::Client
|
448
461
|
def initialize(options)
|
449
|
-
@client_id
|
450
|
-
@client_secret
|
451
|
-
@client_access_token
|
452
|
-
@client_refresh_token
|
462
|
+
@client_id = options[:client_id]
|
463
|
+
@client_secret = options[:client_secret]
|
464
|
+
@client_access_token = options[:client_access_token]
|
465
|
+
@client_refresh_token = options[:client_refresh_token]
|
453
466
|
@client_token_expires_at = options[:client_token_expires_at]
|
454
|
-
@dev_key
|
455
|
-
@legacy_debug_flag
|
456
|
-
@connection_opts = options[:connection_opts]
|
467
|
+
@dev_key = options[:dev_key]
|
468
|
+
@legacy_debug_flag = options[:debug]
|
457
469
|
end
|
458
470
|
|
459
471
|
def oauth_client
|
@@ -464,7 +476,7 @@ class YouTubeIt
|
|
464
476
|
options.merge(:connection_opts => @connection_opts) if @connection_opts
|
465
477
|
@oauth_client ||= ::OAuth2::Client.new(@client_id, @client_secret, options)
|
466
478
|
end
|
467
|
-
|
479
|
+
|
468
480
|
def access_token
|
469
481
|
@access_token ||= ::OAuth2::AccessToken.new(oauth_client, @client_access_token, :refresh_token => @client_refresh_token, :expires_at => @client_token_expires_at)
|
470
482
|
end
|
@@ -478,20 +490,25 @@ class YouTubeIt
|
|
478
490
|
end
|
479
491
|
@access_token
|
480
492
|
end
|
493
|
+
|
494
|
+
def session_token_info
|
495
|
+
response = Faraday.get("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=#{@client_access_token}")
|
496
|
+
{:code => response.status, :body => response.body }
|
497
|
+
end
|
481
498
|
|
482
499
|
def current_user
|
483
500
|
profile = access_token.get("http://gdata.youtube.com/feeds/api/users/default")
|
484
501
|
response_code = profile.status
|
485
502
|
|
486
|
-
if response_code/10 == 20 # success
|
487
|
-
Nokogiri::XML(profile.body).at("
|
503
|
+
if (response_code / 10).to_i == 20 # success
|
504
|
+
Nokogiri::XML(profile.body).at("//yt:username").text
|
488
505
|
elsif response_code == 403 || response_code == 401 # auth failure
|
489
506
|
raise YouTubeIt::Upload::AuthenticationError.new(profile.inspect, response_code)
|
490
507
|
else
|
491
508
|
raise YouTubeIt::Upload::UploadError.new(profile.inspect, response_code)
|
492
509
|
end
|
493
510
|
end
|
494
|
-
|
511
|
+
|
495
512
|
private
|
496
513
|
|
497
514
|
def client
|
@@ -20,10 +20,10 @@ module Faraday
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def on_complete(env) #this method is called after finish request
|
23
|
-
msg = parse_upload_error_from(env[:body].gsub(/\n/, ''))
|
23
|
+
msg = env[:body] ? parse_upload_error_from(env[:body].gsub(/\n/, '')) : ''
|
24
24
|
if env[:status] == 403 || env[:status] == 401
|
25
25
|
raise ::AuthenticationError.new(msg, env[:status])
|
26
|
-
elsif env[:status] / 10 != 20
|
26
|
+
elsif (env[:status] / 10).to_i != 20
|
27
27
|
raise ::UploadError.new(msg, env[:status])
|
28
28
|
end
|
29
29
|
end
|
@@ -12,6 +12,9 @@ class YouTubeIt
|
|
12
12
|
|
13
13
|
# *String*:: Specifies the time offset at which the frame shown in the thumbnail image appears in the video.
|
14
14
|
attr_reader :time
|
15
|
+
|
16
|
+
# *String*:: Specified type of the thumbnail, attribute yt:name in feed
|
17
|
+
attr_reader :name
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
@@ -155,6 +155,22 @@ class YouTubeIt
|
|
155
155
|
def responses
|
156
156
|
YouTubeIt::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/responses?v=2").parse
|
157
157
|
end
|
158
|
+
|
159
|
+
|
160
|
+
# ID of video in playlist listing
|
161
|
+
# Useful if you have to delete this video from a playlist
|
162
|
+
#
|
163
|
+
# === Example
|
164
|
+
# >> video.in_playlist_id
|
165
|
+
# => "PLk3UVPlPEkey09s2W02R48WMDKjvSb6Hq"
|
166
|
+
#
|
167
|
+
# === Returns
|
168
|
+
# String the video id
|
169
|
+
#
|
170
|
+
def in_playlist_id
|
171
|
+
@video_id.split(':').last
|
172
|
+
end
|
173
|
+
|
158
174
|
# The ID of the video, useful for searching for the video again without having to store it anywhere.
|
159
175
|
# A regular query search, with this id will return the same video.
|
160
176
|
#
|
@@ -234,12 +250,13 @@ EDOC
|
|
234
250
|
:id => params[:id] || "",
|
235
251
|
:width => params[:width] || "425",
|
236
252
|
:height => params[:height] || "350",
|
253
|
+
:protocol => params[:protocol] || "http",
|
237
254
|
:frameborder => params[:frameborder] || "0",
|
238
255
|
:url_params => params[:url_params] || {}
|
239
256
|
}
|
240
257
|
url_opts = opts[:url_params].empty? ? "" : "?#{Rack::Utils::build_query(opts[:url_params])}"
|
241
258
|
<<EDOC
|
242
|
-
<iframe class="#{opts[:class]}" id="#{opts[:id]}" type="text/html" width="#{opts[:width]}" height="#{opts[:height]}" src="
|
259
|
+
<iframe class="#{opts[:class]}" id="#{opts[:id]}" type="text/html" width="#{opts[:width]}" height="#{opts[:height]}" src="#{opts[:protocol]}://www.youtube.com/embed/#{unique_id}#{url_opts}" frameborder="#{opts[:frameborder]}"></iframe>
|
243
260
|
EDOC
|
244
261
|
end
|
245
262
|
|
data/lib/youtube_it/parser.rb
CHANGED
@@ -82,7 +82,7 @@ class YouTubeIt
|
|
82
82
|
:title => entry.at("title") && entry.at("title").text,
|
83
83
|
:summary => ((entry.at("summary") || entry.at_xpath("media:group").at_xpath("media:description")).text rescue nil),
|
84
84
|
:description => ((entry.at("summary") || entry.at_xpath("media:group").at_xpath("media:description")).text rescue nil),
|
85
|
-
:playlist_id => (entry.at("id").text[/playlist:(\w+)/, 1] rescue nil),
|
85
|
+
:playlist_id => (entry.at("id").text[/playlist:([\w\-]+)/, 1] rescue nil),
|
86
86
|
:published => entry.at("published") ? entry.at("published").text : nil,
|
87
87
|
:response_code => content.status,
|
88
88
|
:xml => content.body)
|
@@ -365,6 +365,25 @@ class YouTubeIt
|
|
365
365
|
end
|
366
366
|
end
|
367
367
|
|
368
|
+
class CaptionFeedParser < FeedParser #:nodoc:
|
369
|
+
|
370
|
+
def parse_content(content)
|
371
|
+
doc = (content.is_a?(Nokogiri::XML::Document)) ? content : Nokogiri::XML(content)
|
372
|
+
|
373
|
+
entry = doc.at "entry"
|
374
|
+
parse_entry(entry)
|
375
|
+
end
|
376
|
+
|
377
|
+
protected
|
378
|
+
|
379
|
+
def parse_entry(entry)
|
380
|
+
YouTubeIt::Model::Caption.new(
|
381
|
+
:title => entry.at("title").text,
|
382
|
+
:id => entry.at("id").text[/captions([^<]+)/, 1].sub(':',''),
|
383
|
+
:published => entry.at("published") ? entry.at("published").text : nil
|
384
|
+
)
|
385
|
+
end
|
386
|
+
end
|
368
387
|
|
369
388
|
class VideoFeedParser < FeedParser #:nodoc:
|
370
389
|
|
@@ -454,7 +473,8 @@ class YouTubeIt
|
|
454
473
|
:url => thumb_element["url"],
|
455
474
|
:height => thumb_element["height"].to_i,
|
456
475
|
:width => thumb_element["width"].to_i,
|
457
|
-
:time => thumb_element["time"]
|
476
|
+
:time => thumb_element["time"],
|
477
|
+
:name => thumb_element["name"])
|
458
478
|
end
|
459
479
|
|
460
480
|
rating_element = entry.at_xpath("gd:rating")
|
@@ -29,7 +29,7 @@ class YouTubeIt
|
|
29
29
|
@client_id = hash_options[:client_id] || "youtube_it"
|
30
30
|
@config_token = hash_options[:config_token]
|
31
31
|
else
|
32
|
-
puts "* warning: the method YouTubeIt::Upload::VideoUpload.new(username, password, dev_key) is
|
32
|
+
puts "* warning: the method YouTubeIt::Upload::VideoUpload.new(username, password, dev_key) is deprecated, use YouTubeIt::Upload::VideoUpload.new(:username => 'user', :password => 'passwd', :dev_key => 'dev_key')"
|
33
33
|
@user = params.shift
|
34
34
|
@password = params.shift
|
35
35
|
@dev_key = params.shift
|
@@ -115,6 +115,24 @@ class YouTubeIt
|
|
115
115
|
return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
|
116
116
|
end
|
117
117
|
|
118
|
+
|
119
|
+
def captions_update(video_id, data, options)
|
120
|
+
@opts = {
|
121
|
+
:language => 'en-US',
|
122
|
+
:slug => ''
|
123
|
+
}.merge(options)
|
124
|
+
|
125
|
+
upload_header = {
|
126
|
+
"Slug" => "#{URI.escape(@opts[:slug])}",
|
127
|
+
"Content-Language"=>@opts[:language],
|
128
|
+
"Content-Type" => "application/vnd.youtube.timedtext; charset=UTF-8",
|
129
|
+
"Content-Length" => "#{data.length}",
|
130
|
+
}
|
131
|
+
upload_url = "/feeds/api/videos/#{video_id}/captions"
|
132
|
+
response = yt_session(base_url).post(upload_url, data, upload_header)
|
133
|
+
return YouTubeIt::Parser::CaptionFeedParser.new(response.body).parse
|
134
|
+
end
|
135
|
+
|
118
136
|
# Fetches the currently authenticated user's contacts (i.e. friends).
|
119
137
|
# When the authentication credentials are incorrect, an AuthenticationError will be raised.
|
120
138
|
def get_my_contacts(opts)
|
@@ -306,9 +324,20 @@ class YouTubeIt
|
|
306
324
|
return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
|
307
325
|
end
|
308
326
|
|
309
|
-
|
310
|
-
|
311
|
-
|
327
|
+
# Fetches playlists for the given user. An optional hash of parameters can be given and will
|
328
|
+
# be appended to the request. Paging parameters will need to be used to access playlists
|
329
|
+
# beyond the most recent 25 (page size default for YouTube API at the time of this writing)
|
330
|
+
# if a user has more than 25 playlists.
|
331
|
+
#
|
332
|
+
# Paging parameters include the following
|
333
|
+
# start-index - 1-based index of which playlist to start from (default is 1)
|
334
|
+
# max-results - maximum number of playlists to fetch, up to 25 (default is 25)
|
335
|
+
def playlists(user, opts={})
|
336
|
+
playlist_url = "/feeds/api/users/%s/playlists" % (user ? user : "default")
|
337
|
+
params = {'v' => 2}
|
338
|
+
params.merge!(opts) if opts
|
339
|
+
playlist_url << "?#{params.collect { |k,v| [k,v].join '=' }.join('&')}"
|
340
|
+
response = yt_session.get(playlist_url)
|
312
341
|
|
313
342
|
return YouTubeIt::Parser::PlaylistsFeedParser.new(response).parse
|
314
343
|
end
|
@@ -468,18 +497,6 @@ class YouTubeIt
|
|
468
497
|
end
|
469
498
|
end
|
470
499
|
|
471
|
-
def raise_on_faulty_response(response)
|
472
|
-
response_code = response.code.to_i
|
473
|
-
msg = parse_upload_error_from(response.body.gsub(/\n/, ''))
|
474
|
-
|
475
|
-
if response_code == 403 || response_code == 401
|
476
|
-
#if response_code / 10 == 40
|
477
|
-
raise AuthenticationError.new(msg, response_code)
|
478
|
-
elsif response_code / 10 != 20 # Response in 20x means success
|
479
|
-
raise UploadError.new(msg, response_code)
|
480
|
-
end
|
481
|
-
end
|
482
|
-
|
483
500
|
def uploaded_video_id_from(string)
|
484
501
|
xml = Nokogiri::XML(string)
|
485
502
|
xml.at("id").text[/videos\/(.+)/, 1]
|
data/lib/youtube_it/version.rb
CHANGED
metadata
CHANGED
@@ -1,146 +1,154 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: youtube_it
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.7
|
3
|
+
version: !ruby/object:Gem::Version
|
5
4
|
prerelease:
|
5
|
+
version: 2.1.8
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
- kylejginavan
|
9
|
-
- chebyte
|
10
|
-
- mseppae
|
7
|
+
authors:
|
8
|
+
- kylejginavan
|
9
|
+
- chebyte
|
10
|
+
- mseppae
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
14
|
+
|
15
|
+
date: 2012-11-10 00:00:00 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: nokogiri
|
19
|
+
prerelease: false
|
20
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
none: false
|
22
|
+
requirements:
|
23
|
+
- - ~>
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 1.5.2
|
26
|
+
type: :runtime
|
27
|
+
version_requirements: *id001
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: oauth
|
30
|
+
prerelease: false
|
31
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ~>
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.4.4
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id002
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: oauth2
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0.6"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id003
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: simple_oauth
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 0.1.5
|
59
|
+
type: :runtime
|
60
|
+
version_requirements: *id004
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: faraday
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0.8"
|
70
|
+
type: :runtime
|
71
|
+
version_requirements: *id005
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: builder
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
type: :runtime
|
82
|
+
version_requirements: *id006
|
82
83
|
description: Upload, delete, update, comment on youtube videos all from one gem.
|
83
|
-
email:
|
84
|
-
- kylejginavan@gmail.com
|
84
|
+
email:
|
85
|
+
- kylejginavan@gmail.com
|
85
86
|
executables: []
|
87
|
+
|
86
88
|
extensions: []
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
- lib/youtube_it
|
92
|
-
- lib/youtube_it/
|
93
|
-
- lib/youtube_it/
|
94
|
-
- lib/youtube_it/
|
95
|
-
- lib/youtube_it/
|
96
|
-
- lib/youtube_it/
|
97
|
-
- lib/youtube_it/
|
98
|
-
- lib/youtube_it/
|
99
|
-
- lib/youtube_it/
|
100
|
-
- lib/youtube_it/
|
101
|
-
- lib/youtube_it/model/
|
102
|
-
- lib/youtube_it/model/
|
103
|
-
- lib/youtube_it/model/
|
104
|
-
- lib/youtube_it/model/
|
105
|
-
- lib/youtube_it/model/
|
106
|
-
- lib/youtube_it/model/
|
107
|
-
- lib/youtube_it/model/
|
108
|
-
- lib/youtube_it/model/
|
109
|
-
- lib/youtube_it/
|
110
|
-
- lib/youtube_it/
|
111
|
-
- lib/youtube_it/
|
112
|
-
- lib/youtube_it/
|
113
|
-
- lib/youtube_it/
|
114
|
-
- lib/youtube_it/
|
115
|
-
- lib/youtube_it/request/
|
116
|
-
- lib/youtube_it/request/
|
117
|
-
- lib/youtube_it/
|
118
|
-
- lib/youtube_it/
|
119
|
-
- lib/youtube_it.rb
|
120
|
-
-
|
121
|
-
- youtube_it.
|
89
|
+
|
90
|
+
extra_rdoc_files:
|
91
|
+
- README.rdoc
|
92
|
+
files:
|
93
|
+
- lib/youtube_it.rb
|
94
|
+
- lib/youtube_it/chain_io.rb
|
95
|
+
- lib/youtube_it/client.rb
|
96
|
+
- lib/youtube_it/parser.rb
|
97
|
+
- lib/youtube_it/record.rb
|
98
|
+
- lib/youtube_it/version.rb
|
99
|
+
- lib/youtube_it/middleware/faraday_authheader.rb
|
100
|
+
- lib/youtube_it/middleware/faraday_oauth.rb
|
101
|
+
- lib/youtube_it/middleware/faraday_oauth2.rb
|
102
|
+
- lib/youtube_it/middleware/faraday_youtubeit.rb
|
103
|
+
- lib/youtube_it/model/activity.rb
|
104
|
+
- lib/youtube_it/model/author.rb
|
105
|
+
- lib/youtube_it/model/caption.rb
|
106
|
+
- lib/youtube_it/model/category.rb
|
107
|
+
- lib/youtube_it/model/comment.rb
|
108
|
+
- lib/youtube_it/model/contact.rb
|
109
|
+
- lib/youtube_it/model/content.rb
|
110
|
+
- lib/youtube_it/model/message.rb
|
111
|
+
- lib/youtube_it/model/playlist.rb
|
112
|
+
- lib/youtube_it/model/rating.rb
|
113
|
+
- lib/youtube_it/model/subscription.rb
|
114
|
+
- lib/youtube_it/model/thumbnail.rb
|
115
|
+
- lib/youtube_it/model/user.rb
|
116
|
+
- lib/youtube_it/model/video.rb
|
117
|
+
- lib/youtube_it/request/base_search.rb
|
118
|
+
- lib/youtube_it/request/error.rb
|
119
|
+
- lib/youtube_it/request/standard_search.rb
|
120
|
+
- lib/youtube_it/request/user_search.rb
|
121
|
+
- lib/youtube_it/request/video_search.rb
|
122
|
+
- lib/youtube_it/request/video_upload.rb
|
123
|
+
- lib/youtube_it/response/video_search.rb
|
124
|
+
- README.rdoc
|
125
|
+
- youtube_it.gemspec
|
122
126
|
homepage: http://github.com/kylejginavan/youtube_it
|
123
127
|
licenses: []
|
128
|
+
|
124
129
|
post_install_message:
|
125
130
|
rdoc_options: []
|
126
|
-
|
127
|
-
|
128
|
-
|
131
|
+
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
135
|
none: false
|
130
|
-
requirements:
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: "0"
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
141
|
none: false
|
136
|
-
requirements:
|
137
|
-
|
138
|
-
|
139
|
-
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: "0"
|
140
146
|
requirements: []
|
147
|
+
|
141
148
|
rubyforge_project:
|
142
149
|
rubygems_version: 1.8.15
|
143
150
|
signing_key:
|
144
151
|
specification_version: 3
|
145
152
|
summary: The most complete Ruby wrapper for youtube api's
|
146
153
|
test_files: []
|
154
|
+
|