msp-youtube-g 0.4.5 → 0.4.6

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 CHANGED
@@ -1,5 +1,8 @@
1
1
  == trunk
2
2
 
3
+ * Add error-handling for video upload errors. [FiXato]
4
+ * Add error-handling for authentication errors from YouTube during video upload. [FiXato]
5
+ * Add support for making videos private upon video upload. [FiXato]
3
6
  * Fix issue with REXML parsing of video upload response. [FiXato]
4
7
  * Fix issue with response code comparison. [FiXato]
5
8
  * Authcode is now retrieved for video uploads. [FiXato]
@@ -7,6 +7,7 @@ class YouTubeG
7
7
 
8
8
  module Upload
9
9
  class UploadError < Exception; end
10
+ class AuthenticationError < Exception; end
10
11
 
11
12
  # require 'youtube_g'
12
13
  #
@@ -17,9 +18,23 @@ class YouTubeG
17
18
  # :keywords => %w[cool blah test]
18
19
 
19
20
  class VideoUpload
20
-
21
- def initialize user, pass, dev_key, client_id = 'youtube_g'
22
- @user, @pass, @dev_key, @client_id = user, pass, dev_key, client_id
21
+
22
+ attr_accessor :auth_token
23
+ def initialize user, pass, dev_key, client_id = 'youtube_g', auth_token = nil
24
+ @user, @pass, @dev_key, @client_id, @auth_token = user, pass, dev_key, client_id, auth_token
25
+ end
26
+
27
+ # TODO merge this in with logger.rb or replace logger.rb
28
+ def logger
29
+ if not Object.const_defined?(get_rails_default_logger_name)
30
+ Logger.new(STDOUT)
31
+ else
32
+ eval(get_rails_default_logger_name)
33
+ end
34
+ end
35
+
36
+ def get_rails_default_logger_name
37
+ "RAILS_DEFAULT_LOGGER"
23
38
  end
24
39
 
25
40
  #
@@ -32,8 +47,14 @@ class YouTubeG
32
47
  # :description
33
48
  # :category
34
49
  # :keywords
50
+ # :private
51
+ # Specifying :private will make the video private, otherwise it will be public.
35
52
  #
36
-
53
+ # When one of the fields is invalid according to YouTube,
54
+ # an UploadError will be returned. Its message contains a list of newline separated
55
+ # errors, containing the key and its error code.
56
+ #
57
+ # When the authentication credentials are incorrect, an AuthenticationError will be raised.
37
58
  def upload data, opts = {}
38
59
  data = data.respond_to?(:read) ? data.read : data
39
60
  @opts = { :mime_type => 'video/mp4',
@@ -46,29 +67,33 @@ class YouTubeG
46
67
  upload_body = generate_upload_body(boundary, video_xml, data)
47
68
 
48
69
  upload_header = {
49
- "Authorization" => "GoogleLogin auth=#{auth_token}",
70
+ "Authorization" => "GoogleLogin auth=#{derive_auth_token}",
50
71
  "X-GData-Client" => "#{@client_id}",
51
72
  "X-GData-Key" => "key=#{@dev_key}",
52
73
  "Slug" => "#{@opts[:filename]}",
53
74
  "Content-Type" => "multipart/related; boundary=#{boundary}",
54
75
  "Content-Length" => "#{upload_body.length}",
55
76
  }
56
- puts("MSP upload_header [#{upload_header}]")
77
+ logger.debug("upload_header [#{upload_header}]")
57
78
 
58
79
  direct_upload_url = "/feeds/api/users/#{@user}/uploads"
59
- puts("MSP direct_upload_url [#{direct_upload_url}]")
80
+ logger.debug("direct_upload_url [#{direct_upload_url}]")
60
81
 
61
82
  Net::HTTP.start(base_url) do |upload|
62
83
  response = upload.post(direct_upload_url, upload_body, upload_header)
63
- xml = REXML::Document.new(response.body)
64
- if (xml.elements["//id"])
65
- puts("MSP response xml [#{xml}]")
66
- return xml.elements["//id"].text[/videos\/(.+)/, 1]
67
- else
68
- return xml
84
+ if response.code.to_i == 403
85
+ raise AuthenticationError, response.body[/<TITLE>(.+)<\/TITLE>/, 1]
86
+ elsif response.code.to_i != 201
87
+ upload_error = ''
88
+ xml = REXML::Document.new(response.body)
89
+ errors = xml.elements["//errors"]
90
+ errors.each do |error|
91
+ location = error.elements["location"].text[/media:group\/media:(.*)\/text\(\)/,1]
92
+ code = error.elements["code"].text
93
+ upload_error << sprintf("%s: %s\r\n", location, code)
94
+ end
95
+ raise UploadError, upload_error
69
96
  end
70
-
71
-
72
97
  end
73
98
 
74
99
  end
@@ -83,31 +108,34 @@ class YouTubeG
83
108
  "An43094fu"
84
109
  end
85
110
 
86
- def auth_token
111
+ def derive_auth_token
87
112
  unless @auth_token
88
113
  http = Net::HTTP.new("www.google.com", 443)
89
114
  http.use_ssl = true
90
115
  body = "Email=#{CGI::escape @user}&Passwd=#{CGI::escape @pass}&service=youtube&source=#{CGI::escape @client_id}"
91
- puts("MSP auth body [#{body}]")
116
+ logger.debug("auth body [#{body}]")
92
117
  response = http.post("/youtube/accounts/ClientLogin", body, "Content-Type" => "application/x-www-form-urlencoded")
93
- raise UploadError, "MSP "+response.body[/Error=(.+)/,1] if response.code.to_i != 200
94
- puts("MSP response.body [#{response.body}]")
118
+ raise UploadError, ""+response.body[/Error=(.+)/,1] if response.code.to_i != 200
119
+ logger.debug("response.body [#{response.body}]")
95
120
  @auth_token = response.body[/Auth=(.+)/, 1]
96
121
 
97
122
  end
98
- puts "MSP auth_token [#{@auth_token}]"
123
+ logger.debug "auth_token [#{@auth_token}]"
99
124
  @auth_token
100
125
  end
101
126
 
102
127
  def video_xml
103
- %[<?xml version="1.0"?>
104
- <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
105
- <media:group>
106
- <media:title type="plain">#{@opts[:title]}</media:title>
107
- <media:description type="plain">#{@opts[:description]}</media:description>
108
- <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">#{@opts[:category]}</media:category>
109
- <media:keywords>#{@opts[:keywords].join ","}</media:keywords>
110
- </media:group></entry> ]
128
+ video_xml = ''
129
+ video_xml << '<?xml version="1.0"?>'
130
+ video_xml << '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">'
131
+ video_xml << '<media:group>'
132
+ video_xml << '<media:title type="plain">%s</media:title>' % @opts[:title]
133
+ video_xml << '<media:description type="plain">%s</media:description>' % @opts[:description]
134
+ video_xml << '<media:keywords>%s</media:keywords>' % @opts[:keywords].join(",")
135
+ video_xml << '<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">%s</media:category>' % @opts[:category]
136
+ video_xml << '<yt:private/>' if @opts[:private]
137
+ video_xml << '</media:group>'
138
+ video_xml << '</entry>'
111
139
  end
112
140
 
113
141
  def generate_upload_body(boundary, video_xml, data)
@@ -119,8 +147,8 @@ class YouTubeG
119
147
  upload_body << "Content-Type: #{@opts[:mime_type]}\r\nContent-Transfer-Encoding: binary\r\n\r\n"
120
148
  upload_body << data
121
149
  upload_body << "\r\n--#{boundary}--\r\n"
122
- end
123
-
150
+ end
151
+
124
152
  end
125
153
  end
126
154
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msp-youtube-g
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Vitarana