youtube_it 2.1.5 → 2.1.7
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.
- data/README.rdoc +6 -2
- data/lib/youtube_it/client.rb +29 -17
- data/lib/youtube_it/middleware/faraday_youtubeit.rb +9 -8
- data/lib/youtube_it/model/video.rb +3 -0
- data/lib/youtube_it/parser.rb +8 -2
- data/lib/youtube_it/request/video_search.rb +5 -1
- data/lib/youtube_it/request/video_upload.rb +15 -14
- data/lib/youtube_it/version.rb +1 -1
- metadata +14 -14
data/README.rdoc
CHANGED
@@ -36,6 +36,8 @@ You can see to youtube_it in action here: http://youtube-it.heroku.com
|
|
36
36
|
|
37
37
|
== ESTABLISHING A CLIENT
|
38
38
|
|
39
|
+
Important: The Account Authentication API for OAuth 1.0, AuthSub and Client Login has been officially deprecated as of April 20, 2012. It will continue to work as per our deprecation policy(https://developers.google.com/accounts/terms), but we encourage you to migrate to OAuth 2.0 authentication as soon as possible. If you are building a new application, you should use OAuth 2.0 authentication.
|
40
|
+
|
39
41
|
Creating a client:
|
40
42
|
$ require 'youtube_it'
|
41
43
|
$ client = YouTubeIt::Client.new
|
@@ -60,6 +62,8 @@ If your access token is still valid (be careful, access tokens may only be valid
|
|
60
62
|
|
61
63
|
$ client.refresh_access_token!
|
62
64
|
|
65
|
+
* You can see more about oauth 2 in the wiki: https://github.com/kylejginavan/youtube_it/wiki/How-To:-Use-OAuth-2
|
66
|
+
|
63
67
|
== PROFILES
|
64
68
|
you can use multiple profiles in the same account like that
|
65
69
|
|
@@ -208,7 +212,7 @@ Add Video To Playlist:
|
|
208
212
|
$ client.add_video_to_playlist(playlist_id, video_id)
|
209
213
|
|
210
214
|
Remove Video From Playlist:
|
211
|
-
$ client.
|
215
|
+
$ client.delete_video_from_playlist(playlist_id, playlist_entry_id)
|
212
216
|
|
213
217
|
Select All Videos From your Watch Later Playlist:
|
214
218
|
$ watcher_later = client.watcherlater(user) #default: current user
|
@@ -218,7 +222,7 @@ Add Video To Watcher Later Playlist:
|
|
218
222
|
$ client.add_video_to_watchlater(video_id)
|
219
223
|
|
220
224
|
Remove Video From Watch Later Playlist:
|
221
|
-
$ client.
|
225
|
+
$ client.delete_video_from_watchlater(watchlater_entry_id)
|
222
226
|
|
223
227
|
|
224
228
|
List Related Videos
|
data/lib/youtube_it/client.rb
CHANGED
@@ -291,6 +291,7 @@ class YouTubeIt
|
|
291
291
|
|
292
292
|
class AuthSubClient < Client
|
293
293
|
def initialize *params
|
294
|
+
puts "* AuthSubClient will be deprecated. Use OAuth2 Client."
|
294
295
|
if params.first.is_a?(Hash)
|
295
296
|
hash_options = params.first
|
296
297
|
@authsub_token = hash_options[:token]
|
@@ -310,9 +311,11 @@ class YouTubeIt
|
|
310
311
|
response = nil
|
311
312
|
session_token_url = "/accounts/AuthSubSessionToken"
|
312
313
|
|
313
|
-
http_connection do |
|
314
|
-
|
315
|
-
|
314
|
+
response = http_connection.get do |req|
|
315
|
+
req.url session_token_url
|
316
|
+
req.headers = session_token_header
|
317
|
+
end.body
|
318
|
+
|
316
319
|
@authsub_token = response.sub('Token=','')
|
317
320
|
end
|
318
321
|
|
@@ -320,9 +323,11 @@ class YouTubeIt
|
|
320
323
|
response = nil
|
321
324
|
session_token_url = "/accounts/AuthSubRevokeToken"
|
322
325
|
|
323
|
-
http_connection do |
|
324
|
-
|
325
|
-
|
326
|
+
response = http_connection.get do |req|
|
327
|
+
req.url session_token_url
|
328
|
+
req.headers = session_token_header
|
329
|
+
end.status
|
330
|
+
|
326
331
|
response.to_s == '200' ? true : false
|
327
332
|
end
|
328
333
|
|
@@ -330,10 +335,12 @@ class YouTubeIt
|
|
330
335
|
response = nil
|
331
336
|
session_token_url = "/accounts/AuthSubTokenInfo"
|
332
337
|
|
333
|
-
http_connection do |
|
334
|
-
|
338
|
+
response = http_connection.get do |req|
|
339
|
+
req.url session_token_url
|
340
|
+
req.headers = session_token_header
|
335
341
|
end
|
336
|
-
|
342
|
+
|
343
|
+
{:code => response.status, :body => response.body }
|
337
344
|
end
|
338
345
|
|
339
346
|
private
|
@@ -349,16 +356,18 @@ class YouTubeIt
|
|
349
356
|
end
|
350
357
|
|
351
358
|
def http_connection
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
359
|
+
Faraday.new(:url => 'https://www.google.com', :ssl => {:verify => false}) do |builder|
|
360
|
+
builder.request :url_encoded
|
361
|
+
builder.response :logger if @legacy_debug_flag
|
362
|
+
builder.adapter Faraday.default_adapter
|
356
363
|
end
|
357
364
|
end
|
365
|
+
|
358
366
|
end
|
359
367
|
|
360
368
|
class OAuthClient < Client
|
361
369
|
def initialize *params
|
370
|
+
puts "* OAuth 1.0 Client will be deprecated. Use OAuth2 Client."
|
362
371
|
if params.first.is_a?(Hash)
|
363
372
|
hash_options = params.first
|
364
373
|
@consumer_key = hash_options[:consumer_key]
|
@@ -444,13 +453,16 @@ class YouTubeIt
|
|
444
453
|
@client_token_expires_at = options[:client_token_expires_at]
|
445
454
|
@dev_key = options[:dev_key]
|
446
455
|
@legacy_debug_flag = options[:debug]
|
456
|
+
@connection_opts = options[:connection_opts]
|
447
457
|
end
|
448
458
|
|
449
459
|
def oauth_client
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
460
|
+
options = {:site => "https://accounts.google.com",
|
461
|
+
:authorize_url => '/o/oauth2/auth',
|
462
|
+
:token_url => '/o/oauth2/token'
|
463
|
+
}
|
464
|
+
options.merge(:connection_opts => @connection_opts) if @connection_opts
|
465
|
+
@oauth_client ||= ::OAuth2::Client.new(@client_id, @client_secret, options)
|
454
466
|
end
|
455
467
|
|
456
468
|
def access_token
|
@@ -1,19 +1,20 @@
|
|
1
1
|
module Faraday
|
2
2
|
class Response::YouTubeIt < Response::Middleware
|
3
3
|
def parse_upload_error_from(string)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
xml = Nokogiri::XML(string).at('errors')
|
5
|
+
if xml
|
6
|
+
xml.css("error").inject('') do |all_faults, error|
|
7
|
+
if error.at("internalReason")
|
8
|
+
msg_error = error.at("internalReason").text
|
9
|
+
elsif error.at("location")
|
10
|
+
msg_error = error.at("location").text[/media:group\/media:(.*)\/text\(\)/,1]
|
10
11
|
else
|
11
12
|
msg_error = "Unspecified error"
|
12
13
|
end
|
13
|
-
code = error.
|
14
|
+
code = error.at("code").text if error.at("code")
|
14
15
|
all_faults + sprintf("%s: %s\n", msg_error, code)
|
15
16
|
end
|
16
|
-
|
17
|
+
else
|
17
18
|
string[/<TITLE>(.+)<\/TITLE>/, 1] || string
|
18
19
|
end
|
19
20
|
end
|
@@ -82,6 +82,9 @@ class YouTubeIt
|
|
82
82
|
# *Time*:: When the video's was uploaded.
|
83
83
|
attr_reader :uploaded_at
|
84
84
|
|
85
|
+
# *Time*:: When the video's was recorded.
|
86
|
+
attr_reader :recorded_at
|
87
|
+
|
85
88
|
# *Array*:: A array of YouTubeIt::Model::Category objects that describe the videos categories.
|
86
89
|
attr_reader :categories
|
87
90
|
|
data/lib/youtube_it/parser.rb
CHANGED
@@ -17,6 +17,11 @@ class YouTubeIt
|
|
17
17
|
parse_content @content
|
18
18
|
end
|
19
19
|
|
20
|
+
def parse_single_entry
|
21
|
+
doc = Nokogiri::XML(@content)
|
22
|
+
parse_entry(doc.at("entry") || doc)
|
23
|
+
end
|
24
|
+
|
20
25
|
def parse_videos
|
21
26
|
doc = Nokogiri::XML(@content)
|
22
27
|
videos = []
|
@@ -72,7 +77,7 @@ class YouTubeIt
|
|
72
77
|
|
73
78
|
def parse_content(content)
|
74
79
|
xml = Nokogiri::XML(content.body)
|
75
|
-
entry = xml.at("
|
80
|
+
entry = xml.at("feed") || xml.at("entry")
|
76
81
|
YouTubeIt::Model::Playlist.new(
|
77
82
|
:title => entry.at("title") && entry.at("title").text,
|
78
83
|
:summary => ((entry.at("summary") || entry.at_xpath("media:group").at_xpath("media:description")).text rescue nil),
|
@@ -376,6 +381,7 @@ class YouTubeIt
|
|
376
381
|
published_at = entry.at("published") ? Time.parse(entry.at("published").text) : nil
|
377
382
|
uploaded_at = entry.at_xpath("media:group/yt:uploaded") ? Time.parse(entry.at_xpath("media:group/yt:uploaded").text) : nil
|
378
383
|
updated_at = entry.at("updated") ? Time.parse(entry.at("updated").text) : nil
|
384
|
+
recorded_at = entry.at_xpath("yt:recorded") ? Time.parse(entry.at_xpath("yt:recorded").text) : nil
|
379
385
|
|
380
386
|
# parse the category and keyword lists
|
381
387
|
categories = []
|
@@ -479,7 +485,6 @@ class YouTubeIt
|
|
479
485
|
|
480
486
|
comment_feed = entry.at_xpath('gd:comments/gd:feedLink[@rel="http://gdata.youtube.com/schemas/2007#comments"]')
|
481
487
|
comment_count = comment_feed ? comment_feed['countHint'].to_i : 0
|
482
|
-
#puts comment_count.inspect
|
483
488
|
|
484
489
|
access_control = entry.xpath('yt:accessControl').map do |e|
|
485
490
|
{ e['action'] => e['permission'] }
|
@@ -515,6 +520,7 @@ class YouTubeIt
|
|
515
520
|
:published_at => published_at,
|
516
521
|
:updated_at => updated_at,
|
517
522
|
:uploaded_at => uploaded_at,
|
523
|
+
:recorded_at => recorded_at,
|
518
524
|
:categories => categories,
|
519
525
|
:keywords => keywords,
|
520
526
|
:title => title,
|
@@ -25,6 +25,8 @@ class YouTubeIt
|
|
25
25
|
attr_reader :uploader
|
26
26
|
attr_reader :region
|
27
27
|
attr_reader :paid_content
|
28
|
+
attr_reader :location
|
29
|
+
attr_reader :location_radius
|
28
30
|
|
29
31
|
|
30
32
|
def initialize(params={})
|
@@ -35,7 +37,7 @@ class YouTubeIt
|
|
35
37
|
@response_format, @video_format,
|
36
38
|
@safe_search, @author, @lang,
|
37
39
|
@duration, @time, @hd, @caption,
|
38
|
-
@uploader, @region, @paid_content = nil
|
40
|
+
@uploader, @region, @location, @location_radius, @paid_content = nil
|
39
41
|
@url = base_url
|
40
42
|
@dev_key = params[:dev_key] if params[:dev_key]
|
41
43
|
|
@@ -80,6 +82,8 @@ class YouTubeIt
|
|
80
82
|
'hd' => @hd,
|
81
83
|
'caption' => @caption,
|
82
84
|
'region' => @region,
|
85
|
+
'location' => @location,
|
86
|
+
'location-radius' => @location_radius,
|
83
87
|
'paid-content' => @paid_content,
|
84
88
|
'uploader' => @uploader
|
85
89
|
}
|
@@ -195,8 +195,8 @@ class YouTubeIt
|
|
195
195
|
comment_body = comment_xml_for(:comment => comment, :reply_to => reply_to_url(video_id, reply_to))
|
196
196
|
comment_url = "/feeds/api/videos/%s/comments" % video_id
|
197
197
|
response = yt_session.post(comment_url, comment_body)
|
198
|
-
|
199
|
-
return {:code => response.status, :body => response.body}
|
198
|
+
comment = YouTubeIt::Parser::CommentsFeedParser.new(response.body).parse_single_entry
|
199
|
+
return {:code => response.status, :body => response.body, :comment => comment}
|
200
200
|
end
|
201
201
|
|
202
202
|
def delete_comment(video_id, comment_id)
|
@@ -238,26 +238,26 @@ class YouTubeIt
|
|
238
238
|
def profiles(usernames_to_fetch)
|
239
239
|
usernames_to_fetch.each_slice(50).map do |usernames|
|
240
240
|
post = Nokogiri::XML <<-BATCH
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
<batch:operation type="query" />
|
241
|
+
<feed
|
242
|
+
xmlns='http://www.w3.org/2005/Atom'
|
243
|
+
xmlns:media='http://search.yahoo.com/mrss/'
|
244
|
+
xmlns:batch='http://schemas.google.com/gdata/batch'
|
245
|
+
xmlns:yt='http://gdata.youtube.com/schemas/2007'>
|
247
246
|
</feed>
|
248
247
|
BATCH
|
249
248
|
usernames.each do |username|
|
250
249
|
post.at('feed').add_child <<-ENTRY
|
251
|
-
<entry
|
250
|
+
<entry>
|
251
|
+
<batch:operation type="query" />
|
252
252
|
<id>#{profile_url(username)}</id>
|
253
253
|
<batch:id>#{username}</batch:id>
|
254
254
|
</entry>
|
255
255
|
ENTRY
|
256
256
|
end
|
257
257
|
|
258
|
-
post_body = ''
|
258
|
+
post_body = StringIO.new('')
|
259
259
|
post.write_to( post_body, :indent => 2 )
|
260
|
-
post_body_io = StringIO.new(post_body)
|
260
|
+
post_body_io = StringIO.new(post_body.string)
|
261
261
|
|
262
262
|
response = yt_session.post('feeds/api/users/batch', post_body_io )
|
263
263
|
YouTubeIt::Parser::BatchProfileFeedParser.new(response).parse
|
@@ -450,8 +450,9 @@ class YouTubeIt
|
|
450
450
|
end
|
451
451
|
|
452
452
|
def parse_upload_error_from(string)
|
453
|
-
|
454
|
-
|
453
|
+
xml = Nokogiri::XML(string).at('errors')
|
454
|
+
if xml
|
455
|
+
xml.css("error").inject('') do |all_faults, error|
|
455
456
|
if error.at("internalReason")
|
456
457
|
msg_error = error.at("internalReason").text
|
457
458
|
elsif error.at("location")
|
@@ -462,7 +463,7 @@ class YouTubeIt
|
|
462
463
|
code = error.at("code").text if error.at("code")
|
463
464
|
all_faults + sprintf("%s: %s\n", msg_error, code)
|
464
465
|
end
|
465
|
-
|
466
|
+
else
|
466
467
|
string[/<TITLE>(.+)<\/TITLE>/, 1] || string
|
467
468
|
end
|
468
469
|
end
|
data/lib/youtube_it/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: youtube_it
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-07-12 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: nokogiri
|
18
|
-
requirement: &
|
18
|
+
requirement: &70273407416220 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
@@ -23,10 +23,10 @@ dependencies:
|
|
23
23
|
version: 1.5.2
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70273407416220
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: oauth
|
29
|
-
requirement: &
|
29
|
+
requirement: &70273407413640 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ~>
|
@@ -34,10 +34,10 @@ dependencies:
|
|
34
34
|
version: 0.4.4
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70273407413640
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: oauth2
|
40
|
-
requirement: &
|
40
|
+
requirement: &70273407413140 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
@@ -45,10 +45,10 @@ dependencies:
|
|
45
45
|
version: '0.6'
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70273407413140
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: simple_oauth
|
51
|
-
requirement: &
|
51
|
+
requirement: &70273407412680 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ~>
|
@@ -56,10 +56,10 @@ dependencies:
|
|
56
56
|
version: 0.1.5
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70273407412680
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: faraday
|
62
|
-
requirement: &
|
62
|
+
requirement: &70273407412060 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ~>
|
@@ -67,10 +67,10 @@ dependencies:
|
|
67
67
|
version: '0.8'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70273407412060
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: builder
|
73
|
-
requirement: &
|
73
|
+
requirement: &70273407411540 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - ! '>='
|
@@ -78,7 +78,7 @@ dependencies:
|
|
78
78
|
version: '0'
|
79
79
|
type: :runtime
|
80
80
|
prerelease: false
|
81
|
-
version_requirements: *
|
81
|
+
version_requirements: *70273407411540
|
82
82
|
description: Upload, delete, update, comment on youtube videos all from one gem.
|
83
83
|
email:
|
84
84
|
- kylejginavan@gmail.com
|