youtube-g 0.4.1 → 0.4.9.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,27 @@
1
+ == 0.4.9.9 / 2008-09-01
2
+
3
+ * Add Geodata information (thanks Jose Galisteo)
4
+ * Added :page and :per_page options, this allows easier usage of the will_paginate
5
+ plugin with the library. The :offset and :max_results options are no longer available. [Daniel Insley]
6
+ * Added ability to get video responses on the instances of the YouTube::Model::Video object. [Daniel Insley]
7
+ * Added and improved the existing documentation [Daniel Insley]
8
+ * Fixed usage of deprecated yt:racy, now using media:rating [Daniel Insley]
9
+ * Renamed can_embed? method to embeddable? [Daniel Insley]
10
+ * Added ability for padingation and ordering on standard feeds. [Daniel Insley]
11
+ * Add error-handling for video upload errors. [FiXato]
12
+ * Add error-handling for authentication errors from YouTube during video upload. [FiXato]
13
+ * Add support for making videos private upon video upload. [FiXato]
14
+ * Fix issue with REXML parsing of video upload response. [FiXato]
15
+ * Fix issue with response code comparison. [FiXato]
16
+ * Authcode is now retrieved for video uploads. [FiXato]
17
+ * Add basic support for uploading videos [thanks Joe Damato]
18
+ * Add basic support for related videos [tmm1]
19
+ * Improve docs for order_by attribute [thanks Jason Arora]
20
+ * Added support for the "racy" parameter (choices are "include" or "exclude") [thanks Jason Arora]
21
+ * Add missing attribute reader for description [tmm1]
22
+ * Fix issue with missing yt:statistics and viewCount [tmm1]
23
+ * Allow Client#video_by to take either a url or a video id [tmm1]
24
+
1
25
  == 0.4.1 / 2008-02-11
2
26
 
3
27
  * Added 3GPP video format [shane]
@@ -17,7 +17,11 @@ lib/youtube_g/model/user.rb
17
17
  lib/youtube_g/model/video.rb
18
18
  lib/youtube_g/parser.rb
19
19
  lib/youtube_g/record.rb
20
+ lib/youtube_g/request/base_search.rb
21
+ lib/youtube_g/request/standard_search.rb
22
+ lib/youtube_g/request/user_search.rb
20
23
  lib/youtube_g/request/video_search.rb
24
+ lib/youtube_g/request/video_upload.rb
21
25
  lib/youtube_g/response/video_search.rb
22
26
  test/test_client.rb
23
27
  test/test_video.rb
data/README.txt CHANGED
@@ -1,6 +1,9 @@
1
1
  youtube-g
2
2
  by Shane Vitarana and Walter Korman
3
- http://rubyforge.org/projects/youtube-g/
3
+
4
+ Rubyforge: http://rubyforge.org/projects/youtube-g/
5
+ RDoc: http://youtube-g.rubyforge.org/
6
+ Google Group: http://groups.google.com/group/ruby-youtube-library
4
7
 
5
8
  == DESCRIPTION:
6
9
 
@@ -23,13 +26,13 @@ http://code.google.com/apis/youtube/overview.html
23
26
 
24
27
  Create a client:
25
28
 
26
- require 'rubygems'
27
29
  require 'youtube_g'
28
30
  client = YouTubeG::Client.new
29
31
 
30
32
  Basic queries:
31
33
 
32
34
  client.videos_by(:query => "penguin")
35
+ client.videos_by(:query => "penguin", :page => 2, :per_page => 15)
33
36
  client.videos_by(:tags => ['tiger', 'leopard'])
34
37
  client.videos_by(:categories => [:news, :sports])
35
38
  client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
@@ -38,6 +41,7 @@ Basic queries:
38
41
  Standard feeds:
39
42
 
40
43
  client.videos_by(:most_viewed)
44
+ client.videos_by(:most_linked, :page => 3)
41
45
  client.videos_by(:top_rated, :time => :today)
42
46
 
43
47
  Advanced queries (with boolean operators OR (either), AND (include), NOT (exclude)):
data/TODO.txt CHANGED
@@ -1,12 +1,10 @@
1
1
  [ ] stub out http request/response cycle for tests
2
- [ ] consider defaulting the client to no-logger, rather than outputting to STDOUT.
3
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' ]
4
3
  [ ] make sure symbols will work as well as tags everywhere (again, :tags => :chickens is same as :tags => 'chickens')
5
4
  [ ] figure out better structure for class/file (either rename request/video_search.rb or split into one class per file again)
6
5
  [ ] restore spaces after method def names
7
6
  [ ] use a proxy for testing with static sample result xml so we have repeatable tests
8
7
  [ ] Clean up tests using Shoulda to define contexts
9
- [ ] Consolidate requires
10
8
  [ ] Allow :category and :categories for query DSL
11
9
  [ ] Exception handling
12
10
 
@@ -1,3 +1,10 @@
1
+ require 'logger'
2
+ require 'open-uri'
3
+ require 'net/https'
4
+ require 'digest/md5'
5
+ require 'rexml/document'
6
+ require 'cgi'
7
+
1
8
  require File.dirname(__FILE__) + '/youtube_g/client'
2
9
  require File.dirname(__FILE__) + '/youtube_g/record'
3
10
  require File.dirname(__FILE__) + '/youtube_g/parser'
@@ -10,9 +17,13 @@ require File.dirname(__FILE__) + '/youtube_g/model/rating'
10
17
  require File.dirname(__FILE__) + '/youtube_g/model/thumbnail'
11
18
  require File.dirname(__FILE__) + '/youtube_g/model/user'
12
19
  require File.dirname(__FILE__) + '/youtube_g/model/video'
20
+ require File.dirname(__FILE__) + '/youtube_g/request/base_search'
21
+ require File.dirname(__FILE__) + '/youtube_g/request/user_search'
22
+ require File.dirname(__FILE__) + '/youtube_g/request/standard_search'
23
+ require File.dirname(__FILE__) + '/youtube_g/request/video_upload'
13
24
  require File.dirname(__FILE__) + '/youtube_g/request/video_search'
14
25
  require File.dirname(__FILE__) + '/youtube_g/response/video_search'
15
26
 
16
- class YouTubeG
17
- VERSION = '0.4.1'
27
+ class YouTubeG #:nodoc:
28
+ VERSION = '0.4.9.9'
18
29
  end
@@ -1,35 +1,85 @@
1
- require 'logger'
2
-
3
1
  class YouTubeG
4
2
  class Client
5
3
  attr_accessor :logger
6
4
 
7
- def initialize(logger=Logger.new(STDOUT))
8
- @logger = logger
5
+ def initialize(logger=false)
6
+ @logger = Logger.new(STDOUT) if logger
9
7
  end
10
-
11
- # Params can be one of :most_viewed, :top_rated, :recently_featured, :watch_on_mobile
12
- # Or :tags, :categories, :query, :user
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
13
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
+
14
48
  if params.respond_to?(:to_hash) and not params[:user]
15
- request = YouTubeG::Request::VideoSearch.new(params)
16
-
49
+ request = YouTubeG::Request::VideoSearch.new(request_params)
17
50
  elsif (params.respond_to?(:to_hash) && params[:user]) || (params == :favorites)
18
- request = YouTubeG::Request::UserSearch.new(params, options)
19
-
51
+ request = YouTubeG::Request::UserSearch.new(request_params, options)
20
52
  else
21
- request = YouTubeG::Request::StandardSearch.new(params, options)
53
+ request = YouTubeG::Request::StandardSearch.new(params, request_params)
22
54
  end
23
55
 
24
- logger.debug "Submitting request [url=#{request.url}]."
56
+ logger.debug "Submitting request [url=#{request.url}]." if logger
25
57
  parser = YouTubeG::Parser::VideosFeedParser.new(request.url)
26
58
  parser.parse
27
59
  end
28
60
 
29
- def video_by(video_id)
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}"
30
70
  parser = YouTubeG::Parser::VideoFeedParser.new(video_id)
31
71
  parser.parse
32
72
  end
33
73
 
74
+ private
75
+
76
+ def calculate_offset(page, per_page)
77
+ page == 1 ? 1 : ((per_page * page) - per_page + 1)
78
+ end
79
+
80
+ def integer_or_default(value, default)
81
+ value = value.to_i
82
+ value > 0 ? value : default
83
+ end
34
84
  end
35
85
  end
@@ -1,5 +1,3 @@
1
- require 'logger'
2
-
3
1
  class YouTubeG
4
2
 
5
3
  # TODO: Why is this needed? Does this happen if running standalone w/o Rails?
@@ -1,7 +1,10 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Author < YouTubeG::Record
4
+ # *String*: Author's YouTube username.
4
5
  attr_reader :name
6
+
7
+ # *String*: Feed URL of the author.
5
8
  attr_reader :uri
6
9
  end
7
10
  end
@@ -1,7 +1,10 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Category < YouTubeG::Record
4
- attr_reader :label
4
+ # *String*:: Name of the YouTube category
5
+ attr_reader :label
6
+
7
+ # *String*:: Identifies the type of item described.
5
8
  attr_reader :term
6
9
  end
7
10
  end
@@ -1,7 +1,15 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Contact < YouTubeG::Record
4
+ # *String*:: Identifies the status of a contact.
5
+ #
6
+ # * The tag's value will be accepted if the authenticated user and the contact have marked each other as friends.
7
+ # * The tag's value will be requested if the contact has asked to be added to the authenticated user's contact list, but the request has not yet been accepted (or rejected).
8
+ # * The tag's value will be pending if the authenticated user has asked to be added to the contact's contact list, but the request has not yet been accepted or rejected.
9
+ #
4
10
  attr_reader :status
11
+
12
+ # *String*:: The Youtube username of the contact.
5
13
  attr_reader :username
6
14
  end
7
15
  end
@@ -1,10 +1,15 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Content < YouTubeG::Record
4
+ # *Boolean*:: Description of the video.
4
5
  attr_reader :default
6
+ # *Fixnum*:: Length of the video in seconds.
5
7
  attr_reader :duration
8
+ # YouTubeG::Model::Video::Format:: Specifies the video format of the video object
6
9
  attr_reader :format
10
+ # *String*:: Specifies the MIME type of the media object.
7
11
  attr_reader :mime_type
12
+ # *String*:: Specifies the URL for the media object.
8
13
  attr_reader :url
9
14
 
10
15
  alias :is_default? :default
@@ -1,6 +1,7 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Playlist < YouTubeG::Record
4
+ # *String*:: User entered description for the playlist.
4
5
  attr_reader :description
5
6
  end
6
7
  end
@@ -1,9 +1,16 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Rating < YouTubeG::Record
4
+ # *Float*:: Average rating given to the video
4
5
  attr_reader :average
6
+
7
+ # *Fixnum*:: Maximum rating that can be assigned to the video
5
8
  attr_reader :max
9
+
10
+ # *Fixnum*:: Minimum rating that can be assigned to the video
6
11
  attr_reader :min
12
+
13
+ # *Fixnum*:: Indicates how many people have rated the video
7
14
  attr_reader :rater_count
8
15
  end
9
16
  end
@@ -1,9 +1,16 @@
1
1
  class YouTubeG
2
2
  module Model
3
3
  class Thumbnail < YouTubeG::Record
4
+ # *String*:: URL for the thumbnail image.
4
5
  attr_reader :url
6
+
7
+ # *Fixnum*:: Height of the thumbnail image.
5
8
  attr_reader :height
9
+
10
+ # *Fixnum*:: Width of the thumbnail image.
6
11
  attr_reader :width
12
+
13
+ # *String*:: Specifies the time offset at which the frame shown in the thumbnail image appears in the video.
7
14
  attr_reader :time
8
15
  end
9
16
  end
@@ -1,87 +1,171 @@
1
+ # TODO
2
+ # * self atom feed
3
+ # * alternate youtube watch url
4
+ # * comments feedLink
5
+
1
6
  class YouTubeG
2
7
  module Model
3
8
  class Video < YouTubeG::Record
4
9
  # Describes the various file formats in which a Youtube video may be
5
10
  # made available and allows looking them up by format code number.
6
- #
7
11
  class Format
8
12
  @@formats = Hash.new
9
13
 
14
+ # Instantiates a new video format object.
15
+ #
16
+ # == Parameters
17
+ # :format_code<Fixnum>:: The Youtube Format code of the object.
18
+ # :name<Symbol>:: The name of the format
19
+ #
20
+ # == Returns
21
+ # YouTubeG::Model::Video::Format: Video format object
10
22
  def initialize(format_code, name)
11
23
  @format_code = format_code
12
24
  @name = name
13
25
 
14
26
  @@formats[format_code] = self
15
27
  end
16
-
28
+
29
+ # Allows you to get the video format for a specific format code.
30
+ #
31
+ # A full list of format codes is available at:
32
+ #
33
+ # http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:content
34
+ #
35
+ # == Parameters
36
+ # :format_code<Fixnum>:: The Youtube Format code of the object.
37
+ #
38
+ # == Returns
39
+ # YouTubeG::Model::Video::Format: Video format object
17
40
  def self.by_code(format_code)
18
41
  @@formats[format_code]
19
42
  end
20
43
 
21
- # Flash format on YouTube site. All videos are available in this
22
- # format.
23
- #
44
+ # Flash format on YouTube site. All videos are available in this format.
24
45
  FLASH = YouTubeG::Model::Video::Format.new(0, :flash)
25
46
 
26
- # RTSP streaming URL for mobile video playback. H.263 video (176x144)
27
- # and AMR audio.
28
- #
47
+ # RTSP streaming URL for mobile video playback. H.263 video (176x144) and AMR audio.
29
48
  RTSP = YouTubeG::Model::Video::Format.new(1, :rtsp)
30
49
 
31
50
  # HTTP URL to the embeddable player (SWF) for this video. This format
32
51
  # is not available for a video that is not embeddable.
33
- #
34
52
  SWF = YouTubeG::Model::Video::Format.new(5, :swf)
35
53
 
54
+ # RTSP streaming URL for mobile video playback. MPEG-4 SP video (up to 176x144) and AAC audio.
36
55
  THREE_GPP = YouTubeG::Model::Video::Format.new(6, :three_gpp)
37
56
  end
38
-
57
+
58
+ # *Fixnum*:: Duration of a video in seconds.
39
59
  attr_reader :duration
60
+
61
+ # *Boolean*:: Specifies that a video may or may not be embedded on other websites.
40
62
  attr_reader :noembed
63
+
64
+ # *Fixnum*:: Specifies the order in which the video appears in a playlist.
41
65
  attr_reader :position
66
+
67
+ # *Boolean*:: Specifies that a video is flagged as adult or not.
42
68
  attr_reader :racy
43
- attr_reader :statistics
44
69
 
70
+ # *String*: Specifies a URI that uniquely and permanently identifies the video.
45
71
  attr_reader :video_id
72
+
73
+ # *Time*:: When the video was published on Youtube.
46
74
  attr_reader :published_at
75
+
76
+ # *Time*:: When the video's data was last updated.
47
77
  attr_reader :updated_at
78
+
79
+ # *Array*:: A array of YouTubeG::Model::Category objects that describe the videos categories.
48
80
  attr_reader :categories
81
+
82
+ # *Array*:: An array of words associated with the video.
49
83
  attr_reader :keywords
84
+
85
+ # *String*:: Description of the video.
86
+ attr_reader :description
87
+
88
+ # *String*:: Title for the video.
50
89
  attr_reader :title
90
+
91
+ # *String*:: Description of the video.
51
92
  attr_reader :html_content
93
+
94
+ # YouTubeG::Model::Author:: Information about the YouTube user who owns a piece of video content.
52
95
  attr_reader :author
53
-
54
- # YouTubeG::Model::Content records describing the individual media content
55
- # data available for this video. Most, but not all, videos offer this.
96
+
97
+ # *Array*:: An array of YouTubeG::Model::Content objects describing the individual media content data available for this video. Most, but not all, videos offer this.
56
98
  attr_reader :media_content
57
-
58
- attr_reader :thumbnails # YouTubeG::Model::Thumbnail records
99
+
100
+ # *Array*:: An array of YouTubeG::Model::Thumbnail objects that contain information regarding the videos thumbnail images.
101
+ attr_reader :thumbnails
102
+
103
+ # *String*:: The link to watch the URL on YouTubes website.
59
104
  attr_reader :player_url
105
+
106
+ # YouTubeG::Model::Rating:: Information about the videos rating.
60
107
  attr_reader :rating
108
+
109
+ # *Fixnum*:: Number of times that the video has been viewed
61
110
  attr_reader :view_count
62
111
 
63
- # TODO:
64
- # self atom feed
65
- # alternate youtube watch url
66
- # responses feed
67
- # related feed
68
- # comments feedLink
69
-
70
- # For convenience, the video_id with the URL stripped out, useful for searching for the video again
71
- # without having to store it anywhere. A regular query search, with this id will return the same video.
72
- # http://gdata.youtube.com/feeds/videos/ZTUVgYoeN_o
112
+ # Geodata
113
+ attr_reader :where
114
+ attr_reader :position
115
+ attr_reader :latitude
116
+ attr_reader :longitude
117
+
118
+ attr_reader :statistics
119
+
120
+ # Videos related to the current video.
121
+ #
122
+ # === Returns
123
+ # YouTubeG::Response::VideoSearch
124
+ def related
125
+ YouTubeG::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/related").parse
126
+ end
127
+
128
+ # Video responses to the current video.
129
+ #
130
+ # === Returns
131
+ # YouTubeG::Response::VideoSearch
132
+ def responses
133
+ YouTubeG::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/responses").parse
134
+ end
135
+
136
+ # The ID of the video, useful for searching for the video again without having to store it anywhere.
137
+ # A regular query search, with this id will return the same video.
138
+ #
139
+ # === Example
140
+ # >> video.unique_id
141
+ # => "ZTUVgYoeN_o"
142
+ #
143
+ # === Returns
144
+ # String: The Youtube video id.
73
145
  def unique_id
74
- video_id.match(/videos\/([^<]+)/).captures.first
146
+ video_id[/videos\/([^<]+)/, 1]
75
147
  end
76
148
 
77
- def can_embed?
149
+ # Allows you to check whether the video can be embedded on a webpage.
150
+ #
151
+ # === Returns
152
+ # Boolean: True if the video can be embedded, false if not.
153
+ def embeddable?
78
154
  not @noembed
79
155
  end
80
156
 
157
+ # Provides a URL and various other types of information about a video.
158
+ #
159
+ # === Returns
160
+ # YouTubeG::Model::Content: Data about the embeddable video.
81
161
  def default_media_content
82
162
  @media_content.find { |c| c.is_default? }
83
163
  end
84
164
 
165
+ # Gives you the HTML to embed the video on your website.
166
+ #
167
+ # === Returns
168
+ # String: The HTML for embedding the video on your website.
85
169
  def embed_html(width = 425, height = 350)
86
170
  <<EDOC
87
171
  <object width="#{width}" height="#{height}">
@@ -93,6 +177,10 @@ class YouTubeG
93
177
  EDOC
94
178
  end
95
179
 
180
+ # The URL needed for embedding the video in a page.
181
+ #
182
+ # === Returns
183
+ # String: Absolute URL for embedding video
96
184
  def embed_url
97
185
  @player_url.sub('watch?', '').sub('=', '/')
98
186
  end