FiXato-youtube-g 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ == trunk
2
+
3
+ * Fix issue with REXML parsing of video upload response. [FiXato]
4
+ * Fix issue with response code comparison. [FiXato]
5
+ * Authcode is now retrieved for video uploads. [FiXato]
6
+ * Add basic support for uploading videos [thanks Joe Damato]
7
+ * Add basic support for related videos [tmm1]
8
+ * Improve docs for order_by attribute [thanks Jason Arora]
9
+ * Added support for the "racy" parameter (choices are "include" or "exclude") [thanks Jason Arora]
10
+ * Add missing attribute reader for description [tmm1]
11
+ * Fix issue with missing yt:statistics and viewCount [tmm1]
12
+ * Allow Client#video_by to take either a url or a video id [tmm1]
13
+
14
+ == 0.4.1 / 2008-02-11
15
+
16
+ * Added 3GPP video format [shane]
17
+ * Fixed tests [shane]
18
+
19
+ == 0.4.0 / 2007-12-18
20
+
21
+ * Fixed API projection in search URL [Pete Higgins]
22
+ * Fixed embeddable video searching [Pete Higgins]
23
+ * Fixed video embeddable detection [Pete Higgins]
24
+ * Fixed unique id hyphen detection [Pete Higgins, Chris Taggart]
25
+
26
+ == 0.3.0 / 2007-09-17
27
+
28
+ * Initial public release
29
+ * Birthday!
30
+
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ TODO.txt
6
+ lib/youtube_g.rb
7
+ lib/youtube_g/client.rb
8
+ lib/youtube_g/logger.rb
9
+ lib/youtube_g/model/author.rb
10
+ lib/youtube_g/model/category.rb
11
+ lib/youtube_g/model/contact.rb
12
+ lib/youtube_g/model/content.rb
13
+ lib/youtube_g/model/playlist.rb
14
+ lib/youtube_g/model/rating.rb
15
+ lib/youtube_g/model/thumbnail.rb
16
+ lib/youtube_g/model/user.rb
17
+ lib/youtube_g/model/video.rb
18
+ lib/youtube_g/parser.rb
19
+ lib/youtube_g/record.rb
20
+ lib/youtube_g/request/video_search.rb
21
+ lib/youtube_g/request/video_upload.rb
22
+ lib/youtube_g/response/video_search.rb
23
+ test/test_client.rb
24
+ test/test_video.rb
25
+ test/test_video_search.rb
@@ -0,0 +1,81 @@
1
+ youtube-g
2
+ by Shane Vitarana and Walter Korman
3
+
4
+ Rubyforge: http://rubyforge.org/projects/youtube-g/
5
+ RDoc: http://youtube-g.rubyforge.org/
6
+ Google Group: http://groups.google.com/group/ruby-youtube-library
7
+
8
+ == DESCRIPTION:
9
+
10
+ youtube-g is a pure Ruby client for the YouTube GData API. It provides an easy
11
+ way to access the latest YouTube video search results from your own programs.
12
+ In comparison with the earlier Youtube search interfaces, this new API and
13
+ library offers much-improved flexibility around executing complex search
14
+ queries to obtain well-targeted video search results.
15
+
16
+ More detail on the underlying source Google-provided API is available at:
17
+
18
+ http://code.google.com/apis/youtube/overview.html
19
+
20
+ == FEATURES/PROBLEMS:
21
+
22
+ * Aims to be in parity with Google's YouTube GData API. Core functionality
23
+ is currently present -- work is in progress to fill in the rest.
24
+
25
+ == SYNOPSIS:
26
+
27
+ Create a client:
28
+
29
+ require 'youtube_g'
30
+ client = YouTubeG::Client.new
31
+
32
+ Basic queries:
33
+
34
+ client.videos_by(:query => "penguin")
35
+ client.videos_by(:tags => ['tiger', 'leopard'])
36
+ client.videos_by(:categories => [:news, :sports])
37
+ client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
38
+ client.videos_by(:user => 'liz')
39
+
40
+ Standard feeds:
41
+
42
+ client.videos_by(:most_viewed)
43
+ client.videos_by(:top_rated, :time => :today)
44
+
45
+ Advanced queries (with boolean operators OR (either), AND (include), NOT (exclude)):
46
+
47
+ client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] }, :tags => { :include => ['football'], :exclude => ['soccer'] })
48
+
49
+
50
+ == REQUIREMENTS:
51
+
52
+ * None
53
+
54
+ == INSTALL:
55
+
56
+ * sudo gem install youtube-g
57
+
58
+ == LICENSE:
59
+
60
+ MIT License
61
+
62
+ Copyright (c) 2007 Shane Vitarana and Walter Korman
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining
65
+ a copy of this software and associated documentation files (the
66
+ 'Software'), to deal in the Software without restriction, including
67
+ without limitation the rights to use, copy, modify, merge, publish,
68
+ distribute, sublicense, and/or sell copies of the Software, and to
69
+ permit persons to whom the Software is furnished to do so, subject to
70
+ the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be
73
+ included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
79
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
80
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
81
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require 'lib/youtube_g'
4
+
5
+ Hoe.new('youtube-g', YouTubeG::VERSION) do |p|
6
+ p.rubyforge_name = 'youtube-g'
7
+ p.author = ["Shane Vitarana", "Walter Korman", "Aman Gupta", "Filip H.F. Slagter"]
8
+ p.email = 'shanev@gmail.com'
9
+ p.summary = 'Ruby client for the YouTube GData API'
10
+ p.description = p.paragraphs_of('README.txt', 2..8).join("\n\n")
11
+ p.url = 'http://rubyforge.org/projects/youtube-g/'
12
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
13
+ p.remote_rdoc_dir = ''
14
+ end
15
+
16
+ desc 'Tag release'
17
+ task :tag do
18
+ svn_root = 'svn+ssh://drummr77@rubyforge.org/var/svn/youtube-g'
19
+ sh %(svn cp #{svn_root}/trunk #{svn_root}/tags/release-#{YouTubeG::VERSION} -m "Tag YouTubeG release #{YouTubeG::VERSION}")
20
+ end
@@ -0,0 +1,18 @@
1
+ [ ] stub out http request/response cycle for tests
2
+ [ ] consider defaulting the client to no-logger, rather than outputting to STDOUT.
3
+ [ ] allow specifying values as single items where you don't need to wrap in a list, e.g. :tags => :chickens instead of :tags => [ 'chickens' ]
4
+ [ ] make sure symbols will work as well as tags everywhere (again, :tags => :chickens is same as :tags => 'chickens')
5
+ [ ] figure out better structure for class/file (either rename request/video_search.rb or split into one class per file again)
6
+ [ ] restore spaces after method def names
7
+ [ ] use a proxy for testing with static sample result xml so we have repeatable tests
8
+ [ ] Clean up tests using Shoulda to define contexts
9
+ [ ] Consolidate requires
10
+ [ ] Allow :category and :categories for query DSL
11
+ [ ] Exception handling
12
+
13
+ == API Features TODO
14
+
15
+ [ ] Profile feed parsing
16
+ [ ] Playlist feeds
17
+ [ ] User subscriptions
18
+ [ ] Video comments
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/youtube_g/client'
2
+ require File.dirname(__FILE__) + '/youtube_g/record'
3
+ require File.dirname(__FILE__) + '/youtube_g/parser'
4
+ require File.dirname(__FILE__) + '/youtube_g/model/author'
5
+ require File.dirname(__FILE__) + '/youtube_g/model/category'
6
+ require File.dirname(__FILE__) + '/youtube_g/model/contact'
7
+ require File.dirname(__FILE__) + '/youtube_g/model/content'
8
+ require File.dirname(__FILE__) + '/youtube_g/model/playlist'
9
+ require File.dirname(__FILE__) + '/youtube_g/model/rating'
10
+ require File.dirname(__FILE__) + '/youtube_g/model/thumbnail'
11
+ require File.dirname(__FILE__) + '/youtube_g/model/user'
12
+ require File.dirname(__FILE__) + '/youtube_g/model/video'
13
+ require File.dirname(__FILE__) + '/youtube_g/request/video_upload'
14
+ require File.dirname(__FILE__) + '/youtube_g/request/video_search'
15
+ require File.dirname(__FILE__) + '/youtube_g/response/video_search'
16
+
17
+ class YouTubeG
18
+ VERSION = '0.4.5'
19
+ end
@@ -0,0 +1,36 @@
1
+ require 'logger'
2
+
3
+ class YouTubeG
4
+ class Client
5
+ attr_accessor :logger
6
+
7
+ def initialize(logger=Logger.new(STDOUT))
8
+ @logger = logger
9
+ end
10
+
11
+ # Params can be one of :most_viewed, :top_rated, :recently_featured, :watch_on_mobile
12
+ # Or :tags, :categories, :query, :user
13
+ def videos_by(params, options={})
14
+ if params.respond_to?(:to_hash) and not params[:user]
15
+ request = YouTubeG::Request::VideoSearch.new(params)
16
+
17
+ elsif (params.respond_to?(:to_hash) && params[:user]) || (params == :favorites)
18
+ request = YouTubeG::Request::UserSearch.new(params, options)
19
+
20
+ else
21
+ request = YouTubeG::Request::StandardSearch.new(params, options)
22
+ end
23
+
24
+ logger.debug "Submitting request [url=#{request.url}]."
25
+ parser = YouTubeG::Parser::VideosFeedParser.new(request.url)
26
+ parser.parse
27
+ end
28
+
29
+ def video_by(vid)
30
+ video_id = vid =~ /^http/ ? vid : "http://gdata.youtube.com/feeds/videos/#{vid}"
31
+ parser = YouTubeG::Parser::VideoFeedParser.new(video_id)
32
+ parser.parse
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ require 'logger'
2
+
3
+ class YouTubeG
4
+
5
+ # TODO: Why is this needed? Does this happen if running standalone w/o Rails?
6
+ # Anyway, isn't it easier to debug w/o the really long timestamp & log level?
7
+ # How often do you look at the timestamp and log level? Wouldn't it be nice to
8
+ # see your logger output first?
9
+
10
+ # Extension of the base ruby Logger class to restore the default log
11
+ # level and timestamp formatting which is so rudely taken forcibly
12
+ # away from us by the Rails app's use of the ActiveSupport library
13
+ # that wholesale-ly modifies the Logger's format_message method.
14
+ #
15
+ class Logger < ::Logger
16
+ private
17
+ begin
18
+ # restore original log formatting to un-screw the screwage that is
19
+ # foisted upon us by the activesupport library's clean_logger.rb
20
+ alias format_message old_format_message
21
+
22
+ rescue NameError
23
+ # nothing for now -- this means we didn't need to alias since the
24
+ # method wasn't overridden
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Author < YouTubeG::Record
4
+ attr_reader :name
5
+ attr_reader :uri
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Category < YouTubeG::Record
4
+ attr_reader :label
5
+ attr_reader :term
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Contact < YouTubeG::Record
4
+ attr_reader :status
5
+ attr_reader :username
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Content < YouTubeG::Record
4
+ attr_reader :default
5
+ attr_reader :duration
6
+ attr_reader :format
7
+ attr_reader :mime_type
8
+ attr_reader :url
9
+
10
+ alias :is_default? :default
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Playlist < YouTubeG::Record
4
+ attr_reader :description
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Rating < YouTubeG::Record
4
+ attr_reader :average
5
+ attr_reader :max
6
+ attr_reader :min
7
+ attr_reader :rater_count
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Thumbnail < YouTubeG::Record
4
+ attr_reader :url
5
+ attr_reader :height
6
+ attr_reader :width
7
+ attr_reader :time
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ class YouTubeG
2
+ module Model
3
+ class User < YouTubeG::Record
4
+ attr_reader :age
5
+ attr_reader :books
6
+ attr_reader :company
7
+ attr_reader :gender
8
+ attr_reader :hobbies
9
+ attr_reader :hometown
10
+ attr_reader :location
11
+ attr_reader :movies
12
+ attr_reader :music
13
+ attr_reader :occupation
14
+ attr_reader :relationship
15
+ attr_reader :school
16
+ attr_reader :description
17
+ attr_reader :username
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,106 @@
1
+ class YouTubeG
2
+ module Model
3
+ class Video < YouTubeG::Record
4
+ # Describes the various file formats in which a Youtube video may be
5
+ # made available and allows looking them up by format code number.
6
+ #
7
+ class Format
8
+ @@formats = Hash.new
9
+
10
+ def initialize(format_code, name)
11
+ @format_code = format_code
12
+ @name = name
13
+
14
+ @@formats[format_code] = self
15
+ end
16
+
17
+ def self.by_code(format_code)
18
+ @@formats[format_code]
19
+ end
20
+
21
+ # Flash format on YouTube site. All videos are available in this
22
+ # format.
23
+ #
24
+ FLASH = YouTubeG::Model::Video::Format.new(0, :flash)
25
+
26
+ # RTSP streaming URL for mobile video playback. H.263 video (176x144)
27
+ # and AMR audio.
28
+ #
29
+ RTSP = YouTubeG::Model::Video::Format.new(1, :rtsp)
30
+
31
+ # HTTP URL to the embeddable player (SWF) for this video. This format
32
+ # is not available for a video that is not embeddable.
33
+ #
34
+ SWF = YouTubeG::Model::Video::Format.new(5, :swf)
35
+
36
+ THREE_GPP = YouTubeG::Model::Video::Format.new(6, :three_gpp)
37
+ end
38
+
39
+ attr_reader :duration
40
+ attr_reader :noembed
41
+ attr_reader :position
42
+ attr_reader :racy
43
+ attr_reader :statistics
44
+
45
+ attr_reader :video_id
46
+ attr_reader :published_at
47
+ attr_reader :updated_at
48
+ attr_reader :categories
49
+ attr_reader :keywords
50
+ attr_reader :description
51
+ attr_reader :title
52
+ attr_reader :html_content
53
+ attr_reader :author
54
+
55
+ # YouTubeG::Model::Content records describing the individual media content
56
+ # data available for this video. Most, but not all, videos offer this.
57
+ attr_reader :media_content
58
+
59
+ attr_reader :thumbnails # YouTubeG::Model::Thumbnail records
60
+ attr_reader :player_url
61
+ attr_reader :rating
62
+ attr_reader :view_count
63
+
64
+ # TODO:
65
+ # self atom feed
66
+ # alternate youtube watch url
67
+ # responses feed
68
+ # comments feedLink
69
+
70
+ def related
71
+ YouTubeG::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/related").parse
72
+ end
73
+
74
+ # For convenience, the video_id with the URL stripped out, useful for searching for the video again
75
+ # without having to store it anywhere. A regular query search, with this id will return the same video.
76
+ # http://gdata.youtube.com/feeds/videos/ZTUVgYoeN_o
77
+ def unique_id
78
+ video_id[/videos\/([^<]+)/, 1]
79
+ end
80
+
81
+ def can_embed?
82
+ not @noembed
83
+ end
84
+
85
+ def default_media_content
86
+ @media_content.find { |c| c.is_default? }
87
+ end
88
+
89
+ def embed_html(width = 425, height = 350)
90
+ <<EDOC
91
+ <object width="#{width}" height="#{height}">
92
+ <param name="movie" value="#{embed_url}"></param>
93
+ <param name="wmode" value="transparent"></param>
94
+ <embed src="#{embed_url}" type="application/x-shockwave-flash"
95
+ wmode="transparent" width="#{width}" height="#{height}"></embed>
96
+ </object>
97
+ EDOC
98
+ end
99
+
100
+ def embed_url
101
+ @player_url.sub('watch?', '').sub('=', '/')
102
+ end
103
+
104
+ end
105
+ end
106
+ end