ruby_tube 0.3.3
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/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +11 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/lib/ruby_tube.rb +143 -0
- data/lib/ruby_tube_no_auth.rb +72 -0
- data/lib/yt_client.rb +120 -0
- data/lib/yt_comment.rb +13 -0
- data/lib/yt_rating.rb +10 -0
- data/lib/yt_video.rb +44 -0
- data/ruby_tube.gemspec +67 -0
- data/test/josh_walking.mp4 +0 -0
- data/test/maddie.mp4 +0 -0
- data/test/ruby_tube_test.rb +17 -0
- data/test/test_helper.rb +10 -0
- data/test/yt_client_test.rb +33 -0
- metadata +104 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 Mike Green
|
|
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.rdoc
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
= ruby_tube
|
|
2
|
+
|
|
3
|
+
RubyTube is a simple library built to interact with YouTube through ActiveRecord-like methods (like find, count, all, etc).
|
|
4
|
+
|
|
5
|
+
It's far from polished, and not all its methods are AR-like. It does provide a relatively simple interface for uploading videos to YouTube and retrieving info on the videos you've uploaded.
|
|
6
|
+
|
|
7
|
+
Yet another gem I don't expect anyone to actually use - I just built it because I needed basic YouTube functionality for a Rails app I'm working on.
|
|
8
|
+
|
|
9
|
+
== Copyright
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2009 Mike Green. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "ruby_tube"
|
|
8
|
+
gem.summary = %Q{Simple Ruby library for uploading and finding YouTube videos.}
|
|
9
|
+
gem.email = "mike.is.green@gmail.com"
|
|
10
|
+
gem.homepage = "http://github.com/mikedamage/ruby_tube"
|
|
11
|
+
gem.authors = ["Mike Green"]
|
|
12
|
+
gem.add_dependency("gdata", ">= 1.1.0")
|
|
13
|
+
gem.add_dependency("httparty", ">= 0.4.3")
|
|
14
|
+
gem.add_dependency("hpricot", ">= 0.8.1")
|
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
rescue LoadError
|
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require 'rake/testtask'
|
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
|
24
|
+
test.libs << 'lib' << 'test'
|
|
25
|
+
test.pattern = 'test/**/*_test.rb'
|
|
26
|
+
test.verbose = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
begin
|
|
30
|
+
require 'rcov/rcovtask'
|
|
31
|
+
Rcov::RcovTask.new do |test|
|
|
32
|
+
test.libs << 'test'
|
|
33
|
+
test.pattern = 'test/**/*_test.rb'
|
|
34
|
+
test.verbose = true
|
|
35
|
+
end
|
|
36
|
+
rescue LoadError
|
|
37
|
+
task :rcov do
|
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
task :default => :test
|
|
44
|
+
|
|
45
|
+
require 'rake/rdoctask'
|
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
|
47
|
+
if File.exist?('VERSION.yml')
|
|
48
|
+
config = YAML.load(File.read('VERSION.yml'))
|
|
49
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
|
50
|
+
else
|
|
51
|
+
version = ""
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
55
|
+
rdoc.title = "ruby_tube #{version}"
|
|
56
|
+
rdoc.rdoc_files.include('README*')
|
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
58
|
+
end
|
|
59
|
+
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.3.3
|
data/lib/ruby_tube.rb
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "yt_client.rb")
|
|
2
|
+
require File.join(File.dirname(__FILE__), "yt_video.rb")
|
|
3
|
+
require File.join(File.dirname(__FILE__), "yt_comment.rb")
|
|
4
|
+
require File.join(File.dirname(__FILE__), "yt_rating.rb")
|
|
5
|
+
require File.join(File.dirname(__FILE__), "ruby_tube_no_auth.rb")
|
|
6
|
+
|
|
7
|
+
class RubyTube < YTClient
|
|
8
|
+
|
|
9
|
+
def initialize(username, password, key, options={:refresh=>300})
|
|
10
|
+
super(username, password, key, options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def find(id)
|
|
14
|
+
xml = check_video(id)
|
|
15
|
+
entry = (xml/"entry")
|
|
16
|
+
status = (xml/"yt:state").empty? ? "ok" : (xml/"yt:state").attr("name")
|
|
17
|
+
video = YTVideo.new({
|
|
18
|
+
:id => (entry/"yt:videoid").text,
|
|
19
|
+
:title => (entry/"title").text,
|
|
20
|
+
:description => (entry/"media:description").text,
|
|
21
|
+
:keywords => (entry/"media:keywords").text,
|
|
22
|
+
:duration => (entry/"yt:duration").attr("seconds").to_i,
|
|
23
|
+
:player_uri => (entry/"link[@rel='alternate']").attr("href"),
|
|
24
|
+
:ratings_uri => (entry/"link[@rel$='ratings']").attr("href"),
|
|
25
|
+
:comments_uri => (entry/"gd:comments").search("gd:feedlink").attr("href"),
|
|
26
|
+
:comment_count => (entry/"gd:comments").search("gd:feedlink").attr("countHint").to_i,
|
|
27
|
+
:published_at => Time.parse((entry/"published").text),
|
|
28
|
+
:updated_at => Time.parse((entry/"updated").text),
|
|
29
|
+
:view_count => (entry/"yt:statistics").empty? ? 0 : (entry/"yt:statistics").attr("viewCount"),
|
|
30
|
+
:favorite_count => (entry/"yt:statistics").empty? ? 0 : (entry/"yt:statistics").attr("favoriteCount"),
|
|
31
|
+
:comments => comments((entry/"yt:videoid").text),
|
|
32
|
+
:ratings => ratings((entry/"yt:videoid").text),
|
|
33
|
+
:status => status,
|
|
34
|
+
:thumbnails => process_thumbnail_urls(entry)
|
|
35
|
+
})
|
|
36
|
+
return video
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_all
|
|
40
|
+
@all = all()
|
|
41
|
+
videos = Array.new
|
|
42
|
+
(all/"entry").each do |entry|
|
|
43
|
+
status = (entry/"yt:state").empty? ? "ok" : (entry/"yt:state").attr("name")
|
|
44
|
+
video = YTVideo.new({
|
|
45
|
+
:id => (entry/"yt:videoid").text,
|
|
46
|
+
:title => (entry/"title").text,
|
|
47
|
+
:description => (entry/"media:description").text,
|
|
48
|
+
:keywords => (entry/"media:keywords").text,
|
|
49
|
+
:duration => (entry/"yt:duration").attr("seconds").to_i,
|
|
50
|
+
:player_uri => (entry/"link[@rel='alternate']").attr("href"),
|
|
51
|
+
:ratings_uri => (entry/"link[@rel$='ratings']").attr("href"),
|
|
52
|
+
:comments_uri => (entry/"gd:comments").search("gd:feedlink").attr("href"),
|
|
53
|
+
:comment_count => (entry/"gd:comments").search("gd:feedlink").attr("countHint").to_i,
|
|
54
|
+
:published_at => Time.parse((entry/"published").text),
|
|
55
|
+
:updated_at => Time.parse((entry/"updated").text),
|
|
56
|
+
:view_count => (entry/"yt:statistics").empty? ? 0 : (entry/"yt:statistics").attr("viewCount"),
|
|
57
|
+
:favorite_count => (entry/"yt:statistics").empty? ? 0 : (entry/"yt:statistics").attr("favoriteCount"),
|
|
58
|
+
:comments => comments((entry/"yt:videoid").text),
|
|
59
|
+
:ratings => ratings((entry/"yt:videoid").text),
|
|
60
|
+
:status => status,
|
|
61
|
+
:thumbnails => process_thumbnail_urls(entry)
|
|
62
|
+
})
|
|
63
|
+
videos << video
|
|
64
|
+
end
|
|
65
|
+
return videos
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def count
|
|
69
|
+
super
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def comments(id)
|
|
73
|
+
xml = super
|
|
74
|
+
comments = Array.new
|
|
75
|
+
if (xml/"entry").nitems > 0
|
|
76
|
+
(xml/"entry").each do |entry|
|
|
77
|
+
comment = YTComment.new({
|
|
78
|
+
:title => (entry/"title").text,
|
|
79
|
+
:content => (entry/"content").text,
|
|
80
|
+
:author => (entry/"author").search("name").text,
|
|
81
|
+
:author_uri => (entry/"author").search("uri").text,
|
|
82
|
+
:video_uri => (entry/"link[@rel='related']").attr("href")
|
|
83
|
+
})
|
|
84
|
+
comments << comment
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
return comments
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ratings(id)
|
|
91
|
+
xml = super
|
|
92
|
+
rating = nil
|
|
93
|
+
if xml
|
|
94
|
+
rating = YTRating.new({
|
|
95
|
+
:num_raters => xml.attr("numRaters").to_i,
|
|
96
|
+
:max => xml.attr("max").to_i,
|
|
97
|
+
:min => xml.attr("min").to_i,
|
|
98
|
+
:average => xml.attr("average").to_f
|
|
99
|
+
})
|
|
100
|
+
end
|
|
101
|
+
return rating
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def update_video(id, options)
|
|
105
|
+
video = find(id)
|
|
106
|
+
if options[:title]
|
|
107
|
+
video.title = options[:title]
|
|
108
|
+
end
|
|
109
|
+
if options[:description]
|
|
110
|
+
video.description = options[:description]
|
|
111
|
+
end
|
|
112
|
+
if options[:keywords]
|
|
113
|
+
video.keywords = options[:keywords]
|
|
114
|
+
end
|
|
115
|
+
entry = video.to_xml
|
|
116
|
+
response = update(video.id, entry)
|
|
117
|
+
if response.status_code == 200
|
|
118
|
+
return video
|
|
119
|
+
else
|
|
120
|
+
return false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def upload_video(filename, options={})
|
|
125
|
+
response = upload(filename, options)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def delete_video(id)
|
|
129
|
+
response = delete(id)
|
|
130
|
+
if response.status_code == 200
|
|
131
|
+
return true
|
|
132
|
+
else
|
|
133
|
+
return false
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
def process_thumbnail_urls(hpricot)
|
|
139
|
+
thumbs = (hpricot/"media:thumbnail")
|
|
140
|
+
{:big => thumbs.last["url"], :small => thumbs.first["url"]}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
class RubyTubeNoAuth
|
|
2
|
+
attr_accessor :client
|
|
3
|
+
|
|
4
|
+
def initialize(dev_key="")
|
|
5
|
+
@client = GData::Client::YouTube.new
|
|
6
|
+
@client.source = "RubyTube"
|
|
7
|
+
if dev_key
|
|
8
|
+
@client.developer_key = dev_key
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def find(id)
|
|
13
|
+
res = @client.get("http://gdata.youtube.com/feeds/api/videos/#{id}")
|
|
14
|
+
xml = Hpricot.XML(res.body)
|
|
15
|
+
entry = xml.at("entry")
|
|
16
|
+
vid = YTVideo.new({
|
|
17
|
+
:id => (entry/"yt:videoid").text,
|
|
18
|
+
:title => (entry/"title").text,
|
|
19
|
+
:description => (entry/"media:description").text,
|
|
20
|
+
:keywords => (entry/"media:keywords").text,
|
|
21
|
+
:duration => (entry/"yt:duration").attr("seconds").to_i,
|
|
22
|
+
:player_uri => (entry/"link[@rel='alternate']").attr("href"),
|
|
23
|
+
:ratings_uri => (entry/"link[@rel$='ratings']").attr("href"),
|
|
24
|
+
:comments_uri => (entry/"gd:comments").search("gd:feedlink").attr("href"),
|
|
25
|
+
:comment_count => (entry/"gd:comments").search("gd:feedlink").attr("countHint").to_i,
|
|
26
|
+
:published_at => Time.parse((entry/"published").text),
|
|
27
|
+
:updated_at => Time.parse((entry/"updated").text),
|
|
28
|
+
:view_count => (entry/"yt:statistics").nil? ? 0 : (entry/"yt:statistics").attr("viewCount"),
|
|
29
|
+
:favorite_count => (entry/"yt:statistics").nil? ? 0 : (entry/"yt:statistics").attr("favoriteCount"),
|
|
30
|
+
:comments => comments((entry/"yt:videoid").text),
|
|
31
|
+
:ratings => ratings((entry/"yt:videoid").text),
|
|
32
|
+
:status => status,
|
|
33
|
+
:thumbnails => process_thumbnail_urls(entry)
|
|
34
|
+
})
|
|
35
|
+
vid
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def comments(id)
|
|
39
|
+
res = @client.get("http://gdata.youtube.com/feeds/api/videos/#{id}/comments")
|
|
40
|
+
xml = Hpricot.XML(res.body)
|
|
41
|
+
comments = Array.new
|
|
42
|
+
if (xml/"entry").nitems > 0
|
|
43
|
+
(xml/"entry").each do |entry|
|
|
44
|
+
cmt = YTComment.new({
|
|
45
|
+
:title => (entry/"title").text,
|
|
46
|
+
:content => (entry/"content").text,
|
|
47
|
+
:author => (entry/"author").search("name").text,
|
|
48
|
+
:author_uri => (entry/"author").search("uri").text,
|
|
49
|
+
:video_uri => (entry/"link[@rel='related']").attr("href")
|
|
50
|
+
})
|
|
51
|
+
comments << cmt
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
comments
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def ratings(id)
|
|
58
|
+
response = Hpricot.XML(@client.get("http://gdata.youtube.com/feeds/api/videos/#{id}").body)
|
|
59
|
+
ratings = (response/"gd:rating")
|
|
60
|
+
if ratings.nitems > 0
|
|
61
|
+
return ratings
|
|
62
|
+
else
|
|
63
|
+
return nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
def process_thumbnail_urls(hpricot)
|
|
69
|
+
thumbs = (hpricot/"media:thumbnail")
|
|
70
|
+
{:big => thumbs.last["url"], :small => thumbs.first["url"]}
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/yt_client.rb
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require "uri"
|
|
2
|
+
require "net/http"
|
|
3
|
+
require "gdata"
|
|
4
|
+
require "hpricot"
|
|
5
|
+
require "httparty"
|
|
6
|
+
require "time"
|
|
7
|
+
|
|
8
|
+
class YTClient
|
|
9
|
+
attr_accessor :username, :password, :developer_key, :token, :client
|
|
10
|
+
include HTTParty
|
|
11
|
+
|
|
12
|
+
base_uri "http://gdata.youtube.com/feeds/api"
|
|
13
|
+
format :plain
|
|
14
|
+
|
|
15
|
+
UPLOAD_URI = "http://uploads.gdata.youtube.com/feeds/api/users/default/uploads"
|
|
16
|
+
|
|
17
|
+
def initialize(username, password, key, options={:refresh=>300})
|
|
18
|
+
@username = username
|
|
19
|
+
@password = password
|
|
20
|
+
@developer_key = key
|
|
21
|
+
@client = GData::Client::YouTube.new
|
|
22
|
+
@client.source = "acer_timeline_contest"
|
|
23
|
+
@client.developer_key = @developer_key
|
|
24
|
+
@token = @client.clientlogin(@username, @password)
|
|
25
|
+
@options = options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def all
|
|
29
|
+
if @all_vids
|
|
30
|
+
if Time.parse((@all_vids/"updated").text) < (Time.now - @options[:refresh])
|
|
31
|
+
@all_vids = Hpricot.XML(@client.get(self.class.base_uri + "/users/default/uploads").body)
|
|
32
|
+
else
|
|
33
|
+
return @all_vids
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
@all_vids = Hpricot.XML(@client.get(self.class.base_uri + "/users/default/uploads").body)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def count
|
|
41
|
+
(@all_vids/"entry").nitems
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def check_video(id)
|
|
45
|
+
Hpricot.XML(@client.get(self.class.base_uri + "/videos/#{id}").body)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def ratings(id)
|
|
49
|
+
response = Hpricot.XML(@client.get(self.class.base_uri + "/videos/#{id}").body)
|
|
50
|
+
ratings = (response/"gd:rating")
|
|
51
|
+
if ratings.nitems > 0
|
|
52
|
+
return ratings
|
|
53
|
+
else
|
|
54
|
+
return nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def comments(id)
|
|
59
|
+
Hpricot.XML(@client.get(self.class.base_uri + "/videos/#{id}/comments").body)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def upload(file, options={})
|
|
63
|
+
upload_uri = URI.parse(UPLOAD_URI)
|
|
64
|
+
binary_data = read_file(file)
|
|
65
|
+
request_data = <<-REQDATA
|
|
66
|
+
--bbe873dc
|
|
67
|
+
Content-Type: application/atom+xml; charset=utf-8
|
|
68
|
+
|
|
69
|
+
<?xml version="1.0"?>
|
|
70
|
+
<entry xmlns="http://www.w3.org/2005/Atom"
|
|
71
|
+
xmlns:media="http://search.yahoo.com/mrss/"
|
|
72
|
+
xmlns:yt="http://gdata.youtube.com/schemas/2007">
|
|
73
|
+
<media:group>
|
|
74
|
+
<media:title type="plain">#{options[:title]}</media:title>
|
|
75
|
+
<media:description type="plain">
|
|
76
|
+
#{options[:description]}
|
|
77
|
+
</media:description>
|
|
78
|
+
<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">
|
|
79
|
+
People
|
|
80
|
+
</media:category>
|
|
81
|
+
<media:keywords>#{options[:keywords]}</media:keywords>
|
|
82
|
+
</media:group>
|
|
83
|
+
</entry>
|
|
84
|
+
--bbe873dc
|
|
85
|
+
Content-Type: #{options[:content_type]}
|
|
86
|
+
Content-Transfer-Encoding: binary
|
|
87
|
+
|
|
88
|
+
#{binary_data}
|
|
89
|
+
--bbe873dc
|
|
90
|
+
REQDATA
|
|
91
|
+
http = Net::HTTP.new(upload_uri.host)
|
|
92
|
+
http.read_timeout = 6000
|
|
93
|
+
headers = {
|
|
94
|
+
'GData-Version' => "2",
|
|
95
|
+
'X-GData-Key' => "key=#{@developer_key}",
|
|
96
|
+
'Slug' => File.basename(file),
|
|
97
|
+
'Authorization' => "GoogleLogin auth=#{@token}",
|
|
98
|
+
'Content-Type' => 'multipart/related; boundary="bbe873dc"',
|
|
99
|
+
'Content-Length' => binary_data.length.to_s,
|
|
100
|
+
'Connection' => 'close'
|
|
101
|
+
}
|
|
102
|
+
res = http.post(upload_uri.path, request_data, headers)
|
|
103
|
+
response = {:code => res.code, :body => Hpricot.XML(res.body)}
|
|
104
|
+
return response
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def update(id, xml)
|
|
108
|
+
response = @client.put(self.class.base_uri + "/users/default/uploads/#{id}", xml)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def delete(id)
|
|
112
|
+
response = @client.delete(self.class.base_uri + "/users/default/uploads/#{id}")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
def read_file(file)
|
|
117
|
+
contents = File.open(file, "r") {|io| io.read }
|
|
118
|
+
return contents
|
|
119
|
+
end
|
|
120
|
+
end
|
data/lib/yt_comment.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class YTComment
|
|
2
|
+
|
|
3
|
+
attr_accessor :title, :content, :author, :author_uri, :video_uri
|
|
4
|
+
|
|
5
|
+
def initialize(data)
|
|
6
|
+
@title = data[:title]
|
|
7
|
+
@content = data[:content]
|
|
8
|
+
@author = data[:author]
|
|
9
|
+
@author_uri = data[:author_uri]
|
|
10
|
+
@video_uri = data[:video_uri]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
data/lib/yt_rating.rb
ADDED
data/lib/yt_video.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class YTVideo
|
|
2
|
+
|
|
3
|
+
attr_reader :id, :duration, :player_uri, :thumbnails, :published_at, :updated_at, :ratings_uri, :comments_uri, :view_count, :favorite_count, :comment_count, :ratings, :comments, :status
|
|
4
|
+
attr_accessor :title, :description, :keywords
|
|
5
|
+
|
|
6
|
+
def initialize(data)
|
|
7
|
+
@id = data[:id]
|
|
8
|
+
@title = data[:title]
|
|
9
|
+
@description = data[:description]
|
|
10
|
+
@keywords = data[:keywords]
|
|
11
|
+
@duration = data[:duration]
|
|
12
|
+
@player_uri = data[:player_uri]
|
|
13
|
+
@ratings_uri = data[:ratings_uri]
|
|
14
|
+
@comments_uri = data[:comments_uri]
|
|
15
|
+
@published_at = data[:published_at]
|
|
16
|
+
@updated_at = data[:updated_at]
|
|
17
|
+
@thumbnails = data[:thumbnails]
|
|
18
|
+
@view_count = data[:view_count]
|
|
19
|
+
@favorite_count = data[:favorite_count]
|
|
20
|
+
@comment_count = data[:comment_count]
|
|
21
|
+
@ratings = data[:ratings]
|
|
22
|
+
@comments = data[:comments]
|
|
23
|
+
@status = data[:status]
|
|
24
|
+
@thumbnails = data[:thumbnails]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_xml
|
|
28
|
+
data = <<-XMLSTOP
|
|
29
|
+
<?xml version="1.0"?>
|
|
30
|
+
<entry xmlns="http://www.w3.org/2005/Atom"
|
|
31
|
+
xmlns:media="http://search.yahoo.com/mrss/"
|
|
32
|
+
xmlns:yt="http://gdata.youtube.com/schemas/2007">
|
|
33
|
+
<media:group>
|
|
34
|
+
<media:title type="plain">#{@title}</media:title>
|
|
35
|
+
<media:description type="plain">#{@description}</media:description>
|
|
36
|
+
<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Tech</media:category>
|
|
37
|
+
<media:keywords>#{@keywords}</media:keywords>
|
|
38
|
+
</media:group>
|
|
39
|
+
</entry>
|
|
40
|
+
XMLSTOP
|
|
41
|
+
return data
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
data/ruby_tube.gemspec
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Generated by jeweler
|
|
2
|
+
# DO NOT EDIT THIS FILE
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
|
4
|
+
# -*- encoding: utf-8 -*-
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = %q{ruby_tube}
|
|
8
|
+
s.version = "0.3.3"
|
|
9
|
+
|
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
+
s.authors = ["Mike Green"]
|
|
12
|
+
s.date = %q{2009-09-18}
|
|
13
|
+
s.email = %q{mike.is.green@gmail.com}
|
|
14
|
+
s.extra_rdoc_files = [
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.rdoc"
|
|
17
|
+
]
|
|
18
|
+
s.files = [
|
|
19
|
+
".document",
|
|
20
|
+
".gitignore",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"README.rdoc",
|
|
23
|
+
"Rakefile",
|
|
24
|
+
"VERSION",
|
|
25
|
+
"lib/ruby_tube.rb",
|
|
26
|
+
"lib/ruby_tube_no_auth.rb",
|
|
27
|
+
"lib/yt_client.rb",
|
|
28
|
+
"lib/yt_comment.rb",
|
|
29
|
+
"lib/yt_rating.rb",
|
|
30
|
+
"lib/yt_video.rb",
|
|
31
|
+
"ruby_tube.gemspec",
|
|
32
|
+
"test/josh_walking.mp4",
|
|
33
|
+
"test/maddie.mp4",
|
|
34
|
+
"test/ruby_tube_test.rb",
|
|
35
|
+
"test/test_helper.rb",
|
|
36
|
+
"test/yt_client_test.rb"
|
|
37
|
+
]
|
|
38
|
+
s.homepage = %q{http://github.com/mikedamage/ruby_tube}
|
|
39
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
40
|
+
s.require_paths = ["lib"]
|
|
41
|
+
s.rubygems_version = %q{1.3.5}
|
|
42
|
+
s.summary = %q{Simple Ruby library for uploading and finding YouTube videos.}
|
|
43
|
+
s.test_files = [
|
|
44
|
+
"test/ruby_tube_test.rb",
|
|
45
|
+
"test/test_helper.rb",
|
|
46
|
+
"test/yt_client_test.rb"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
if s.respond_to? :specification_version then
|
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
51
|
+
s.specification_version = 3
|
|
52
|
+
|
|
53
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
54
|
+
s.add_runtime_dependency(%q<gdata>, [">= 1.1.0"])
|
|
55
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0.4.3"])
|
|
56
|
+
s.add_runtime_dependency(%q<hpricot>, [">= 0.8.1"])
|
|
57
|
+
else
|
|
58
|
+
s.add_dependency(%q<gdata>, [">= 1.1.0"])
|
|
59
|
+
s.add_dependency(%q<httparty>, [">= 0.4.3"])
|
|
60
|
+
s.add_dependency(%q<hpricot>, [">= 0.8.1"])
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
s.add_dependency(%q<gdata>, [">= 1.1.0"])
|
|
64
|
+
s.add_dependency(%q<httparty>, [">= 0.4.3"])
|
|
65
|
+
s.add_dependency(%q<hpricot>, [">= 0.8.1"])
|
|
66
|
+
end
|
|
67
|
+
end
|
|
Binary file
|
data/test/maddie.mp4
ADDED
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class RubyTubeTest < Test::Unit::TestCase
|
|
4
|
+
context "a RubyTube instance" do
|
|
5
|
+
setup do
|
|
6
|
+
@yt = RubyTube.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
should "contain an instance of GData::Client::YouTube" do
|
|
10
|
+
assert @yt.client.is_a?(GData::Client::YouTube)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
should "get a ClientLogin token from YouTube" do
|
|
14
|
+
assert @yt.token
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class YTClientTest < Test::Unit::TestCase
|
|
5
|
+
context "A YTClient instance" do
|
|
6
|
+
setup do
|
|
7
|
+
@yt = YTClient.new("frcmike", "k2130k", RubyTube::DEV_KEY)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "retrieve a ClientLogin token on instantiation" do
|
|
11
|
+
assert not_nil(@yt.token)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "return a list of uploaded files" do
|
|
15
|
+
assert not_nil(@yt.all)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
should "return Fixnum when #count is called" do
|
|
19
|
+
assert @yt.count.is_a?(Fixnum)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# TODO: write upload tests w/o having to repeat the upload process for each test
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
def not_nil(item)
|
|
27
|
+
!item.nil?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def not_empty(item)
|
|
31
|
+
!item.empty?
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruby_tube
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mike Green
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-09-18 00:00:00 -04:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: gdata
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 1.1.0
|
|
24
|
+
version:
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: httparty
|
|
27
|
+
type: :runtime
|
|
28
|
+
version_requirement:
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.4.3
|
|
34
|
+
version:
|
|
35
|
+
- !ruby/object:Gem::Dependency
|
|
36
|
+
name: hpricot
|
|
37
|
+
type: :runtime
|
|
38
|
+
version_requirement:
|
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 0.8.1
|
|
44
|
+
version:
|
|
45
|
+
description:
|
|
46
|
+
email: mike.is.green@gmail.com
|
|
47
|
+
executables: []
|
|
48
|
+
|
|
49
|
+
extensions: []
|
|
50
|
+
|
|
51
|
+
extra_rdoc_files:
|
|
52
|
+
- LICENSE
|
|
53
|
+
- README.rdoc
|
|
54
|
+
files:
|
|
55
|
+
- .document
|
|
56
|
+
- .gitignore
|
|
57
|
+
- LICENSE
|
|
58
|
+
- README.rdoc
|
|
59
|
+
- Rakefile
|
|
60
|
+
- VERSION
|
|
61
|
+
- lib/ruby_tube.rb
|
|
62
|
+
- lib/ruby_tube_no_auth.rb
|
|
63
|
+
- lib/yt_client.rb
|
|
64
|
+
- lib/yt_comment.rb
|
|
65
|
+
- lib/yt_rating.rb
|
|
66
|
+
- lib/yt_video.rb
|
|
67
|
+
- ruby_tube.gemspec
|
|
68
|
+
- test/josh_walking.mp4
|
|
69
|
+
- test/maddie.mp4
|
|
70
|
+
- test/ruby_tube_test.rb
|
|
71
|
+
- test/test_helper.rb
|
|
72
|
+
- test/yt_client_test.rb
|
|
73
|
+
has_rdoc: true
|
|
74
|
+
homepage: http://github.com/mikedamage/ruby_tube
|
|
75
|
+
licenses: []
|
|
76
|
+
|
|
77
|
+
post_install_message:
|
|
78
|
+
rdoc_options:
|
|
79
|
+
- --charset=UTF-8
|
|
80
|
+
require_paths:
|
|
81
|
+
- lib
|
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: "0"
|
|
87
|
+
version:
|
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: "0"
|
|
93
|
+
version:
|
|
94
|
+
requirements: []
|
|
95
|
+
|
|
96
|
+
rubyforge_project:
|
|
97
|
+
rubygems_version: 1.3.5
|
|
98
|
+
signing_key:
|
|
99
|
+
specification_version: 3
|
|
100
|
+
summary: Simple Ruby library for uploading and finding YouTube videos.
|
|
101
|
+
test_files:
|
|
102
|
+
- test/ruby_tube_test.rb
|
|
103
|
+
- test/test_helper.rb
|
|
104
|
+
- test/yt_client_test.rb
|