youtube_it 0.0.3 → 0.0.7
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/History.txt +11 -48
- data/README.txt +48 -5
- data/Rakefile +7 -14
- data/VERSION +2 -1
- data/lib/youtube_it/chain_io.rb +6 -1
- data/lib/youtube_it/client.rb +70 -3
- data/lib/youtube_it/model/playlist.rb +5 -2
- data/lib/youtube_it/parser.rb +31 -6
- data/lib/youtube_it/request/video_upload.rb +203 -60
- data/test/test_client.rb +45 -28
- data/test/test_video.rb +4 -3
- data/youtube_it.gemspec +6 -10
- metadata +7 -10
- data/pkg/youtube_it-0.0.1.gem +0 -0
- data/pkg/youtube_it-0.0.2.gem +0 -0
- data/pkg/youtube_it-0.0.3.gem +0 -0
- data/youtube_it.tmproj +0 -27
data/History.txt
CHANGED
@@ -1,52 +1,15 @@
|
|
1
|
-
*
|
2
|
-
* Refactor the uploader slightly
|
3
|
-
* Use Builder to generate XML packets
|
4
|
-
* Use a faster Camping-based URL escaper (also avoid cgi.rb)
|
5
|
-
* Removed the logger nightmare, use YouTubeIt.logger for everything whatever that may be
|
6
|
-
* Use streams for file uploads instead of in-memory strings
|
1
|
+
* Initial fork
|
7
2
|
|
8
|
-
== 0.
|
3
|
+
== 0.0.1 / 2010-07-05
|
9
4
|
|
10
|
-
*
|
5
|
+
* Enhanced youtube-g to support:
|
6
|
+
~> direct uploads to youtube
|
7
|
+
~> update video on youtube
|
8
|
+
~> comment on youtube video
|
9
|
+
~> delete youtube video
|
10
|
+
|
11
|
+
== 0.0.2 / 2010-07-07
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
* Add Geodata information (thanks Jose Galisteo)
|
15
|
-
* Added :page and :per_page options, this allows easier usage of the will_paginate
|
16
|
-
plugin with the library. The :offset and :max_results options are no longer available. [Daniel Insley]
|
17
|
-
* Added ability to get video responses on the instances of the YouTube::Model::Video object. [Daniel Insley]
|
18
|
-
* Added and improved the existing documentation [Daniel Insley]
|
19
|
-
* Fixed usage of deprecated yt:racy, now using media:rating [Daniel Insley]
|
20
|
-
* Renamed can_embed? method to embeddable? [Daniel Insley]
|
21
|
-
* Added ability for padingation and ordering on standard feeds. [Daniel Insley]
|
22
|
-
* Add error-handling for video upload errors. [FiXato]
|
23
|
-
* Add error-handling for authentication errors from YouTube during video upload. [FiXato]
|
24
|
-
* Add support for making videos private upon video upload. [FiXato]
|
25
|
-
* Fix issue with REXML parsing of video upload response. [FiXato]
|
26
|
-
* Fix issue with response code comparison. [FiXato]
|
27
|
-
* Authcode is now retrieved for video uploads. [FiXato]
|
28
|
-
* Add basic support for uploading videos [thanks Joe Damato]
|
29
|
-
* Add basic support for related videos [tmm1]
|
30
|
-
* Improve docs for order_by attribute [thanks Jason Arora]
|
31
|
-
* Added support for the "racy" parameter (choices are "include" or "exclude") [thanks Jason Arora]
|
32
|
-
* Add missing attribute reader for description [tmm1]
|
33
|
-
* Fix issue with missing yt:statistics and viewCount [tmm1]
|
34
|
-
* Allow Client#video_by to take either a url or a video id [tmm1]
|
35
|
-
|
36
|
-
== 0.4.1 / 2008-02-11
|
37
|
-
|
38
|
-
* Added 3GPP video format [shane]
|
39
|
-
* Fixed tests [shane]
|
40
|
-
|
41
|
-
== 0.4.0 / 2007-12-18
|
42
|
-
|
43
|
-
* Fixed API projection in search URL [Pete Higgins]
|
44
|
-
* Fixed embeddable video searching [Pete Higgins]
|
45
|
-
* Fixed video embeddable detection [Pete Higgins]
|
46
|
-
* Fixed unique id hyphen detection [Pete Higgins, Chris Taggart]
|
47
|
-
|
48
|
-
== 0.3.0 / 2007-09-17
|
49
|
-
|
50
|
-
* Initial public release
|
51
|
-
* Birthday!
|
13
|
+
* ACL support
|
52
14
|
|
15
|
+
== 0.0.3 / 2010-08-12
|
data/README.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
== DESCRIPTION:
|
2
2
|
|
3
|
-
youtube_it is
|
3
|
+
youtube_it is the most complete Ruby client for the YouTube GData API. It provides an easy
|
4
4
|
way to access the latest YouTube video search results from your own programs.
|
5
5
|
In comparison with the earlier Youtube search interfaces, this new API and
|
6
6
|
library offers much-improved flexibility around executing complex search
|
@@ -42,6 +42,11 @@ Upload videos:
|
|
42
42
|
|
43
43
|
client = YouTubeIt::Client.new("youtube_username", "youtube_passwd", "developer_key")
|
44
44
|
|
45
|
+
Or better yet, you can use OAuth
|
46
|
+
|
47
|
+
client = YouTubeIt::OAuthClient.new("consumer_key", "consumer_secret", "youtube_username", "developer_key")
|
48
|
+
client.authorize_from_access("access_token", "access_secret")
|
49
|
+
|
45
50
|
* upload video
|
46
51
|
|
47
52
|
client.video_upload(File.open("test.mov"), :title => "test",:description => 'some description', :category => 'People',:keywords => %w[cool blah test])
|
@@ -71,7 +76,7 @@ Comments
|
|
71
76
|
|
72
77
|
Favorites
|
73
78
|
|
74
|
-
You can add,
|
79
|
+
You can add, delete or list your favorites videos:
|
75
80
|
|
76
81
|
client = YouTubeIt::Client.new("youtube_username", "youtube_passwd", "developer_key")
|
77
82
|
|
@@ -83,9 +88,46 @@ Favorites
|
|
83
88
|
|
84
89
|
client.add_favorite(video_id)
|
85
90
|
|
86
|
-
*
|
91
|
+
* delete favorite:
|
92
|
+
|
93
|
+
client.delete_favorite(video_id)
|
94
|
+
|
95
|
+
Playlist
|
96
|
+
|
97
|
+
You can add, delete or list your playlists:
|
98
|
+
|
99
|
+
client = YouTubeIt::Client.new("youtube_username", "youtube_passwd", "developer_key")
|
100
|
+
|
101
|
+
* get all playlists:
|
102
|
+
|
103
|
+
client.playlists
|
104
|
+
|
105
|
+
* select your playlist:
|
106
|
+
|
107
|
+
client.playlist(playlist_id)
|
108
|
+
|
109
|
+
* get all videos from your playlist:
|
110
|
+
|
111
|
+
my_playlist = client.playlist(playlist_id)
|
112
|
+
|
113
|
+
my_playlist.videos
|
114
|
+
|
115
|
+
* create new playlist:
|
116
|
+
|
117
|
+
my_playlist = client.add_playlist(:title => "new playlist", :description => "playlist description")
|
118
|
+
|
119
|
+
* delete a playlist:
|
120
|
+
|
121
|
+
client.delete_playlist(playlist_id)
|
122
|
+
|
123
|
+
* add video to playlist:
|
124
|
+
|
125
|
+
client.add_video_to_playlist(playlist_id, video_id)
|
126
|
+
|
127
|
+
* remove video from playlist:
|
128
|
+
|
129
|
+
client.remove_video_from_playlist(playlist_id, playlist_entry_id)
|
87
130
|
|
88
|
-
client.del_favorite(video_id)
|
89
131
|
|
90
132
|
Access Control List
|
91
133
|
|
@@ -145,11 +187,12 @@ YouTubeIt passes all logs through the logger variable on the class itself. In Ra
|
|
145
187
|
== INSTALL:
|
146
188
|
|
147
189
|
* sudo gem install youtube_it
|
190
|
+
|
148
191
|
== LICENSE:
|
149
192
|
|
150
193
|
MIT License
|
151
194
|
|
152
|
-
Copyright (c)
|
195
|
+
Copyright (c) 2010 Kyle J. Ginavan
|
153
196
|
|
154
197
|
Permission is hereby granted, free of charge, to any person obtaining
|
155
198
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -5,11 +5,11 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "youtube_it"
|
8
|
-
gem.summary = %Q{
|
9
|
-
gem.description = %Q{
|
8
|
+
gem.summary = %Q{The most complete Ruby wrapper for youtube api's}
|
9
|
+
gem.description = %Q{Upload, delete, update, comment on youtube videos all from one gem.}
|
10
10
|
gem.email = "kylejginavan@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/kylejginavan/youtube_it"
|
12
|
-
gem.authors = ["
|
12
|
+
gem.authors = ["chebyte","kylejginavan"]
|
13
13
|
end
|
14
14
|
Jeweler::GemcutterTasks.new
|
15
15
|
rescue LoadError
|
@@ -18,16 +18,16 @@ end
|
|
18
18
|
|
19
19
|
require 'rake/testtask'
|
20
20
|
Rake::TestTask.new(:test) do |test|
|
21
|
-
test.libs << '
|
22
|
-
test.pattern = '
|
21
|
+
test.libs << 'test'
|
22
|
+
test.pattern = 'test/**/test_*.rb'
|
23
23
|
test.verbose = true
|
24
24
|
end
|
25
25
|
|
26
26
|
begin
|
27
27
|
require 'rcov/rcovtask'
|
28
28
|
Rcov::RcovTask.new do |test|
|
29
|
-
test.libs << '
|
30
|
-
test.pattern = '
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/test_*.rb'
|
31
31
|
test.verbose = true
|
32
32
|
end
|
33
33
|
rescue LoadError
|
@@ -50,10 +50,3 @@ Rake::RDocTask.new do |rdoc|
|
|
50
50
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
51
|
end
|
52
52
|
|
53
|
-
require 'spec/rake/spectask'
|
54
|
-
desc "Run all specs"
|
55
|
-
Spec::Rake::SpecTask.new('spec') do |t|
|
56
|
-
t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
|
57
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
58
|
-
end
|
59
|
-
|
data/VERSION
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
2
|
+
|
data/lib/youtube_it/chain_io.rb
CHANGED
data/lib/youtube_it/client.rb
CHANGED
@@ -6,7 +6,6 @@ class YouTubeIt
|
|
6
6
|
@user, @pass, @dev_key, @client_id = user, pass, dev_key, client_id
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
9
|
# Retrieves an array of standard feed, custom query, or user videos.
|
11
10
|
#
|
12
11
|
# === Parameters
|
@@ -107,14 +106,42 @@ class YouTubeIt
|
|
107
106
|
client.add_favorite(video_id)
|
108
107
|
end
|
109
108
|
|
110
|
-
def
|
111
|
-
client.
|
109
|
+
def delete_favorite(video_id)
|
110
|
+
client.delete_favorite(video_id)
|
112
111
|
end
|
113
112
|
|
114
113
|
def favorites
|
115
114
|
client.favorites
|
116
115
|
end
|
117
116
|
|
117
|
+
def playlist(playlist_id)
|
118
|
+
client.playlist playlist_id
|
119
|
+
end
|
120
|
+
|
121
|
+
def playlists
|
122
|
+
client.playlists
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_playlist(options)
|
126
|
+
client.add_playlist(options)
|
127
|
+
end
|
128
|
+
|
129
|
+
def update_playlist(playlist_id, options)
|
130
|
+
client.update_playlist(playlist_id, options)
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_video_to_playlist(playlist_id, video_id)
|
134
|
+
client.add_video_to_playlist(playlist_id, video_id)
|
135
|
+
end
|
136
|
+
|
137
|
+
def delete_video_from_playlist(playlist_id, playlist_entry_id)
|
138
|
+
client.delete_video_from_playlist(playlist_id, playlist_entry_id)
|
139
|
+
end
|
140
|
+
|
141
|
+
def delete_playlist(playlist_id)
|
142
|
+
client.delete_playlist(playlist_id)
|
143
|
+
end
|
144
|
+
|
118
145
|
def enable_http_debugging
|
119
146
|
client.enable_http_debugging
|
120
147
|
end
|
@@ -134,5 +161,45 @@ class YouTubeIt
|
|
134
161
|
value > 0 ? value : default
|
135
162
|
end
|
136
163
|
end
|
164
|
+
|
165
|
+
class OAuthClient < Client
|
166
|
+
def initialize ctoken = nil, csecret = nil, user = nil, dev_key = nil, client_id = 'youtube_it', legacy_debug_flag = nil
|
167
|
+
@consumer_key, @consumer_secret, @user, @dev_key, @client_id = ctoken, csecret, user, dev_key, client_id
|
168
|
+
end
|
169
|
+
|
170
|
+
def consumer
|
171
|
+
@consumer ||= OAuth::Consumer.new(@consumer_key,@consumer_secret,{
|
172
|
+
:site=>"https://www.google.com",
|
173
|
+
:request_token_path=>"/accounts/OAuthGetRequestToken",
|
174
|
+
:authorize_path=>"/accounts/OAuthAuthorizeToken",
|
175
|
+
:access_token_path=>"/accounts/OAuthGetAccessToken"})
|
176
|
+
end
|
177
|
+
|
178
|
+
def request_token(callback)
|
179
|
+
@request_token = consumer.get_request_token({:oauth_callback => callback},{:scope => "http://gdata.youtube.com"})
|
180
|
+
end
|
181
|
+
|
182
|
+
def access_token
|
183
|
+
@access_token = OAuth::AccessToken.new(consumer, @atoken, @asecret)
|
184
|
+
end
|
185
|
+
|
186
|
+
def authorize_from_request(rtoken,rsecret,verifier)
|
187
|
+
request_token = OAuth::RequestToken.new(consumer,rtoken,rsecret)
|
188
|
+
access_token = request_token.get_access_token({:oauth_verifier => verifier})
|
189
|
+
@atoken,@asecret = access_token.token, access_token.secret
|
190
|
+
end
|
191
|
+
|
192
|
+
def authorize_from_access(atoken,asecret)
|
193
|
+
@atoken,@asecret = atoken, asecret
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def client
|
199
|
+
# IMPORTANT: make sure authorize_from_access is called before client is fetched
|
200
|
+
@client ||= YouTubeIt::Upload::VideoUpload.new(@user, "", @dev_key, "youtube_it", access_token)
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
137
204
|
end
|
138
205
|
|
@@ -1,8 +1,11 @@
|
|
1
1
|
class YouTubeIt
|
2
2
|
module Model
|
3
3
|
class Playlist < YouTubeIt::Record
|
4
|
-
|
5
|
-
|
4
|
+
attr_reader :title, :description, :summary, :playlist_id, :xml, :published, :response_code
|
5
|
+
def videos
|
6
|
+
YouTubeIt::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/playlists/#{playlist_id}?v=2").parse_videos
|
7
|
+
end
|
6
8
|
end
|
7
9
|
end
|
8
10
|
end
|
11
|
+
|
data/lib/youtube_it/parser.rb
CHANGED
@@ -1,12 +1,37 @@
|
|
1
1
|
class YouTubeIt
|
2
2
|
module Parser #:nodoc:
|
3
3
|
class FeedParser #:nodoc:
|
4
|
-
def initialize(
|
5
|
-
@
|
4
|
+
def initialize(content)
|
5
|
+
@content = open(content).read rescue content
|
6
6
|
end
|
7
7
|
|
8
8
|
def parse
|
9
|
-
parse_content @
|
9
|
+
parse_content @content
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_videos
|
13
|
+
doc = REXML::Document.new(@content)
|
14
|
+
videos = []
|
15
|
+
doc.elements.each("*/entry") do |video|
|
16
|
+
videos << parse_entry(video)
|
17
|
+
end
|
18
|
+
videos
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class PlaylistFeedParser < FeedParser #:nodoc:
|
23
|
+
|
24
|
+
def parse_content(content)
|
25
|
+
xml = REXML::Document.new(content.body)
|
26
|
+
entry = xml.elements["entry"] || xml.elements["feed"]
|
27
|
+
YouTubeIt::Model::Playlist.new(
|
28
|
+
:title => entry.elements["title"].text,
|
29
|
+
:summary => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
|
30
|
+
:description => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
|
31
|
+
:playlist_id => entry.elements["id"].text[/playlist([^<]+)/, 1].sub(':',''),
|
32
|
+
:published => entry.elements["published"] ? entry.elements["published"].text : nil,
|
33
|
+
:response_code => content.code,
|
34
|
+
:xml => content.body)
|
10
35
|
end
|
11
36
|
end
|
12
37
|
|
@@ -21,8 +46,8 @@ class YouTubeIt
|
|
21
46
|
protected
|
22
47
|
def parse_entry(entry)
|
23
48
|
video_id = entry.elements["id"].text
|
24
|
-
published_at
|
25
|
-
updated_at
|
49
|
+
published_at = entry.elements["published"] ? Time.parse(entry.elements["published"].text) : nil
|
50
|
+
updated_at = entry.elements["updated"] ? Time.parse(entry.elements["updated"].text) : nil
|
26
51
|
|
27
52
|
# parse the category and keyword lists
|
28
53
|
categories = []
|
@@ -43,7 +68,7 @@ class YouTubeIt
|
|
43
68
|
end
|
44
69
|
|
45
70
|
title = entry.elements["title"].text
|
46
|
-
html_content = entry.elements["content"].text
|
71
|
+
html_content = entry.elements["content"] ? entry.elements["content"].text : nil
|
47
72
|
|
48
73
|
# parse the author
|
49
74
|
author_element = entry.elements["author"]
|
@@ -16,8 +16,8 @@ class YouTubeIt
|
|
16
16
|
#
|
17
17
|
class VideoUpload
|
18
18
|
include YouTubeIt::Logging
|
19
|
-
def initialize user, pass, dev_key, client_id = 'youtube_it'
|
20
|
-
@user, @pass, @dev_key, @client_id = user, pass, dev_key, client_id
|
19
|
+
def initialize user, pass, dev_key, client_id = 'youtube_it', access_token = nil
|
20
|
+
@user, @pass, @dev_key, @client_id, @access_token = user, pass, dev_key, client_id, access_token
|
21
21
|
@http_debugging = false
|
22
22
|
end
|
23
23
|
|
@@ -52,6 +52,7 @@ class YouTubeIt
|
|
52
52
|
#
|
53
53
|
# When the authentication credentials are incorrect, an AuthenticationError will be raised.
|
54
54
|
def upload data, opts = {}
|
55
|
+
response = ""
|
55
56
|
@opts = { :mime_type => 'video/mp4',
|
56
57
|
:title => '',
|
57
58
|
:description => '',
|
@@ -62,28 +63,31 @@ class YouTubeIt
|
|
62
63
|
|
63
64
|
post_body_io = generate_upload_io(video_xml, data)
|
64
65
|
|
65
|
-
upload_headers =
|
66
|
+
upload_headers = {
|
66
67
|
"Slug" => "#{@opts[:filename]}",
|
67
68
|
"Content-Type" => "multipart/related; boundary=#{boundary}",
|
68
69
|
"Content-Length" => "#{post_body_io.expected_length}", # required per YouTube spec
|
69
70
|
# "Transfer-Encoding" => "chunked" # We will stream instead of posting at once
|
70
|
-
}
|
71
|
-
|
72
|
-
path = '/feeds/api/users/%s/uploads' % @user
|
73
|
-
|
74
|
-
http = Net::HTTP.new(uploads_url)
|
75
|
-
http.set_debug_output(logger) if @http_debugging
|
76
|
-
http.start do | session |
|
77
|
-
|
78
|
-
# Use the chained IO as body so that Net::HTTP reads into the socket for us
|
79
|
-
post = Net::HTTP::Post.new(path, upload_headers)
|
80
|
-
post.body_stream = post_body_io
|
81
|
-
|
82
|
-
response = session.request(post)
|
83
|
-
raise_on_faulty_response(response)
|
71
|
+
}
|
84
72
|
|
85
|
-
|
73
|
+
if @access_token.nil?
|
74
|
+
upload_headers.merge!(authorization_headers)
|
75
|
+
http = Net::HTTP.new(uploads_url)
|
76
|
+
http.set_debug_output(logger) if @http_debugging
|
77
|
+
path = '/feeds/api/users/%s/uploads' % @user
|
78
|
+
http.start do | session |
|
79
|
+
# Use the chained IO as body so that Net::HTTP reads into the socket for us
|
80
|
+
post = Net::HTTP::Post.new(path, upload_headers)
|
81
|
+
post.body_stream = post_body_io
|
82
|
+
response = session.request(post)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
upload_headers.merge!(authorization_headers_for_soap)
|
86
|
+
url = 'http://%s/feeds/api/users/%s/uploads' % [uploads_url, @user]
|
87
|
+
response = @access_token.post(url, post_body_io, upload_headers)
|
86
88
|
end
|
89
|
+
raise_on_faulty_response(response)
|
90
|
+
return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
|
87
91
|
end
|
88
92
|
|
89
93
|
# Updates a video in YouTube. Requires:
|
@@ -95,42 +99,55 @@ class YouTubeIt
|
|
95
99
|
# :private
|
96
100
|
# When the authentication credentials are incorrect, an AuthenticationError will be raised.
|
97
101
|
def update(video_id, options)
|
102
|
+
response = ""
|
98
103
|
@opts = options
|
99
104
|
|
100
105
|
update_body = video_xml
|
101
106
|
|
102
|
-
update_header =
|
107
|
+
update_header = {
|
103
108
|
"GData-Version" => "2",
|
104
109
|
"Content-Type" => "application/atom+xml",
|
105
110
|
"Content-Length" => "#{update_body.length}",
|
106
|
-
}
|
111
|
+
}
|
107
112
|
|
108
113
|
update_url = "/feeds/api/users/#{@user}/uploads/#{video_id}"
|
109
114
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
if @access_token.nil?
|
116
|
+
update_header.merge!(authorization_headers)
|
117
|
+
http_connection do |session|
|
118
|
+
response = session.put(update_url, update_body, update_header)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
upload_headers.merge!(authorization_headers_for_soap)
|
122
|
+
response = @access_token.put("http://"+base_url+update_url, update_body, update_header)
|
117
123
|
end
|
124
|
+
|
125
|
+
raise_on_faulty_response(response)
|
126
|
+
return YouTubeIt::Parser::VideoFeedParser.new(response.body).parse
|
118
127
|
end
|
119
128
|
|
120
129
|
# Delete a video on YouTube
|
121
130
|
def delete(video_id)
|
122
|
-
delete_header =
|
131
|
+
delete_header = {
|
123
132
|
"Content-Type" => "application/atom+xml; charset=UTF-8",
|
124
133
|
"Content-Length" => "0",
|
125
|
-
}
|
134
|
+
}
|
126
135
|
|
127
136
|
delete_url = "/feeds/api/users/#{@user}/uploads/#{video_id}"
|
128
137
|
|
129
|
-
|
130
|
-
|
138
|
+
if @access_token.nil?
|
139
|
+
delete_header.merge!(authorization_headers)
|
140
|
+
http_connection do |session|
|
141
|
+
response = session.delete(delete_url, delete_header)
|
142
|
+
raise_on_faulty_response(response)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
upload_headers.merge!(authorization_headers_for_soap)
|
146
|
+
response = @access_token.delete("http://"+base_url+delete_url, delete_header)
|
131
147
|
raise_on_faulty_response(response)
|
132
|
-
return true
|
133
148
|
end
|
149
|
+
|
150
|
+
return true
|
134
151
|
end
|
135
152
|
|
136
153
|
def get_upload_token(options, nexturl)
|
@@ -143,7 +160,7 @@ class YouTubeIt
|
|
143
160
|
})
|
144
161
|
token_url = "/action/GetUploadToken"
|
145
162
|
|
146
|
-
|
163
|
+
http_connection do |session|
|
147
164
|
response = session.post(token_url, token_body, token_header)
|
148
165
|
raise_on_faulty_response(response)
|
149
166
|
return {:url => "#{response.body[/<url>(.+)<\/url>/, 1]}?nexturl=#{nexturl}",
|
@@ -161,23 +178,19 @@ class YouTubeIt
|
|
161
178
|
|
162
179
|
comment_url = "/feeds/api/videos/#{video_id}/comments"
|
163
180
|
|
164
|
-
|
165
|
-
http.set_debug_output(logger) if @http_debugging
|
166
|
-
http.start do | session |
|
181
|
+
http_connection do |session|
|
167
182
|
response = session.post(comment_url, comment_body, comment_header)
|
168
183
|
raise_on_faulty_response(response)
|
169
|
-
|
184
|
+
{:code => response.code, :body => response.body}
|
170
185
|
end
|
171
186
|
end
|
172
187
|
|
173
188
|
def comments(video_id)
|
174
189
|
comment_url = "/feeds/api/videos/#{video_id}/comments"
|
175
|
-
|
176
|
-
http.set_debug_output(logger) if @http_debugging
|
177
|
-
http.start do | session |
|
190
|
+
http_connection do |session|
|
178
191
|
response = session.get(comment_url)
|
179
192
|
raise_on_faulty_response(response)
|
180
|
-
|
193
|
+
{:code => response.code, :body => response.body}
|
181
194
|
end
|
182
195
|
end
|
183
196
|
|
@@ -191,16 +204,14 @@ class YouTubeIt
|
|
191
204
|
|
192
205
|
favorite_url = "/feeds/api/users/#{@user}/favorites"
|
193
206
|
|
194
|
-
|
195
|
-
http.set_debug_output(logger) if @http_debugging
|
196
|
-
http.start do | session |
|
207
|
+
http_connection do |session|
|
197
208
|
response = session.post(favorite_url, favorite_body, favorite_header)
|
198
209
|
raise_on_faulty_response(response)
|
199
|
-
|
210
|
+
{:code => response.code, :body => response.body}
|
200
211
|
end
|
201
212
|
end
|
202
213
|
|
203
|
-
def
|
214
|
+
def delete_favorite(video_id)
|
204
215
|
favorite_header = authorization_headers.merge({
|
205
216
|
"Content-Type" => "application/atom+xml; charset=UTF-8",
|
206
217
|
"Content-Length" => "0",
|
@@ -208,20 +219,116 @@ class YouTubeIt
|
|
208
219
|
|
209
220
|
favorite_url = "/feeds/api/users/#{@user}/favorites/#{video_id}"
|
210
221
|
|
211
|
-
|
212
|
-
http.set_debug_output(logger) if @http_debugging
|
213
|
-
http.start do | session |
|
222
|
+
http_connection do |session|
|
214
223
|
response = session.delete(favorite_url, favorite_header)
|
215
224
|
raise_on_faulty_response(response)
|
216
225
|
return true
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|
229
|
+
def playlist(playlist_id)
|
230
|
+
playlist_url = "/feeds/api/playlists/#{playlist_id}?v=2"
|
231
|
+
http_connection do |session|
|
232
|
+
response = session.get(playlist_url)
|
233
|
+
raise_on_faulty_response(response)
|
234
|
+
return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def playlists
|
239
|
+
playlist_url = "/feeds/api/users/#{@user}/playlists?v=2"
|
240
|
+
http_connection do |session|
|
241
|
+
response = session.get(playlist_url)
|
242
|
+
raise_on_faulty_response(response)
|
243
|
+
return response.body
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def add_playlist(options)
|
248
|
+
playlist_body = video_xml_for_playlist(options)
|
249
|
+
playlist_header = authorization_headers.merge({
|
250
|
+
"GData-Version" => "2",
|
251
|
+
"Content-Type" => "application/atom+xml",
|
252
|
+
"Content-Length" => "#{playlist_body.length}",
|
253
|
+
})
|
254
|
+
|
255
|
+
playlist_url = "/feeds/api/users/#{@user}/playlists"
|
256
|
+
|
257
|
+
http_connection do |session|
|
258
|
+
response = session.post(playlist_url, playlist_body, playlist_header)
|
259
|
+
raise_on_faulty_response(response)
|
260
|
+
return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def add_video_to_playlist(playlist_id, video_id)
|
265
|
+
playlist_body = video_xml_for(:playlist => video_id)
|
266
|
+
playlist_header = authorization_headers.merge({
|
267
|
+
"GData-Version" => "2",
|
268
|
+
"Content-Type" => "application/atom+xml",
|
269
|
+
"Content-Length" => "#{playlist_body.length}",
|
270
|
+
})
|
271
|
+
|
272
|
+
playlist_url = "/feeds/api/playlists/#{playlist_id}"
|
273
|
+
|
274
|
+
http_connection do |session|
|
275
|
+
response = session.post(playlist_url, playlist_body, playlist_header)
|
276
|
+
raise_on_faulty_response(response)
|
277
|
+
{:code => response.code, :body => response.body, :playlist_entry_id => playlist_entry_id_from_playlist(response.body)}
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def update_playlist(playlist_id, options)
|
282
|
+
playlist_body = video_xml_for_playlist(options)
|
283
|
+
playlist_header = authorization_headers.merge({
|
284
|
+
"GData-Version" => "2",
|
285
|
+
"Content-Type" => "application/atom+xml",
|
286
|
+
"Content-Length" => "#{playlist_body.length}",
|
287
|
+
})
|
288
|
+
playlist_url = "/feeds/api/users/#{@user}/playlists/#{playlist_id}"
|
289
|
+
|
290
|
+
http_connection do |session|
|
291
|
+
response = session.put(playlist_url, playlist_body, playlist_header)
|
292
|
+
raise_on_faulty_response(response)
|
293
|
+
return YouTubeIt::Parser::PlaylistFeedParser.new(response).parse
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
def delete_video_from_playlist(playlist_id, playlist_entry_id)
|
299
|
+
playlist_header = {
|
300
|
+
"Content-Type" => "application/atom+xml",
|
301
|
+
"GData-Version" => "2",
|
302
|
+
"X-GData-Key" => "key=#{@dev_key}",
|
303
|
+
"Authorization" => "GoogleLogin auth=#{auth_token}",
|
304
|
+
}
|
305
|
+
|
306
|
+
playlist_url = "/feeds/api/playlists/#{playlist_id}/#{playlist_entry_id}"
|
307
|
+
|
308
|
+
http_connection do |session|
|
309
|
+
response = session.delete(playlist_url, playlist_header)
|
310
|
+
raise_on_faulty_response(response)
|
311
|
+
return true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def delete_playlist(playlist_id)
|
316
|
+
playlist_header = authorization_headers.merge({
|
317
|
+
"Content-Type" => "application/atom+xml; charset=UTF-8",
|
318
|
+
"GData-Version" => "2"
|
319
|
+
})
|
320
|
+
|
321
|
+
playlist_url = "/feeds/api/users/#{@user}/playlists/#{playlist_id}"
|
322
|
+
http_connection do |session|
|
323
|
+
response = session.delete(playlist_url, playlist_header)
|
324
|
+
raise_on_faulty_response(response)
|
325
|
+
return true
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
220
329
|
def favorites
|
221
330
|
favorite_url = "/feeds/api/users/#{@user}/favorites"
|
222
|
-
|
223
|
-
http.set_debug_output(logger) if @http_debugging
|
224
|
-
http.start do | session |
|
331
|
+
http_connection do |session|
|
225
332
|
response = session.get(favorite_url)
|
226
333
|
raise_on_faulty_response(response)
|
227
334
|
return response.body
|
@@ -242,6 +349,12 @@ class YouTubeIt
|
|
242
349
|
"An43094fu"
|
243
350
|
end
|
244
351
|
|
352
|
+
def authorization_headers_for_soap
|
353
|
+
{
|
354
|
+
"X-GData-Key" => "key=#{@dev_key}"
|
355
|
+
}
|
356
|
+
end
|
357
|
+
|
245
358
|
def authorization_headers
|
246
359
|
{
|
247
360
|
"Authorization" => "GoogleLogin auth=#{auth_token}",
|
@@ -251,10 +364,18 @@ class YouTubeIt
|
|
251
364
|
end
|
252
365
|
|
253
366
|
def parse_upload_error_from(string)
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
367
|
+
begin
|
368
|
+
REXML::Document.new(string).elements["//errors"].inject('') do | all_faults, error|
|
369
|
+
if error.elements["internalReason"]
|
370
|
+
msg_error = error.elements["internalReason"].text
|
371
|
+
elsif error.elements["location"]
|
372
|
+
msg_error = error.elements["location"].text[/media:group\/media:(.*)\/text\(\)/,1]
|
373
|
+
end
|
374
|
+
code = error.elements["code"].text if error.elements["code"]
|
375
|
+
all_faults + sprintf("%s: %s\n", msg_error, code)
|
376
|
+
end
|
377
|
+
rescue
|
378
|
+
string
|
258
379
|
end
|
259
380
|
end
|
260
381
|
|
@@ -262,7 +383,7 @@ class YouTubeIt
|
|
262
383
|
if response.code.to_i == 403
|
263
384
|
raise AuthenticationError, response.body[/<TITLE>(.+)<\/TITLE>/, 1]
|
264
385
|
elsif response.code.to_i / 10 != 20 # Response in 20x means success
|
265
|
-
raise UploadError, parse_upload_error_from(response.body)
|
386
|
+
raise UploadError, parse_upload_error_from(response.body.gsub(/\n/,''))
|
266
387
|
end
|
267
388
|
end
|
268
389
|
|
@@ -271,6 +392,12 @@ class YouTubeIt
|
|
271
392
|
xml.elements["//id"].text[/videos\/(.+)/, 1]
|
272
393
|
end
|
273
394
|
|
395
|
+
def playlist_id_from(string)
|
396
|
+
xml = REXML::Document.new(string)
|
397
|
+
entry = xml.elements["entry"]
|
398
|
+
entry.elements["id"].text[/playlist([^<]+)/, 1].sub(':','')
|
399
|
+
end
|
400
|
+
|
274
401
|
# If data can be read, use the first 1024 bytes as filename. If data
|
275
402
|
# is a file, use path. If data is a string, checksum it
|
276
403
|
def generate_uniq_filename_from(data)
|
@@ -323,15 +450,17 @@ class YouTubeIt
|
|
323
450
|
b.instruct!
|
324
451
|
b.entry(:xmlns => "http://www.w3.org/2005/Atom", 'xmlns:yt' => "http://gdata.youtube.com/schemas/2007") do | m |
|
325
452
|
m.content(data[:comment]) if data[:comment]
|
326
|
-
m.id(data[:favorite]) if data[:favorite]
|
453
|
+
m.id(data[:favorite] || data[:playlist]) if data[:favorite] || data[:playlist]
|
327
454
|
end.to_s
|
328
455
|
end
|
329
456
|
|
330
|
-
def
|
457
|
+
def video_xml_for_playlist(data)
|
331
458
|
b = Builder::XmlMarkup.new
|
332
459
|
b.instruct!
|
333
460
|
b.entry(:xmlns => "http://www.w3.org/2005/Atom", 'xmlns:yt' => "http://gdata.youtube.com/schemas/2007") do | m |
|
334
|
-
m.
|
461
|
+
m.title(data[:title]) if data[:title]
|
462
|
+
m.summary(data[:description] || data[:summary]) if data[:description] || data[:summary]
|
463
|
+
m.tag!('yt:private') if data[:private]
|
335
464
|
end.to_s
|
336
465
|
end
|
337
466
|
|
@@ -350,6 +479,20 @@ class YouTubeIt
|
|
350
479
|
YouTubeIt::GreedyChainIO.new(post_body)
|
351
480
|
end
|
352
481
|
|
482
|
+
def playlist_entry_id_from_playlist(string)
|
483
|
+
playlist_xml = REXML::Document.new(string)
|
484
|
+
playlist_xml.elements.each("/entry") do |item|
|
485
|
+
return item.elements["id"].text[/^.*:([^:]+)$/,1]
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def http_connection
|
490
|
+
http = Net::HTTP.new(base_url)
|
491
|
+
http.set_debug_output(logger) if @http_debugging
|
492
|
+
http.start do |session|
|
493
|
+
yield(session)
|
494
|
+
end
|
495
|
+
end
|
353
496
|
end
|
354
497
|
end
|
355
498
|
end
|
data/test/test_client.rb
CHANGED
@@ -45,7 +45,7 @@ class TestClient < Test::Unit::TestCase
|
|
45
45
|
assert_equal 25, response.max_result_count
|
46
46
|
assert_equal 1, response.offset
|
47
47
|
|
48
|
-
|
48
|
+
response = @client.videos_by(:query => "penguin", :page => 2)
|
49
49
|
assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
|
50
50
|
assert_equal 25, response.max_result_count
|
51
51
|
assert_equal 26, response.offset
|
@@ -145,13 +145,13 @@ class TestClient < Test::Unit::TestCase
|
|
145
145
|
|
146
146
|
def test_should_get_videos_for_query_search_with_categories_excluded
|
147
147
|
video = @client.video_by("EkF4JD2rO3Q")
|
148
|
-
assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/EkF4JD2rO3Q&feature=
|
148
|
+
assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/EkF4JD2rO3Q&feature=youtube_gdata_player\"></param>\n <param name=\"wmode\" value=\"transparent\"></param>\n <embed src=\"http://www.youtube.com/v/EkF4JD2rO3Q&feature=youtube_gdata_player\" type=\"application/x-shockwave-flash\" \n wmode=\"transparent\" width=\"425\" height=\"350\"></embed>\n</object>\n", video.embed_html
|
149
149
|
assert_valid_video video
|
150
150
|
end
|
151
151
|
|
152
152
|
def test_should_get_video_from_user
|
153
153
|
video = @client.video_by_user("chebyte","FQK1URcxmb4")
|
154
|
-
assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/FQK1URcxmb4&feature=
|
154
|
+
assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/FQK1URcxmb4&feature=youtube_gdata_player\"></param>\n <param name=\"wmode\" value=\"transparent\"></param>\n <embed src=\"http://www.youtube.com/v/FQK1URcxmb4&feature=youtube_gdata_player\" type=\"application/x-shockwave-flash\" \n wmode=\"transparent\" width=\"425\" height=\"350\"></embed>\n</object>\n", video.embed_html
|
155
155
|
assert_valid_video video
|
156
156
|
end
|
157
157
|
|
@@ -190,51 +190,45 @@ class TestClient < Test::Unit::TestCase
|
|
190
190
|
end
|
191
191
|
|
192
192
|
def test_should_upload_a_video
|
193
|
-
|
194
|
-
video = @client.video_by_user(ACCOUNT[:user], video_id)
|
193
|
+
video = @client.video_upload(File.open("test/test.mov"), OPTIONS)
|
195
194
|
assert_valid_video video
|
196
|
-
@client.video_delete(
|
195
|
+
@client.video_delete(video.unique_id)
|
197
196
|
end
|
198
197
|
|
199
198
|
def test_should_update_a_video
|
200
199
|
OPTIONS[:title] = "title changed"
|
201
|
-
@client.video_update("
|
202
|
-
video = @client.video_by("BhTw20Lr4v8")
|
200
|
+
video = @client.video_update("iKqJ8z1DPrQ", OPTIONS)
|
203
201
|
assert video.title == "title changed"
|
204
|
-
OPTIONS[:title] = "
|
205
|
-
@client.video_update("
|
202
|
+
OPTIONS[:title] = "test rails"
|
203
|
+
@client.video_update("iKqJ8z1DPrQ", OPTIONS)
|
206
204
|
end
|
207
205
|
|
208
206
|
def test_should_delete_video
|
209
|
-
|
210
|
-
video = @client.video_by_user(ACCOUNT[:user], video_id)
|
207
|
+
video = @client.video_upload(File.open("test/test.mov"), OPTIONS)
|
211
208
|
assert_valid_video video
|
212
|
-
assert @client.video_delete(
|
209
|
+
assert @client.video_delete(video.unique_id)
|
213
210
|
end
|
214
211
|
|
215
212
|
def test_should_denied_comments
|
216
|
-
|
217
|
-
video = @client.video_by_user(ACCOUNT[:user], video_id)
|
213
|
+
video = @client.video_upload(File.open("test/test.mov"), OPTIONS.merge(:comment => "denied"))
|
218
214
|
assert_valid_video video
|
219
|
-
doc = Nokogiri::HTML(open("http://www.youtube.com/watch?v=#{
|
215
|
+
doc = Nokogiri::HTML(open("http://www.youtube.com/watch?v=#{video.unique_id}"))
|
220
216
|
doc.css('.comments-disabled').each{|tag| assert (tag.content.strip == "Adding comments has been disabled for this video.")}
|
221
|
-
@client.video_delete(
|
217
|
+
@client.video_delete(video.unique_id)
|
222
218
|
end
|
223
219
|
|
224
220
|
def test_should_denied_rate
|
225
|
-
|
226
|
-
video = @client.video_by_user(ACCOUNT[:user], video_id)
|
221
|
+
video = @client.video_upload(File.open("test/test.mov"), OPTIONS.merge(:rate => "denied"))
|
227
222
|
assert_valid_video video
|
228
|
-
doc = Nokogiri::HTML(open("http://www.youtube.com/watch?v=#{
|
223
|
+
doc = Nokogiri::HTML(open("http://www.youtube.com/watch?v=#{video.unique_id}"))
|
229
224
|
doc.css('#watch-like').each{|tag|; assert (tag.attributes["title"].to_s == "Ratings have been disabled for this video.")}
|
230
|
-
@client.video_delete(
|
225
|
+
@client.video_delete(video.unique_id)
|
231
226
|
end
|
232
227
|
|
233
228
|
def test_should_denied_embed
|
234
|
-
|
235
|
-
video = @client.video_by_user(ACCOUNT[:user], video_id)
|
229
|
+
video = @client.video_upload(File.open("test/test.mov"), OPTIONS.merge(:embed => "denied"))
|
236
230
|
assert video.noembed
|
237
|
-
@client.video_delete(
|
231
|
+
@client.video_delete(video.unique_id)
|
238
232
|
end
|
239
233
|
|
240
234
|
def test_should_add_new_comment
|
@@ -244,10 +238,33 @@ class TestClient < Test::Unit::TestCase
|
|
244
238
|
assert comment.match(/test comment/)
|
245
239
|
end
|
246
240
|
|
247
|
-
def
|
241
|
+
def test_shoul_add_and_delete_video_to_favorite
|
248
242
|
video_id ="H1TrfM3xbgc"
|
249
|
-
|
250
|
-
assert
|
243
|
+
result = @client.add_favorite(video_id)
|
244
|
+
assert result[:code], 201
|
245
|
+
sleep 4
|
246
|
+
assert @client.delete_favorite(video_id)
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_should_add_and_del_video_from_playlist
|
250
|
+
playlist = @client.add_playlist(:title => "youtube_it test!", :description => "test playlist")
|
251
|
+
video = @client.add_video_to_playlist(playlist.playlist_id,"iKqJ8z1DPrQ")
|
252
|
+
assert_equal video[:code].to_i, 201
|
253
|
+
assert @client.delete_video_from_playlist(playlist.playlist_id, video[:playlist_entry_id])
|
254
|
+
assert @client.delete_playlist(playlist.playlist_id)
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_should_add_and_del_new_playlist
|
258
|
+
result = @client.add_playlist(:title => "youtube_it test!", :description => "test playlist")
|
259
|
+
assert result.title, "youtube_it test!"
|
260
|
+
assert @client.delete_playlist(result.playlist_id)
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_should_update_playlist
|
264
|
+
playlist = @client.add_playlist(:title => "youtube_it test!", :description => "test playlist")
|
265
|
+
playlist_updated = @client.update_playlist(playlist.playlist_id, :title => "title changed")
|
266
|
+
assert_equal playlist_updated.title, "title changed"
|
267
|
+
assert @client.delete_playlist(playlist.playlist_id)
|
251
268
|
end
|
252
269
|
|
253
270
|
private
|
@@ -297,7 +314,7 @@ class TestClient < Test::Unit::TestCase
|
|
297
314
|
|
298
315
|
assert_instance_of Time, video.updated_at
|
299
316
|
# http://gdata.youtube.com/feeds/videos/IHVaXG1thXM
|
300
|
-
assert_valid_url video.
|
317
|
+
assert_valid_url video.unique_id
|
301
318
|
assert_instance_of Fixnum, video.view_count
|
302
319
|
assert_instance_of Fixnum, video.favorite_count
|
303
320
|
|
data/test/test_video.rb
CHANGED
@@ -22,17 +22,18 @@ class TestVideo < Test::Unit::TestCase
|
|
22
22
|
assert(response.total_result_count > 0)
|
23
23
|
assert_instance_of Time, response.updated_at
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def test_should_have_response_videos
|
27
27
|
video = YouTubeIt::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
|
28
28
|
response = video.responses
|
29
29
|
|
30
30
|
assert_equal "http://gdata.youtube.com/feeds/api/videos/BDqs-OZWw9o/responses", response.feed_id
|
31
31
|
assert_equal 25, response.max_result_count
|
32
|
-
assert_equal
|
32
|
+
assert_equal 24, response.videos.length
|
33
33
|
assert_equal 1, response.offset
|
34
34
|
assert(response.total_result_count > 0)
|
35
35
|
assert_instance_of Time, response.updated_at
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
end
|
39
|
+
|
data/youtube_it.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{youtube_it}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["
|
12
|
-
s.date = %q{2010-
|
13
|
-
s.description = %q{
|
11
|
+
s.authors = ["chebyte", "kylejginavan"]
|
12
|
+
s.date = %q{2010-10-18}
|
13
|
+
s.description = %q{Upload, delete, update, comment on youtube videos all from one gem.}
|
14
14
|
s.email = %q{kylejginavan@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README.txt"
|
@@ -43,23 +43,19 @@ Gem::Specification.new do |s|
|
|
43
43
|
"lib/youtube_it/request/video_upload.rb",
|
44
44
|
"lib/youtube_it/response/video_search.rb",
|
45
45
|
"lib/youtube_it/version.rb",
|
46
|
-
"pkg/youtube_it-0.0.1.gem",
|
47
|
-
"pkg/youtube_it-0.0.2.gem",
|
48
|
-
"pkg/youtube_it-0.0.3.gem",
|
49
46
|
"test/helper.rb",
|
50
47
|
"test/test.mov",
|
51
48
|
"test/test_chain_io.rb",
|
52
49
|
"test/test_client.rb",
|
53
50
|
"test/test_video.rb",
|
54
51
|
"test/test_video_search.rb",
|
55
|
-
"youtube_it.gemspec"
|
56
|
-
"youtube_it.tmproj"
|
52
|
+
"youtube_it.gemspec"
|
57
53
|
]
|
58
54
|
s.homepage = %q{http://github.com/kylejginavan/youtube_it}
|
59
55
|
s.rdoc_options = ["--charset=UTF-8"]
|
60
56
|
s.require_paths = ["lib"]
|
61
57
|
s.rubygems_version = %q{1.3.6}
|
62
|
-
s.summary = %q{
|
58
|
+
s.summary = %q{The most complete Ruby wrapper for youtube api's}
|
63
59
|
s.test_files = [
|
64
60
|
"test/helper.rb",
|
65
61
|
"test/test_chain_io.rb",
|
metadata
CHANGED
@@ -5,20 +5,21 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
|
-
-
|
12
|
+
- chebyte
|
13
|
+
- kylejginavan
|
13
14
|
autorequire:
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-10-18 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
21
|
-
description:
|
22
|
+
description: Upload, delete, update, comment on youtube videos all from one gem.
|
22
23
|
email: kylejginavan@gmail.com
|
23
24
|
executables: []
|
24
25
|
|
@@ -54,9 +55,6 @@ files:
|
|
54
55
|
- lib/youtube_it/request/video_upload.rb
|
55
56
|
- lib/youtube_it/response/video_search.rb
|
56
57
|
- lib/youtube_it/version.rb
|
57
|
-
- pkg/youtube_it-0.0.1.gem
|
58
|
-
- pkg/youtube_it-0.0.2.gem
|
59
|
-
- pkg/youtube_it-0.0.3.gem
|
60
58
|
- test/helper.rb
|
61
59
|
- test/test.mov
|
62
60
|
- test/test_chain_io.rb
|
@@ -64,7 +62,6 @@ files:
|
|
64
62
|
- test/test_video.rb
|
65
63
|
- test/test_video_search.rb
|
66
64
|
- youtube_it.gemspec
|
67
|
-
- youtube_it.tmproj
|
68
65
|
has_rdoc: true
|
69
66
|
homepage: http://github.com/kylejginavan/youtube_it
|
70
67
|
licenses: []
|
@@ -94,7 +91,7 @@ rubyforge_project:
|
|
94
91
|
rubygems_version: 1.3.6
|
95
92
|
signing_key:
|
96
93
|
specification_version: 3
|
97
|
-
summary:
|
94
|
+
summary: The most complete Ruby wrapper for youtube api's
|
98
95
|
test_files:
|
99
96
|
- test/helper.rb
|
100
97
|
- test/test_chain_io.rb
|
data/pkg/youtube_it-0.0.1.gem
DELETED
Binary file
|
data/pkg/youtube_it-0.0.2.gem
DELETED
Binary file
|
data/pkg/youtube_it-0.0.3.gem
DELETED
Binary file
|
data/youtube_it.tmproj
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
-
<plist version="1.0">
|
4
|
-
<dict>
|
5
|
-
<key>documents</key>
|
6
|
-
<array>
|
7
|
-
<dict>
|
8
|
-
<key>expanded</key>
|
9
|
-
<true/>
|
10
|
-
<key>name</key>
|
11
|
-
<string>youtube_it</string>
|
12
|
-
<key>regexFolderFilter</key>
|
13
|
-
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
|
14
|
-
<key>sourceDirectory</key>
|
15
|
-
<string></string>
|
16
|
-
</dict>
|
17
|
-
</array>
|
18
|
-
<key>fileHierarchyDrawerWidth</key>
|
19
|
-
<integer>200</integer>
|
20
|
-
<key>metaData</key>
|
21
|
-
<dict/>
|
22
|
-
<key>showFileHierarchyDrawer</key>
|
23
|
-
<true/>
|
24
|
-
<key>windowFrame</key>
|
25
|
-
<string>{{1769, 105}, {1144, 1070}}</string>
|
26
|
-
</dict>
|
27
|
-
</plist>
|