youtube_it 1.4.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,6 +22,51 @@ class YouTubeIt
22
22
  end
23
23
  end
24
24
 
25
+
26
+ module FieldSearch
27
+ def default_fields
28
+ "id,updated,openSearch:totalResults,openSearch:startIndex,openSearch:itemsPerPage"
29
+ end
30
+
31
+ def fields_to_params(fields)
32
+ return "" unless fields
33
+
34
+ fields_param = [default_fields]
35
+
36
+ if fields[:recorded]
37
+ if fields[:recorded].is_a? Range
38
+ fields_param << "entry[xs:date(yt:recorded) > xs:date('#{formatted_date(fields[:recorded].first)}') and xs:date(yt:recorded) < xs:date('#{formatted_date(fields[:recorded].last)}')]"
39
+ else
40
+ fields_param << "entry[xs:date(yt:recorded) = xs:date('#{formatted_date(fields[:recorded])}')]"
41
+ end
42
+ end
43
+
44
+ if fields[:published]
45
+ if fields[:published].is_a? Range
46
+ fields_param << "entry[xs:dateTime(published) > xs:dateTime('#{formatted_date(fields[:published].first)}T00:00:00') and xs:dateTime(published) < xs:dateTime('#{formatted_date(fields[:published].last)}T00:00:00')]"
47
+ else
48
+ fields_param << "entry[xs:date(published) = xs:date('#{formatted_date(fields[:published])}')]"
49
+ end
50
+ end
51
+
52
+ if fields[:view_count]
53
+ fields_param << "entry[yt:statistics/@viewCount > #{fields[:view_count]}]"
54
+ end
55
+
56
+
57
+ return "&fields=#{URI.escape(fields_param.join(","))}"
58
+ end
59
+
60
+ #youtube taked dates that look like 'YYYY-MM-DD'
61
+ def formatted_date(date)
62
+ return date if date.is_a? String
63
+ if date.respond_to? :strftime
64
+ date.strftime("%Y-%m-%d")
65
+ else
66
+ ""
67
+ end
68
+ end
69
+ end
25
70
  end
26
71
  end
27
72
 
@@ -0,0 +1,15 @@
1
+ class UploadError < YouTubeIt::Error
2
+ attr_reader :code
3
+ def initialize(msg, code = 0)
4
+ super(msg)
5
+ @code = code
6
+ end
7
+ end
8
+
9
+ class AuthenticationError < YouTubeIt::Error
10
+ attr_reader :code
11
+ def initialize(msg, code = 0)
12
+ super(msg)
13
+ @code = code
14
+ end
15
+ end
@@ -1,6 +1,7 @@
1
1
  class YouTubeIt
2
2
  module Request #:nodoc:
3
3
  class UserSearch < BaseSearch #:nodoc:
4
+ include FieldSearch
4
5
  attr_reader :max_results # max_results
5
6
  attr_reader :order_by # orderby, ([relevance], viewCount, published, rating)
6
7
  attr_reader :offset # start-index
@@ -22,6 +23,7 @@ class YouTubeIt
22
23
  end
23
24
 
24
25
  @url << build_query_params(to_youtube_params)
26
+ @url << fields_to_params(params.delete(:fields)) if params != :favorites && params[:fields]
25
27
  end
26
28
 
27
29
  private
@@ -1,6 +1,8 @@
1
1
  class YouTubeIt
2
2
  module Request #:nodoc:
3
3
  class VideoSearch < BaseSearch #:nodoc:
4
+ include FieldSearch
5
+
4
6
  # From here: http://code.google.com/apis/youtube/reference.html#yt_format
5
7
  ONLY_EMBEDDABLE = 5
6
8
 
@@ -16,7 +18,6 @@ class YouTubeIt
16
18
  attr_reader :author
17
19
  attr_reader :lang # lt
18
20
 
19
-
20
21
  def initialize(params={})
21
22
  # Initialize our various member data to avoid warnings and so we'll
22
23
  # automatically fall back to the youtube api defaults
@@ -41,6 +42,7 @@ class YouTubeIt
41
42
  end
42
43
 
43
44
  @url << build_query_params(to_youtube_params)
45
+ @url << fields_to_params(params.delete(:fields)) if params[:fields]
44
46
  end
45
47
 
46
48
  private
@@ -64,6 +66,7 @@ class YouTubeIt
64
66
  }
65
67
  end
66
68
 
69
+
67
70
  # Convert category symbols into strings and build the URL. GData requires categories to be capitalized.
68
71
  # Categories defined like: categories => { :include => [:news], :exclude => [:sports], :either => [..] }
69
72
  # or like: categories => [:news, :sports]
@@ -1,25 +1,7 @@
1
1
  class YouTubeIt
2
-
3
2
  module Upload
4
- class UploadError < YouTubeIt::Error; end
5
- class AuthenticationError < YouTubeIt::Error; end
6
-
7
- # Implements video uploads/updates/deletions
8
- #
9
- # require 'youtube_it'
10
- #
11
- # uploader = YouTubeIt::Upload::VideoUpload.new("user", "pass", "dev-key")
12
- # uploader.upload File.open("test.m4v"), :title => 'test',
13
- # :description => 'cool vid d00d',
14
- # :category => 'People',
15
- # :keywords => %w[cool blah test]
16
- #
17
3
  class VideoUpload
18
4
  include YouTubeIt::Logging
19
- def initialize user, pass, dev_key, access_token = nil, authsub_token = nil, client_id = 'youtube_it'
20
- @user, @password, @dev_key, @access_token, @authsub_token, @client_id = user, pass, dev_key, access_token, authsub_token, client_id
21
- @http_debugging = false
22
- end
23
5
 
24
6
  def initialize *params
25
7
  if params.first.is_a?(Hash)
@@ -30,6 +12,7 @@ class YouTubeIt
30
12
  @access_token = hash_options[:access_token]
31
13
  @authsub_token = hash_options[:authsub_token]
32
14
  @client_id = hash_options[:client_id] || "youtube_it"
15
+ @config_token = hash_options[:config_token]
33
16
  else
34
17
  puts "* warning: the method YouTubeIt::Upload::VideoUpload.new(username, password, dev_key) is depricated, use YouTubeIt::Upload::VideoUpload.new(:username => 'user', :password => 'passwd', :dev_key => 'dev_key')"
35
18
  @user = params.shift
@@ -38,6 +21,7 @@ class YouTubeIt
38
21
  @access_token = params.shift
39
22
  @authsub_token = params.shift
40
23
  @client_id = params.shift || "youtube_it"
24
+ @config_token = params.shift
41
25
  end
42
26
  end
43
27
 
@@ -73,7 +57,6 @@ class YouTubeIt
73
57
  #
74
58
  # When the authentication credentials are incorrect, an AuthenticationError will be raised.
75
59
  def upload(data, opts = {})
76
- response = nil
77
60
  @opts = { :mime_type => 'video/mp4',
78
61
  :title => '',
79
62
  :description => '',
@@ -90,22 +73,9 @@ class YouTubeIt
90
73
  "Content-Length" => "#{post_body_io.expected_length}",
91
74
  }
92
75
 
93
- if @access_token.nil?
94
- upload_header.merge!(authorization_headers).delete("GData-Version")
95
- http = Net::HTTP.new(uploads_url)
96
- http.set_debug_output(logger) if @http_debugging
97
- path = '/feeds/api/users/default/uploads'
98
- http.start do | session |
99
- post = Net::HTTP::Post.new(path, upload_header)
100
- post.body_stream = post_body_io
101
- response = session.request(post)
102
- end
103
- else
104
- upload_header.merge!(authorization_headers_for_oauth).delete("GData-Version")
105
- url = 'http://%s/feeds/api/users/default/uploads' % uploads_url
106
- response = @access_token.post(url, post_body_io, upload_header)
107
- end
108
- raise_on_faulty_response(response)
76
+ upload_url = "/feeds/api/users/default/uploads"
77
+ response = yt_session(uploads_url).post(upload_url, post_body_io, upload_header)
78
+
109
79
  return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
110
80
  end
111
81
 
@@ -118,53 +88,59 @@ class YouTubeIt
118
88
  # :private
119
89
  # When the authentication credentials are incorrect, an AuthenticationError will be raised.
120
90
  def update(video_id, options)
121
- response = nil
122
- @opts = options
123
- update_body = video_xml
91
+ @opts = options
92
+ update_body = video_xml
124
93
  update_header = {
125
94
  "Content-Type" => "application/atom+xml",
126
95
  "Content-Length" => "#{update_body.length}",
127
96
  }
128
97
  update_url = "/feeds/api/users/default/uploads/%s" % video_id
98
+ response = yt_session.put(update_url, update_body, update_header)
99
+
100
+ return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
101
+ end
129
102
 
130
- if @access_token.nil?
131
- update_header.merge!(authorization_headers)
132
- http_connection do |session|
133
- response = session.put(update_url, update_body, update_header)
134
- end
135
- else
136
- update_header.merge!(authorization_headers_for_oauth)
137
- response = @access_token.put("http://%s%s" % [base_url,update_url], update_body, update_header)
138
- end
139
-
140
- raise_on_faulty_response(response)
103
+ # Fetches the data of a video, which may be private. The video must be owned by this user.
104
+ # When the authentication credentials are incorrect, an AuthenticationError will be raised.
105
+ def get_my_video(video_id)
106
+ get_header = {
107
+ "Content-Type" => "application/atom+xml",
108
+ "Content-Length" => "0",
109
+ }
110
+ get_url = "/feeds/api/users/default/uploads/%s" % video_id
111
+ response = yt_session.get(get_url, get_header)
112
+
141
113
  return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
142
114
  end
143
115
 
116
+ # Fetches the data of the videos of the current user, which may be private.
117
+ # When the authentication credentials are incorrect, an AuthenticationError will be raised.
118
+ def get_my_videos(opts)
119
+ max_results = opts[:per_page] || 50
120
+ start_index = ((opts[:page] || 1) -1) * max_results +1
121
+ get_header = {
122
+ "Content-Type" => "application/atom+xml",
123
+ "Content-Length" => "0",
124
+ }
125
+ get_url = "/feeds/api/users/default/uploads?max-results=#{max_results}&start-index=#{start_index}"
126
+ response = yt_session.get(get_url, get_header)
127
+
128
+ return YouTubeIt::Parser::VideosFeedParser.new(response.body).parse
129
+ end
130
+
144
131
  # Delete a video on YouTube
145
132
  def delete(video_id)
146
- response = nil
147
133
  delete_header = {
148
134
  "Content-Type" => "application/atom+xml; charset=UTF-8",
149
135
  "Content-Length" => "0",
150
136
  }
151
137
  delete_url = "/feeds/api/users/default/uploads/%s" % video_id
138
+ response = yt_session.delete(delete_url, delete_header)
152
139
 
153
- if @access_token.nil?
154
- delete_header.merge!(authorization_headers)
155
- http_connection do |session|
156
- response = session.delete(delete_url, delete_header)
157
- end
158
- else
159
- delete_header.merge!(authorization_headers_for_oauth)
160
- response = @access_token.delete("http://%s%s" % [base_url,delete_url], delete_header)
161
- end
162
- raise_on_faulty_response(response)
163
140
  return true
164
141
  end
165
142
 
166
143
  def get_upload_token(options, nexturl)
167
- response = nil
168
144
  @opts = options
169
145
  token_body = video_xml
170
146
  token_header = {
@@ -172,23 +148,13 @@ class YouTubeIt
172
148
  "Content-Length" => "#{token_body.length}",
173
149
  }
174
150
  token_url = "/action/GetUploadToken"
175
-
176
- if @access_token.nil?
177
- token_header.merge!(authorization_headers)
178
- http_connection do |session|
179
- response = session.post(token_url, token_body, token_header)
180
- end
181
- else
182
- token_header.merge!(authorization_headers_for_oauth)
183
- response = @access_token.post("http://%s%s" % [base_url, token_url], token_body, token_header)
184
- end
185
- raise_on_faulty_response(response)
151
+ response = yt_session.post(token_url, token_body, token_header)
152
+
186
153
  return {:url => "#{response.body[/<url>(.+)<\/url>/, 1]}?nexturl=#{nexturl}",
187
154
  :token => response.body[/<token>(.+)<\/token>/, 1]}
188
155
  end
189
156
 
190
157
  def add_comment(video_id, comment)
191
- response = nil
192
158
  comment_body = video_xml_for(:comment => comment)
193
159
  comment_header = {
194
160
  "Content-Type" => "application/atom+xml",
@@ -196,265 +162,193 @@ class YouTubeIt
196
162
  }
197
163
  comment_url = "/feeds/api/videos/%s/comments" % video_id
198
164
 
199
- if @access_token.nil?
200
- comment_header.merge!(authorization_headers)
201
- http_connection do |session|
202
- response = session.post(comment_url, comment_body, comment_header)
203
- end
204
- else
205
- comment_header.merge!(authorization_headers_for_oauth)
206
- response = @access_token.post("http://%s%s" % [base_url, comment_url], comment_body, comment_header)
207
- end
208
- raise_on_faulty_response(response)
209
- {:code => response.code, :body => response.body}
165
+ response = yt_session.post(comment_url, comment_body, comment_header)
166
+
167
+ return {:code => response.status, :body => response.body}
210
168
  end
211
169
 
212
170
  def comments(video_id, opts = {})
213
171
  comment_url = "/feeds/api/videos/%s/comments?" % video_id
214
172
  comment_url << opts.collect { |k,p| [k,p].join '=' }.join('&')
215
- http_connection do |session|
216
- response = session.get(comment_url)
217
- raise_on_faulty_response(response)
218
- {:code => response.code, :body => response.body}
219
- return YouTubeIt::Parser::CommentsFeedParser.new(response).parse
220
- end
173
+ response = yt_session.get(comment_url)
174
+
175
+ return YouTubeIt::Parser::CommentsFeedParser.new(response).parse
221
176
  end
222
177
 
223
178
  def add_favorite(video_id)
224
- response = nil
225
179
  favorite_body = video_xml_for(:favorite => video_id)
226
180
  favorite_header = {
227
181
  "Content-Type" => "application/atom+xml",
228
182
  "Content-Length" => "#{favorite_body.length}",
229
183
  }
230
184
  favorite_url = "/feeds/api/users/default/favorites"
231
-
232
- if @access_token.nil?
233
- favorite_header.merge!(authorization_headers)
234
- http_connection do |session|
235
- response = session.post(favorite_url, favorite_body, favorite_header)
236
- end
237
- else
238
- favorite_header.merge!(authorization_headers_for_oauth)
239
- response = @access_token.post("http://%s%s" % [base_url, favorite_url], favorite_body, favorite_header)
240
- end
241
- raise_on_faulty_response(response)
242
- {:code => response.code, :body => response.body}
185
+ response = yt_session.post(favorite_url, favorite_body, favorite_header)
186
+
187
+ return {:code => response.status, :body => response.body}
243
188
  end
244
189
 
245
190
  def delete_favorite(video_id)
246
- response = nil
247
191
  favorite_header = {
248
192
  "Content-Type" => "application/atom+xml; charset=UTF-8",
249
193
  "Content-Length" => "0",
250
194
  }
251
195
  favorite_url = "/feeds/api/users/default/favorites/%s" % video_id
252
-
253
- if @access_token.nil?
254
- favorite_header.merge!(authorization_headers).delete("GData-Version")
255
- http_connection do |session|
256
- response = session.delete(favorite_url, favorite_header)
257
- end
258
- else
259
- favorite_header.merge!(authorization_headers_for_oauth).delete("GData-Version")
260
- response = @access_token.delete("http://%s%s" % [base_url, favorite_url], favorite_header)
261
- end
262
- raise_on_faulty_response(response)
196
+ response = yt_session.delete(favorite_url, favorite_header)
197
+
263
198
  return true
264
199
  end
265
200
 
266
- def profile(user_id)
267
- profile_url = "/feeds/api/users/%s?v=2" % user_id
268
- http_connection do |session|
269
- response = session.get(profile_url)
270
- raise_on_faulty_response(response)
271
- return YouTubeIt::Parser::ProfileFeedParser.new(response).parse
272
- end
201
+ def profile(user)
202
+ profile_url = "/feeds/api/users/%s?v=2" % (user ? user : "default")
203
+ profile_header = {
204
+ "Content-Type" => "application/atom+xml; charset=UTF-8"
205
+ }
206
+ response = yt_session.get(profile_url, profile_header)
207
+
208
+ return YouTubeIt::Parser::ProfileFeedParser.new(response).parse
273
209
  end
274
210
 
275
211
  def playlist(playlist_id)
276
212
  playlist_url = "/feeds/api/playlists/%s?v=2" % playlist_id
277
- http_connection do |session|
278
- response = session.get(playlist_url)
279
- raise_on_faulty_response(response)
280
- return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
281
- end
282
- end
283
-
284
- def playlists
285
- playlist_url = "/feeds/api/users/default/playlists?v=2"
286
- http_connection do |session|
287
- response = session.get(playlist_url)
288
- raise_on_faulty_response(response)
289
- return response.body
290
- end
213
+ response = yt_session.get(playlist_url)
214
+
215
+ return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
291
216
  end
292
217
 
293
- def playlists_for(user)
294
- playlist_url = "/feeds/api/users/#{user}/playlists?v=2"
295
- http_connection do |session|
296
- response = session.get(playlist_url)
297
- raise_on_faulty_response(response)
298
- return YouTubeIt::Parser::PlaylistsFeedParser.new(response).parse #return response.body
299
- end
218
+ def playlists(user)
219
+ playlist_url = "/feeds/api/users/%s/playlists?v=2" % (user ? user : "default")
220
+ response = yt_session.get(playlist_url)
221
+
222
+ return YouTubeIt::Parser::PlaylistsFeedParser.new(response).parse
300
223
  end
301
-
224
+
302
225
  def add_playlist(options)
303
- response = nil
304
226
  playlist_body = video_xml_for_playlist(options)
305
227
  playlist_header = {
306
228
  "Content-Type" => "application/atom+xml",
307
229
  "Content-Length" => "#{playlist_body.length}",
308
230
  }
309
231
  playlist_url = "/feeds/api/users/default/playlists"
310
-
311
- if @access_token.nil?
312
- playlist_header.merge!(authorization_headers)
313
- http_connection do |session|
314
- response = session.post(playlist_url, playlist_body, playlist_header)
315
- end
316
- else
317
- playlist_header.merge!(authorization_headers_for_oauth)
318
- response = @access_token.post("http://%s%s" % [base_url, playlist_url], playlist_body, playlist_header)
319
- end
320
- raise_on_faulty_response(response)
232
+ response = yt_session.post(playlist_url, playlist_body, playlist_header)
233
+
321
234
  return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
322
235
  end
323
236
 
324
237
  def add_video_to_playlist(playlist_id, video_id)
325
- response = nil
326
238
  playlist_body = video_xml_for(:playlist => video_id)
327
239
  playlist_header = {
328
240
  "Content-Type" => "application/atom+xml",
329
241
  "Content-Length" => "#{playlist_body.length}",
330
242
  }
331
243
  playlist_url = "/feeds/api/playlists/%s" % playlist_id
332
-
333
- if @access_token.nil?
334
- playlist_header.merge!(authorization_headers)
335
- http_connection do |session|
336
- response = session.post(playlist_url, playlist_body, playlist_header)
337
- end
338
- else
339
- playlist_header.merge!(authorization_headers_for_oauth)
340
- response = @access_token.post("http://%s%s" % [base_url, playlist_url], playlist_body, playlist_header)
341
- end
342
- raise_on_faulty_response(response)
343
- {:code => response.code, :body => response.body, :playlist_entry_id => playlist_entry_id_from_playlist(response.body)}
244
+ response = yt_session.post(playlist_url, playlist_body, playlist_header)
245
+
246
+ return {:code => response.status, :body => response.body, :playlist_entry_id => playlist_entry_id_from_playlist(response.body)}
344
247
  end
345
248
 
346
249
  def update_playlist(playlist_id, options)
347
- response = nil
348
250
  playlist_body = video_xml_for_playlist(options)
349
251
  playlist_header = {
350
252
  "Content-Type" => "application/atom+xml",
351
253
  "Content-Length" => "#{playlist_body.length}",
352
254
  }
353
255
  playlist_url = "/feeds/api/users/default/playlists/%s" % playlist_id
354
-
355
- if @access_token.nil?
356
- playlist_header.merge!(authorization_headers)
357
- http_connection do |session|
358
- response = session.put(playlist_url, playlist_body, playlist_header)
359
- end
360
- else
361
- playlist_header.merge!(authorization_headers_for_oauth)
362
- response = @access_token.put("http://%s%s" % [base_url, playlist_url], playlist_body, playlist_header)
363
- end
364
- raise_on_faulty_response(response)
256
+ response = yt_session.put(playlist_url, playlist_body, playlist_header)
257
+
365
258
  return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
366
259
  end
367
260
 
368
261
  def delete_video_from_playlist(playlist_id, playlist_entry_id)
369
- response = nil
370
262
  playlist_header = {
371
263
  "Content-Type" => "application/atom+xml",
372
264
  }
373
265
  playlist_url = "/feeds/api/playlists/%s/%s" % [playlist_id, playlist_entry_id]
374
-
375
- if @access_token.nil?
376
- playlist_header.merge!(authorization_headers)
377
- http_connection do |session|
378
- response = session.delete(playlist_url, playlist_header)
379
- end
380
- else
381
- playlist_header.merge!(authorization_headers_for_oauth)
382
- response = @access_token.delete("http://%s%s" % [base_url, playlist_url], playlist_header)
383
- end
384
- raise_on_faulty_response(response)
266
+ response = yt_session.delete(playlist_url, playlist_header)
267
+
385
268
  return true
386
269
  end
387
270
 
388
271
  def delete_playlist(playlist_id)
389
- response = nil
390
- playlist_header = {
391
- "Content-Type" => "application/atom+xml; charset=UTF-8",
272
+ playlist_header = {
273
+ "Content-Type" => "application/atom+xml; charset=UTF-8",
392
274
  }
393
- playlist_url = "/feeds/api/users/default/playlists/%s" % playlist_id
394
-
395
- if @access_token.nil?
396
- playlist_header.merge!(authorization_headers)
397
- http_connection do |session|
398
- response = session.delete(playlist_url, playlist_header)
399
- end
400
- else
401
- playlist_header.merge!(authorization_headers_for_oauth)
402
- response = @access_token.delete("http://%s%s" % [base_url, playlist_url], playlist_header)
403
- end
404
- raise_on_faulty_response(response)
275
+ playlist_url = "/feeds/api/users/default/playlists/%s" % playlist_id
276
+ response = yt_session.delete(playlist_url, playlist_header)
277
+
405
278
  return true
406
279
  end
407
280
 
408
- def favorites(opts = {})
409
- favorite_url = "/feeds/api/users/default/favorites?#{opts.to_param}"
410
- if @access_token.nil?
411
- http_connection do |session|
412
- response = session.get(favorite_url)
413
- end
414
- else
415
- response = @access_token.get("http://%s%s" % [base_url, favorite_url])
416
- end
417
- raise_on_faulty_response(response)
281
+ def rate_video(video_id, rating)
282
+ rating_body = video_xml_for(:rating => rating)
283
+ rating_header = {
284
+ "Content-Type" => "application/atom+xml",
285
+ "Content-Length" => "#{rating_body.length}",
286
+ }
287
+ rating_url = "/feeds/api/videos/#{video_id}/ratings"
288
+ response = yt_session.post(rating_url, rating_body, rating_header)
289
+
290
+ return {:code => response.status, :body => response.body}
291
+ end
292
+
293
+ def subscriptions(user)
294
+ subscription_url = "/feeds/api/users/%s/subscriptions?v=2" % (user ? user : "default")
295
+ subscription_header = {
296
+ "Content-Type" => "application/atom+xml",
297
+ }
298
+ response = yt_session.get(subscription_url, subscription_header)
299
+
300
+ return YouTubeIt::Parser::SubscriptionFeedParser.new(response).parse
301
+ end
302
+
303
+ def subscribe_channel(channel_name)
304
+ subscribe_body = video_xml_for(:subscribe => channel_name)
305
+ subscribe_header = {
306
+ "Content-Type" => "application/atom+xml",
307
+ "Content-Length" => "#{subscribe_body.length}",
308
+ }
309
+ subscribe_url = "/feeds/api/users/default/subscriptions"
310
+ response = yt_session.post(subscribe_url, subscribe_body, subscribe_header)
311
+
312
+ return {:code => response.status, :body => response.body}
313
+ end
314
+
315
+ def unsubscribe_channel(subscription_id)
316
+ unsubscribe_header = {
317
+ "Content-Type" => "application/atom+xml"
318
+ }
319
+ unsubscribe_url = "/feeds/api/users/default/subscriptions/%s" % subscription_id
320
+ response = yt_session.delete(unsubscribe_url, unsubscribe_header)
321
+
322
+ return {:code => response.status, :body => response.body}
323
+ end
324
+
325
+ def favorites(user, opts = {})
326
+ favorite_url = "/feeds/api/users/%s/favorites#{opts.empty? ? '' : '?#{opts.to_param}'}" % (user ? user : "default")
327
+ response = yt_session.get(favorite_url)
418
328
  return YouTubeIt::Parser::VideosFeedParser.new(response.body).parse
419
329
  end
420
330
 
421
331
  def get_current_user
422
332
  current_user_url = "/feeds/api/users/default"
423
- response = ''
424
- if @access_token.nil?
425
- http_connection do |session|
426
- response = session.get2(current_user_url, authorization_headers)
427
- end
428
- else
429
- response = @access_token.get("http://gdata.youtube.com/feeds/api/users/default")
430
- end
333
+ response = yt_session.get(current_user_url, authorization_headers)
431
334
 
432
- raise_on_faulty_response(response)
433
- REXML::Document.new(response.body).elements["entry"].elements['author'].elements['name'].text
335
+ return REXML::Document.new(response.body).elements["entry"].elements['author'].elements['name'].text
434
336
  end
435
337
 
436
338
  private
437
339
 
438
340
  def uploads_url
439
- ["uploads", base_url].join('.')
341
+ ["http://uploads", base_url.sub("http://","")].join('.')
440
342
  end
441
343
 
442
344
  def base_url
443
- "gdata.youtube.com"
345
+ "http://gdata.youtube.com"
444
346
  end
445
347
 
446
348
  def boundary
447
349
  "An43094fu"
448
350
  end
449
351
 
450
- def authorization_headers_for_oauth
451
- {
452
- "X-GData-Client" => "#{@client_id}",
453
- "X-GData-Key" => "key=#{@dev_key}",
454
- "GData-Version" => "2",
455
- }
456
- end
457
-
458
352
  def authorization_headers
459
353
  header = {
460
354
  "X-GData-Client" => "#{@client_id}",
@@ -463,42 +357,12 @@ class YouTubeIt
463
357
  }
464
358
  if @authsub_token
465
359
  header.merge!("Authorization" => "AuthSub token=#{@authsub_token}")
466
- else
360
+ elsif @access_token.nil? && @authsub_token.nil?
467
361
  header.merge!("Authorization" => "GoogleLogin auth=#{auth_token}")
468
362
  end
469
363
  header
470
364
  end
471
365
 
472
- def parse_upload_error_from(string)
473
- begin
474
- REXML::Document.new(string).elements["//errors"].inject('') do | all_faults, error|
475
- if error.elements["internalReason"]
476
- msg_error = error.elements["internalReason"].text
477
- elsif error.elements["location"]
478
- msg_error = error.elements["location"].text[/media:group\/media:(.*)\/text\(\)/,1]
479
- else
480
- msg_error = "Unspecified error"
481
- end
482
- code = error.elements["code"].text if error.elements["code"]
483
- all_faults + sprintf("%s: %s\n", msg_error, code)
484
- end
485
- rescue
486
- string[/<TITLE>(.+)<\/TITLE>/, 1] || string
487
- end
488
- end
489
-
490
- def raise_on_faulty_response(response)
491
- response_code = response.code.to_i
492
- msg = parse_upload_error_from(response.body.gsub(/\n/, ''))
493
-
494
- if response_code == 403 || response_code == 401
495
- #if response_code / 10 == 40
496
- raise AuthenticationError, msg
497
- elsif response_code / 10 != 20 # Response in 20x means success
498
- raise UploadError, msg
499
- end
500
- end
501
-
502
366
  def uploaded_video_id_from(string)
503
367
  xml = REXML::Document.new(string)
504
368
  xml.elements["//id"].text[/videos\/(.+)/, 1]
@@ -526,11 +390,10 @@ class YouTubeIt
526
390
 
527
391
  def auth_token
528
392
  @auth_token ||= begin
529
- http = Net::HTTP.new("www.google.com", 443)
530
- http.use_ssl = true
393
+ http = Faraday.new("https://www.google.com")
531
394
  body = "Email=#{YouTubeIt.esc @user}&Passwd=#{YouTubeIt.esc @password}&service=youtube&source=#{YouTubeIt.esc @client_id}"
532
395
  response = http.post("/youtube/accounts/ClientLogin", body, "Content-Type" => "application/x-www-form-urlencoded")
533
- raise UploadError, response.body[/Error=(.+)/,1] if response.code.to_i != 200
396
+ raise ::AuthenticationError.new(response.body[/Error=(.+)/,1], response.status.to_i) if response.status.to_i != 200
534
397
  @auth_token = response.body[/Auth=(.+)/, 1]
535
398
  end
536
399
  end
@@ -564,6 +427,11 @@ class YouTubeIt
564
427
  b.entry(:xmlns => "http://www.w3.org/2005/Atom", 'xmlns:yt' => "http://gdata.youtube.com/schemas/2007") do | m |
565
428
  m.content(data[:comment]) if data[:comment]
566
429
  m.id(data[:favorite] || data[:playlist]) if data[:favorite] || data[:playlist]
430
+ m.tag!("yt:rating", :value => data[:rating]) if data[:rating]
431
+ if(data[:subscribe])
432
+ m.category(:scheme => "http://gdata.youtube.com/schemas/2007/subscriptiontypes.cat", :term => "channel")
433
+ m.tag!("yt:username", data[:subscribe])
434
+ end
567
435
  end.to_s
568
436
  end
569
437
 
@@ -599,11 +467,12 @@ class YouTubeIt
599
467
  end
600
468
  end
601
469
 
602
- def http_connection
603
- http = Net::HTTP.new(base_url)
604
- http.set_debug_output(logger) if @http_debugging
605
- http.start do |session|
606
- yield(session)
470
+ def yt_session(url = nil)
471
+ Faraday.new(:url => url ? url : base_url) do |builder|
472
+ builder.use Faraday::Request::OAuth, @config_token if @config_token
473
+ builder.use Faraday::Request::AuthHeader, authorization_headers
474
+ builder.use Faraday::Response::YouTubeIt
475
+ builder.adapter Faraday.default_adapter
607
476
  end
608
477
  end
609
478
  end