chocolate_rain 0.0.1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/chocolate_rain.gemspec +26 -0
- data/generators/youtube_model/USAGE +3 -0
- data/generators/youtube_model/templates/config.yml +6 -0
- data/generators/youtube_model/templates/model.rb +17 -0
- data/generators/youtube_model/templates/unit_test.rb +7 -0
- data/generators/youtube_model/youtube_model_generator.rb +15 -0
- data/lib/.DS_Store +0 -0
- data/lib/chocolate_rain.rb +5 -0
- data/lib/chocolate_rain/version.rb +3 -0
- data/lib/gdata/auth/authsub.rb +161 -0
- data/lib/gdata/auth/clientlogin.rb +102 -0
- data/lib/gdata/client.rb +84 -0
- data/lib/gdata/client/apps.rb +27 -0
- data/lib/gdata/client/base.rb +182 -0
- data/lib/gdata/client/blogger.rb +28 -0
- data/lib/gdata/client/booksearch.rb +28 -0
- data/lib/gdata/client/calendar.rb +58 -0
- data/lib/gdata/client/contacts.rb +28 -0
- data/lib/gdata/client/doclist.rb +28 -0
- data/lib/gdata/client/finance.rb +28 -0
- data/lib/gdata/client/gbase.rb +28 -0
- data/lib/gdata/client/gmail.rb +28 -0
- data/lib/gdata/client/health.rb +28 -0
- data/lib/gdata/client/notebook.rb +28 -0
- data/lib/gdata/client/photos.rb +29 -0
- data/lib/gdata/client/spreadsheets.rb +28 -0
- data/lib/gdata/client/webmaster_tools.rb +28 -0
- data/lib/gdata/client/youtube.rb +47 -0
- data/lib/gdata/g_data.rb +22 -0
- data/lib/gdata/http.rb +18 -0
- data/lib/gdata/http/default_service.rb +82 -0
- data/lib/gdata/http/mime_body.rb +95 -0
- data/lib/gdata/http/request.rb +74 -0
- data/lib/gdata/http/response.rb +44 -0
- data/lib/youtube_helpers.rb +58 -0
- data/lib/youtube_model.rb +341 -0
- metadata +84 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (C) 2008 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "rexml/document"
|
16
|
+
|
17
|
+
module GData
|
18
|
+
module HTTP
|
19
|
+
|
20
|
+
# Very simple class to hold everything about an HTTP request.
|
21
|
+
class Request
|
22
|
+
|
23
|
+
# The URL of the request.
|
24
|
+
attr_accessor :url
|
25
|
+
# The body of the request.
|
26
|
+
attr_accessor :body
|
27
|
+
# The HTTP method being used in the request.
|
28
|
+
attr_accessor :method
|
29
|
+
# The HTTP headers of the request.
|
30
|
+
attr_accessor :headers
|
31
|
+
|
32
|
+
# Only the URL itself is required, everything else is optional.
|
33
|
+
def initialize(url, options = {})
|
34
|
+
@url = url
|
35
|
+
options.each do |key, value|
|
36
|
+
self.send("#{key}=", value)
|
37
|
+
end
|
38
|
+
|
39
|
+
@method ||= :get
|
40
|
+
@headers ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns whether or not a request is chunked.
|
44
|
+
def chunked?
|
45
|
+
if @headers['Transfer-Encoding'] == 'chunked'
|
46
|
+
return true
|
47
|
+
else
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sets if the request is using chunked transfer-encoding.
|
53
|
+
def chunked=(enabled)
|
54
|
+
if enabled
|
55
|
+
@headers['Transfer-Encoding'] = 'chunked'
|
56
|
+
else
|
57
|
+
@headers.delete('Transfer-Encoding')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Calculates and sets the length of the body.
|
62
|
+
def calculate_length!
|
63
|
+
if not @headers['Content-Length'] and not chunked? \
|
64
|
+
and method != :get and method != :delete
|
65
|
+
if @body
|
66
|
+
@headers['Content-Length'] = @body.length
|
67
|
+
else
|
68
|
+
@headers['Content-Length'] = 0
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (C) 2008 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'gdata/client'
|
16
|
+
|
17
|
+
module GData
|
18
|
+
module HTTP
|
19
|
+
|
20
|
+
# An extremely simple class to hold the values of an HTTP response.
|
21
|
+
class Response
|
22
|
+
|
23
|
+
# The HTTP response code.
|
24
|
+
attr_accessor :status_code
|
25
|
+
# The body of the HTTP response.
|
26
|
+
attr_accessor :body
|
27
|
+
# The headers of the HTTP response.
|
28
|
+
attr_accessor :headers
|
29
|
+
|
30
|
+
# Converts the response body into a REXML::Document
|
31
|
+
def to_xml
|
32
|
+
if @body
|
33
|
+
begin
|
34
|
+
return REXML::Document.new(@body).root
|
35
|
+
rescue
|
36
|
+
raise GData::Client::Error, "Response body not XML."
|
37
|
+
end
|
38
|
+
else
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module YouTubeModel # :nodoc:
|
2
|
+
module Helpers
|
3
|
+
# This helper returns the required html to embed a youtube video.
|
4
|
+
# You can customize it with the following options:
|
5
|
+
# * <tt>:border</tt> Specifies if the player is bordered or not.
|
6
|
+
# * <tt>:related</tt> Specifies if the player will include related videos.
|
7
|
+
# * <tt>:colors</tt> Array with the desired colors of the player.
|
8
|
+
# * <tt>:language</tt> Specifies the language of the player.
|
9
|
+
# * <tt>:width</tt> Specifies the player's width.
|
10
|
+
# * <tt>:height</tt> Specifies the player's height.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# # in controller:
|
14
|
+
# @top_rated = YouTube.top_rated(:today)
|
15
|
+
#
|
16
|
+
# # in view:
|
17
|
+
# <% @top_rated.videos.each do |video| -%>
|
18
|
+
# <p><%= youtube_embed video, :border => true %></p>
|
19
|
+
# <% end -%>
|
20
|
+
def youtube_embed(video, options = {})
|
21
|
+
settings = {
|
22
|
+
:border => '0',
|
23
|
+
:rel => '0',
|
24
|
+
:color1 => '0x666666',
|
25
|
+
:color2 => '0x666666',
|
26
|
+
:hl => 'en',
|
27
|
+
:width => 425,
|
28
|
+
:height => 373
|
29
|
+
}.merge(options)
|
30
|
+
|
31
|
+
params = settings.to_query
|
32
|
+
%Q(
|
33
|
+
<object width="#{settings[:width]}" height="#{settings[:height]}">
|
34
|
+
<param name="movie" value="http://www.youtube.com/v/#{video.id}&#{params}"></param>
|
35
|
+
<param name="wmode" value="transparent"></param>
|
36
|
+
<embed src="http://www.youtube.com/v/#{video.id}&#{params}" type="application/x-shockwave-flash" wmode="transparent" width="#{settings[:width]}" height="#{settings[:height]}"></embed>
|
37
|
+
</object>
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns a link to the authentication Google page.
|
42
|
+
#
|
43
|
+
# Pass the new_<your-controller>_url or whatever url you use to the Upload's step 1
|
44
|
+
#
|
45
|
+
# Example:
|
46
|
+
# <%= link_to 'Upload a new video', youtube_auth_url(new_videos_url) %>
|
47
|
+
#
|
48
|
+
def youtube_auth_url(next_url)
|
49
|
+
params = {
|
50
|
+
:session => YT_CONFIG['auth_sub']['session'],
|
51
|
+
:secure => YT_CONFIG['auth_sub']['secure'],
|
52
|
+
:scope => 'http://gdata.youtube.com',
|
53
|
+
:next => next_url
|
54
|
+
}
|
55
|
+
"https://www.google.com/accounts/AuthSubRequest?#{params.to_query}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,341 @@
|
|
1
|
+
include GData
|
2
|
+
|
3
|
+
module YouTubeModel # :nodoc:
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Call this method to make an ActiveResource model ready to roll with YouTube
|
10
|
+
def acts_as_youtube_model
|
11
|
+
self.site = "http://gdata.youtube.com/feeds/api"
|
12
|
+
self.timeout = 5
|
13
|
+
|
14
|
+
extend YouTubeModel::SingletonMethods
|
15
|
+
include YouTubeModel::InstanceMethods
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
# Returns an array of +entry+, or an empty array when there's no such +entry+
|
21
|
+
def videos
|
22
|
+
if respond_to?(:entry)
|
23
|
+
entry.is_a?(Array) ? entry : [entry]
|
24
|
+
else
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module SingletonMethods
|
31
|
+
# Retrieve the top rated videos for a time. Valid times are:
|
32
|
+
# * :today (1 day)
|
33
|
+
# * :this_week (7 days)
|
34
|
+
# * :this_month (1 month)
|
35
|
+
# * :all_time (default)
|
36
|
+
def top_rated(time = :all_time)
|
37
|
+
request("standardfeeds/top_rated#{query_string(:time => time)}")
|
38
|
+
end
|
39
|
+
|
40
|
+
# Retrieve the top favorited videos for a time. Valid times are:
|
41
|
+
# * :today (1 day)
|
42
|
+
# * :this_week (7 days)
|
43
|
+
# * :this_month (1 month)
|
44
|
+
# * :all_time (default)
|
45
|
+
def top_favorites(time = :all_time)
|
46
|
+
request("standardfeeds/top_favorites#{query_string(:time => time)}")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Retrieve the most viewed videos for a time. Valid times are:
|
50
|
+
# * :today (1 day)
|
51
|
+
# * :this_week (7 days)
|
52
|
+
# * :this_month (1 month)
|
53
|
+
# * :all_time (default)
|
54
|
+
def most_viewed(time = :all_time)
|
55
|
+
request("standardfeeds/most_viewed#{query_string(:time => time)}")
|
56
|
+
end
|
57
|
+
|
58
|
+
# Retrieve the most recent videos for a time. Valid times are:
|
59
|
+
# * :today (1 day)
|
60
|
+
# * :this_week (7 days)
|
61
|
+
# * :this_month (1 month)
|
62
|
+
# * :all_time (default)
|
63
|
+
def most_recent(time = :all_time)
|
64
|
+
request("standardfeeds/most_recent#{query_string(:time => time)}")
|
65
|
+
end
|
66
|
+
|
67
|
+
# Retrieve the most discussed videos for a time. Valid times are:
|
68
|
+
# * :today (1 day)
|
69
|
+
# * :this_week (7 days)
|
70
|
+
# * :this_month (1 month)
|
71
|
+
# * :all_time (default)
|
72
|
+
def most_discussed(time = :all_time)
|
73
|
+
request("standardfeeds/most_discussed#{query_string(:time => time)}")
|
74
|
+
end
|
75
|
+
|
76
|
+
# Retrieve the most linked videos for a time. Valid times are:
|
77
|
+
# * :today (1 day)
|
78
|
+
# * :this_week (7 days)
|
79
|
+
# * :this_month (1 month)
|
80
|
+
# * :all_time (default)
|
81
|
+
def most_linked(time = :all_time)
|
82
|
+
request("standardfeeds/most_linked#{query_string(:time => time)}")
|
83
|
+
end
|
84
|
+
|
85
|
+
# Retrieve the most responded videos for a time. Valid times are:
|
86
|
+
# * :today (1 day)
|
87
|
+
# * :this_week (7 days)
|
88
|
+
# * :this_month (1 month)
|
89
|
+
# * :all_time (default)
|
90
|
+
def most_responded(time = :all_time)
|
91
|
+
request("standardfeeds/most_responded#{query_string(:time => time)}")
|
92
|
+
end
|
93
|
+
|
94
|
+
# Retrieve the recently featured videos.
|
95
|
+
def recently_featured
|
96
|
+
request("standardfeeds/recently_featured")
|
97
|
+
end
|
98
|
+
|
99
|
+
# Retrieve the videos watchables on mobile.
|
100
|
+
def watch_on_mobile
|
101
|
+
request("standardfeeds/watch_on_mobile")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Finds videos by categories or keywords.
|
105
|
+
#
|
106
|
+
# Capitalize words if you refer to a category.
|
107
|
+
#
|
108
|
+
# You can use the operators +NOT+(-) and +OR+(|). For example:
|
109
|
+
# find_by_category_and_tag('cats|dogs', '-rats', 'Comedy')
|
110
|
+
def find_by_category_and_tag(*tags_and_cats)
|
111
|
+
request("videos/-/#{tags_and_cats.map{ |t| CGI::escape(t) }.join('/')}")
|
112
|
+
end
|
113
|
+
|
114
|
+
# Finds videos by tags (keywords).
|
115
|
+
#
|
116
|
+
# You can use the operators +NOT+(-) and +OR+(|). For example:
|
117
|
+
# find_by_tag('cats|dogs', '-rats')
|
118
|
+
def find_by_tag(*tags)
|
119
|
+
url = "videos/-/%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fkeywords.cat%7D"
|
120
|
+
keywords = tags.map{ |t| CGI::escape(t) }.join('/')
|
121
|
+
request("#{url}#{keywords}")
|
122
|
+
end
|
123
|
+
|
124
|
+
# Finds videos by tags (keywords).
|
125
|
+
#
|
126
|
+
# You can use the operators +NOT+(-) and +OR+(|). For example:
|
127
|
+
# find_by_tag('cats|dogs', '-rats')
|
128
|
+
def find_by_category(*categories)
|
129
|
+
url = "videos/-/%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fcategories.cat%7D"
|
130
|
+
keywords = categories.map{ |c| CGI::escape(c) }.join('/')
|
131
|
+
request("#{url}#{keywords}")
|
132
|
+
end
|
133
|
+
|
134
|
+
# Find uploaded videos by a user.
|
135
|
+
def uploaded_by(username)
|
136
|
+
request("users/#{username}/uploads")
|
137
|
+
end
|
138
|
+
|
139
|
+
# Comments for a video.
|
140
|
+
def comments_for(video)
|
141
|
+
request(video.comments.feedLink.href)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Related videos for a video.
|
145
|
+
def related_to(video)
|
146
|
+
request(video.link[2].href)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Responses videos for a video.
|
150
|
+
def responses_to(video)
|
151
|
+
request(video.link[1].href)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Find uploaded videos by a user as default.
|
155
|
+
def uploaded_by_user(token)
|
156
|
+
get_request_with_user_as_default("users/default/uploads", token)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Find a video through a search query. Options are:
|
160
|
+
# * :orderby (:relevance, :published, :viewCount, :rating)
|
161
|
+
# * :start_index
|
162
|
+
# * :max_results
|
163
|
+
# * :author
|
164
|
+
# * :lr
|
165
|
+
# * :racy (:include, :exclude)
|
166
|
+
# * :restriction
|
167
|
+
#
|
168
|
+
# See options details at {YouTube API}[http://code.google.com/apis/youtube/developers_guide_protocol.html#Searching_for_Videos]
|
169
|
+
#
|
170
|
+
# Note: +alt+ option is still in researching because it causes some errors.
|
171
|
+
def find(query, options = {})
|
172
|
+
options[:vq] = query
|
173
|
+
options[:orderby] ||= :relevance
|
174
|
+
options.delete(:alt)
|
175
|
+
params = Hash[*options.stringify_keys.collect{ |k, v|
|
176
|
+
[k.dasherize, v] }.flatten
|
177
|
+
]
|
178
|
+
request("videos#{query_string(params)}")
|
179
|
+
end
|
180
|
+
|
181
|
+
# Search for a specific video by its ID.
|
182
|
+
# http://www.youtube.com/watch?v=JMDcOViViNY
|
183
|
+
# Here the id is: *JMDcOViViNY* NOTE: this method returns the video itself,
|
184
|
+
# no need to call @yt.video
|
185
|
+
def find_by_id(id)
|
186
|
+
request("videos/#{id}")
|
187
|
+
end
|
188
|
+
|
189
|
+
# Fetchs few YouTube categories
|
190
|
+
def video_categories
|
191
|
+
[["Film & Animation", "Film"], ["Autos & Vehicles", "Autos"], ["Music", "Music"], ["Pets & Animals", "Animals"], ["Sports", "Sports"],
|
192
|
+
["Travel & Events", "Travel"], ["News & Politics", "News"], ["Howto & Style", "Howto"], ["Gaming", "Games"], ["Comedy", "Comedy"],
|
193
|
+
["People & Blogs", "People"], ["Entertainment", "Entertainment"], ["Education", "Education"], ["Nonprofits & Activism", "Nonprofit"],
|
194
|
+
["Science & Technology", "Tech"]]
|
195
|
+
end
|
196
|
+
|
197
|
+
# Fetchs all YouTube categories
|
198
|
+
def categories
|
199
|
+
connection.get('/schemas/2007/categories.cat')['category']
|
200
|
+
end
|
201
|
+
|
202
|
+
# Returns an array with only the +label+ and +term+ attributes of categories.
|
203
|
+
def categories_collection
|
204
|
+
categories.collect { |cat|
|
205
|
+
[cat['label'], cat['term']]
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
# Sends a POST to YouTube to get the upload url and token.
|
210
|
+
#
|
211
|
+
# Receives a hash with the following keys:
|
212
|
+
# * <tt>:title</tt> Title of the video.
|
213
|
+
# * <tt>:description</tt> Description of the video.
|
214
|
+
# * <tt>:category</tt> Category of the video.
|
215
|
+
# * <tt>:keywords</tt> Keywords for the video.
|
216
|
+
# * <tt>:auth_sub</tt> Authentication token.
|
217
|
+
# * <tt>:nexturl</tt> Url to redirect after the video has been uploaded. Leave it nil to go to http://www.youtube.com/my_videos
|
218
|
+
#
|
219
|
+
# Returns a hash with the keys:
|
220
|
+
# * <tt>:url</tt> url for upload the video to.
|
221
|
+
# * <tt>:token</tt> token hash necessary to upload.
|
222
|
+
# * <tt>:code</tt> response code of the POST.
|
223
|
+
def get_upload_url(meta)
|
224
|
+
xml_entry = build_xml_entry(meta)
|
225
|
+
headers = {
|
226
|
+
'Authorization' => %Q(AuthSub token="#{meta[:auth_sub]}"),
|
227
|
+
'X-GData-Client' => YT_CONFIG['auth_sub']['client_key'],
|
228
|
+
'X-GData-Key' => "key=#{YT_CONFIG['auth_sub']['developer_key']}",
|
229
|
+
'Content-Length' => xml_entry.length.to_s,
|
230
|
+
'Content-Type' => "application/atom+xml; charset=UTF-8"
|
231
|
+
}
|
232
|
+
response = connection.post('/action/GetUploadToken', xml_entry, headers)
|
233
|
+
meta[:nexturl] ||= 'http://www.youtube.com/my_videos'
|
234
|
+
upload = {}
|
235
|
+
(Hpricot.XML(response.body)/:response).each do |elm|
|
236
|
+
upload[:url] = "#{(elm/:url).text}?#{{:nexturl => meta[:nexturl]}.to_query}"
|
237
|
+
upload[:token] = (elm/:token).text
|
238
|
+
end if response.code == "200"
|
239
|
+
upload[:code] = response.code
|
240
|
+
|
241
|
+
upload
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
def delete_video(video_id, token)
|
246
|
+
delete_request_with_user_as_default("users/default/uploads/#{video_id}", token)
|
247
|
+
end
|
248
|
+
|
249
|
+
def update_video(video_id, token, video_params)
|
250
|
+
xml_entry = build_xml_entry(video_params)
|
251
|
+
put_request_with_user_as_default("users/default/uploads/#{video_id}", token, xml_entry)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Find status of video uploaded by a user.
|
255
|
+
def video_status(token, video_id)
|
256
|
+
get_request_with_user_as_default("users/default/uploads/#{video_id}", token)
|
257
|
+
end
|
258
|
+
|
259
|
+
def videos_with_user_as_default(token)
|
260
|
+
get_request_with_user_as_default("users/default/uploads", token)
|
261
|
+
end
|
262
|
+
|
263
|
+
protected
|
264
|
+
|
265
|
+
# Loads a response into a new Object of this class
|
266
|
+
def request(url)
|
267
|
+
url = "#{self.prefix}#{url}" unless url =~ /\Ahttp:/
|
268
|
+
new.load(extend_attributes(connection.get(url, 'Accept' => '*/*')))
|
269
|
+
end
|
270
|
+
|
271
|
+
def put_request_with_user_as_default(url, token, meta)
|
272
|
+
headers = {
|
273
|
+
'Content-Type' => "application/atom+xml",
|
274
|
+
'Content-Length' => meta.length.to_s,
|
275
|
+
'Authorization' => %Q(AuthSub token="#{token}"),
|
276
|
+
'X-GData-Client' => YT_CONFIG['auth_sub']['client_key'],
|
277
|
+
'X-GData-Key' => "key=#{YT_CONFIG['auth_sub']['developer_key']}"
|
278
|
+
}
|
279
|
+
url = "#{self.prefix}#{url}" unless url =~ /\Ahttp:/
|
280
|
+
connection.put(url, meta, headers) rescue nil
|
281
|
+
end
|
282
|
+
|
283
|
+
def delete_request_with_user_as_default(url, token)
|
284
|
+
headers = {
|
285
|
+
'Accept' => 'application/atom+xml',
|
286
|
+
'Authorization' => %Q(AuthSub token="#{token}"),
|
287
|
+
'X-GData-Client' => YT_CONFIG['auth_sub']['client_key'],
|
288
|
+
'X-GData-Key' => "key=#{YT_CONFIG['auth_sub']['developer_key']}"
|
289
|
+
}
|
290
|
+
url = "#{self.prefix}#{url}" unless url =~ /\Ahttp:/
|
291
|
+
connection.delete(url, headers) rescue nil
|
292
|
+
end
|
293
|
+
|
294
|
+
def get_request_with_user_as_default(url, token)
|
295
|
+
headers = {
|
296
|
+
'Accept' => '*/*',
|
297
|
+
'Authorization' => %Q(AuthSub token="#{token}")
|
298
|
+
}
|
299
|
+
url = "#{self.prefix}#{url}" unless url =~ /\Ahttp:/
|
300
|
+
new.load(extend_attributes(connection.get(url, headers)))
|
301
|
+
end
|
302
|
+
|
303
|
+
private
|
304
|
+
|
305
|
+
# Adds some extra keys to the +attributes+ hash
|
306
|
+
def extend_attributes(yt)
|
307
|
+
unless yt['entry'].nil?
|
308
|
+
(yt['entry'].is_a?(Array) ? yt['entry'] : [yt['entry']]).each { |v| scan_id(v) }
|
309
|
+
else
|
310
|
+
scan_id(yt)
|
311
|
+
end
|
312
|
+
yt
|
313
|
+
end
|
314
|
+
|
315
|
+
# Renames the +id+ key to +api_id+ and leaves the simple video id on the
|
316
|
+
# +id+ key
|
317
|
+
def scan_id(attrs)
|
318
|
+
attrs['api_id'] = attrs['id']
|
319
|
+
attrs['id'] = attrs['api_id'].scan(/[\w-]+$/).to_s
|
320
|
+
attrs
|
321
|
+
end
|
322
|
+
|
323
|
+
# Builds the XML content to do the POST to obtain the upload url and token.
|
324
|
+
def build_xml_entry(attrs)
|
325
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
326
|
+
xml.instruct! :xml, :version => '1.0', :encoding => nil
|
327
|
+
xml.entry :xmlns => 'http://www.w3.org/2005/Atom',
|
328
|
+
'xmlns:media' => 'http://search.yahoo.com/mrss/',
|
329
|
+
'xmlns:yt' => 'http://gdata.youtube.com/schemas/2007' do
|
330
|
+
xml.media :group do
|
331
|
+
xml.tag! 'media:title', attrs[:title]
|
332
|
+
xml.media :description, attrs[:content], :type => 'plain'
|
333
|
+
xml.media :category, attrs[:category], :scheme => 'http://gdata.youtube.com/schemas/2007/categories.cat'
|
334
|
+
xml.media :category, "ytm_#{YT_CONFIG['developer_tag']}", :scheme => 'http://gdata.youtube.com/schemas/2007/developertags.cat'
|
335
|
+
xml.tag! 'media:keywords', attrs[:keywords]
|
336
|
+
end
|
337
|
+
end
|
338
|
+
xml.target!
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|