agiley-youtube-g 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Author < YouTubeG::Record
4
+ # *String*: Author's YouTube username.
5
+ attr_reader :name
6
+
7
+ # *String*: Feed URL of the author.
8
+ attr_reader :uri
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Category < YouTubeG::Record
4
+ # *String*:: Name of the YouTube category
5
+ attr_reader :label
6
+
7
+ # *String*:: Identifies the type of item described.
8
+ attr_reader :term
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Comment < YouTubeG::Record
4
+ # *Time*:: When the video was published on Youtube.
5
+ attr_reader :published_at
6
+
7
+ # *Time*:: When the video's data was last updated.
8
+ attr_reader :updated_at
9
+
10
+ # *String*:: Title for the video.
11
+ attr_reader :title
12
+
13
+ # *String*:: Description of the video.
14
+ attr_reader :content
15
+
16
+ # YouTubeG::Model::Author:: Information about the YouTube user who owns a piece of video content.
17
+ attr_reader :author
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ class YouTubeG
2
+ module Model
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
+ #
10
+ attr_reader :status
11
+
12
+ # *String*:: The Youtube username of the contact.
13
+ attr_reader :username
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Content < YouTubeG::Record
4
+ # *Boolean*:: Description of the video.
5
+ attr_reader :default
6
+ # *Fixnum*:: Length of the video in seconds.
7
+ attr_reader :duration
8
+ # YouTubeG::Model::Video::Format:: Specifies the video format of the video object
9
+ attr_reader :format
10
+ # *String*:: Specifies the MIME type of the media object.
11
+ attr_reader :mime_type
12
+ # *String*:: Specifies the URL for the media object.
13
+ attr_reader :url
14
+
15
+ alias :is_default? :default
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Playlist < YouTubeG::Record
4
+ # *String*:: User entered description for the playlist.
5
+ attr_reader :description
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Rating < YouTubeG::Record
4
+ # *Float*:: Average rating given to the video
5
+ attr_reader :average
6
+
7
+ # *Fixnum*:: Maximum rating that can be assigned to the video
8
+ attr_reader :max
9
+
10
+ # *Fixnum*:: Minimum rating that can be assigned to the video
11
+ attr_reader :min
12
+
13
+ # *Fixnum*:: Indicates how many people have rated the video
14
+ attr_reader :rater_count
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Thumbnail < YouTubeG::Record
4
+ # *String*:: URL for the thumbnail image.
5
+ attr_reader :url
6
+
7
+ # *Fixnum*:: Height of the thumbnail image.
8
+ attr_reader :height
9
+
10
+ # *Fixnum*:: Width of the thumbnail image.
11
+ attr_reader :width
12
+
13
+ # *String*:: Specifies the time offset at which the frame shown in the thumbnail image appears in the video.
14
+ attr_reader :time
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ class YouTubeG
2
+ module Model
3
+ class User < YouTubeG::Record
4
+ attr_reader :age
5
+ attr_reader :books
6
+ attr_reader :company
7
+ attr_reader :gender
8
+ attr_reader :hobbies
9
+ attr_reader :hometown
10
+ attr_reader :location
11
+ attr_reader :movies
12
+ attr_reader :music
13
+ attr_reader :occupation
14
+ attr_reader :relationship
15
+ attr_reader :school
16
+ attr_reader :description
17
+ attr_reader :username
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,204 @@
1
+ # TODO
2
+ # * self atom feed
3
+ # * alternate youtube watch url
4
+ # * comments feedLink
5
+
6
+ class YouTubeG
7
+ module Model
8
+ class Video < YouTubeG::Record
9
+ # Describes the various file formats in which a Youtube video may be
10
+ # made available and allows looking them up by format code number.
11
+ class Format
12
+ @@formats = Hash.new
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
22
+ def initialize(format_code, name)
23
+ @format_code = format_code
24
+ @name = name
25
+
26
+ @@formats[format_code] = self
27
+ end
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
40
+ def self.by_code(format_code)
41
+ @@formats[format_code]
42
+ end
43
+
44
+ # Flash format on YouTube site. All videos are available in this format.
45
+ FLASH = YouTubeG::Model::Video::Format.new(0, :flash)
46
+
47
+ # RTSP streaming URL for mobile video playback. H.263 video (176x144) and AMR audio.
48
+ RTSP = YouTubeG::Model::Video::Format.new(1, :rtsp)
49
+
50
+ # HTTP URL to the embeddable player (SWF) for this video. This format
51
+ # is not available for a video that is not embeddable.
52
+ SWF = YouTubeG::Model::Video::Format.new(5, :swf)
53
+
54
+ # RTSP streaming URL for mobile video playback. MPEG-4 SP video (up to 176x144) and AAC audio.
55
+ THREE_GPP = YouTubeG::Model::Video::Format.new(6, :three_gpp)
56
+ end
57
+
58
+ # *Fixnum*:: Duration of a video in seconds.
59
+ attr_reader :duration
60
+
61
+ # *Boolean*:: Specifies that a video may or may not be embedded on other websites.
62
+ attr_reader :noembed
63
+
64
+ # *Fixnum*:: Specifies the order in which the video appears in a playlist.
65
+ attr_reader :position
66
+
67
+ # *Boolean*:: Specifies that a video is flagged as adult or not.
68
+ attr_reader :racy
69
+
70
+ # *String*: Specifies a URI that uniquely and permanently identifies the video.
71
+ attr_reader :video_id
72
+
73
+ # *Time*:: When the video was published on Youtube.
74
+ attr_reader :published_at
75
+
76
+ # *Time*:: When the video's data was last updated.
77
+ attr_reader :updated_at
78
+
79
+ # *Array*:: A array of YouTubeG::Model::Category objects that describe the videos categories.
80
+ attr_reader :categories
81
+
82
+ # *Array*:: An array of words associated with the video.
83
+ attr_reader :keywords
84
+
85
+ # *String*:: Description of the video.
86
+ attr_reader :description
87
+
88
+ # *String*:: Title for the video.
89
+ attr_reader :title
90
+
91
+ # *String*:: Description of the video.
92
+ attr_reader :html_content
93
+
94
+ # YouTubeG::Model::Author:: Information about the YouTube user who owns a piece of video content.
95
+ attr_reader :author
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.
98
+ attr_reader :media_content
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.
104
+ attr_reader :player_url
105
+
106
+ # YouTubeG::Model::Rating:: Information about the videos rating.
107
+ attr_reader :rating
108
+
109
+ # *Fixnum*:: Number of times that the video has been viewed
110
+ attr_reader :view_count
111
+
112
+ # *Fixnum*:: Number of times that the video has been favorited
113
+ attr_reader :favorite_count
114
+
115
+
116
+ # Geodata
117
+ attr_reader :where
118
+ attr_reader :position
119
+ attr_reader :latitude
120
+ attr_reader :longitude
121
+
122
+ attr_reader :statistics
123
+
124
+ # Videos related to the current video.
125
+ #
126
+ # === Returns
127
+ # YouTubeG::Response::VideoSearch
128
+ def related
129
+ YouTubeG::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/related").parse
130
+ end
131
+
132
+ # Video responses to the current video.
133
+ #
134
+ # === Returns
135
+ # YouTubeG::Response::VideoSearch
136
+ def responses
137
+ YouTubeG::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/responses").parse
138
+ end
139
+
140
+ # Comments on the current video.
141
+ #
142
+ # === Returns
143
+ # YouTubeG::Response::CommentsSearch
144
+ def comments_search(options={})
145
+ url = YouTubeG::Request::CommentsSearch.new(unique_id,options).url
146
+ YouTubeG::Parser::CommentsFeedParser.new(url).parse
147
+ end
148
+
149
+
150
+ # The ID of the video, useful for searching for the video again without having to store it anywhere.
151
+ # A regular query search, with this id will return the same video.
152
+ #
153
+ # === Example
154
+ # >> video.unique_id
155
+ # => "ZTUVgYoeN_o"
156
+ #
157
+ # === Returns
158
+ # String: The Youtube video id.
159
+ def unique_id
160
+ video_id[/videos\/([^<]+)/, 1]
161
+ end
162
+
163
+ # Allows you to check whether the video can be embedded on a webpage.
164
+ #
165
+ # === Returns
166
+ # Boolean: True if the video can be embedded, false if not.
167
+ def embeddable?
168
+ not @noembed
169
+ end
170
+
171
+ # Provides a URL and various other types of information about a video.
172
+ #
173
+ # === Returns
174
+ # YouTubeG::Model::Content: Data about the embeddable video.
175
+ def default_media_content
176
+ @media_content.find { |c| c.is_default? }
177
+ end
178
+
179
+ # Gives you the HTML to embed the video on your website.
180
+ #
181
+ # === Returns
182
+ # String: The HTML for embedding the video on your website.
183
+ def embed_html(width = 425, height = 350)
184
+ <<EDOC
185
+ <object width="#{width}" height="#{height}">
186
+ <param name="movie" value="#{embed_url}"></param>
187
+ <param name="wmode" value="transparent"></param>
188
+ <embed src="#{embed_url}" type="application/x-shockwave-flash"
189
+ wmode="transparent" width="#{width}" height="#{height}"></embed>
190
+ </object>
191
+ EDOC
192
+ end
193
+
194
+ # The URL needed for embedding the video in a page.
195
+ #
196
+ # === Returns
197
+ # String: Absolute URL for embedding video
198
+ def embed_url
199
+ @player_url.sub('watch?', '').sub('=', '/')
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,252 @@
1
+ class YouTubeG
2
+ module Parser #:nodoc:
3
+ class FeedParser #:nodoc:
4
+ def initialize(url)
5
+ @url = url
6
+ end
7
+
8
+ def parse
9
+ parse_content open(@url).read
10
+ end
11
+ end
12
+
13
+ class VideoFeedParser < FeedParser #:nodoc:
14
+
15
+ def parse_content(content)
16
+ doc = REXML::Document.new(content)
17
+ entry = doc.elements["entry"]
18
+ parse_entry(entry)
19
+ end
20
+
21
+ protected
22
+ def parse_entry(entry)
23
+ video_id = entry.elements["id"].text
24
+
25
+ if entry.elements["app:control/yt:state"]
26
+ # yt:state generally indicates a video is unavailable
27
+ # see: http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state
28
+ unless entry.elements["app:control/yt:state[@name='restricted']"]
29
+ # the exception I've found is for *restricted* videos, which generally
30
+ # means they're not available for viewing on a device other than a web browser
31
+ # or in a certain region
32
+ return nil
33
+ end
34
+ end
35
+
36
+ # if there's no content we're going to puke later
37
+ unless entry.elements['content']
38
+ return nil
39
+ end
40
+
41
+ published_at = Time.parse(entry.elements["published"].text)
42
+ updated_at = Time.parse(entry.elements["updated"].text)
43
+
44
+ # parse the category and keyword lists
45
+ categories = []
46
+ keywords = []
47
+ entry.elements.each("category") do |category|
48
+ # determine if it's really a category, or just a keyword
49
+ scheme = category.attributes["scheme"]
50
+ if (scheme =~ /\/categories\.cat$/)
51
+ # it's a category
52
+ categories << YouTubeG::Model::Category.new(
53
+ :term => category.attributes["term"],
54
+ :label => category.attributes["label"])
55
+
56
+ elsif (scheme =~ /\/keywords\.cat$/)
57
+ # it's a keyword
58
+ keywords << category.attributes["term"]
59
+ end
60
+ end
61
+
62
+ title = entry.elements["title"].text
63
+ html_content = entry.elements["content"].text
64
+
65
+ # parse the author
66
+ author_element = entry.elements["author"]
67
+ author = nil
68
+ if author_element
69
+ author = YouTubeG::Model::Author.new(
70
+ :name => author_element.elements["name"].text,
71
+ :uri => author_element.elements["uri"].text)
72
+ end
73
+
74
+ media_group = entry.elements["media:group"]
75
+ description = media_group.elements["media:description"].text
76
+ duration = media_group.elements["yt:duration"].attributes["seconds"].to_i
77
+
78
+ media_content = []
79
+ media_group.elements.each("media:content") do |mce|
80
+ media_content << parse_media_content(mce)
81
+ end
82
+
83
+ player_url = media_group.elements["media:player"].attributes["url"]
84
+
85
+ # parse thumbnails
86
+ thumbnails = []
87
+ media_group.elements.each("media:thumbnail") do |thumb_element|
88
+ # TODO: convert time HH:MM:ss string to seconds?
89
+ thumbnails << YouTubeG::Model::Thumbnail.new(
90
+ :url => thumb_element.attributes["url"],
91
+ :height => thumb_element.attributes["height"].to_i,
92
+ :width => thumb_element.attributes["width"].to_i,
93
+ :time => thumb_element.attributes["time"])
94
+ end
95
+
96
+ rating_element = entry.elements["gd:rating"]
97
+ rating = nil
98
+ if rating_element
99
+ rating = YouTubeG::Model::Rating.new(
100
+ :min => rating_element.attributes["min"].to_i,
101
+ :max => rating_element.attributes["max"].to_i,
102
+ :rater_count => rating_element.attributes["numRaters"].to_i,
103
+ :average => rating_element.attributes["average"].to_f)
104
+ end
105
+
106
+ if (el = entry.elements["yt:statistics"])
107
+ view_count, favorite_count = el.attributes["viewCount"].to_i, el.attributes["favoriteCount"].to_i
108
+ else
109
+ view_count, favorite_count = 0,0
110
+ end
111
+
112
+ noembed = entry.elements["yt:noembed"] ? true : false
113
+ racy = entry.elements["media:rating"] ? true : false
114
+
115
+ if where = entry.elements["georss:where"]
116
+ position = where.elements["gml:Point"].elements["gml:pos"].text
117
+ latitude, longitude = position.split(" ")
118
+ end
119
+
120
+ YouTubeG::Model::Video.new(
121
+ :video_id => video_id,
122
+ :published_at => published_at,
123
+ :updated_at => updated_at,
124
+ :categories => categories,
125
+ :keywords => keywords,
126
+ :title => title,
127
+ :html_content => html_content,
128
+ :author => author,
129
+ :description => description,
130
+ :duration => duration,
131
+ :media_content => media_content,
132
+ :player_url => player_url,
133
+ :thumbnails => thumbnails,
134
+ :rating => rating,
135
+ :view_count => view_count,
136
+ :favorite_count => favorite_count,
137
+ :noembed => noembed,
138
+ :racy => racy,
139
+ :where => where,
140
+ :position => position,
141
+ :latitude => latitude,
142
+ :longitude => longitude)
143
+ end
144
+
145
+ def parse_media_content (media_content_element)
146
+ content_url = media_content_element.attributes["url"]
147
+ format_code = media_content_element.attributes["yt:format"].to_i
148
+ format = YouTubeG::Model::Video::Format.by_code(format_code)
149
+ duration = media_content_element.attributes["duration"].to_i
150
+ mime_type = media_content_element.attributes["type"]
151
+ default = (media_content_element.attributes["isDefault"] == "true")
152
+
153
+ YouTubeG::Model::Content.new(
154
+ :url => content_url,
155
+ :format => format,
156
+ :duration => duration,
157
+ :mime_type => mime_type,
158
+ :default => default)
159
+ end
160
+ end
161
+
162
+ class VideosFeedParser < VideoFeedParser #:nodoc:
163
+
164
+ private
165
+ def parse_content(content)
166
+ doc = REXML::Document.new(content)
167
+ feed = doc.elements["feed"]
168
+
169
+ if (feed)
170
+ feed_id = feed.elements["id"].text
171
+ updated_at = Time.parse(feed.elements["updated"].text)
172
+ total_result_count = feed.elements["openSearch:totalResults"].text.to_i
173
+ offset = feed.elements["openSearch:startIndex"].text.to_i
174
+ max_result_count = feed.elements["openSearch:itemsPerPage"].text.to_i
175
+
176
+ videos = []
177
+ feed.elements.each("entry") do |entry|
178
+ if video = parse_entry(entry)
179
+ videos << video
180
+ end
181
+ end
182
+
183
+ YouTubeG::Response::VideoSearch.new(
184
+ :feed_id => feed_id,
185
+ :updated_at => updated_at,
186
+ :total_result_count => total_result_count,
187
+ :offset => offset,
188
+ :max_result_count => max_result_count,
189
+ :videos => videos)
190
+ else
191
+ entry = doc.elements["entry"]
192
+ video = parse_entry(entry) if (entry)
193
+ end
194
+ end
195
+ end
196
+
197
+ class CommentsFeedParser < FeedParser
198
+
199
+ def parse_content(content)
200
+ doc = REXML::Document.new(content)
201
+ feed = doc.elements['feed']
202
+
203
+ feed_id = feed.elements["id"].text
204
+ updated_at = Time.parse(feed.elements["updated"].text)
205
+ total_result_count = feed.elements["openSearch:totalResults"].text.to_i
206
+ offset = feed.elements["openSearch:startIndex"].text.to_i
207
+ max_result_count = feed.elements["openSearch:itemsPerPage"].text.to_i
208
+
209
+ comments = []
210
+ feed.elements.each('entry') do |entry|
211
+ comments << parse_entry(entry)
212
+ end
213
+ YouTubeG::Response::CommentsSearch.new(
214
+ :feed_id => feed_id,
215
+ :updated_at => updated_at,
216
+ :total_result_count => total_result_count,
217
+ :offset => offset,
218
+ :max_result_count => max_result_count,
219
+ :comments => comments)
220
+ end
221
+
222
+ private
223
+ def parse_entry(entry)
224
+ comment_id = entry.elements["id"].text
225
+
226
+ published_at = Time.parse(entry.elements["published"].text)
227
+ updated_at = Time.parse(entry.elements["updated"].text)
228
+
229
+ title = entry.elements["title"].text
230
+ content = entry.elements["content"].text
231
+
232
+ # parse the author
233
+ author_element = entry.elements["author"]
234
+ author = nil
235
+ if author_element
236
+ author = YouTubeG::Model::Author.new(
237
+ :name => author_element.elements["name"].text,
238
+ :uri => author_element.elements["uri"].text)
239
+ end
240
+
241
+
242
+ comment = YouTubeG::Model::Comment.new(
243
+ :published_at => published_at,
244
+ :updated_at => updated_at,
245
+ :title => title,
246
+ :content => content,
247
+ :author => author)
248
+ return comment
249
+ end
250
+ end
251
+ end
252
+ end