howcast 0.4.3 → 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,15 @@
1
+ == 0.4.9 2009-08-19
2
+
3
+ * require hpricot, update readme
4
+
5
+ == 0.4.8 2009-08-19
6
+
7
+ * Move gem to github, use echoe to clean up configuration, remove dependency on hpricot
8
+
9
+ == 0.4.5 2009-07-27
10
+
11
+ * Removed guide wrappers, Howcast API just has how-to's which merges old video and guides
12
+
1
13
  == 0.4.3 2009-03-02
2
14
 
3
15
  * Compatibility with ruby 1.9 - replacing dependency on hpricot with why-hpricot as github as the ruby 1.9 hpricot gem
data/Manifest ADDED
@@ -0,0 +1,19 @@
1
+ CHANGELOG
2
+ lib/howcast/client/base.rb
3
+ lib/howcast/client/category.rb
4
+ lib/howcast/client/search.rb
5
+ lib/howcast/client/video.rb
6
+ lib/howcast/client.rb
7
+ lib/howcast/errors.rb
8
+ lib/howcast.rb
9
+ License.txt
10
+ Manifest
11
+ Rakefile
12
+ README.markdown
13
+ spec/howcast/client/base_spec.rb
14
+ spec/howcast/client/category_spec.rb
15
+ spec/howcast/client/search_spec.rb
16
+ spec/howcast/client/video_spec.rb
17
+ spec/spec.opts
18
+ spec/spec_helper.rb
19
+ tasks/github.rake
data/README.markdown CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Copyright (c) 2008 Howcast Media Inc.
4
4
 
5
- Author: Michael Murray <michael@howcast.com>
5
+ Author: Jingshen Jimmy Zhang <jimmy@howcast.com>
6
6
 
7
7
  ## Installing
8
8
 
9
- sudo gem install howcast
9
+ sudo gem install howcast-howcast
10
10
 
11
11
  ## Example
12
12
 
@@ -20,14 +20,14 @@ Author: Michael Murray <michael@howcast.com>
20
20
  puts v.title
21
21
  end
22
22
 
23
- puts "2nd Page of Recent Featured Videos"
24
- # Will print out the video titles of the 2nd page of recent featured videos
25
- hc.videos(:page => 2, :sort => "most_recent", :filter => "featured").each do |v|
23
+ puts "2nd Page of Top Rated Videos"
24
+ # Will print out the video titles of the 2nd page of top rated videos
25
+ hc.videos(:page => 2, :sort => "top_rated", :filter => "all").each do |v|
26
26
  puts v.title
27
27
  end
28
28
 
29
29
  puts "Videos matching 'origami'"
30
- hc.video_search("origami").each do |v|
30
+ hc.search("origami").each do |v|
31
31
  puts v.title
32
32
  end
33
33
 
data/Rakefile CHANGED
@@ -1,4 +1,32 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
1
+ require 'rubygems'
2
+ require 'rake'
3
3
 
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "howcast"
8
+ gemspec.summary = "Howcast API Ruby Wrapper"
9
+ gemspec.description = <<-EOS
10
+ Howcast offers an Application Programming Interface (API) which allows
11
+ developers to build applications that interface with Howcast. The Howcast
12
+ API is RESTful (REpresentational State Transfer) and users of this API will
13
+ be able: 1) Retreive detailed information about a single video, including
14
+ metadata such as title, description, video views, rating etc; 2) Retrieve a
15
+ list of videos restricted by a set of filters offered by Howcast and sorted
16
+ using several metrics that you can specify (most recent, most views, etc);
17
+ 3) Search for video; 4) And much more. Note: Before you can use our APIs,
18
+ you must register an API key, that is submitted with each request.
19
+ EOS
20
+ gemspec.email = "support@howcast.com"
21
+ gemspec.homepage = "http://github.com/howcast/howcast-gem"
22
+ gemspec.authors = ["Jingshen Jimmy Zhang", "Ian Smith-Heisters"]
23
+ gemspec.add_dependency "hpricot"
24
+ gemspec.add_development_dependency "rspec"
25
+ gemspec.files = FileList['**/*'].exclude('tmp/*', 'script/*', 'tags', 'pkg')
26
+ end
27
+ rescue LoadError
28
+ puts "Jeweler not available. Install it with: gem install jeweler"
29
+ end
30
+
31
+
32
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.10
data/howcast.gemspec ADDED
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{howcast}
8
+ s.version = "0.4.10"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jingshen Jimmy Zhang", "Ian Smith-Heisters"]
12
+ s.date = %q{2010-01-04}
13
+ s.description = %q{ Howcast offers an Application Programming Interface (API) which allows
14
+ developers to build applications that interface with Howcast. The Howcast
15
+ API is RESTful (REpresentational State Transfer) and users of this API will
16
+ be able: 1) Retreive detailed information about a single video, including
17
+ metadata such as title, description, video views, rating etc; 2) Retrieve a
18
+ list of videos restricted by a set of filters offered by Howcast and sorted
19
+ using several metrics that you can specify (most recent, most views, etc);
20
+ 3) Search for video; 4) And much more. Note: Before you can use our APIs,
21
+ you must register an API key, that is submitted with each request.
22
+ }
23
+ s.email = %q{support@howcast.com}
24
+ s.extra_rdoc_files = [
25
+ "README.markdown"
26
+ ]
27
+ s.files = [
28
+ "CHANGELOG",
29
+ "License.txt",
30
+ "Manifest",
31
+ "README.markdown",
32
+ "Rakefile",
33
+ "VERSION",
34
+ "howcast.gemspec",
35
+ "lib/howcast.rb",
36
+ "lib/howcast/client.rb",
37
+ "lib/howcast/client/base.rb",
38
+ "lib/howcast/client/category.rb",
39
+ "lib/howcast/client/search.rb",
40
+ "lib/howcast/client/video.rb",
41
+ "lib/howcast/errors.rb",
42
+ "spec/howcast/client/base_spec.rb",
43
+ "spec/howcast/client/category_spec.rb",
44
+ "spec/howcast/client/search_spec.rb",
45
+ "spec/howcast/client/video_spec.rb",
46
+ "spec/spec.opts",
47
+ "spec/spec_helper.rb",
48
+ "tasks/github.rake"
49
+ ]
50
+ s.homepage = %q{http://github.com/howcast/howcast-gem}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.5}
54
+ s.summary = %q{Howcast API Ruby Wrapper}
55
+ s.test_files = [
56
+ "spec/howcast/client/base_spec.rb",
57
+ "spec/howcast/client/category_spec.rb",
58
+ "spec/howcast/client/search_spec.rb",
59
+ "spec/howcast/client/video_spec.rb",
60
+ "spec/spec_helper.rb"
61
+ ]
62
+
63
+ if s.respond_to? :specification_version then
64
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
68
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
69
+ s.add_development_dependency(%q<rspec>, [">= 0"])
70
+ else
71
+ s.add_dependency(%q<hpricot>, [">= 0"])
72
+ s.add_dependency(%q<rspec>, [">= 0"])
73
+ end
74
+ else
75
+ s.add_dependency(%q<hpricot>, [">= 0"])
76
+ s.add_dependency(%q<rspec>, [">= 0"])
77
+ end
78
+ end
79
+
data/lib/howcast.rb CHANGED
@@ -4,6 +4,5 @@ def require_local(suffix)
4
4
  require(File.expand_path(File.join(File.dirname(__FILE__), suffix)))
5
5
  end
6
6
 
7
- require_local('howcast/version')
8
7
  require_local('howcast/client')
9
8
  require_local('howcast/errors')
@@ -4,6 +4,5 @@ end
4
4
 
5
5
  require_local('howcast/client/base.rb')
6
6
  require_local('howcast/client/video.rb')
7
- require_local('howcast/client/guide.rb')
8
7
  require_local('howcast/client/search.rb')
9
8
  require_local('howcast/client/category.rb')
@@ -24,6 +24,7 @@
24
24
  require 'rubygems'
25
25
  require 'hpricot'
26
26
  require 'open-uri'
27
+ require 'uri'
27
28
 
28
29
  class Howcast::Client
29
30
  attr_accessor :key
@@ -43,7 +44,21 @@ class Howcast::Client
43
44
  raise Howcast::ApiKeyNotFound if options[:key].nil?
44
45
  @key = options[:key]
45
46
  end
46
-
47
+
48
+ class << self
49
+ def base_uri= new_base_uri
50
+ @base_uri = case new_base_uri
51
+ when URI then new_base_uri
52
+ when String then URI.parse new_base_uri
53
+ when Hash then URI::HTTP.build new_base_uri
54
+ else; raise ArgumentError, "can't convert URI: #{new_base_uri.inspect}"
55
+ end
56
+ end
57
+
58
+ def base_uri
59
+ @base_uri ||= URI.parse("http://www.howcast.com")
60
+ end
61
+ end
47
62
  protected
48
63
  # Establishes a connection with the Howcast API. Will auto append the api key, that was used
49
64
  # to instantiate the Client object, to the URL
@@ -65,8 +80,11 @@ class Howcast::Client
65
80
  #
66
81
  # Get the Hpricot data for most recent howcast studios videos
67
82
  # establish_connection("videos/most_recent/howcast_studios.xml")
68
- def establish_connection(relative_path)
69
- h = Hpricot.XML(open(url = attach_api_key("http://www.howcast.com/#{relative_path}")))
83
+ def establish_connection(relative_path_and_query)
84
+ uri = self.class.base_uri.dup
85
+ relative_path_and_query = '/' + relative_path_and_query unless relative_path_and_query[0] == '/'
86
+ uri.path, uri.query = *relative_path_and_query.split('?')
87
+ h = Hpricot.XML(open(url = attach_api_key(uri)))
70
88
  puts "Established connection with: '#{url}'"
71
89
  raise Howcast::ApiKeyNotFound if h.at(:error) && h.at(:error).inner_html.match(/Invalid API Key/)
72
90
  return h
@@ -79,10 +97,10 @@ class Howcast::Client
79
97
  # === Inputs
80
98
  #
81
99
  # * <tt>xml</tt> -- See below for a sample xml input
82
- # * <tt>klass</tt> -- Class to create - Guide | Video | Category supported
100
+ # * <tt>klass</tt> -- Class to create - Video | Category supported
83
101
  #
84
102
  # Sample input xml
85
- # <guide>
103
+ # <video>
86
104
  # <id>1086</id>
87
105
  # <rating>96</rating>
88
106
  # <title>How To Choose a Paintbrush</title>
@@ -94,7 +112,7 @@ class Howcast::Client
94
112
  # <permalink>http://www.howcast.com/guides/1086-How-To-Choose-a-Paintbrush</permalink>
95
113
  # <username>michaelrsanchez</username>
96
114
  # <created-at>Thu, 20 Dec 2007 14:14:58 -0800</created-at>
97
- # </guide>
115
+ # </video>
98
116
  #
99
117
  # === Outputs
100
118
  #
@@ -130,25 +148,55 @@ class Howcast::Client
130
148
  opts && opts[:page] ? "#{opts[:use_ampersand] ? '&' : '?'}page=#{opts[:page]}" : ""
131
149
  end
132
150
 
133
- # Appends the api key to a url and returns the appended url
151
+ # Appends the api key to a uri and returns the appended uri
134
152
  #
135
153
  # === Inputs
136
154
  #
137
- # * <tt>url</tt> -- the url to append the api_key to
155
+ # * <tt>uri</tt> -- the URI object to append the api_key to
138
156
  #
139
157
  # === Outputs
140
158
  #
141
- # The url with the api_key appended
159
+ # The uri with the api_key appended to the query string
142
160
  #
143
161
  # === Examples
144
162
  #
145
- # attach_api_key("http://www.howcast.com")
163
+ # attach_api_key(URI.parse("http://www.howcast.com")).to_s
146
164
  # => "http://www.howcast.com?api_key=APIKEYHERE"
147
165
  #
148
- # attach_api_key("http://www.howcast.com/videos/most_recent/all?page=2")
166
+ # attach_api_key(URI.parse("http://www.howcast.com/videos/most_recent/all?page=2")).to_s
149
167
  # => "http://www.howcast.com/videos/most_recent/all?page=2&api_key=APIKEYHERE"
150
- def attach_api_key(url)
151
- url.match(/\?/) ? "#{url}&api_key=#{self.key}" : "#{url}?api_key=#{self.key}"
168
+ def attach_api_key(uri)
169
+ uri = uri.dup
170
+ key = "api_key=#{self.key}"
171
+ uri.query = uri.query.to_s.strip != "" ? uri.query+"&"+key : key
172
+ uri
173
+ end
174
+
175
+ # From merb/core_ext/hash.rb, line 87
176
+ def hash_to_params hash
177
+ params = ''
178
+ stack = []
179
+
180
+ hash.each do |k, v|
181
+ if v.is_a?(Hash)
182
+ stack << [k,v]
183
+ else
184
+ params << "#{k}=#{v}&"
185
+ end
186
+ end
187
+
188
+ stack.each do |parent, h|
189
+ h.each do |k, v|
190
+ if v.is_a?(Hash)
191
+ stack << ["#{parent}[#{k}]", v]
192
+ else
193
+ params << "#{parent}[#{k}]=#{v}&"
194
+ end
195
+ end
196
+ end
197
+
198
+ params.chop! # trailing &
199
+ params
152
200
  end
153
201
  end
154
202
 
@@ -25,13 +25,15 @@ require 'cgi'
25
25
 
26
26
  class Howcast::Client
27
27
  # Provides access to the Howcast video search API.
28
- #
28
+ #
29
29
  # === Inputs
30
30
  #
31
- # * <tt>query</tt> -- The string query which you want to search for
32
- # The options are:
33
- # * <tt>:page</tt> -- The page number to retrieve (defaults to 1). There are 10 videos per page.
34
- # * <tt>:mode</tt> -- Mode to search, using :extended will allow title:something searches
31
+ # * <tt>query</tt> -- The string query which you want to search for
32
+ # The options are:
33
+ # ** <tt>:page</tt> -- The page number to retrieve (defaults to 1). There are
34
+ # 10 videos per page.
35
+ # ** <tt>:mode</tt> -- Mode to search, using :extended will allow
36
+ # title:something searches
35
37
  #
36
38
  # === Outputs
37
39
  #
@@ -39,43 +41,46 @@ class Howcast::Client
39
41
  #
40
42
  # === Exceptions
41
43
  #
42
- # * <tt>Howcast::ApiNotFound</tt> -- raised if the requested sort and filter is malformed or not available (404)
43
- # * <tt>ArgumentError</tt> -- raised when the required 1 argument isn't supplied
44
+ # * <tt>Howcast::ApiNotFound</tt> -- raised if the requested sort and filter
45
+ # is malformed or not available (404)
46
+ # * <tt>ArgumentError</tt> -- raised when the required 1 argument isn't
47
+ # supplied
44
48
  #
45
49
  # === Examples
46
50
  #
47
- # Get the first page of howcast videos matching 'poker'.
51
+ # Get the first page of howcast videos matching 'poker'.
48
52
  # Howcast::Client.new.video_search("poker")
49
53
  # Get the third page of howcast videos matching 'traveling'
50
54
  # Howcast::Client.new.video_search("traveling", :page => 3)
51
- def video_search(query, options = {})
52
- uri = search_url(query, options.merge(:view => 'video'))
53
- (establish_connection(uri)/:video).inject([]){ |r, i| r << parse_single_xml(i, Video)}
55
+ def search(query, options = {})
56
+ defaults = {:view => "videos", :q => query}
57
+ params = defaults.merge options
58
+ do_search params
54
59
  end
55
-
56
- # Provides access to the Howcast wiki guide search API.
57
- #
58
- # See video_search documentation for inputs, outputs and exceptions
60
+
61
+ # Provides low-level access to the Howcast video search API.
59
62
  #
60
- # === Examples
63
+ # === Inputs
61
64
  #
62
- # Get the first page of howcast wiki guides matching 'poker'.
63
- # Howcast::Client.new.guide_search("poker")
64
- # Get the third page of howcast wiki guides matching 'traveling'
65
- # Howcast::Client.new.guide_search("traveling", :page => 3)
66
- def guide_search(query, options = {})
67
- uri = search_url(query, options.merge(:view => 'guide'))
68
- (establish_connection(uri)/:guide).inject([]){ |r, i| r << parse_single_xml(i, Guide) }
65
+ # * <tt>params</tt> -- A hash of params that will be URL encoded and appended
66
+ # to the URI. You'll have to know what you're doing.
67
+ #
68
+ # Other than its arguments, this method is identical to +search+.
69
+ def advanced_search params
70
+ do_search params
69
71
  end
70
-
71
- private
72
- def search_url(query, options={})
73
- defaults = {:page => nil, :view => nil, :mode => nil}
74
- options = defaults.update(options)
75
- query = CGI.escape(query)
76
- uri = "search.xml?q=#{query}"
77
- uri += "&view=#{options[:view]}" unless options[:view].nil?
78
- uri += "&mode=extended" if (options[:mode] == :extended)
79
- uri + uri_suffix(options.merge(:use_ampersand => true))
72
+
73
+ private
74
+ def do_search params
75
+ uri = search_url params
76
+ (establish_connection(uri)/:video).inject([]){ |r, i| r << parse_single_xml(i, Video)}
77
+ end
78
+
79
+ def search_url params
80
+ uri = "search.xml?"
81
+ params[:q] = CGI.escape params[:q] if params[:q]
82
+ uri += hash_to_params params
83
+ uri += uri_suffix(params.merge(:use_ampersand => true)) unless params[:page]
84
+ uri
80
85
  end
81
86
  end
@@ -90,9 +90,9 @@ class Howcast::Client
90
90
  # === Inputs
91
91
  #
92
92
  # The options are:
93
- # * <tt>:page</tt> -- The page number to retrieve (defaults to 1). There are 16 videos per page.
94
- # * <tt>:sort</tt> -- One of +most_recent+ (default) | +most_viewed+ | +top_rated+ | +most_emailed+ | +most_discussed+ | +top_favorites+
95
- # * <tt>:filter</tt> -- One of +all+ | +featured+ | +howcast_studios+ (default) | +directors_program+ | +community+
93
+ # * <tt>:page</tt> -- The page number to retrieve (defaults to 1). There are 20 videos per page.
94
+ # * <tt>:sort</tt> -- One of +most_recent+ (default) | +most_viewed+ | +top_rated+
95
+ # * <tt>:filter</tt> -- One of +all+ | +howcast_studios+ (default)
96
96
  #
97
97
  # === Outputs
98
98
  # An array of video objects
@@ -105,7 +105,7 @@ class Howcast::Client
105
105
  # Get the first page of most recent howcast studios videos.
106
106
  # Howcast::Client.new.videos
107
107
  # Get the third page of top favorites which are featured
108
- # Howcast::Client.new.videos(:page => 3, :sort => "top_favorites", :filter => "featured")
108
+ # Howcast::Client.new.videos(:page => 3, :sort => "top_favorites", :filter => "top_rated")
109
109
  def videos(options = {})
110
110
  uri = videos_url(options)
111
111
  (establish_connection(uri)/:video).inject([]){ |r, i| r << parse_single_xml(i, Video)}