binged 0.3.0 → 1.0.0

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/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem "hashie"
4
+ gem 'activesupport', '>= 3.0.0'
5
+
6
+ group :development do
7
+ gem "rspec", ">= 1.3.0"
8
+ gem "fakeweb", ">=1.2.8"
9
+ gem "yard", ">= 0"
10
+ end
data/HISTORY CHANGED
@@ -1,9 +1,13 @@
1
+ == 1.0.0 (unreleased)
2
+ * Migrate to Bing Search API 2.0. See https://datamarket.azure.com/dataset/bing/search and http://go.microsoft.com/fwlink/?LinkID=248077 for more details.
3
+ * Raise a Bing::Search::Error in at least some of the failure modes.
4
+
1
5
  == 0.3.0 2010-03-15
2
6
 
3
7
  === New features
4
8
  * Added an Video source provider to allow for Video searching with Binged
5
9
 
6
10
  == 0.2.0 2010-03-12
7
-
11
+
8
12
  === New features
9
13
  * Added an Image source provider to allow for Image searching with Binged
data/README.md CHANGED
@@ -15,19 +15,19 @@ To use binged, you will require a Bing API key. Create one at: [http://www.bing.
15
15
  ## Usage
16
16
 
17
17
  ### Instantiate a client
18
- binged = Binged::Client.new(:api_key => 'binged')
19
-
18
+ binged = Binged::Client.new(:account_key => 'binged')
19
+
20
20
  ### Ruby on Rails
21
-
21
+
22
22
  Binged allows for configuration to be done once using a configure block. To use binged in your Ruby on Rails project, configure it globally in an initializer.
23
-
23
+
24
24
  # config/initializers/binged.rb
25
25
  Binged.configure do |config|
26
- config.api_key = 'api_key'
26
+ config.account_key = 'account_key'
27
27
  end
28
-
28
+
29
29
  # Client initialization
30
- binged = Binged::Client.new
30
+ binged = Binged::Client.new
31
31
 
32
32
  ### Web Search Example
33
33
 
@@ -39,10 +39,10 @@ Binged allows for configuration to be done once using a configure block. To use
39
39
 
40
40
  # Find all portrait Matz images with a wide aspect ratio
41
41
  image_search = Binged::Client.new.image
42
- image_search.containing('Yukihiro Matsumoto').portrait.wide.each {|image| pp image}
43
-
42
+ image_search.containing('Yukihiro Matsumoto').portrait.safe_search(:strict).wide.each {|image| pp image}
43
+
44
44
  ## Note on Patches/Pull Requests
45
-
45
+
46
46
  * Fork the project.
47
47
  * Make your feature addition or bug fix.
48
48
  * Add tests for it. This is important so I don't break it in a
data/Rakefile CHANGED
@@ -10,11 +10,6 @@ begin
10
10
  gem.email = "kevin.faustino@gmail.com"
11
11
  gem.homepage = "http://github.com/kfaustino/binged"
12
12
  gem.authors = ["Kevin Faustino"]
13
- gem.add_dependency "hashie", "~>0.1.0"
14
- gem.add_dependency "crack", ">=0.1.6"
15
- gem.add_development_dependency "rspec", ">= 1.3.0"
16
- gem.add_development_dependency "fakeweb", ">=1.2.8"
17
- gem.add_development_dependency "yard", ">= 0"
18
13
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
14
  end
20
15
  Jeweler::GemcutterTasks.new
@@ -22,20 +17,16 @@ rescue LoadError
22
17
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
18
  end
24
19
 
25
- require 'spec/rake/spectask'
26
- Spec::Rake::SpecTask.new(:spec) do |spec|
27
- spec.libs << 'lib' << 'spec'
28
- spec.spec_files = FileList['spec/**/*_spec.rb']
20
+ require 'rspec/core/rake_task'
21
+ RSpec::Core::RakeTask.new do |t|
22
+ t.pattern = 'spec/**/*_spec.rb'
29
23
  end
30
24
 
31
- Spec::Rake::SpecTask.new(:rcov) do |spec|
32
- spec.libs << 'lib' << 'spec'
33
- spec.pattern = 'spec/**/*_spec.rb'
34
- spec.rcov = true
25
+ RSpec::Core::RakeTask.new(:rcov) do |t|
26
+ t.pattern = 'spec/**/*_spec.rb'
27
+ t.rcov = true
35
28
  end
36
29
 
37
- task :spec => :check_dependencies
38
-
39
30
  task :default => :spec
40
31
 
41
32
  begin
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 1.0.0
data/binged.gemspec CHANGED
@@ -1,85 +1,76 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{binged}
8
- s.version = "0.3.0"
7
+ s.name = "binged"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kevin Faustino"]
12
- s.date = %q{2010-03-15}
13
- s.description = %q{A wrapper for the bing api}
14
- s.email = %q{kevin.faustino@gmail.com}
12
+ s.date = "2012-11-06"
13
+ s.description = "A wrapper for the bing api"
14
+ s.email = "kevin.faustino@gmail.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.md"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
- ".gitignore",
22
- "HISTORY",
23
- "LICENSE",
24
- "README.md",
25
- "Rakefile",
26
- "VERSION",
27
- "binged.gemspec",
28
- "lib/binged.rb",
29
- "lib/binged/client.rb",
30
- "lib/binged/hashie_extensions.rb",
31
- "lib/binged/search.rb",
32
- "lib/binged/search/base.rb",
33
- "lib/binged/search/image.rb",
34
- "lib/binged/search/video.rb",
35
- "lib/binged/search/web.rb",
36
- "spec/binged/search/image_spec.rb",
37
- "spec/binged/search/video_spec.rb",
38
- "spec/binged/search/web_spec.rb",
39
- "spec/binged_spec.rb",
40
- "spec/fixtures/images.json",
41
- "spec/fixtures/videos.json",
42
- "spec/fixtures/web.json",
43
- "spec/spec.opts",
44
- "spec/spec_helper.rb",
45
- "spec/support/shared_examples/filter.rb",
46
- "spec/support/shared_examples/pageable.rb"
47
- ]
48
- s.homepage = %q{http://github.com/kfaustino/binged}
49
- s.rdoc_options = ["--charset=UTF-8"]
50
- s.require_paths = ["lib"]
51
- s.rubygems_version = %q{1.3.6}
52
- s.summary = %q{A wrapper for the bing api}
53
- s.test_files = [
21
+ "Gemfile",
22
+ "HISTORY",
23
+ "LICENSE",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "binged.gemspec",
28
+ "lib/binged.rb",
29
+ "lib/binged/client.rb",
30
+ "lib/binged/hashie_extensions.rb",
31
+ "lib/binged/search.rb",
32
+ "lib/binged/search/base.rb",
33
+ "lib/binged/search/image.rb",
34
+ "lib/binged/search/video.rb",
35
+ "lib/binged/search/web.rb",
36
+ "spec/binged/search/client_spec.rb",
54
37
  "spec/binged/search/image_spec.rb",
55
- "spec/binged/search/video_spec.rb",
56
- "spec/binged/search/web_spec.rb",
57
- "spec/binged_spec.rb",
58
- "spec/spec_helper.rb",
59
- "spec/support/shared_examples/filter.rb",
60
- "spec/support/shared_examples/pageable.rb"
38
+ "spec/binged/search/video_spec.rb",
39
+ "spec/binged/search/web_spec.rb",
40
+ "spec/binged_spec.rb",
41
+ "spec/fixtures/bad_request.curl",
42
+ "spec/fixtures/images.curl",
43
+ "spec/fixtures/videos.curl",
44
+ "spec/fixtures/web.curl",
45
+ "spec/spec.opts",
46
+ "spec/spec_helper.rb",
47
+ "spec/support/shared_examples/filter.rb",
48
+ "spec/support/shared_examples/pageable.rb"
61
49
  ]
50
+ s.homepage = "http://github.com/kfaustino/binged"
51
+ s.require_paths = ["lib"]
52
+ s.rubygems_version = "1.8.23"
53
+ s.summary = "A wrapper for the bing api"
62
54
 
63
55
  if s.respond_to? :specification_version then
64
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
56
  s.specification_version = 3
66
57
 
67
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
68
- s.add_runtime_dependency(%q<hashie>, ["~> 0.1.0"])
69
- s.add_runtime_dependency(%q<crack>, [">= 0.1.6"])
58
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
59
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
60
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0"])
70
61
  s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
71
62
  s.add_development_dependency(%q<fakeweb>, [">= 1.2.8"])
72
63
  s.add_development_dependency(%q<yard>, [">= 0"])
73
64
  else
74
- s.add_dependency(%q<hashie>, ["~> 0.1.0"])
75
- s.add_dependency(%q<crack>, [">= 0.1.6"])
65
+ s.add_dependency(%q<hashie>, [">= 0"])
66
+ s.add_dependency(%q<activesupport>, [">= 3.0.0"])
76
67
  s.add_dependency(%q<rspec>, [">= 1.3.0"])
77
68
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
78
69
  s.add_dependency(%q<yard>, [">= 0"])
79
70
  end
80
71
  else
81
- s.add_dependency(%q<hashie>, ["~> 0.1.0"])
82
- s.add_dependency(%q<crack>, [">= 0.1.6"])
72
+ s.add_dependency(%q<hashie>, [">= 0"])
73
+ s.add_dependency(%q<activesupport>, [">= 3.0.0"])
83
74
  s.add_dependency(%q<rspec>, [">= 1.3.0"])
84
75
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
85
76
  s.add_dependency(%q<yard>, [">= 0"])
data/lib/binged/client.rb CHANGED
@@ -3,30 +3,32 @@ module Binged
3
3
  # A client which encapsulates the Bing API
4
4
  class Client
5
5
 
6
- attr_accessor :api_key
6
+ attr_accessor :account_key
7
7
 
8
8
  # @param [Hash] options the options to create a client with.
9
- # @option options [String] :api_key The Bing API key used to make all API calls.
9
+ # @option options [String] :account_key The Bing API key used to make all API calls.
10
10
  def initialize(options = {})
11
- @api_key = options[:api_key] || Binged.api_key
11
+ invalid_options = options.keys - [:account_key]
12
+ raise ArgumentError, "Invalid options: #{invalid_options.inspect}." unless invalid_options.empty?
13
+ @account_key = options[:account_key] || Binged.account_key
12
14
  end
13
15
 
14
16
  # Create a web search through Bing
15
- #
17
+ #
16
18
  # @param [String] query The search term to be sent to Bing
17
19
  def web(query='')
18
20
  Search::Web.new(self,query)
19
21
  end
20
-
22
+
21
23
  # Create a image search through Bing
22
- #
24
+ #
23
25
  # @param [String] query The search term to be sent to Bing
24
26
  def image(query='')
25
27
  Search::Image.new(self,query)
26
28
  end
27
-
29
+
28
30
  # Create a video search through Bing
29
- #
31
+ #
30
32
  # @param [String] query The search term to be sent to Bing
31
33
  def video(query='')
32
34
  Search::Video.new(self,query)
@@ -1,12 +1,16 @@
1
1
  module Binged
2
2
  module Search
3
+ class Error < StandardError
4
+ end
3
5
 
4
6
  # @abstract Subclass and set @source to implement a custom Searchable class
5
7
  class Base
6
8
  include Enumerable
7
9
  attr_reader :client, :query, :source
8
10
 
9
- BASE_URI = 'http://api.bing.net/json.aspx?'
11
+ BASE_URI = 'https://api.datamarket.azure.com/Data.ashx/Bing/Search/'
12
+
13
+ SUPPORTED_ADULT_OPTIONS = [:off, :moderate, :strict]
10
14
 
11
15
  # @param [Binged::Client] client
12
16
  # @param [String] query The search term to be sent to Bing
@@ -26,6 +30,12 @@ module Binged
26
30
  self
27
31
  end
28
32
 
33
+ def adult(adult_option)
34
+ @query[:Adult] = adult_option if SUPPORTED_ADULT_OPTIONS.include?(adult_option)
35
+ self
36
+ end
37
+ alias safe_search adult
38
+
29
39
  # Clears all filters to perform a new search
30
40
  def clear
31
41
  @fetch = nil
@@ -39,7 +49,7 @@ module Binged
39
49
  def fetch
40
50
  if @fetch.nil?
41
51
  response = perform
42
- @fetch = Hashie::Mash.new(response["SearchResponse"][self.source.to_s.capitalize])
52
+ @fetch = Hashie::Mash.new(response["d"])
43
53
  end
44
54
 
45
55
  @fetch
@@ -49,16 +59,26 @@ module Binged
49
59
  #
50
60
  # @return [Hash] Hash of Bing API response
51
61
  def perform
52
- url = URI.parse BASE_URI
62
+ url = URI.parse [BASE_URI, self.source.to_s.capitalize].join
53
63
  query = @query.dup
54
64
  query[:Query] = query[:Query].join(' ')
55
- query[:Sources] = self.source
56
65
  callbacks.each {|callback| callback.call(query) }
57
- query_options = default_options.merge(query).to_params
66
+ query.each do |key, value|
67
+ query[key] = %{'#{value}'} unless key[0] == '$' || ['Latitude', 'Longitude'].include?(key)
68
+ end
69
+ query_options = default_options.merge(query).to_query
58
70
  query_options.gsub! '%2B', '+'
59
71
  url.query = query_options
60
- response = Net::HTTP.get(url)
61
- Crack::JSON.parse(response)
72
+ request = Net::HTTP::Get.new(url.request_uri)
73
+ request.basic_auth(@client.account_key, @client.account_key)
74
+ response = Net::HTTP.start(url.hostname, url.port, :use_ssl => true) {|http|
75
+ http.request(request)
76
+ }
77
+ begin
78
+ JSON.parse(response.body)
79
+ rescue JSON::ParserError => e
80
+ raise Error, response.body.strip
81
+ end
62
82
  end
63
83
 
64
84
  # @yieldreturn [Hash] A result from a Bing query
@@ -73,13 +93,13 @@ module Binged
73
93
  private
74
94
 
75
95
  def default_options
76
- {:AppId => @client.api_key, :JsonType => 'raw', :Version => '2.2' }
96
+ { '$format' => 'JSON' }
77
97
  end
78
98
 
79
99
  def reset_query
80
100
  @query = { :Query => [] }
81
101
  end
82
-
102
+
83
103
  end
84
104
 
85
105
  end
@@ -17,7 +17,7 @@ module Binged
17
17
  end
18
18
 
19
19
  # Restrict images to those small in size
20
- #
20
+ #
21
21
  # @return [self]
22
22
  def small
23
23
  filter << 'Size:Small'
@@ -25,7 +25,7 @@ module Binged
25
25
  end
26
26
 
27
27
  # Restrict images to those medium in size
28
- #
28
+ #
29
29
  # @return [self]
30
30
  def medium
31
31
  filter << 'Size:Medium'
@@ -58,7 +58,7 @@ module Binged
58
58
  end
59
59
 
60
60
  # Restrict images to those that have a square aspect ratio
61
- #
61
+ #
62
62
  # @return [self]
63
63
  def square
64
64
  filter << 'Aspect:Square'
@@ -66,7 +66,7 @@ module Binged
66
66
  end
67
67
 
68
68
  # Restrict images to those that have a wide aspect ratio
69
- #
69
+ #
70
70
  # @return [self]
71
71
  def wide
72
72
  filter << 'Aspect:Wide'
@@ -74,55 +74,55 @@ module Binged
74
74
  end
75
75
 
76
76
  # Restrict images to those that have a tall aspect ratio
77
- #
77
+ #
78
78
  # @return [self]
79
79
  def tall
80
80
  filter << 'Aspect:Tall'
81
81
  self
82
82
  end
83
-
83
+
84
84
  # Restrict images to those that are in color
85
- #
85
+ #
86
86
  # @return [self]
87
87
  def color
88
88
  filter << 'Color:Color'
89
- self
89
+ self
90
+ end
91
+
92
+ # Restrict images to those that are in black and white
93
+ #
94
+ # @return [self]
95
+ def monochrome
96
+ filter << 'Color:Monochrome'
97
+ self
90
98
  end
91
-
99
+
92
100
  # Restrict images to those which contain photos
93
- #
101
+ #
94
102
  # @return [self]
95
103
  def photo
96
104
  filter << 'Style:Photo'
97
105
  self
98
106
  end
99
-
107
+
100
108
  # Restrict images to those which contain graphics or illustrations
101
- #
109
+ #
102
110
  # @return [self]
103
111
  def graphics
104
112
  filter << 'Style:Graphics'
105
113
  self
106
114
  end
107
-
108
- # Restrict images to those that are in black and white
109
- #
110
- # @return [self]
111
- def monochrome
112
- filter << 'Color:Monochrome'
113
- self
114
- end
115
-
115
+
116
116
  # Restrict images to those which contain faces
117
- #
117
+ #
118
118
  # @return [self]
119
119
  def face
120
120
  filter << 'Face:Face'
121
121
  self
122
122
  end
123
-
123
+
124
124
  # Restrict images to those which contain portraits(head and shoulders)
125
- #
125
+ #
126
126
  # @return [self]
127
127
  def portrait
128
128
  filter << 'Face:Portrait'
@@ -132,11 +132,11 @@ module Binged
132
132
  private
133
133
 
134
134
  def create_filter_callback
135
- @callbacks << Proc.new { |query| query['Image.Filters'] = query['Image.Filters'].join('+') if query['Image.Filters'] }
135
+ @callbacks << Proc.new { |query| query['ImageFilters'] = query['ImageFilters'].join('+') if query['ImageFilters'] && !query['ImageFilters'].empty? }
136
136
  end
137
137
 
138
138
  def filter
139
- @query['Image.Filters'] ||= []
139
+ @query['ImageFilters'] ||= []
140
140
  end
141
141
 
142
142
  end
data/lib/binged/search.rb CHANGED
@@ -8,14 +8,14 @@ module Binged
8
8
  autoload :Video, "binged/search/video"
9
9
 
10
10
  module Pageable
11
-
11
+
12
12
  # Set the page number of the results to display
13
13
  #
14
14
  # @param [Fixnum] num The page number of the search results
15
15
  # @return [self]
16
16
  def page(num=1)
17
17
  @offset = num - 1
18
- @query["#{@source.to_s.capitalize}.Offset"] = @results_per_page * @offset
18
+ @query["$skip"] = @results_per_page * @offset
19
19
  self
20
20
  end
21
21
 
@@ -25,20 +25,20 @@ module Binged
25
25
  # @return [self]
26
26
  def per_page(num)
27
27
  @results_per_page = num
28
- @query["#{@source.to_s.capitalize}.Count"] = @results_per_page
28
+ @query["$top"] = @results_per_page
29
29
  self
30
30
  end
31
-
31
+
32
32
  protected
33
-
33
+
34
34
  def set_paging_defaults
35
35
  self.per_page(20).page(1)
36
36
  end
37
-
37
+
38
38
  end
39
-
39
+
40
40
  module Filter
41
-
41
+
42
42
  # # Isolate search results to a specific site
43
43
  #
44
44
  # @example
@@ -50,8 +50,8 @@ module Binged
50
50
  @query[:Query] << "site:#{site}"
51
51
  self
52
52
  end
53
-
53
+
54
54
  end
55
-
55
+
56
56
  end
57
57
  end
data/lib/binged.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'crack'
1
+ require 'active_support/core_ext/object/to_query'
2
+ require 'json'
2
3
  require 'hashie'
3
- require 'net/http'
4
+ require 'net/https'
4
5
  require 'uri'
5
6
 
6
- Hash.send :include, Hashie::HashExtensions
7
7
  require 'binged/hashie_extensions'
8
8
 
9
9
  # The module that contains everything Binged related
@@ -13,23 +13,21 @@ require 'binged/hashie_extensions'
13
13
  module Binged
14
14
  autoload :Client, "binged/client"
15
15
  autoload :Search, "binged/search"
16
-
16
+
17
+ extend self
18
+
17
19
  # Configure global options for Binged
18
- #
20
+ #
19
21
  # For example:
20
- #
22
+ #
21
23
  # Binged.configure do |config|
22
- # config.api_key = 'api_key'
24
+ # config.account_key = 'account_key'
23
25
  # end
24
- def self.configure
26
+ attr_accessor :account_key
27
+
28
+ def configure
25
29
  yield self
26
30
  true
27
31
  end
28
32
 
29
- class << self
30
- attr_accessor :api_key
31
- end
32
-
33
33
  end
34
-
35
-
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binged::Client do
4
+ describe '.new' do
5
+ context 'with a defunct api_key' do
6
+ it 'raises' do
7
+ expect {
8
+ Binged::Client.new(:api_key => 'binged')
9
+ }.to raise_error(ArgumentError)
10
+ end
11
+ end
12
+ end
13
+ end