sadikzzz-heyspread-ruby 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README +47 -0
  3. data/lib/heyspread.rb +532 -0
  4. 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("&amp;", "&")
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
+