mikedemers-rbing 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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.0"
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| "#{s}".strip }.join(" OR ")
136
+ queries << " (#{kw}:#{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,48 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'rbing'
3
+
4
+ describe "RBing" do
5
+ before :each do
6
+ @bing = RBing.new
7
+ end
8
+
9
+ it "should provide an ad search method" do
10
+ @bing.should respond_to(:ad)
11
+ end
12
+
13
+ it "should provide an image search method" do
14
+ @bing.should respond_to(:image)
15
+ end
16
+
17
+ it "should provide an instant_answer search method" do
18
+ @bing.should respond_to(:instant_answer)
19
+ end
20
+
21
+ it "should provide a news search method" do
22
+ @bing.should respond_to(:news)
23
+ end
24
+
25
+ it "should provide a phonebook search method" do
26
+ @bing.should respond_to(:phonebook)
27
+ end
28
+
29
+ it "should provide a related_search method" do
30
+ @bing.should respond_to(:related_search)
31
+ end
32
+
33
+ it "should provide an spell method" do
34
+ @bing.should respond_to(:spell)
35
+ end
36
+
37
+ it "should provide a web search method" do
38
+ @bing.should respond_to(:web)
39
+ end
40
+
41
+ it "should return a ResponseData object" do
42
+ @bing.web("ruby").should be_a(RBing::ResponseData)
43
+ end
44
+
45
+ it "should return search results" do
46
+ @bing.web("ruby").web.results.should_not be_empty
47
+ end
48
+ end
@@ -0,0 +1,2 @@
1
+ $TESTING=true
2
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mikedemers-rbing
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mike Demers
8
+ autorequire: rbing
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-08 00:00:00 -07:00
13
+ default_executable: rbing
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: false
45
+ homepage: http://9astronauts.com/code/ruby/rbing
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --main
49
+ - README.rdoc
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.2.0
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A gem that provides an interface to Microsoft's Bing search API
71
+ test_files: []
72
+