agiley-youtube-g 0.6.2
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/History.txt +52 -0
- data/Manifest.txt +34 -0
- data/README.txt +102 -0
- data/Rakefile +24 -0
- data/TODO.txt +16 -0
- data/lib/youtube_g.rb +70 -0
- data/lib/youtube_g/chain_io.rb +71 -0
- data/lib/youtube_g/client.rb +100 -0
- data/lib/youtube_g/model/author.rb +11 -0
- data/lib/youtube_g/model/category.rb +11 -0
- data/lib/youtube_g/model/comment.rb +20 -0
- data/lib/youtube_g/model/contact.rb +16 -0
- data/lib/youtube_g/model/content.rb +18 -0
- data/lib/youtube_g/model/playlist.rb +8 -0
- data/lib/youtube_g/model/rating.rb +17 -0
- data/lib/youtube_g/model/thumbnail.rb +17 -0
- data/lib/youtube_g/model/user.rb +20 -0
- data/lib/youtube_g/model/video.rb +204 -0
- data/lib/youtube_g/parser.rb +252 -0
- data/lib/youtube_g/record.rb +12 -0
- data/lib/youtube_g/request/base_search.rb +26 -0
- data/lib/youtube_g/request/comments_search.rb +41 -0
- data/lib/youtube_g/request/standard_search.rb +40 -0
- data/lib/youtube_g/request/user_search.rb +43 -0
- data/lib/youtube_g/request/video_search.rb +93 -0
- data/lib/youtube_g/request/video_upload.rb +218 -0
- data/lib/youtube_g/response/comments_search.rb +41 -0
- data/lib/youtube_g/response/video_search.rb +41 -0
- data/lib/youtube_g/version.rb +3 -0
- data/test/helper.rb +6 -0
- data/test/test_chain_io.rb +63 -0
- data/test/test_client.rb +265 -0
- data/test/test_video.rb +38 -0
- data/test/test_video_search.rb +134 -0
- metadata +140 -0
data/History.txt
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
* Implement video update and video delete in Upload
|
2
|
+
* Refactor the uploader slightly
|
3
|
+
* Use Builder to generate XML packets
|
4
|
+
* Use a faster Camping-based URL escaper (also avoid cgi.rb)
|
5
|
+
* Removed the logger nightmare, use YouTubeG.logger for everything whatever that may be
|
6
|
+
* Use streams for file uploads instead of in-memory strings
|
7
|
+
|
8
|
+
== 0.5.0 / 2009-01-07
|
9
|
+
|
10
|
+
* Fixed bug in user favorites (thanks Pius Uzamere)
|
11
|
+
|
12
|
+
== 0.4.9.9 / 2008-09-01
|
13
|
+
|
14
|
+
* Add Geodata information (thanks Jose Galisteo)
|
15
|
+
* Added :page and :per_page options, this allows easier usage of the will_paginate
|
16
|
+
plugin with the library. The :offset and :max_results options are no longer available. [Daniel Insley]
|
17
|
+
* Added ability to get video responses on the instances of the YouTube::Model::Video object. [Daniel Insley]
|
18
|
+
* Added and improved the existing documentation [Daniel Insley]
|
19
|
+
* Fixed usage of deprecated yt:racy, now using media:rating [Daniel Insley]
|
20
|
+
* Renamed can_embed? method to embeddable? [Daniel Insley]
|
21
|
+
* Added ability for padingation and ordering on standard feeds. [Daniel Insley]
|
22
|
+
* Add error-handling for video upload errors. [FiXato]
|
23
|
+
* Add error-handling for authentication errors from YouTube during video upload. [FiXato]
|
24
|
+
* Add support for making videos private upon video upload. [FiXato]
|
25
|
+
* Fix issue with REXML parsing of video upload response. [FiXato]
|
26
|
+
* Fix issue with response code comparison. [FiXato]
|
27
|
+
* Authcode is now retrieved for video uploads. [FiXato]
|
28
|
+
* Add basic support for uploading videos [thanks Joe Damato]
|
29
|
+
* Add basic support for related videos [tmm1]
|
30
|
+
* Improve docs for order_by attribute [thanks Jason Arora]
|
31
|
+
* Added support for the "racy" parameter (choices are "include" or "exclude") [thanks Jason Arora]
|
32
|
+
* Add missing attribute reader for description [tmm1]
|
33
|
+
* Fix issue with missing yt:statistics and viewCount [tmm1]
|
34
|
+
* Allow Client#video_by to take either a url or a video id [tmm1]
|
35
|
+
|
36
|
+
== 0.4.1 / 2008-02-11
|
37
|
+
|
38
|
+
* Added 3GPP video format [shane]
|
39
|
+
* Fixed tests [shane]
|
40
|
+
|
41
|
+
== 0.4.0 / 2007-12-18
|
42
|
+
|
43
|
+
* Fixed API projection in search URL [Pete Higgins]
|
44
|
+
* Fixed embeddable video searching [Pete Higgins]
|
45
|
+
* Fixed video embeddable detection [Pete Higgins]
|
46
|
+
* Fixed unique id hyphen detection [Pete Higgins, Chris Taggart]
|
47
|
+
|
48
|
+
== 0.3.0 / 2007-09-17
|
49
|
+
|
50
|
+
* Initial public release
|
51
|
+
* Birthday!
|
52
|
+
|
data/Manifest.txt
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
TODO.txt
|
6
|
+
lib/youtube_g.rb
|
7
|
+
lib/youtube_g/chain_io.rb
|
8
|
+
lib/youtube_g/client.rb
|
9
|
+
lib/youtube_g/model/author.rb
|
10
|
+
lib/youtube_g/model/category.rb
|
11
|
+
lib/youtube_g/model/comment.rb
|
12
|
+
lib/youtube_g/model/contact.rb
|
13
|
+
lib/youtube_g/model/content.rb
|
14
|
+
lib/youtube_g/model/playlist.rb
|
15
|
+
lib/youtube_g/model/rating.rb
|
16
|
+
lib/youtube_g/model/thumbnail.rb
|
17
|
+
lib/youtube_g/model/user.rb
|
18
|
+
lib/youtube_g/model/video.rb
|
19
|
+
lib/youtube_g/parser.rb
|
20
|
+
lib/youtube_g/record.rb
|
21
|
+
lib/youtube_g/request/base_search.rb
|
22
|
+
lib/youtube_g/request/comments_search.rb
|
23
|
+
lib/youtube_g/request/standard_search.rb
|
24
|
+
lib/youtube_g/request/user_search.rb
|
25
|
+
lib/youtube_g/request/video_search.rb
|
26
|
+
lib/youtube_g/request/video_upload.rb
|
27
|
+
lib/youtube_g/response/comments_search.rb
|
28
|
+
lib/youtube_g/response/video_search.rb
|
29
|
+
lib/youtube_g/version.rb
|
30
|
+
test/helper.rb
|
31
|
+
test/test_chain_io.rb
|
32
|
+
test/test_client.rb
|
33
|
+
test/test_video.rb
|
34
|
+
test/test_video_search.rb
|
data/README.txt
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
= youtube-g
|
2
|
+
|
3
|
+
http://youtube-g.rubyforge.org/
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
youtube-g is a pure Ruby client for the YouTube GData API. It provides an easy
|
8
|
+
way to access the latest YouTube video search results from your own programs.
|
9
|
+
In comparison with the earlier Youtube search interfaces, this new API and
|
10
|
+
library offers much-improved flexibility around executing complex search
|
11
|
+
queries to obtain well-targeted video search results.
|
12
|
+
|
13
|
+
More detail on the underlying source Google-provided API is available at:
|
14
|
+
|
15
|
+
http://code.google.com/apis/youtube/overview.html
|
16
|
+
|
17
|
+
== AUTHORS
|
18
|
+
|
19
|
+
Shane Vitarana and Walter Korman
|
20
|
+
|
21
|
+
== WHERE TO GET HELP
|
22
|
+
|
23
|
+
http://rubyforge.org/projects/youtube-g
|
24
|
+
http://groups.google.com/group/ruby-youtube-library
|
25
|
+
|
26
|
+
== FEATURES/PROBLEMS:
|
27
|
+
|
28
|
+
* Aims to be in parity with Google's YouTube GData API. Core functionality
|
29
|
+
is currently present -- work is in progress to fill in the rest.
|
30
|
+
|
31
|
+
== SYNOPSIS:
|
32
|
+
|
33
|
+
Create a client:
|
34
|
+
|
35
|
+
require 'youtube_g'
|
36
|
+
client = YouTubeG::Client.new
|
37
|
+
|
38
|
+
Basic queries:
|
39
|
+
|
40
|
+
client.videos_by(:query => "penguin")
|
41
|
+
client.videos_by(:query => "penguin", :page => 2, :per_page => 15)
|
42
|
+
client.videos_by(:tags => ['tiger', 'leopard'])
|
43
|
+
client.videos_by(:categories => [:news, :sports])
|
44
|
+
client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
|
45
|
+
client.videos_by(:user => 'liz')
|
46
|
+
client.videos_by(:favorites, :user => 'liz')
|
47
|
+
|
48
|
+
Standard feeds:
|
49
|
+
|
50
|
+
client.videos_by(:most_viewed)
|
51
|
+
client.videos_by(:most_linked, :page => 3)
|
52
|
+
client.videos_by(:top_rated, :time => :today)
|
53
|
+
|
54
|
+
Advanced queries (with boolean operators OR (either), AND (include), NOT (exclude)):
|
55
|
+
|
56
|
+
client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] }, :tags => { :include => ['football'], :exclude => ['soccer'] })
|
57
|
+
|
58
|
+
Comment feeds for videos:
|
59
|
+
client.comments_for('some_youtube_id').comments
|
60
|
+
video = client.video_by('some_youtube_id')
|
61
|
+
video.comments_seach(:page => 2, :per_page => 12).comments
|
62
|
+
|
63
|
+
== LOGGING
|
64
|
+
|
65
|
+
YouTubeG passes all logs through the logger variable on the class itself. In Rails context, assign the Rails logger to that variable to collect the messages
|
66
|
+
(don't forget to set the level to debug):
|
67
|
+
|
68
|
+
YouTubeG.logger = RAILS_DEFAULT_LOGGER
|
69
|
+
RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
|
70
|
+
|
71
|
+
== REQUIREMENTS:
|
72
|
+
|
73
|
+
* builder gem
|
74
|
+
|
75
|
+
== INSTALL:
|
76
|
+
|
77
|
+
* sudo gem install youtube-g
|
78
|
+
|
79
|
+
== LICENSE:
|
80
|
+
|
81
|
+
MIT License
|
82
|
+
|
83
|
+
Copyright (c) 2007 Shane Vitarana and Walter Korman
|
84
|
+
|
85
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
86
|
+
a copy of this software and associated documentation files (the
|
87
|
+
'Software'), to deal in the Software without restriction, including
|
88
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
89
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
90
|
+
permit persons to whom the Software is furnished to do so, subject to
|
91
|
+
the following conditions:
|
92
|
+
|
93
|
+
The above copyright notice and this permission notice shall be
|
94
|
+
included in all copies or substantial portions of the Software.
|
95
|
+
|
96
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
97
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
98
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
99
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
100
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
101
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
102
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
require 'lib/youtube_g/version'
|
4
|
+
|
5
|
+
Hoe.new('youtube-g', YouTubeG::VERSION) do |p|
|
6
|
+
p.rubyforge_name = 'youtube-g'
|
7
|
+
p.author = ["Shane Vitarana", "Walter Korman", "Aman Gupta", "Filip H.F. Slagter", "msp"]
|
8
|
+
p.email = 'shanev@gmail.com'
|
9
|
+
p.summary = 'Ruby client for the YouTube GData API'
|
10
|
+
p.url = 'http://rubyforge.org/projects/youtube-g/'
|
11
|
+
p.extra_deps << 'builder'
|
12
|
+
p.remote_rdoc_dir = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Tag release'
|
16
|
+
task :tag do
|
17
|
+
svn_root = 'svn+ssh://drummr77@rubyforge.org/var/svn/youtube-g'
|
18
|
+
sh %(svn cp #{svn_root}/trunk #{svn_root}/tags/release-#{YouTubeG::VERSION} -m "Tag YouTubeG release #{YouTubeG::VERSION}")
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Load the library in an IRB session'
|
22
|
+
task :console do
|
23
|
+
sh %(irb -r lib/youtube_g.rb)
|
24
|
+
end
|
data/TODO.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
[ ] stub out http request/response cycle for tests
|
2
|
+
[ ] allow specifying values as single items where you don't need to wrap in a list, e.g. :tags => :chickens instead of :tags => [ 'chickens' ]
|
3
|
+
[ ] make sure symbols will work as well as tags everywhere (again, :tags => :chickens is same as :tags => 'chickens')
|
4
|
+
[ ] figure out better structure for class/file (either rename request/video_search.rb or split into one class per file again)
|
5
|
+
[ ] restore spaces after method def names
|
6
|
+
[ ] use a proxy for testing with static sample result xml so we have repeatable tests
|
7
|
+
[ ] Clean up tests using Shoulda to define contexts
|
8
|
+
[ ] Allow :category and :categories for query DSL
|
9
|
+
[ ] Exception handling
|
10
|
+
|
11
|
+
== API Features TODO
|
12
|
+
|
13
|
+
[ ] Profile feed parsing
|
14
|
+
[ ] Playlist feeds
|
15
|
+
[ ] User subscriptions
|
16
|
+
[ ] Video comments
|
data/lib/youtube_g.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'net/https'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'rexml/document'
|
6
|
+
require 'builder'
|
7
|
+
|
8
|
+
class YouTubeG
|
9
|
+
|
10
|
+
# Base error class for the extension
|
11
|
+
class Error < RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
# URL-escape a string. Stolen from Camping (wonder how many Ruby libs in the wild can say the same)
|
15
|
+
def self.esc(s) #:nodoc:
|
16
|
+
s.to_s.gsub(/[^ \w.-]+/n){'%'+($&.unpack('H2'*$&.size)*'%').upcase}.tr(' ', '+')
|
17
|
+
end
|
18
|
+
|
19
|
+
# Set the logger for the library
|
20
|
+
def self.logger=(any_logger)
|
21
|
+
@logger = any_logger
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get the logger for the library (by default will log to STDOUT). TODO: this is where we grab the Rails logger too
|
25
|
+
def self.logger
|
26
|
+
@logger ||= create_default_logger
|
27
|
+
end
|
28
|
+
|
29
|
+
# Gets mixed into the classes to provide the logger method
|
30
|
+
module Logging #:nodoc:
|
31
|
+
|
32
|
+
# Return the base logger set for the library
|
33
|
+
def logger
|
34
|
+
YouTubeG.logger
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def self.create_default_logger
|
40
|
+
logger = Logger.new(STDOUT)
|
41
|
+
logger.level = Logger::DEBUG
|
42
|
+
logger
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
%w(
|
47
|
+
version
|
48
|
+
client
|
49
|
+
record
|
50
|
+
parser
|
51
|
+
model/author
|
52
|
+
model/category
|
53
|
+
model/comment
|
54
|
+
model/contact
|
55
|
+
model/content
|
56
|
+
model/playlist
|
57
|
+
model/rating
|
58
|
+
model/thumbnail
|
59
|
+
model/user
|
60
|
+
model/video
|
61
|
+
request/base_search
|
62
|
+
request/comments_search
|
63
|
+
request/user_search
|
64
|
+
request/standard_search
|
65
|
+
request/video_upload
|
66
|
+
request/video_search
|
67
|
+
response/comments_search
|
68
|
+
response/video_search
|
69
|
+
chain_io
|
70
|
+
).each{|m| require File.dirname(__FILE__) + '/youtube_g/' + m }
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
#:stopdoc:
|
3
|
+
|
4
|
+
# Stream wrapper that reads IOs in succession. Can be fed to Net::HTTP as post body stream. We use it internally to stream file content
|
5
|
+
# instead of reading whole video files into memory. Strings passed to the constructor will be wrapped in StringIOs. By default it will auto-close
|
6
|
+
# file handles when they have been read completely to prevent our uploader from leaking file handles
|
7
|
+
#
|
8
|
+
# chain = ChainIO.new(File.open(__FILE__), File.open('/etc/passwd'), "abcd")
|
9
|
+
class YouTubeG::ChainIO
|
10
|
+
attr_accessor :autoclose
|
11
|
+
|
12
|
+
def initialize(*any_ios)
|
13
|
+
@autoclose = true
|
14
|
+
@chain = any_ios.flatten.map{|e| e.respond_to?(:read) ? e : StringIO.new(e.to_s) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(buffer_size = 1024)
|
18
|
+
# Read off the first element in the stack
|
19
|
+
current_io = @chain.shift
|
20
|
+
return false if !current_io
|
21
|
+
|
22
|
+
buf = current_io.read(buffer_size)
|
23
|
+
if !buf && @chain.empty? # End of streams
|
24
|
+
release_handle(current_io) if @autoclose
|
25
|
+
false
|
26
|
+
elsif !buf # This IO is depleted, but next one is available
|
27
|
+
release_handle(current_io) if @autoclose
|
28
|
+
read(buffer_size)
|
29
|
+
elsif buf.length < buffer_size # This IO is depleted, but we were asked for more
|
30
|
+
release_handle(current_io) if @autoclose
|
31
|
+
buf + (read(buffer_size - buf.length) || '') # and recurse
|
32
|
+
else # just return the buffer
|
33
|
+
@chain.unshift(current_io) # put the current back
|
34
|
+
buf
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Predict the length of all embedded IOs. Will automatically send file size.
|
39
|
+
def expected_length
|
40
|
+
@chain.inject(0) do | len, io |
|
41
|
+
if io.respond_to?(:length)
|
42
|
+
len + (io.length - io.pos)
|
43
|
+
elsif io.is_a?(File)
|
44
|
+
len + File.size(io.path) - io.pos
|
45
|
+
else
|
46
|
+
raise "Cannot predict length of #{io.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def release_handle(io)
|
53
|
+
io.close if io.respond_to?(:close)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Net::HTTP only can send chunks of 1024 bytes. This is very inefficient, so we have a spare IO that will send more when asked for 1024.
|
58
|
+
# We use delegation because the read call is recursive.
|
59
|
+
class YouTubeG::GreedyChainIO < DelegateClass(YouTubeG::ChainIO)
|
60
|
+
BIG_CHUNK = 512 * 1024 # 500 kb
|
61
|
+
|
62
|
+
def initialize(*with_ios)
|
63
|
+
__setobj__(YouTubeG::ChainIO.new(with_ios))
|
64
|
+
end
|
65
|
+
|
66
|
+
def read(any_buffer_size)
|
67
|
+
__getobj__.read(BIG_CHUNK)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#:startdoc:
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class YouTubeG
|
2
|
+
class Client
|
3
|
+
include YouTubeG::Logging
|
4
|
+
|
5
|
+
# Previously this was a logger instance but we now do it globally
|
6
|
+
def initialize(legacy_debug_flag = nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Retrieves an array of standard feed, custom query, or user videos.
|
10
|
+
#
|
11
|
+
# === Parameters
|
12
|
+
# If fetching videos for a standard feed:
|
13
|
+
# params<Symbol>:: Accepts a symbol of :top_rated, :top_favorites, :most_viewed,
|
14
|
+
# :most_popular, :most_recent, :most_discussed, :most_linked,
|
15
|
+
# :most_responded, :recently_featured, and :watch_on_mobile.
|
16
|
+
#
|
17
|
+
# You can find out more specific information about what each standard feed provides
|
18
|
+
# by visiting: http://code.google.com/apis/youtube/reference.html#Standard_feeds
|
19
|
+
#
|
20
|
+
# options<Hash> (optional):: Accepts the options of :time, :page (default is 1),
|
21
|
+
# and :per_page (default is 25). :offset and :max_results
|
22
|
+
# can also be passed for a custom offset.
|
23
|
+
#
|
24
|
+
# If fetching videos by tags, categories, query:
|
25
|
+
# params<Hash>:: Accepts the keys :tags, :categories, :query, :order_by,
|
26
|
+
# :author, :racy, :response_format, :video_format, :page (default is 1),
|
27
|
+
# and :per_page(default is 25)
|
28
|
+
#
|
29
|
+
# options<Hash>:: Not used. (Optional)
|
30
|
+
#
|
31
|
+
# If fetching videos for a particular user:
|
32
|
+
# params<Hash>:: Key of :user with a value of the username.
|
33
|
+
# options<Hash>:: Not used. (Optional)
|
34
|
+
# === Returns
|
35
|
+
# YouTubeG::Response::VideoSearch
|
36
|
+
def videos_by(params, options={})
|
37
|
+
request_params = params.respond_to?(:to_hash) ? params : options
|
38
|
+
request_params[:page] = integer_or_default(request_params[:page], 1)
|
39
|
+
|
40
|
+
unless request_params[:max_results]
|
41
|
+
request_params[:max_results] = integer_or_default(request_params[:per_page], 25)
|
42
|
+
end
|
43
|
+
|
44
|
+
unless request_params[:offset]
|
45
|
+
request_params[:offset] = calculate_offset(request_params[:page], request_params[:max_results] )
|
46
|
+
end
|
47
|
+
|
48
|
+
if params.respond_to?(:to_hash) and not params[:user]
|
49
|
+
request = YouTubeG::Request::VideoSearch.new(request_params)
|
50
|
+
elsif (params.respond_to?(:to_hash) && params[:user]) || (params == :favorites)
|
51
|
+
request = YouTubeG::Request::UserSearch.new(params, request_params)
|
52
|
+
else
|
53
|
+
request = YouTubeG::Request::StandardSearch.new(params, request_params)
|
54
|
+
end
|
55
|
+
|
56
|
+
logger.debug "Submitting request [url=#{request.url}]."
|
57
|
+
parser = YouTubeG::Parser::VideosFeedParser.new(request.url)
|
58
|
+
parser.parse
|
59
|
+
end
|
60
|
+
|
61
|
+
# Retrieves a single YouTube video.
|
62
|
+
#
|
63
|
+
# === Parameters
|
64
|
+
# vid<String>:: The ID or URL of the video that you'd like to retrieve.
|
65
|
+
#
|
66
|
+
# === Returns
|
67
|
+
# YouTubeG::Model::Video
|
68
|
+
def video_by(vid)
|
69
|
+
video_id = vid =~ /^http/ ? vid : "http://gdata.youtube.com/feeds/videos/#{vid}"
|
70
|
+
parser = YouTubeG::Parser::VideoFeedParser.new(video_id)
|
71
|
+
parser.parse
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retrieves a single YouTube video.
|
75
|
+
#
|
76
|
+
# === Parameters
|
77
|
+
# vid<String>:: The ID of the video whose contents you'd like to retrieve
|
78
|
+
#
|
79
|
+
# options<Hash> (optional):: Accepts the options of :page (default is 1),
|
80
|
+
# and :per_page (default is 25). :offset and :max_results
|
81
|
+
# can also be passed for a custom offset.
|
82
|
+
# === Returns
|
83
|
+
# YouTubeG::Response::CommentsSearch
|
84
|
+
def comments_for(vid, options={})
|
85
|
+
url = YouTubeG::Request::CommentsSearch.new(vid, options).url
|
86
|
+
YouTubeG::Parser::CommentsFeedParser.new(url).parse
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def calculate_offset(page, per_page)
|
92
|
+
page == 1 ? 1 : ((per_page * page) - per_page + 1)
|
93
|
+
end
|
94
|
+
|
95
|
+
def integer_or_default(value, default)
|
96
|
+
value = value.to_i
|
97
|
+
value > 0 ? value : default
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|