vibedeck-youtube_it 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README.rdoc +234 -0
  2. data/Rakefile +35 -0
  3. data/lib/youtube_it/chain_io.rb +76 -0
  4. data/lib/youtube_it/client.rb +367 -0
  5. data/lib/youtube_it/middleware/faraday_authheader.rb +24 -0
  6. data/lib/youtube_it/middleware/faraday_oauth.rb +21 -0
  7. data/lib/youtube_it/middleware/faraday_youtubeit.rb +30 -0
  8. data/lib/youtube_it/model/author.rb +13 -0
  9. data/lib/youtube_it/model/category.rb +11 -0
  10. data/lib/youtube_it/model/comment.rb +16 -0
  11. data/lib/youtube_it/model/contact.rb +16 -0
  12. data/lib/youtube_it/model/content.rb +18 -0
  13. data/lib/youtube_it/model/playlist.rb +11 -0
  14. data/lib/youtube_it/model/rating.rb +23 -0
  15. data/lib/youtube_it/model/subscription.rb +7 -0
  16. data/lib/youtube_it/model/thumbnail.rb +17 -0
  17. data/lib/youtube_it/model/user.rb +26 -0
  18. data/lib/youtube_it/model/video.rb +225 -0
  19. data/lib/youtube_it/parser.rb +357 -0
  20. data/lib/youtube_it/record.rb +12 -0
  21. data/lib/youtube_it/request/base_search.rb +72 -0
  22. data/lib/youtube_it/request/error.rb +15 -0
  23. data/lib/youtube_it/request/standard_search.rb +43 -0
  24. data/lib/youtube_it/request/user_search.rb +47 -0
  25. data/lib/youtube_it/request/video_search.rb +102 -0
  26. data/lib/youtube_it/request/video_upload.rb +415 -0
  27. data/lib/youtube_it/response/video_search.rb +41 -0
  28. data/lib/youtube_it/version.rb +4 -0
  29. data/lib/youtube_it.rb +75 -0
  30. data/test/helper.rb +10 -0
  31. data/test/test_chain_io.rb +63 -0
  32. data/test/test_client.rb +418 -0
  33. data/test/test_field_search.rb +48 -0
  34. data/test/test_video.rb +43 -0
  35. data/test/test_video_feed_parser.rb +271 -0
  36. data/test/test_video_search.rb +141 -0
  37. metadata +150 -0
data/README.rdoc ADDED
@@ -0,0 +1,234 @@
1
+ == DESCRIPTION
2
+
3
+ youtube_it is the most complete Ruby client for the YouTube GData API. It provides an easy
4
+ way to access the latest and most complete access to YouTube's video API.
5
+ In comparison with the earlier Youtube interfaces, this new API and
6
+ library offers much-improved flexibility around executing complex search
7
+ queries to obtain well-targeted video search results. In addition, standard video management
8
+ including but not limited to uploading, deleting, updating, like, dislike, ratings and
9
+ comments.
10
+
11
+ == INSTALLATION & SETUP:
12
+ * Create a youtube account.
13
+ * Create a developer key here http://code.google.com/apis/youtube/dashboard.
14
+ * sudo gem install youtube_it
15
+
16
+ Note: youtube_it supports ClientLogin(YouTube account), OAuth or AuthSub authentication methods.
17
+
18
+ == ESTABLISHING A CLIENT
19
+
20
+ Creating a client:
21
+ $ require 'youtube_it'
22
+ $ client = YouTubeIt::Client.new
23
+
24
+ Client with developer key:
25
+ $ client = YouTubeIt::Client.new(:dev_key => "developer_key")
26
+
27
+ Client with youtube account and developer key:
28
+ $ client = YouTubeIt::Client.new(:username => "youtube_username", :password => "youtube_passwd", :dev_key => "developer_key")
29
+
30
+ Client with AuthSub:
31
+ $ client = YouTubeIt::AuthSubClient.new(:token => "token" , :dev_key => "developer_key")
32
+
33
+ Client with OAuth:
34
+ $ client = YouTubeIt::OAuthClient.new("consumer_key", "consumer_secret", "youtube_username", "developer_key")
35
+ $ client.authorize_from_access("access_token", "access_secret")
36
+
37
+ == VIDEO QUERIES
38
+
39
+ Note: Each type of client enables searching capabilities.
40
+
41
+ Basic Queries:
42
+ $ client.videos_by(:query => "penguin")
43
+ $ client.videos_by(:query => "penguin", :page => 2, :per_page => 15)
44
+ $ client.videos_by(:tags => ['tiger', 'leopard'])
45
+ $ client.videos_by(:categories => [:news, :sports])
46
+ $ client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
47
+ $ client.videos_by(:user => 'liz')
48
+ $ client.videos_by(:favorites, :user => 'liz')
49
+ $ client.video_by("FQK1URcxmb4")
50
+ $ client.video_by_user("chebyte","FQK1URcxmb4")
51
+
52
+ Standard Queries:
53
+ $ client.videos_by(:most_viewed)
54
+ $ client.videos_by(:most_linked, :page => 3)
55
+ $ client.videos_by(:top_rated, :time => :today)
56
+
57
+ Advanced Queries (with boolean operators OR (either), AND (include), NOT (exclude)):
58
+ $ client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] }, :tags => { :include => ['football'], :exclude => ['soccer'] })
59
+
60
+
61
+ Fields Parameter(experimental features):
62
+ Return videos more than 1000 views
63
+ $ client.videos_by(:fields => {:view_count => "1000"})
64
+
65
+ Filter by date
66
+ $ client.videos_by(:fields => {:published => ((Date.today)})
67
+ $ client.videos_by(:fields => {:recorded => ((Date.today)})
68
+
69
+ Filter by date with range
70
+ $ client.videos_by(:fields => {:published => ((Date.today - 30)..(Date.today))})
71
+ $ client.videos_by(:fields => {:recorded => ((Date.today - 30)..(Date.today))})
72
+
73
+ == VIDEO MANAGEMENT
74
+
75
+ Note: YouTube account, OAuth or AuthSub enables video management.
76
+
77
+ Upload Video:
78
+ $ client.video_upload(File.open("test.mov"), :title => "test",:description => 'some description', :category => 'People',:keywords => %w[cool blah test])
79
+
80
+ Upload Video With A Developer Tag (Note the tags are not immediately available):
81
+ $ client.video_upload(File.open("test.mov"), :title => "test",:description => 'some description', :category => 'People',:keywords => %w[cool blah test], :dev_tag => 'tagdev')
82
+
83
+ Update Video:
84
+ $ client.video_update("FQK1URcxmb4", :title => "new test",:description => 'new description', :category => 'People',:keywords => %w[cool blah test])
85
+
86
+ Delete Video:
87
+ $ client.video_delete("FQK1URcxmb4")
88
+
89
+ My Videos:
90
+ $ client.my_videos
91
+
92
+ My Video:
93
+ $ client.my_video(video_id)
94
+
95
+ Profile Details:
96
+ $ client.profile(user) #default: current user
97
+
98
+ List Comments:
99
+ $ client.comments(video_id)
100
+
101
+ Add A Comment:
102
+ $ client.add_comment(video_id, "test comment!")
103
+
104
+ List Favorites:
105
+ $ client.favorites(user) # default: current user
106
+
107
+ Add Favorite:
108
+ $ client.add_favorite(video_id)
109
+
110
+ Delete Favorite:
111
+ $ client.delete_favorite(video_id)
112
+
113
+ Like A Video:
114
+ $ client.like_video(video_id)
115
+
116
+ Dislike A Video:
117
+ $ client.dislike_video(video_id)
118
+
119
+ List Subscriptions:
120
+ $ client.subscriptions(user) # default: current user
121
+
122
+ Subscribe To A Channel:
123
+ $ client.subscribe_channel(channel_name)
124
+
125
+ Unsubscribe To A Channel:
126
+ $ client.unsubscribe_channel(subscription_id)
127
+
128
+ List Playlists:
129
+ $ client.playlists(user) # default: current user
130
+
131
+ Select Playlist:
132
+ $ client.playlist(playlist_id)
133
+
134
+ Select All Videos From A Playlist:
135
+ $ playlist = client.playlist(playlist_id)
136
+ $ playlist.videos
137
+
138
+ Create Playlist:
139
+ $ playlist = client.add_playlist(:title => "new playlist", :description => "playlist description")
140
+
141
+ Delete Playlist:
142
+ $ client.delete_playlist(playlist_id)
143
+
144
+ Add Video To Playlist:
145
+ $ client.add_video_to_playlist(playlist_id, video_id)
146
+
147
+ Remove Video From Playlist:
148
+ $ client.remove_video_from_playlist(playlist_id, playlist_entry_id)
149
+
150
+ == ACCESS CONTROL LIST
151
+
152
+ You can give permissions in your videos, for example denied comments, rate, etc...
153
+ you can read more there http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:accessControl
154
+ you have available the followings options:
155
+
156
+ * :rate, :comment, :commentVote, :videoRespond, :list, :embed, :syndicate
157
+
158
+ with just two values:
159
+ * allowed or denied
160
+
161
+ Example
162
+
163
+ client = YouTubeIt::Client.new(:username => "youtube_username", :password => "youtube_passwd", :dev_key => "developer_key")
164
+
165
+ * upload video with denied comments
166
+
167
+ client.video_upload(File.open("test.mov"), :title => "test",:description => 'some description', :category => 'People',:keywords => %w[cool blah test], :comment => "denied")
168
+
169
+
170
+ == Video Upload From Browser:
171
+
172
+ When uploading a video from your browser you need make a form upload with the followings params:
173
+ $ upload_token(params, nexturl)
174
+ params => params like :title => "title", :description => "description", :category => "People", :tags => ["test"]
175
+ nexturl => redirect to this url after upload
176
+
177
+
178
+ Controller
179
+ def upload
180
+ @upload_info = YouTubeIt::Client.new.upload_token(params, videos_url)
181
+ end
182
+
183
+ View (upload.html.erb)
184
+ <% form_tag @upload_info[:url], :multipart => true do %>
185
+ <%= hidden_field_tag :token, @upload_info[:token] %>
186
+ <%= label_tag :file %>
187
+ <%= file_field_tag :file %>
188
+ <%= submit_tag "Upload video" %>
189
+ <% end %>
190
+
191
+ == WIDESCREEN VIDEOS
192
+
193
+ If the videos has support for widescreen:
194
+ $ video.embed_html_with_width(1280)
195
+
196
+ Note: you can specify width or just use the default of 1280.
197
+
198
+ == LOGGING
199
+
200
+ YouTubeIt passes all logs through the logger variable on the class itself. In Rails context, assign the Rails logger to that variable to collect the messages
201
+ (don't forget to set the level to debug):
202
+ $ YouTubeIt.logger = RAILS_DEFAULT_LOGGER
203
+ $ RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
204
+
205
+ == CONTRIBUTORS:
206
+
207
+ * Kyle J. Ginavan.
208
+ * Mauro Torres - http://github.com/chebyte
209
+ * Marko Seppa - https://github.com/mseppae
210
+
211
+ == LICENSE:
212
+
213
+ MIT License
214
+
215
+ Copyright (c) 2010 Kyle J. Ginavan
216
+
217
+ Permission is hereby granted, free of charge, to any person obtaining
218
+ a copy of this software and associated documentation files (the
219
+ 'Software'), to deal in the Software without restriction, including
220
+ without limitation the rights to use, copy, modify, merge, publish,
221
+ distribute, sublicense, and/or sell copies of the Software, and to
222
+ permit persons to whom the Software is furnished to do so, subject to
223
+ the following conditions:
224
+
225
+ The above copyright notice and this permission notice shall be
226
+ included in all copies or substantial portions of the Software.
227
+
228
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
229
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
230
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
231
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
232
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
233
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
234
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ begin
12
+ require 'rcov/rcovtask'
13
+ Rcov::RcovTask.new do |test|
14
+ test.libs << 'test'
15
+ test.pattern = 'test/**/test_*.rb'
16
+ test.verbose = true
17
+ end
18
+ rescue LoadError
19
+ task :rcov do
20
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
21
+ end
22
+ end
23
+
24
+ task :default => :test
25
+
26
+ require 'rake/rdoctask'
27
+ Rake::RDocTask.new do |rdoc|
28
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
29
+
30
+ rdoc.rdoc_dir = 'rdoc'
31
+ rdoc.title = "constantations #{version}"
32
+ rdoc.rdoc_files.include('README*')
33
+ rdoc.rdoc_files.include('lib/**/*.rb')
34
+ end
35
+
@@ -0,0 +1,76 @@
1
+ require 'delegate'
2
+ #:stopdoc:
3
+
4
+ # Stream wrapper that reads IOs in succession. Can be fed to Net::HTTP as post body stream. We use it internally to stream file content
5
+ # instead of reading whole video files into memory. Strings passed to the constructor will be wrapped in StringIOs. By default it will auto-close
6
+ # file handles when they have been read completely to prevent our uploader from leaking file handles
7
+ #
8
+ # chain = ChainIO.new(File.open(__FILE__), File.open('/etc/passwd'), "abcd")
9
+ class YouTubeIt::ChainIO
10
+ attr_accessor :autoclose
11
+
12
+ def initialize(*any_ios)
13
+ @autoclose = true
14
+ @chain = any_ios.flatten.map{|e| e.respond_to?(:read) ? e : StringIO.new(e.to_s) }
15
+ end
16
+
17
+ def read(buffer_size = 1024)
18
+ # Read off the first element in the stack
19
+ current_io = @chain.shift
20
+ return false if !current_io
21
+
22
+ buf = current_io.read(buffer_size)
23
+ if !buf && @chain.empty? # End of streams
24
+ release_handle(current_io) if @autoclose
25
+ false
26
+ elsif !buf # This IO is depleted, but next one is available
27
+ release_handle(current_io) if @autoclose
28
+ read(buffer_size)
29
+ elsif buf.length < buffer_size # This IO is depleted, but we were asked for more
30
+ release_handle(current_io) if @autoclose
31
+ buf + (read(buffer_size - buf.length) || '') # and recurse
32
+ else # just return the buffer
33
+ @chain.unshift(current_io) # put the current back
34
+ buf
35
+ end
36
+ end
37
+
38
+ # Predict the length of all embedded IOs. Will automatically send file size.
39
+ def expected_length
40
+ @chain.inject(0) do | len, io |
41
+ if io.respond_to?(:length)
42
+ len + (io.length - io.pos)
43
+ elsif io.is_a?(File)
44
+ len + File.size(io.path) - io.pos
45
+ else
46
+ raise "Cannot predict length of #{io.inspect}"
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+ def release_handle(io)
53
+ io.close if io.respond_to?(:close)
54
+ end
55
+ end
56
+
57
+ # Net::HTTP only can send chunks of 1024 bytes. This is very inefficient, so we have a spare IO that will send more when asked for 1024.
58
+ # We use delegation because the read call is recursive.
59
+ class YouTubeIt::GreedyChainIO < DelegateClass(YouTubeIt::ChainIO)
60
+ BIG_CHUNK = 512 * 1024 # 500 kb
61
+
62
+ def initialize(*with_ios)
63
+ __setobj__(YouTubeIt::ChainIO.new(with_ios))
64
+ end
65
+
66
+ def read(any_buffer_size)
67
+ __getobj__.read(BIG_CHUNK)
68
+ end
69
+
70
+ def length()
71
+ __getobj__.expected_length
72
+ end
73
+
74
+ end
75
+
76
+ #:startdoc: