sadikzzz-heyspread-ruby 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/MIT-LICENSE +20 -0
- data/README +47 -0
- data/lib/heyspread.rb +532 -0
- metadata +63 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2008 Bruno Celeste
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
= Hey!Spread: Video Promoting Web Service
|
|
2
|
+
|
|
3
|
+
* Address: http://heyspread.com
|
|
4
|
+
* Email: bruno.celeste@particle-s.com
|
|
5
|
+
* Blog: http://particle-s.com
|
|
6
|
+
* Twitter: http://twitter.com/HeyWatch
|
|
7
|
+
|
|
8
|
+
* API documentation: http://heyspread.com/page/api-documentation
|
|
9
|
+
* Valid site names to use the API: http://heyspread.com/page/api-documentation-sites
|
|
10
|
+
|
|
11
|
+
= Usage
|
|
12
|
+
|
|
13
|
+
== Upload a video to YouTube and Google Video:
|
|
14
|
+
|
|
15
|
+
HeySpread::Account.api_key = "api_key"
|
|
16
|
+
|
|
17
|
+
video = HeySpread::Video.new(
|
|
18
|
+
:title => "HS test",
|
|
19
|
+
:category => "Comedy",
|
|
20
|
+
:tags => "heyspread tag testing",
|
|
21
|
+
:file => "/home/user/video.avi",
|
|
22
|
+
:description => "Test the HeySpread API"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
#Set the destination sites
|
|
26
|
+
#Not required if you saved you Credentials
|
|
27
|
+
video.destinations["youtube"] = ["login", "password"]
|
|
28
|
+
video.destinations["google"] = ["email", "password"]
|
|
29
|
+
|
|
30
|
+
video.upload
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
== Save YouTube credentials:
|
|
34
|
+
|
|
35
|
+
HeySpread::Credentials.save(
|
|
36
|
+
:site => "youtube",
|
|
37
|
+
:login => "testyt",
|
|
38
|
+
:password => "test"
|
|
39
|
+
)
|
|
40
|
+
=> true
|
|
41
|
+
|
|
42
|
+
== Track videos
|
|
43
|
+
|
|
44
|
+
track = Track.new
|
|
45
|
+
track.video_urls << "http://youtube.com/watch?v=fsdfsd"
|
|
46
|
+
track.video_urls << "http://dailymotion.com/video/xefds"
|
|
47
|
+
video = track.save
|
data/lib/heyspread.rb
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
require "rubygems"
|
|
3
|
+
require "hpricot"
|
|
4
|
+
require "cgi"
|
|
5
|
+
|
|
6
|
+
# Hey!Spread: Video Promoting Web Service
|
|
7
|
+
#
|
|
8
|
+
# * Address: http://heyspread.com
|
|
9
|
+
# * Email: bruno.celeste@particle-s.com
|
|
10
|
+
# * Blog: http://particle-s.com
|
|
11
|
+
# * Twitter: http://twitter.com/HeyWatch
|
|
12
|
+
#
|
|
13
|
+
# * API documentation: http://heyspread.com/page/api-documentation
|
|
14
|
+
# * Valid site names to use the API: http://heyspread.com/page/api-documentation-sites
|
|
15
|
+
|
|
16
|
+
module HeySpread
|
|
17
|
+
URL = "http://heyspread.com/api2" unless HeySpread.const_defined?(:URL)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Authenticate your account
|
|
21
|
+
#
|
|
22
|
+
# You can find the API key in your account page
|
|
23
|
+
# http://heyspread.com/account
|
|
24
|
+
#
|
|
25
|
+
# HeySpread::Account.api_key = "api_key"
|
|
26
|
+
|
|
27
|
+
class Account
|
|
28
|
+
def self.api_key=(api_key)
|
|
29
|
+
@@api_key = api_key
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.api_key
|
|
33
|
+
@@api_key ||= nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Manage your videos
|
|
39
|
+
#
|
|
40
|
+
# Upload a video to YouTube and Google Video:
|
|
41
|
+
#
|
|
42
|
+
# HeySpread::Account.api_key = "api_key"
|
|
43
|
+
#
|
|
44
|
+
# video = HeySpread::Video.new(
|
|
45
|
+
# :title => "HS test",
|
|
46
|
+
# :category => "Comedy",
|
|
47
|
+
# :tags => "heyspread tag testing",
|
|
48
|
+
# :file => "/home/user/video.avi",
|
|
49
|
+
# :description => "Test the HeySpread API"
|
|
50
|
+
# )
|
|
51
|
+
#
|
|
52
|
+
# # Set the destination sites
|
|
53
|
+
# # Not required if you saved you Credentials
|
|
54
|
+
# video.destinations["youtube"] = ["login", "password"]
|
|
55
|
+
# video.destinations["google"] = ["email", "password"]
|
|
56
|
+
#
|
|
57
|
+
# video.upload
|
|
58
|
+
#
|
|
59
|
+
|
|
60
|
+
class Video
|
|
61
|
+
attr_accessor :id, :title, :description, :tags, :category, :file, :url,
|
|
62
|
+
:ping, :destinations
|
|
63
|
+
|
|
64
|
+
attr_reader :links, :errors, :uploads, :status, :stat, :created_at,
|
|
65
|
+
:updated_at, :auto_stat_updated_at, :total_views
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Attributes:
|
|
69
|
+
#
|
|
70
|
+
# * :title
|
|
71
|
+
# * :category: can be 'Auto & vehicles', 'Comedy', 'Entertainment',
|
|
72
|
+
# 'Film & Animation', 'Gadgets & Games', 'Howto & DIY', 'Music',
|
|
73
|
+
# 'News & Politics', 'People & Blogs', 'Pets & Animals', 'Sports',
|
|
74
|
+
# 'Travel & Places'
|
|
75
|
+
# * :tags
|
|
76
|
+
# * :description
|
|
77
|
+
# * :file
|
|
78
|
+
# * :url: video URL, can be direct link, YouTube or Google Video link
|
|
79
|
+
# * :ping: when the upload is done, you'll receive all the links and errors
|
|
80
|
+
# to this HTTP address
|
|
81
|
+
# * :destinations: Must be an Hash:
|
|
82
|
+
# {"site1" => ["login", "password"], "site2" => ["login", "password"]}
|
|
83
|
+
#
|
|
84
|
+
#
|
|
85
|
+
# video = HeySpread::Video.new(:title => "HS test", :category => "Comedy",
|
|
86
|
+
# :tags => "heyspread tag testing", :file => "/home/user/video.avi",
|
|
87
|
+
# :description => "Test the HeySpread API",
|
|
88
|
+
# :destinations => {"veoh" => ["login", "password"]}
|
|
89
|
+
# )
|
|
90
|
+
#
|
|
91
|
+
# video = HeySpread::Video.new
|
|
92
|
+
# video.title = "My super video"
|
|
93
|
+
# video.description = "A cool new video"
|
|
94
|
+
# ...
|
|
95
|
+
# video.destinations["dailymotion"] = ["login", password"]
|
|
96
|
+
def initialize(attributes={})
|
|
97
|
+
@destinations = {}
|
|
98
|
+
attributes_to_instance_variables(attributes)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# return an Hash with all the attributes
|
|
102
|
+
def attributes
|
|
103
|
+
attr = {}
|
|
104
|
+
instance_variables.each do |iv|
|
|
105
|
+
attr.merge!(iv.gsub("@", "").to_sym => instance_variable_get(iv))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
attr
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Upload the video on all the sites.
|
|
112
|
+
def upload
|
|
113
|
+
credentials = {}
|
|
114
|
+
if @destinations
|
|
115
|
+
@destinations.each_pair do |site, c|
|
|
116
|
+
credentials.merge!(site => "#{c[0]}:#{c[1]}")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
result = HTTP.post("/video", {
|
|
121
|
+
:title => @title,
|
|
122
|
+
:description => @description,
|
|
123
|
+
:tags => @tags,
|
|
124
|
+
:category => @category,
|
|
125
|
+
:file => @file,
|
|
126
|
+
:url => @url,
|
|
127
|
+
:ping => @ping
|
|
128
|
+
}.merge(credentials)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
Video.new(Video.hpricot_to_hash(result))
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Reload the video object
|
|
135
|
+
def reload
|
|
136
|
+
if @id
|
|
137
|
+
attributes_to_instance_variables(Video.find(@id).attributes)
|
|
138
|
+
end
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Restart the failed uploads
|
|
143
|
+
#
|
|
144
|
+
# HeySpread::Video.find(555).restart
|
|
145
|
+
def restart
|
|
146
|
+
Video.restart(@id)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Delete the video from all the sites
|
|
150
|
+
#
|
|
151
|
+
# HeySpread::Video.find(555).delete
|
|
152
|
+
def delete
|
|
153
|
+
Video.delete(@id)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Enable statistics for this video
|
|
157
|
+
#
|
|
158
|
+
# HeySpread::Video.find(555).enable_statistics
|
|
159
|
+
def enable_statistics
|
|
160
|
+
HTTP.put("/video/#{@id}", {:stat => true})
|
|
161
|
+
true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Get the stats for this video
|
|
165
|
+
#
|
|
166
|
+
# Arguments:
|
|
167
|
+
#
|
|
168
|
+
# * :from: Eg. 2008-05-01
|
|
169
|
+
# * :to: Eg. 2008-05-03
|
|
170
|
+
# * :format: can be "png", "csv", "rss" or "xml". Default is "xml"
|
|
171
|
+
#
|
|
172
|
+
# video = HeySpread::Video.find(555)
|
|
173
|
+
# video.statistics(:from => "2008-05-08", :to => "2008-05-09")
|
|
174
|
+
#
|
|
175
|
+
# => {"2008-05-08"=>{"putfile"=>2, "revver"=>20, "youtube"=>98, "veoh"=>12},
|
|
176
|
+
# "2008-05-09"=>{"putfile"=>16, "revver"=>46, "youtube"=>115, "veoh"=>22}}
|
|
177
|
+
#
|
|
178
|
+
# To access the YouTube stats of May 8, 2008:
|
|
179
|
+
#
|
|
180
|
+
# video.statistics["2008-05-08"]["youtube"]
|
|
181
|
+
# => 98
|
|
182
|
+
#
|
|
183
|
+
# Save the statistics graphic for the current month into a file:
|
|
184
|
+
#
|
|
185
|
+
# File.open("stats.png", "wb") do |f|
|
|
186
|
+
# f.write(video.statistics(:format => "png"))
|
|
187
|
+
# end
|
|
188
|
+
def statistics(options={})
|
|
189
|
+
format = options.delete(:format) || "xml"
|
|
190
|
+
result = HTTP.get("/video/#{@id}/stats.#{format}", options)
|
|
191
|
+
if format == "xml"
|
|
192
|
+
stats = {}
|
|
193
|
+
(result/"statistic").each do |stat|
|
|
194
|
+
views = {}
|
|
195
|
+
stat.each_child do |v|
|
|
196
|
+
views.merge!(v["site"] => v.inner_html.to_i) unless v.to_s.strip.empty?
|
|
197
|
+
end
|
|
198
|
+
stats.merge!(stat["date"] => views)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
stats
|
|
202
|
+
else
|
|
203
|
+
result.to_html
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Update the statistics right now
|
|
208
|
+
#
|
|
209
|
+
# HeySpread::Video.find(555).update_statistics
|
|
210
|
+
def update_statistics
|
|
211
|
+
HTTP.post("/video/#{@id}/stats")
|
|
212
|
+
true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Find a specific video by its ID
|
|
216
|
+
#
|
|
217
|
+
# HeySpread::Video.find(555)
|
|
218
|
+
def self.find(id)
|
|
219
|
+
result = HTTP.get("/video/#{id}")
|
|
220
|
+
Video.new(hpricot_to_hash(result))
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Restart the failed uploads
|
|
224
|
+
#
|
|
225
|
+
# HeySpread::Video.restart(555)
|
|
226
|
+
def self.restart(id)
|
|
227
|
+
HTTP.post("/video/#{id}/restart")
|
|
228
|
+
true
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Delete the video from all the sites
|
|
232
|
+
#
|
|
233
|
+
# HeySpread::Video.delete(555)
|
|
234
|
+
def self.delete(id)
|
|
235
|
+
HTTP.delete("/video/#{id}")
|
|
236
|
+
true
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
private
|
|
240
|
+
|
|
241
|
+
def attributes_to_instance_variables(attributes) #:nodoc:
|
|
242
|
+
attributes.each_pair do |key, value|
|
|
243
|
+
instance_variable_set("@#{key}", value)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def self.hpricot_to_hash(xml) #:nodoc:
|
|
248
|
+
attributes = {}
|
|
249
|
+
attributes[:id] = (xml/"id/").to_s.to_i
|
|
250
|
+
attributes[:title] = (xml/"title/").to_s
|
|
251
|
+
attributes[:description] = (xml/"description/").to_s
|
|
252
|
+
attributes[:tags] = (xml/"tags/").to_s
|
|
253
|
+
attributes[:category] = (xml/"category/").to_s.gsub("&", "&")
|
|
254
|
+
attributes[:stat] = ((xml/"stat/").to_s == "true" ? true : false)
|
|
255
|
+
attributes[:status] = (xml/"status/").to_s
|
|
256
|
+
attributes[:total_views] = (xml/"total-views/").to_s.to_i
|
|
257
|
+
attributes[:created_at] = Time.parse((xml/"created-at/").to_s)
|
|
258
|
+
attributes[:updated_at] = Time.parse((xml/"updated-at/").to_s)
|
|
259
|
+
|
|
260
|
+
stat_updated_at = (xml/"auto-stat-updated-at/").to_s
|
|
261
|
+
if ! stat_updated_at.empty?
|
|
262
|
+
attributes[:auto_stat_updated_at] = Time.parse(stat_updated_at)
|
|
263
|
+
else
|
|
264
|
+
attributes[:auto_stat_updated_at] = nil
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
attributes[:links] = {}
|
|
268
|
+
attributes[:errors] = {}
|
|
269
|
+
attributes[:uploads] = {}
|
|
270
|
+
|
|
271
|
+
(xml/"links/link").each do |link|
|
|
272
|
+
attributes[:links].merge!(link["site"] => link.inner_html)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
(xml/"errors/error").each do |error|
|
|
276
|
+
attributes[:errors].merge!(error["site"] => error.inner_html)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
(xml/"uploads/upload").each do |upload|
|
|
280
|
+
attributes[:uploads].merge!(upload["site"] => {
|
|
281
|
+
:percent => upload["percent"], :speed => upload["speed"],
|
|
282
|
+
:time_left => upload["time-left"],
|
|
283
|
+
:transferred => upload["transferred"], :total => upload["total"]
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
attributes
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# Check, save and delete your credentials
|
|
294
|
+
#
|
|
295
|
+
# Check if the YouTube credentials are valid:
|
|
296
|
+
#
|
|
297
|
+
# HeySpread::Credentials.valid?(
|
|
298
|
+
# :site => "youtube",
|
|
299
|
+
# :login => "testyt",
|
|
300
|
+
# :password => "test"
|
|
301
|
+
# )
|
|
302
|
+
#
|
|
303
|
+
# => false
|
|
304
|
+
#
|
|
305
|
+
# Save YouTube credentials:
|
|
306
|
+
# Return true if they're valid and saved.
|
|
307
|
+
# Otherwise raise an HTTPError, wrong login or password
|
|
308
|
+
#
|
|
309
|
+
# HeySpread::Credentials.save(
|
|
310
|
+
# :site => "youtube",
|
|
311
|
+
# :login => "testyt",
|
|
312
|
+
# :password => "test"
|
|
313
|
+
# )
|
|
314
|
+
# => true
|
|
315
|
+
#
|
|
316
|
+
# Delete the Dailymotion credentials:
|
|
317
|
+
#
|
|
318
|
+
# HeySpread::Credentials.delete("dailymotion")
|
|
319
|
+
# => true
|
|
320
|
+
class Credentials
|
|
321
|
+
# Create or update credentials
|
|
322
|
+
# Raise HTTPError wrong login or password
|
|
323
|
+
# if the credentials are not valid
|
|
324
|
+
def self.save(credentials={})
|
|
325
|
+
HTTP.post("/credentials", credentials)
|
|
326
|
+
true
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Delete credentials for the given site
|
|
330
|
+
def self.delete(site)
|
|
331
|
+
HTTP.delete("/credentials/#{site}")
|
|
332
|
+
true
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Check if the given credentials are valid
|
|
336
|
+
def self.valid?(credentials={})
|
|
337
|
+
result = HTTP.post("/credentials/check", credentials)
|
|
338
|
+
(result/"response/valid").inner_html == "true" ? true : false
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
# Track videos
|
|
344
|
+
#
|
|
345
|
+
# track = Track.new
|
|
346
|
+
# # video_urls is an Array of links
|
|
347
|
+
# track.video_urls << "http://youtube.com/watch?v=fsdfsd"
|
|
348
|
+
# track.video_urls << "http://dailymotion.com/video/xefds"
|
|
349
|
+
#
|
|
350
|
+
# # return a Video object
|
|
351
|
+
# video = track.save
|
|
352
|
+
#
|
|
353
|
+
# # enable the stats
|
|
354
|
+
# video.enable_statistics
|
|
355
|
+
#
|
|
356
|
+
# if there is no YouTube link, you must give the title, description,
|
|
357
|
+
# category and tags
|
|
358
|
+
|
|
359
|
+
class Track
|
|
360
|
+
attr_accessor :video_urls, :title, :description, :tags, :category
|
|
361
|
+
|
|
362
|
+
# Track the given video URLS
|
|
363
|
+
#
|
|
364
|
+
# track = Track.new
|
|
365
|
+
# track.title = "my title"
|
|
366
|
+
# track.description = "my description"
|
|
367
|
+
#
|
|
368
|
+
# track = Track.new(
|
|
369
|
+
# :title => "my title",
|
|
370
|
+
# #...
|
|
371
|
+
# :video_urls => ["http://youtube.com/watch?v=dsfsd"]
|
|
372
|
+
# )
|
|
373
|
+
def initialize(options={})
|
|
374
|
+
@video_urls = []
|
|
375
|
+
options.each_pair do |k,v|
|
|
376
|
+
instance_variable_set("@#{k}", v)
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# Track the given video URL
|
|
381
|
+
def <<(url)
|
|
382
|
+
@video_urls << url
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Save all the video urls and return a Video object
|
|
386
|
+
def save
|
|
387
|
+
result = HTTP.post("/track", {
|
|
388
|
+
:video_urls => @video_urls.join(" "),
|
|
389
|
+
:title => @title,
|
|
390
|
+
:description => @description,
|
|
391
|
+
:tags => @tags,
|
|
392
|
+
:category => @category
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
Video.new(Video.hpricot_to_hash(result))
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
# Export videos from a YouTube account to any other video sites
|
|
402
|
+
#
|
|
403
|
+
# Export all the Youtube videos of a given account to Dailymotion:
|
|
404
|
+
#
|
|
405
|
+
# export = YouClone.new
|
|
406
|
+
# export.youtube_account = ["login", "password"]
|
|
407
|
+
# export.destinations["dailymotion"] = ["login", "password"]
|
|
408
|
+
# export.save
|
|
409
|
+
#
|
|
410
|
+
# If you don't set the destinations, you'll use your saved Credentials
|
|
411
|
+
|
|
412
|
+
class YouClone
|
|
413
|
+
attr_accessor :destinations
|
|
414
|
+
|
|
415
|
+
# Set the destinations (including YouTube)
|
|
416
|
+
#
|
|
417
|
+
# export = YouClone.new(
|
|
418
|
+
# "youtube" => ["login", "password"],
|
|
419
|
+
# "dailymotion" => ["login", "password"]
|
|
420
|
+
# )
|
|
421
|
+
def initialize(destinations={})
|
|
422
|
+
@destinations = destinations
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
# Set the YouTube account
|
|
426
|
+
#
|
|
427
|
+
# export.youtube_account = ["login", "password"]
|
|
428
|
+
def youtube_account=(credentials=[])
|
|
429
|
+
@destinations["youtube"] = credentials
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Export the videos of a YouTube account to any other video sites
|
|
433
|
+
def save
|
|
434
|
+
credentials = {}
|
|
435
|
+
if @destinations
|
|
436
|
+
@destinations.each_pair do |site, c|
|
|
437
|
+
credentials.merge!(site => "#{c[0]}:#{c[1]}")
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
HTTP.post("/youclone", credentials)
|
|
442
|
+
|
|
443
|
+
true
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
class HTTPError < RuntimeError #:nodoc:
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
class HTTP #:nodoc:
|
|
452
|
+
%w(get post delete put).each do |m|
|
|
453
|
+
HTTP.module_eval(%(
|
|
454
|
+
def self.#{m}(path, query={})
|
|
455
|
+
request(:method => '#{m}', :path => path, :query => query)
|
|
456
|
+
end
|
|
457
|
+
))
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
private
|
|
461
|
+
|
|
462
|
+
class << self
|
|
463
|
+
|
|
464
|
+
def parse(str)
|
|
465
|
+
Hpricot.XML(str)
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def request(options={})
|
|
469
|
+
uri = URI.parse(HeySpread::URL)
|
|
470
|
+
options[:query].merge!(:api_key => HeySpread::Account.api_key)
|
|
471
|
+
options[:path] = uri.path + options[:path]
|
|
472
|
+
|
|
473
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
474
|
+
if options[:query][:file].nil?
|
|
475
|
+
res = http.send_request(options[:method].to_s.upcase, options[:path],
|
|
476
|
+
query_to_string(options[:query]))
|
|
477
|
+
else
|
|
478
|
+
boundary = rand(9).to_s * 36
|
|
479
|
+
res = http.send_request(options[:method].to_s.upcase, options[:path],
|
|
480
|
+
query_to_multipart(boundary, options[:query]),
|
|
481
|
+
"Content-Type" => "multipart/form-data; boundary=" + boundary
|
|
482
|
+
)
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
body = parse(res.body || "")
|
|
486
|
+
|
|
487
|
+
unless res.code =~ /^[2|3]/
|
|
488
|
+
error = (body/"errors/error").map{|e| e.inner_html}.join(", ") rescue ""
|
|
489
|
+
raise(HTTPError, "#{res.message}#{'. Reason: ' + error}")
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
body
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
def query_to_multipart(boundary, attributes={}) #:nodoc:
|
|
496
|
+
file = attributes.delete(:file)
|
|
497
|
+
params = [file_to_multipart("file", File.basename(file),
|
|
498
|
+
"application/octet-stream", File.read(file))]
|
|
499
|
+
|
|
500
|
+
attributes.each_pair{|k,v| params << text_to_multipart(k.to_s, v.to_s)}
|
|
501
|
+
params.map do |p|
|
|
502
|
+
'--' + boundary + "\r\n" + p
|
|
503
|
+
end.join('') + "--" + boundary + "--\r\n"
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def text_to_multipart(key,value) #:nodoc:
|
|
507
|
+
return "Content-Disposition: form-data; name=\"#{CGI::escape(key.to_s)}\"\r\n" +
|
|
508
|
+
"\r\n" +
|
|
509
|
+
"#{value}\r\n"
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def file_to_multipart(key,filename,mime_type,content) #:nodoc:
|
|
513
|
+
return "Content-Disposition: form-data; name=\"#{CGI::escape(key.to_s)}\"; filename=\"#{filename}\"\r\n" +
|
|
514
|
+
"Content-Transfer-Encoding: binary\r\n" +
|
|
515
|
+
"Content-Type: #{mime_type}\r\n" +
|
|
516
|
+
"\r\n" +
|
|
517
|
+
"#{content}\r\n"
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def query_to_string(query)
|
|
521
|
+
str = ""
|
|
522
|
+
query.each do |key, value|
|
|
523
|
+
str << (str.empty? ? "" : "&")
|
|
524
|
+
if ! value.to_s.empty?
|
|
525
|
+
str << "#{key}=#{CGI::escape(value.to_s)}"
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
str
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sadikzzz-heyspread-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: "0.1"
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Bruno Celeste
|
|
8
|
+
autorequire: heyspread
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2008-07-08 00:00:00 -07:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: hpricot
|
|
17
|
+
version_requirement:
|
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
19
|
+
requirements:
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: "0"
|
|
23
|
+
version:
|
|
24
|
+
description: An interface library that allows Ruby applications to distribute videos over the best video sites.
|
|
25
|
+
email: bruno.celeste@particle-s.com
|
|
26
|
+
executables: []
|
|
27
|
+
|
|
28
|
+
extensions: []
|
|
29
|
+
|
|
30
|
+
extra_rdoc_files: []
|
|
31
|
+
|
|
32
|
+
files:
|
|
33
|
+
- MIT-LICENSE
|
|
34
|
+
- README
|
|
35
|
+
- lib/heyspread.rb
|
|
36
|
+
has_rdoc: false
|
|
37
|
+
homepage: http://heyspread.com
|
|
38
|
+
post_install_message:
|
|
39
|
+
rdoc_options: []
|
|
40
|
+
|
|
41
|
+
require_paths:
|
|
42
|
+
- lib
|
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: "0"
|
|
48
|
+
version:
|
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: "0"
|
|
54
|
+
version:
|
|
55
|
+
requirements: []
|
|
56
|
+
|
|
57
|
+
rubyforge_project:
|
|
58
|
+
rubygems_version: 1.2.0
|
|
59
|
+
signing_key:
|
|
60
|
+
specification_version: 2
|
|
61
|
+
summary: An interface library that allows Ruby applications to distribute videos over the best video sites.
|
|
62
|
+
test_files: []
|
|
63
|
+
|