gaiottino-amazon-awis 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/*.gem
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ 0.1.0 2009-10-16
2
+ ----------------
3
+ Initial Release
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009 Hasham Malik
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.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,54 @@
1
+ == amazon-awis
2
+
3
+ Ruby Amazon Alexa web service REST API using Hpricot with configurable
4
+ default options and method call options. Uses Response and
5
+ Element wrapper classes for easy access to REST XML output.
6
+
7
+ This version is based on http://github.com/hasham2/amazon-awis but I didn't
8
+ like how it was possible to globally alter options. The AWS_ACCESS_KEY_ID and AWS_SECRET_KEY
9
+ are still global since one will likely only want to initialize these once.
10
+
11
+ == INSTALLATION
12
+
13
+ $ gem install amazon-awis
14
+
15
+ == EXAMPLE
16
+
17
+ require 'rubygems'
18
+ require 'amazon/awis'
19
+
20
+ # set the default config; config will be camelized and converted to REST request parameters.
21
+ Amazon::Awis.configure do |config|
22
+ config[:aws_access_key_id] = AWS_ACCESS_KEY_ID
23
+ config[:aws_secret_key] = AWS_SECRET_KEY
24
+ end
25
+
26
+ # create an instance of Awis for a specific action and domain
27
+ awis = Amazon::Awis.new({ :action => :url_info, :domain => 'google.com' })
28
+
29
+ # call query with the Response Group you want
30
+ resp = awis.query(:rank)
31
+
32
+ # some common response object methods
33
+ res.is_success? # return true if request was successful
34
+
35
+ #dynamic methods
36
+ res.rank # return the rank of domain name that was passed
37
+ res.dataurl # returns the url which was queried
38
+
39
+ # Query another action/domain after updating the options
40
+ awis.options[:domain] = 'yahoo.com/'
41
+
42
+
43
+ Refer to Amazon AWIS documentation for more information on Amazon REST request parameters and XML output:
44
+ http://docs.amazonwebservices.com/AlexaWebInfoService/2005-07-11/
45
+
46
+ == SOURCE CODES
47
+
48
+ * http://github.com/gaiottino/amazon-awis
49
+
50
+ == LICENSE
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2010 Daniel Gaiottino (Based on the initial work by Hasham Malik)
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/packagetask'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gemspec|
10
+ gemspec.name = "gaiottino-amazon-awis"
11
+ gemspec.summary = "Ruby Amazon Alexa web information service REST API"
12
+ gemspec.description = "Ruby Amazon Alexa web information service REST API"
13
+ gemspec.email = "daniel.gaiottino@gmail.com"
14
+ gemspec.homepage = "http://github.com/gaiottino/amazon-awis"
15
+ gemspec.authors = ["Daniel Gaiottino"]
16
+ gemspec.add_dependency('hpricot', '>= 0.4')
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ desc "Run the unit tests in test"
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << "test"
26
+ t.pattern = 'test/**/*_test.rb'
27
+ t.verbose = true
28
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,53 @@
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{gaiottino-amazon-awis}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Daniel Gaiottino"]
12
+ s.date = %q{2010-04-29}
13
+ s.description = %q{Ruby Amazon Alexa web information service REST API}
14
+ s.email = %q{daniel.gaiottino@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "CHANGELOG",
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "gaiottino-amazon-awis.gemspec",
26
+ "lib/amazon/awis.rb",
27
+ "test/amazon/awis_test.rb",
28
+ "test/test_helper.rb"
29
+ ]
30
+ s.homepage = %q{http://github.com/gaiottino/amazon-awis}
31
+ s.rdoc_options = ["--charset=UTF-8"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.3.6}
34
+ s.summary = %q{Ruby Amazon Alexa web information service REST API}
35
+ s.test_files = [
36
+ "test/amazon/awis_test.rb",
37
+ "test/test_helper.rb"
38
+ ]
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ s.add_runtime_dependency(%q<hpricot>, [">= 0.4"])
46
+ else
47
+ s.add_dependency(%q<hpricot>, [">= 0.4"])
48
+ end
49
+ else
50
+ s.add_dependency(%q<hpricot>, [">= 0.4"])
51
+ end
52
+ end
53
+
@@ -0,0 +1,274 @@
1
+ #--
2
+ # Copyright (c) 2010 Daniel Gaiottino (Based on the initial work by Hasham Malik)
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require "cgi"
25
+ require "base64"
26
+ require "openssl"
27
+ require "digest/sha1"
28
+ require "uri"
29
+ require "net/https"
30
+ require "time"
31
+ require "hpricot"
32
+
33
+ module Amazon
34
+
35
+ class RequestError < StandardError; end
36
+
37
+ class Awis
38
+ @@config = {}
39
+
40
+ @@debug = false
41
+
42
+ def initialize(opts={})
43
+ @options = {
44
+ :action => "UrlInfo",
45
+ }
46
+ @options.merge!(opts)
47
+
48
+ raise 'Use Awis.configure before creating a new object to set :aws_access_key_id and :aws_secret_key' unless @@config[:aws_access_key_id] && @@config[:aws_secret_key]
49
+ raise 'Missing required option :domain' unless options[:domain]
50
+ end
51
+
52
+ def self.configure(&proc)
53
+ raise ArgumentError, "Block is required." unless block_given?
54
+ yield @@config
55
+ end
56
+
57
+ # Default service options
58
+ def options
59
+ @options
60
+ end
61
+
62
+ # Set default service options
63
+ def options=(opts)
64
+ @options = opts
65
+ end
66
+
67
+ # Get debug flag.
68
+ def self.debug
69
+ @@debug
70
+ end
71
+
72
+ # Set debug flag to true or false.
73
+ def self.debug=(dbg)
74
+ @@debug = dbg
75
+ end
76
+
77
+ def query(response_group)
78
+ raise 'Must specify Response Group e.g. :rank, rank, or Rank for Rank' unless response_group
79
+
80
+ url = prepare_url(options[:domain], response_group)
81
+
82
+ log "Request URL: #{url}"
83
+ res = Net::HTTP.get_response(url)
84
+ unless res.kind_of? Net::HTTPSuccess
85
+ raise Amazon::RequestError, "HTTP Response: #{res.code} #{res.message}"
86
+ end
87
+ log "Response text: #{res.body}"
88
+ Response.new(res.body)
89
+ end
90
+
91
+ # Response object returned after a REST call to Amazon service.
92
+ class Response
93
+ # XML input is in string format
94
+ def initialize(xml)
95
+ @doc = Hpricot(xml)
96
+ end
97
+
98
+ # Return Hpricot object.
99
+ def doc
100
+ @doc
101
+ end
102
+
103
+ # Return true if response has an error.
104
+ def has_error?
105
+ !(error.nil? || error.empty?)
106
+ end
107
+
108
+ # Return error message.
109
+ def error
110
+ Element.get(@doc, "error/message")
111
+ end
112
+
113
+ # Return error code
114
+ def error_code
115
+ Element.get(@doc, "error/code")
116
+ end
117
+
118
+ # Return error message.
119
+ def is_success?
120
+ (@doc/"aws:statuscode").innerHTML == "Success"
121
+ end
122
+
123
+ #returns inner html of any tag in awis response i.e resp.rank => 3
124
+ def method_missing(methodId)
125
+ txt = (@doc/"aws:#{methodId.id2name}").innerHTML
126
+ if txt.empty?
127
+ raise NoMethodError
128
+ else
129
+ txt
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ protected
136
+
137
+ def log(s)
138
+ return unless Awis.debug
139
+ if defined? RAILS_DEFAULT_LOGGER
140
+ RAILS_DEFAULT_LOGGER.error(s)
141
+ elsif defined? LOGGER
142
+ LOGGER.error(s)
143
+ else
144
+ puts s
145
+ end
146
+ end
147
+
148
+ private
149
+
150
+ def prepare_url(domain, response_group)
151
+ timestamp = ( Time::now ).utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
152
+ secret_key = @@config[:aws_secret_key]
153
+ action = options[:action]
154
+ signature = Base64.encode64( OpenSSL::HMAC.digest( OpenSSL::Digest::Digest.new( "sha1" ), secret_key, action + timestamp)).strip
155
+ url = URI.parse("http://awis.amazonaws.com/?" +
156
+ {
157
+ "Action" => action,
158
+ "AWSAccessKeyId" => @@config[:aws_access_key_id],
159
+ "Signature" => signature,
160
+ "Timestamp" => timestamp,
161
+ "ResponseGroup" => camelize(response_group.to_s),
162
+ "Url" => domain
163
+ }.to_a.collect{|item| item.first + "=" + CGI::escape(item.last) }.join("&")
164
+ )
165
+ return url
166
+ end
167
+
168
+ def camelize(lower_case_and_underscored_word)
169
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
170
+ end
171
+
172
+ end
173
+
174
+ # Internal wrapper class to provide convenient method to access Hpricot element value.
175
+ class Element
176
+ # Pass Hpricot::Elements object
177
+ def initialize(element)
178
+ @element = element
179
+ end
180
+
181
+ # Returns Hpricot::Elments object
182
+ def elem
183
+ @element
184
+ end
185
+
186
+ # Find Hpricot::Elements matching the given path. Example: element/"author".
187
+ def /(path)
188
+ elements = @element/path
189
+ return nil if elements.size == 0
190
+ elements
191
+ end
192
+
193
+ # Find Hpricot::Elements matching the given path, and convert to Amazon::Element.
194
+ # Returns an array Amazon::Elements if more than Hpricot::Elements size is greater than 1.
195
+ def search_and_convert(path)
196
+ elements = self./(path)
197
+ return unless elements
198
+
199
+ elements = elements.map{|element| Element.new(element)}
200
+ return elements.first if elements.size == 1
201
+
202
+ elements
203
+ end
204
+
205
+ # Get the text value of the given path, leave empty to retrieve current element value.
206
+ def get(path='')
207
+ Element.get(@element, path)
208
+ end
209
+
210
+ # Get the unescaped HTML text of the given path.
211
+ def get_unescaped(path='')
212
+ Element.get_unescaped(@element, path)
213
+ end
214
+
215
+ # Get the array values of the given path.
216
+ def get_array(path='')
217
+ Element.get_array(@element, path)
218
+ end
219
+
220
+ # Get the children element text values in hash format with the element names as the hash keys.
221
+ def get_hash(path='')
222
+ Element.get_hash(@element, path)
223
+ end
224
+
225
+ # Similar to #get, except an element object must be passed-in.
226
+ def self.get(element, path='')
227
+ return unless element
228
+ result = element.at(path)
229
+ result = result.inner_html if result
230
+ result
231
+ end
232
+
233
+ # Similar to #get_unescaped, except an element object must be passed-in.
234
+ def self.get_unescaped(element, path='')
235
+ result = get(element, path)
236
+ CGI::unescapeHTML(result) if result
237
+ end
238
+
239
+ # Similar to #get_array, except an element object must be passed-in.
240
+ def self.get_array(element, path='')
241
+ return unless element
242
+
243
+ result = element/path
244
+ if (result.is_a? Hpricot::Elements) || (result.is_a? Array)
245
+ parsed_result = []
246
+ result.each {|item|
247
+ parsed_result << Element.get(item)
248
+ }
249
+ parsed_result
250
+ else
251
+ [Element.get(result)]
252
+ end
253
+ end
254
+
255
+ # Similar to #get_hash, except an element object must be passed-in.
256
+ def self.get_hash(element, path='')
257
+ return unless element
258
+
259
+ result = element.at(path)
260
+ if result
261
+ hash = {}
262
+ result = result.children
263
+ result.each do |item|
264
+ hash[item.name.to_sym] = item.inner_html
265
+ end
266
+ hash
267
+ end
268
+ end
269
+
270
+ def to_s
271
+ elem.to_s if elem
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class Amazon::AwisTest < Test::Unit::TestCase
4
+
5
+ AWS_ACCESS_KEY_ID = ''
6
+ AWS_SECRET_KEY = ''
7
+
8
+ DOMAIN_STRING = 'yahoo.com'
9
+
10
+ raise "Please specify set your AWS_ACCESS_KEY_ID" if AWS_ACCESS_KEY_ID.empty?
11
+ raise "Please specify set your AWS_SECRET_KEY" if AWS_SECRET_KEY.empty?
12
+
13
+ Amazon::Awis.configure do |config|
14
+ config[:aws_access_key_id] = AWS_ACCESS_KEY_ID
15
+ config[:aws_secret_key] = AWS_SECRET_KEY
16
+ end
17
+
18
+ Amazon::Awis.debug = true
19
+
20
+ def setup
21
+ @awis = Amazon::Awis.new({
22
+ :domain => DOMAIN_STRING
23
+ })
24
+ end
25
+
26
+ ## Test get_info
27
+ def test_query
28
+ resp = @awis.query(:rank)
29
+
30
+ assert(resp.is_success?)
31
+ assert(resp.dataurl == 'yahoo.com/')
32
+ assert(resp.rank == 4.to_s)
33
+ end
34
+
35
+ # Test get_info with SiteData response group
36
+ def test_site_data_response
37
+ resp = @awis.query(:site_data)
38
+
39
+ assert(resp.is_success?)
40
+ assert(resp.title == 'Yahoo!')
41
+ assert(resp.onlinesince == '18-Jan-1995')
42
+ end
43
+
44
+ ## Test get_info with ContactInfo response group
45
+ def test_contact_info_response
46
+ resp = @awis.query(:contact_info)
47
+
48
+ assert(resp.is_success?)
49
+ assert(resp.symbol == 'YHOO')
50
+ end
51
+
52
+ def test_with_another_domain
53
+ @awis.options[:domain] = 'google.com/'
54
+
55
+ resp = @awis.query(:rank)
56
+
57
+ assert(resp.is_success?)
58
+ assert(resp.dataurl == 'google.com/')
59
+ assert(resp.rank == 1.to_s)
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/amazon/awis'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gaiottino-amazon-awis
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Gaiottino
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-29 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: hpricot
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 4
30
+ version: "0.4"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Ruby Amazon Alexa web information service REST API
34
+ email: daniel.gaiottino@gmail.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README.rdoc
41
+ files:
42
+ - .gitignore
43
+ - CHANGELOG
44
+ - MIT-LICENSE
45
+ - README.rdoc
46
+ - Rakefile
47
+ - VERSION
48
+ - gaiottino-amazon-awis.gemspec
49
+ - lib/amazon/awis.rb
50
+ - test/amazon/awis_test.rb
51
+ - test/test_helper.rb
52
+ has_rdoc: true
53
+ homepage: http://github.com/gaiottino/amazon-awis
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.6
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Ruby Amazon Alexa web information service REST API
82
+ test_files:
83
+ - test/amazon/awis_test.rb
84
+ - test/test_helper.rb