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.
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
+