rbing 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Mike Demers <mike_(at)_9astronauts.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,92 @@
1
+
2
+ == RBing
3
+
4
+ A gem that provides an interface to Microsoft's Bing search API.
5
+
6
+
7
+ == Usage
8
+
9
+ Get a App ID at: <http://www.bing.com/developers/createapp.aspx>
10
+
11
+ require 'rubygems'
12
+ require 'rbing'
13
+ bing = RBing.new("YOURAPPID")
14
+
15
+ rsp = bing.web("ruby")
16
+ puts rsp.web.results[0].title
17
+ => "Ruby (programming language) - Wikipedia, the free encyclopedia"
18
+
19
+ rsp = bing.web("ruby", :site => "github.com")
20
+ puts rsp.web.results[0].url
21
+ => "http://github.com/vim-ruby/vim-ruby/tree/master"
22
+
23
+ rsp = bing.web("ruby", :site => ["github.com", "rubyforge.org"])
24
+ puts rsp.web.results[0].url
25
+ => "http://rubyforge.org/"
26
+
27
+ rsp = bing.news("search engines")
28
+ puts rsp.web.results[0].title
29
+ => "Microsoft Bing more popular than Yahoo"
30
+
31
+ rsp = bing.spell("coincidance")
32
+ puts rsp.spell.results[0].value
33
+ => "coincidence"
34
+
35
+ rsp = bing.instant_answer("How many rods in a furlong?")
36
+ puts rsp.instant_answer.results[0].instant_answer_specific_data.encarta.value
37
+ => "1 furlong = 40 rods"
38
+
39
+
40
+ == Command Line Utility
41
+
42
+ RBing also has a simple command line interface.
43
+
44
+ Put your App Id into $HOME/.rbing_app_id and you can use rbing:
45
+
46
+ $> rbing "ruby gems"
47
+ [{"Url"=>"http://rubygems.org/",
48
+ "Title"=>"RubyGems Manuals",
49
+ "CacheUrl"=>
50
+ "http://cc.bingj.com/cache.aspx?q=ruby+gems&d=76167709461212&w=39b024d8,55a87382",
51
+ "DisplayUrl"=>"rubygems.org",
52
+ "DateTime"=>Wed Jun 03 11:25:29 UTC 2009,
53
+ "Description"=>
54
+ "The Gem::Specification object controls the data..."},
55
+ ...
56
+ ]
57
+
58
+ The default source is "web" but you can specify another:
59
+
60
+ $> rbing news "revolutionary technology"
61
+ [{"BreakingNews"=>0,
62
+ "Url"=>
63
+ "http://www.tmcnet.com/usubmit/-bt-successfully-completes-exchange-exchange-cisco-telepresence-call-/2009/06/04/4211245.htm",
64
+ "Source"=>"TMCnet",
65
+ "Title"=>
66
+ "BT Successfully Completes Exchange to Exchange Cisco TelePresence Call ... ",
67
+ "Snippet"=>
68
+ "BT Successfully Completes Exchange to Exchange Cisco TelePresence Call; Revolutionary...",
69
+ "Date"=>Thu Jun 04 13:33:09 UTC 2009},
70
+ ...
71
+ ]
72
+
73
+
74
+ == Dependencies
75
+
76
+ - HTTParty: http://httparty.rubyforge.org/
77
+
78
+
79
+ == Resources
80
+
81
+ RBing:
82
+
83
+ - Source Code: http://github.com/mikedemers/rbing/tree
84
+ - Support: http://github.com/mikedemers/rbing/issues
85
+
86
+ Bing:
87
+
88
+ - Bing API: http://www.bing.com/developers
89
+ - Register for App Id: http://www.bing.com/developers/createapp.aspx
90
+ - Bing API Reference: http://msdn.microsoft.com/en-us/library/dd251056.aspx
91
+ - Query Keywords: http://help.live.com/help.aspx?project=wl_searchv1&market=en-US&querytype=keyword&query=redliub&tmt=&domain=www.bing.com:80
92
+
data/Rakefile ADDED
@@ -0,0 +1,59 @@
1
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'spec/rake/spectask'
6
+
7
+ GEM = "rbing"
8
+ GEM_VERSION = "1.0.1"
9
+ AUTHOR = "Mike Demers"
10
+ EMAIL = "mike@9astronauts.com"
11
+ HOMEPAGE = "http://9astronauts.com/code/ruby/rbing"
12
+ SUMMARY = "A gem that provides an interface to Microsoft's Bing search API"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = GEM
16
+ s.version = GEM_VERSION
17
+ s.platform = Gem::Platform::RUBY
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE", 'TODO']
20
+ s.summary = SUMMARY
21
+ s.description = s.summary
22
+ s.author = AUTHOR
23
+ s.email = EMAIL
24
+ s.homepage = HOMEPAGE
25
+ s.rdoc_options = ["--main", "README.rdoc"]
26
+
27
+ s.add_dependency("httparty", [">= 0.4.0"])
28
+
29
+ s.require_path = 'lib'
30
+ s.autorequire = GEM
31
+ s.files = %w(LICENSE README.rdoc Rakefile TODO) + Dir.glob("{bin,lib,spec}/**/*")
32
+
33
+ s.executables = ["rbing"]
34
+ end
35
+
36
+ task :default => :spec
37
+
38
+ desc "Run specs"
39
+ Spec::Rake::SpecTask.new do |t|
40
+ t.spec_files = FileList['spec/**/*_spec.rb']
41
+ t.spec_opts = %w(-fs --color)
42
+ end
43
+
44
+
45
+ Rake::GemPackageTask.new(spec) do |pkg|
46
+ pkg.gem_spec = spec
47
+ end
48
+
49
+ desc "install the gem locally"
50
+ task :install => [:package] do
51
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
52
+ end
53
+
54
+ desc "create a gemspec file"
55
+ task :make_spec do
56
+ File.open("#{GEM}.gemspec", "w") do |file|
57
+ file.puts spec.to_ruby
58
+ end
59
+ end
data/TODO ADDED
File without changes
data/bin/rbing ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pp'
4
+ require 'rubygems'
5
+ require 'rbing'
6
+
7
+ bing = RBing.new
8
+
9
+ if query = ARGV[1]
10
+ source = ARGV[0]
11
+ elsif query = ARGV[0]
12
+ source = "web"
13
+ else
14
+ STDERR.puts "Usage: #{$0} [source] query"
15
+ STDERR.puts ""
16
+ STDERR.puts "Also, don't forget to put your App Id in $HOME/.rbing_app_id"
17
+ STDERR.puts ""
18
+ STDERR.puts "If you don't have an App Id, get one here: http://www.bing.com/developers"
19
+ STDERR.puts ""
20
+ exit
21
+ end
22
+
23
+ rsp = bing.search(source, query)
24
+
25
+ begin
26
+ pp rsp.send(source).results
27
+ rescue
28
+ pp rsp
29
+ end
data/lib/rbing.rb ADDED
@@ -0,0 +1,192 @@
1
+ require "httparty"
2
+ require "yaml"
3
+ #
4
+ # Usage:
5
+ #
6
+ # bing = RBing.new("YOURAPPID")
7
+ #
8
+ # rsp = bing.web("ruby")
9
+ # puts rsp.web.results[0].title
10
+ # => "Ruby (programming language) - Wikipedia, the free encyclopedia"
11
+ #
12
+ # rsp = bing.web("ruby", :site => "github.com")
13
+ # puts rsp.web.results[0].url
14
+ # => "http://github.com/vim-ruby/vim-ruby/tree/master"
15
+ #
16
+ # rsp = bing.web("ruby", :site => ["github.com", "rubyforge.org"])
17
+ # puts rsp.web.results[0].url
18
+ # => "http://rubyforge.org/"
19
+ #
20
+ # rsp = bing.news("search engines")
21
+ # puts rsp.web.results[0].title
22
+ # => "Microsoft Bing more popular than Yahoo"
23
+ #
24
+ # rsp = bing.spell("coincidance")
25
+ # puts rsp.spell.results[0].value
26
+ # => "coincidence"
27
+ #
28
+ # rsp = bing.instant_answer("How many rods in a furlong?")
29
+ # puts rsp.instant_answer.results[0].instant_answer_specific_data.encarta.value
30
+ # => "1 furlong = 40 rods"
31
+ #
32
+ class RBing
33
+
34
+ # Convenience wrapper for the response Hash.
35
+ # Converts keys to Strings. Crawls through all
36
+ # member data and converts any other Hashes it
37
+ # finds. Provides access to values through
38
+ # method calls, which will convert underscored
39
+ # to camel case.
40
+ #
41
+ # Usage:
42
+ #
43
+ # rd = ResponseData.new("AlphaBeta" => 1, "Results" => {"Gamma" => 2, "delta" => [3, 4]})
44
+ # puts rd.alpha_beta
45
+ # => 1
46
+ # puts rd.alpha_beta.results.gamma
47
+ # => 2
48
+ # puts rd.alpha_beta.results.delta
49
+ # => [3, 4]
50
+ #
51
+ class ResponseData < Hash
52
+ private
53
+ def initialize(data={})
54
+ data.each_pair {|k,v| self[k.to_s] = deep_parse(v) }
55
+ end
56
+ def deep_parse(data)
57
+ case data
58
+ when Hash
59
+ self.class.new(data)
60
+ when Array
61
+ data.map {|v| deep_parse(v) }
62
+ else
63
+ data
64
+ end
65
+ end
66
+ def method_missing(*args)
67
+ name = args[0].to_s
68
+ return self[name] if has_key? name
69
+ camelname = name.split('_').map {|w| "#{w[0,1].upcase}#{w[1..-1]}" }.join("")
70
+ if has_key? camelname
71
+ self[camelname]
72
+ else
73
+ super *args
74
+ end
75
+ end
76
+ end
77
+
78
+ include HTTParty
79
+
80
+ attr_accessor :instance_options
81
+
82
+ base_uri "http://api.search.live.net/json.aspx"
83
+ format :json
84
+
85
+ BASE_OPTIONS = [:version, :market, :adult, :query, :appid, :sources]
86
+
87
+ # Query Keywords: <http://help.live.com/help.aspx?project=wl_searchv1&market=en-US&querytype=keyword&query=redliub&tmt=&domain=www.bing.com:80>
88
+ #
89
+ QUERY_KEYWORDS = [:site, :language, :contains, :filetype, :inanchor, :inbody, :intitle, :ip, :loc, :location, :prefer, :feed, :hasfeed, :url]
90
+
91
+ # Source Types: <http://msdn.microsoft.com/en-us/library/dd250847.aspx>
92
+ #
93
+ SOURCES = %w(Ad Image InstantAnswer News Phonebook RelatedSearch Spell Web)
94
+
95
+ # Set up methods for each search source:
96
+ # +ad+, +image+, +instant_answer+, +news+, +phonebook+, +related_search+,
97
+ # +spell+ and +web+
98
+ #
99
+ # Example:
100
+ #
101
+ # bing = RBing.new(YOUR_APP_ID)
102
+ # bing.web("ruby gems", :count => 10)
103
+ #
104
+ SOURCES.each do |source|
105
+ fn = source.to_s.gsub(/[a-z][A-Z]/) {|c| "#{c[0,1]}_#{c[1,1]}" }.downcase
106
+ class_eval "def #{fn}(query, options={}) ; search('#{source}', query, options) ; end"
107
+ end
108
+
109
+
110
+ # issues a search for +query+ in +source+
111
+ #
112
+ def search(source, query, options={})
113
+ rsp = self.class.get('', options_for(source, query, options))
114
+ ResponseData.new(rsp['SearchResponse']) if rsp
115
+ end
116
+
117
+
118
+ private
119
+
120
+
121
+ # instantiates a new RBing client with the given +app_id+.
122
+ # +options+ can contain values to be passed with each query.
123
+ #
124
+ def initialize(app_id=nil, options={})
125
+ @instance_options = options.merge(:AppId => (app_id || user_app_id))
126
+ end
127
+ # constructs a query string for the given
128
+ # +query+ and the optional query +options+
129
+ #
130
+ def build_query(query, options={})
131
+ queries = []
132
+ QUERY_KEYWORDS.each do |kw|
133
+ next unless options[kw]
134
+ if options[kw].is_a? Array
135
+ kw_query = options[kw].map {|s| "#{kw}:#{s}".strip }.join(" OR ")
136
+ queries << " (#{kw_query})"
137
+ else
138
+ queries << " #{kw}:#{options[kw]}"
139
+ end
140
+ end
141
+ "#{query} #{queries.join(' ')}".strip
142
+ end
143
+
144
+
145
+ # returns +options+ with its keys converted to
146
+ # strings and any keys in +exclude+ omitted.
147
+ #
148
+ def filter_hash(options, exclude=[])
149
+ ex = exclude.inject({}) {|h,k| h[k.to_s] = true; h }
150
+ options.inject({}) {|h,kv| h[kv[0]] = kv[1] unless ex[kv[0].to_s]; h }
151
+ end
152
+
153
+
154
+ # returns an options Hash suitable for passing to
155
+ # HTTParty's +get+ method
156
+ #
157
+ def options_for(type, query, options={})
158
+ opts = instance_options.merge(filter_hash(options, BASE_OPTIONS))
159
+ opts.merge!(:sources => type.to_s, :query => build_query(query, options))
160
+
161
+ source_options = filter_hash(options, [:http] + BASE_OPTIONS + QUERY_KEYWORDS)
162
+ opts.merge!(scope_source_options(type, source_options))
163
+
164
+ http_options = options[:http] || {}
165
+ http_options.merge(:query => opts)
166
+ end
167
+
168
+
169
+ # returns a Hash containing the data in +options+
170
+ # with the keys prefixed with +type+ and '.'
171
+ #
172
+ def scope_source_options(type, options={})
173
+ options.inject({}) {|h,kv| h["#{type}.#{kv[0]}"] = kv[1]; h }
174
+ end
175
+
176
+
177
+ # returns the user's default app id, if one has been
178
+ # defined in ~/.rbing_app_id
179
+ #
180
+ def user_app_id(force=false)
181
+ @user_app_id = nil if force
182
+ @user_app_id ||= read_user_app_id
183
+ end
184
+
185
+
186
+ # reads the App Id stored in ~/.rbing_app_id
187
+ #
188
+ def read_user_app_id
189
+ fn = File.join(RUBY_PLATFORM =~ /mswin32/ ? ENV['USERPROFILE'] : ENV['HOME'], ".rbing_app_id")
190
+ File.read(fn).strip if File.exists?(fn)
191
+ end
192
+ end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "RBing" do
4
+ before :each do
5
+ @bing = RBing.new
6
+ end
7
+
8
+ it "should provide an ad search method" do
9
+ @bing.should respond_to(:ad)
10
+ end
11
+
12
+ it "should provide an image search method" do
13
+ @bing.should respond_to(:image)
14
+ end
15
+
16
+ it "should provide an instant_answer search method" do
17
+ @bing.should respond_to(:instant_answer)
18
+ end
19
+
20
+ it "should provide a news search method" do
21
+ @bing.should respond_to(:news)
22
+ end
23
+
24
+ it "should provide a phonebook search method" do
25
+ @bing.should respond_to(:phonebook)
26
+ end
27
+
28
+ it "should provide a related_search method" do
29
+ @bing.should respond_to(:related_search)
30
+ end
31
+
32
+ it "should provide an spell method" do
33
+ @bing.should respond_to(:spell)
34
+ end
35
+
36
+ it "should provide a web search method" do
37
+ @bing.should respond_to(:web)
38
+ end
39
+
40
+ it "should return a ResponseData object" do
41
+ @bing.web("ruby").should be_a(RBing::ResponseData)
42
+ end
43
+
44
+ it "should return search results" do
45
+ @bing.web("ruby").web.results.should_not be_empty
46
+ end
47
+ end
@@ -0,0 +1,6 @@
1
+ $TESTING=true
2
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'rubygems'
5
+ require 'rbing'
6
+ require 'spec'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbing
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mike Demers
8
+ autorequire: rbing
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-27 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.0
24
+ version:
25
+ description: A gem that provides an interface to Microsoft's Bing search API
26
+ email: mike@9astronauts.com
27
+ executables:
28
+ - rbing
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - LICENSE
34
+ - TODO
35
+ files:
36
+ - LICENSE
37
+ - README.rdoc
38
+ - Rakefile
39
+ - TODO
40
+ - bin/rbing
41
+ - lib/rbing.rb
42
+ - spec/rbing_spec.rb
43
+ - spec/spec_helper.rb
44
+ has_rdoc: true
45
+ homepage: http://9astronauts.com/code/ruby/rbing
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --main
51
+ - README.rdoc
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: A gem that provides an interface to Microsoft's Bing search API
73
+ test_files: []
74
+