msp-youtube-g 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/lib/youtube_g/request/video_upload.rb +58 -30
- metadata +1 -1
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
|
-
|
22
|
-
|
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=#{
|
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
|
-
|
77
|
+
logger.debug("upload_header [#{upload_header}]")
|
57
78
|
|
58
79
|
direct_upload_url = "/feeds/api/users/#{@user}/uploads"
|
59
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
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
|
-
|
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, "
|
94
|
-
|
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
|
-
|
123
|
+
logger.debug "auth_token [#{@auth_token}]"
|
99
124
|
@auth_token
|
100
125
|
end
|
101
126
|
|
102
127
|
def video_xml
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|