ruby-aaws-simple 0.0.2

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ #gem 'ruby-aaws', '0.8.1'
4
+ gem 'ruby-aaws'
5
+
6
+ # Specify your gem's dependencies in ruby-aaws-simple.gemspec
7
+ gemspec
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # ruby-aaws-simple
2
+ Simple wrapper for ruby-aaws
3
+
4
+ ## Installation
5
+ gem install ruby-aaws-simple
6
+
7
+ ## Usage
8
+ require 'amazon/aws/simple'
9
+ aws = Amazon::AWS::Simple::Search.new(key_id, secret_key_id, affiliate_tag, country_code, encoding, cacahe_dir)
10
+ items = aws.retrieve_by_keyword('Ruby')
11
+ items.first.title
12
+ # => 7.50 Carat Ruby & White Sapphire Heart Pendant in Sterling Silver with 18" Chain,
13
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/examples/test.rb ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/env ruby
2
+ require 'amazon/aws/simple'
3
+
4
+ if $0 == __FILE__
5
+ key_id = ""
6
+ secret_key_id = ""
7
+ cache_dir = "/tmp/amazon/"
8
+
9
+ Amazon::AWS::Simple::Search.logger = Logger.new(STDERR)
10
+ aws = Amazon::AWS::Simple::Search.new(key_id, secret_key_id, "hoge-22", "us", "utf-8", cache_dir)
11
+ puts aws.retrieve_by_keyword('ruby').map(&:title)
12
+ end
@@ -0,0 +1,143 @@
1
+ # monkey patch
2
+ #
3
+ module Amazon
4
+
5
+ module AWS
6
+
7
+ # This class provides a simple results caching system for operations
8
+ # performed by AWS.
9
+ #
10
+ # To use it, set _cache_ to *true* in either <tt>/etc/amazonrc</tt> or
11
+ # <tt>~/.amazonrc</tt>.
12
+ #
13
+ # By default, the cache directory used is <tt>/tmp/amazon</tt>, but this
14
+ # can be changed by defining _cache_dir_ in either <tt>/etc/amazonrc</tt>
15
+ # or <tt>~/.amazonrc</tt>.
16
+ #
17
+ # When a cache is used, Ruby/AWS will check the cache directory for a
18
+ # recent copy of a response to the exact operation that you are
19
+ # performing. If found, the cached response will be returned instead of
20
+ # the request being forwarded to the AWS servers for processing. If no
21
+ # (recent) copy is found, the request will be forwarded to the AWS servers
22
+ # as usual. Recency is defined here as less than 24 hours old.
23
+ #
24
+ class Cache
25
+
26
+ require 'fileutils'
27
+
28
+ begin
29
+ require 'md5'
30
+ rescue LoadError
31
+ # Ruby 1.9 has moved MD5.
32
+ #
33
+ require 'digest/md5'
34
+ end
35
+
36
+ # Exception class for bad cache paths.
37
+ #
38
+ class PathError < StandardError; end
39
+
40
+ # Length of one day in seconds
41
+ #
42
+ ONE_DAY = 86400 # :nodoc:
43
+
44
+ # Age in days below which to consider cache files valid.
45
+ #
46
+ MAX_AGE = 1.0
47
+
48
+ # Default cache location.
49
+ #
50
+ DEFAULT_CACHE_DIR = '/tmp/amazon'
51
+
52
+ attr_reader :path
53
+
54
+ def initialize(path=DEFAULT_CACHE_DIR)
55
+ path ||= DEFAULT_CACHE_DIR
56
+
57
+ ::FileUtils::mkdir_p( path ) unless File.exists? path
58
+
59
+ unless File.directory? path
60
+ raise PathError, "cache path #{path} is not a directory"
61
+ end
62
+
63
+ unless File.readable? path
64
+ raise PathError, "cache path #{path} is not readable"
65
+ end
66
+
67
+ unless File.writable? path
68
+ raise PathError, "cache path #{path} is not writable"
69
+ end
70
+
71
+ @path = path
72
+ end
73
+
74
+
75
+ # Determine whether or not the the response to a given URL is cached.
76
+ # Returns *true* or *false*.
77
+ #
78
+ def cached?(url)
79
+ digest = Digest::MD5.hexdigest( url )
80
+
81
+ cache_files = Dir.glob( File.join( @path, '*' ) ).map do |d|
82
+ File.basename( d )
83
+ end
84
+
85
+ return cache_files.include?( digest ) &&
86
+ ( Time.now - File.mtime( File.join( @path, digest ) ) ) /
87
+ ONE_DAY <= MAX_AGE
88
+ end
89
+
90
+
91
+ # Retrieve the cached response associated with _url_.
92
+ #
93
+ def fetch(url)
94
+ digest = Digest::MD5.hexdigest( url )
95
+ cache_file = File.join( @path, digest )
96
+
97
+ return nil unless File.exist? cache_file
98
+
99
+ Amazon.dprintf( 'Fetching %s from cache...', digest )
100
+ #File.open( File.join( cache_file ) ).readlines.to_s
101
+ File.read(cache_file)
102
+ end
103
+
104
+
105
+ # Cache the data from _contents_ and associate it with _url_.
106
+ #
107
+ def store(url, contents)
108
+ digest = Digest::MD5.hexdigest( url )
109
+ cache_file = File.join( @path, digest )
110
+
111
+ Amazon.dprintf( 'Caching %s...', digest )
112
+ content.force_encoding("UTF-8")
113
+ #File.open( cache_file, 'w' ) { |f| f.puts contents }
114
+ File.write cache_file, contents
115
+ end
116
+
117
+
118
+ # This method flushes all files from the cache directory specified
119
+ # in the object's <i>@path</i> variable.
120
+ #
121
+ def flush_all
122
+ FileUtils.rm Dir.glob( File.join( @path, '*' ) )
123
+ end
124
+
125
+
126
+ # This method flushes expired files from the cache directory specified
127
+ # in the object's <i>@path</i> variable.
128
+ #
129
+ def flush_expired
130
+ now = Time.now
131
+
132
+ expired_files = Dir.glob( File.join( @path, '*' ) ).find_all do |f|
133
+ ( now - File.mtime( f ) ) / ONE_DAY > MAX_AGE
134
+ end
135
+
136
+ FileUtils.rm expired_files
137
+ end
138
+
139
+ end
140
+
141
+ end
142
+
143
+ end
@@ -0,0 +1,183 @@
1
+ require_relative "simple_version"
2
+ require 'amazon/aws/search'
3
+ require 'amazon/aws'
4
+ require 'logger'
5
+ require 'cgi'
6
+
7
+ module Amazon::AWS::Simple
8
+ class APIWrapper
9
+ @@logger = Logger.new(nil)
10
+ def self.logger=(logger)
11
+ @@logger = logger
12
+ end
13
+
14
+ def initialize(key_id, secret_key_id, tag, locale, encoding, cache_dir)
15
+ @key_id = key_id
16
+ @secret_key_id = secret_key_id
17
+ @tag = tag
18
+ @locale = locale
19
+ @encoding = encoding
20
+ @cache_dir = cache_dir
21
+ end
22
+
23
+ def request(query)
24
+ req = Amazon::AWS::Search::Request.new(@key_id, @tag)
25
+ req.config["cache_dir"] = @cache_dir
26
+ req.config["secret_key_id"] = @secret_key_id
27
+ req.locale = @locale
28
+ req.encoding = @encoding
29
+ req.cache = Amazon::AWS::Cache.new(@cache_dir)
30
+
31
+ rg = Amazon::AWS::ResponseGroup.new(:Large)
32
+ query.response_group = rg
33
+
34
+ req.search(query)
35
+ end
36
+
37
+ def item_lookup(type, params={})
38
+ request(Amazon::AWS::ItemLookup.new(type, params)).item_lookup_response.items.item
39
+ end
40
+
41
+ def item_search(type, params={})
42
+ request(Amazon::AWS::ItemSearch.new(type, params)).item_search_response.items.item
43
+ end
44
+ end
45
+
46
+ class Search < APIWrapper
47
+ attr_reader :errors
48
+ def initialize(*args)
49
+ super(*args)
50
+ @errors = []
51
+ end
52
+
53
+ ## どんだけたくさんのASINでも全部自動でAPIの最大数にあわせて分割してリクエストしてくれる版
54
+ ## エラーは全部無視しますが、@errorsに記録されます
55
+ ITEM_LOOKUP_MAX_ITEMS = 10
56
+ def search_by_asin(*asins)
57
+ asins.flatten.each_slice(ITEM_LOOKUP_MAX_ITEMS).map{ |asin_codes|
58
+ @@logger.info "try to fetch: #{asin_codes.inspect}"
59
+ _search_by_asin(asin_codes)
60
+ }.flatten
61
+ end
62
+
63
+ def search_by_keyword(keyword)
64
+ _search_by_keyword(keyword)
65
+ end
66
+
67
+ ## 更につかいやすくしたやつ
68
+ def retrieve_by_asin(*asins)
69
+ search_by_asin(*asins).map{ |item|
70
+ Data.new.load_from_aws_item(item)
71
+ }
72
+ end
73
+
74
+ def retrieve_by_keyword(keyword)
75
+ search_by_keyword(keyword).map{ |item|
76
+ Data.new.load_from_aws_item(item)
77
+ }
78
+ end
79
+
80
+ private
81
+ # 10以上は検索できないAPI, 仕様を満たしてる
82
+ def _search_by_asin(*asins)
83
+ params = asins.flatten
84
+ if params.size > ITEM_LOOKUP_MAX_ITEMS
85
+ raise ArgumentError.new("asin_codes > #{ITEM_LOOKUP_MAX_ITEMS}, #{params.inspect}")
86
+ end
87
+ begin
88
+ results = item_lookup("ASIN", {"ItemId" => params.join(",")})
89
+ rescue Amazon::AmazonError => ex
90
+ @@logger.error "Multiple fetch mode error! change to single fetch mode: #{ex}"
91
+ @@logger.error ex.backtrace.join($/)
92
+ results = []
93
+ params.each{ |asin|
94
+ begin
95
+ @@logger.info "try to fetch: #{asin.inspect}"
96
+ results << item_lookup("ASIN", {"ItemId" => asin})
97
+ rescue Amazon::AmazonError => ex
98
+ @@logger.error ex
99
+ @@logger.error ex.backtrace.join($/)
100
+ @errors << asin
101
+ end
102
+ }
103
+ results
104
+ end
105
+ end
106
+
107
+ def _search_by_keyword(keyword)
108
+ item_search("All", {'Keywords' => keyword})
109
+ end
110
+ end
111
+
112
+ class Search::Data
113
+ attr_accessor :asin
114
+ attr_accessor :title
115
+ attr_accessor :product_group
116
+ attr_accessor :publisher
117
+ attr_accessor :published_at
118
+ attr_accessor :image_url
119
+ attr_accessor :image_code
120
+ attr_accessor :alt_image_urls
121
+ attr_accessor :alt_image_codes
122
+ attr_accessor :price
123
+ attr_accessor :discount_price
124
+ attr_accessor :discount_percentage
125
+ attr_accessor :detail
126
+
127
+ def load_from_aws_item(item)
128
+ # 値段関係
129
+ price = item.item_attributes.list_price.amount.first rescue nil
130
+ discount_price = item.offers.offer.offer_listing.price.amount.first rescue nil
131
+ discount_percentage = item.offers.offer.offer_listing.percentage_saved.first rescue nil
132
+
133
+ # 画像関係
134
+ image_url = item.large_image.url rescue nil
135
+ image_code = extract_image_code_from_image_url(image_url)
136
+ alt_image_urls = item.image_sets.image_set.map{ |set| set.swatch_image.url }.flatten rescue []
137
+ alt_image_codes = alt_image_urls.map{|url| extract_image_code_from_image_url(url) }
138
+
139
+ # 日付関係
140
+ publication_date = item.item_attributes.publication_date.first rescue nil
141
+ release_date = item.item_attributes.release_date.first rescue nil
142
+
143
+ published_at = publication_date
144
+ if published_at.nil?
145
+ published_at = release_date
146
+ end
147
+
148
+ @asin = item.asin.first.to_s rescue nil
149
+ @title = CGI.unescape_html(item.item_attributes.title.join(",")) rescue nil
150
+ @product_group = item.item_attributes.product_group.first.to_s
151
+ @publisher = item.item_attributes.publisher.join(",") rescue nil
152
+ @published_at = published_at rescue nil
153
+ @image_url = image_url.first.to_s rescue nil
154
+ @image_code = image_code
155
+ @alt_image_urls = alt_image_urls
156
+ @alt_image_codes = alt_image_codes
157
+ @price = price
158
+ @discount_price = discount_price
159
+ @discount_percentage = discount_percentage
160
+ @detail = item.detail_page_url rescue nil
161
+ self
162
+ end
163
+
164
+ def to_s
165
+ "#<AWS::Simple::Data: #{@title}(#{@asin}) - #{@publisher} $#{@price}>"
166
+ end
167
+
168
+ private
169
+ def extract_basename_from_image_url(image_url)
170
+ if /([^\/]+)\.jpg$/.match(image_url)
171
+ Regexp.last_match(0)
172
+ end
173
+ end
174
+
175
+ def extract_image_code_from_image_url(image_url)
176
+ basename = extract_basename_from_image_url(image_url)
177
+ # 先頭の.までを抽出
178
+ if /(^[^\.]+)\./.match(basename)
179
+ Regexp.last_match(1)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,7 @@
1
+ module Amazon
2
+ module AWS
3
+ module Simple
4
+ VERSION = "0.0.2"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/amazon/aws/simple_version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["kimoto"]
6
+ gem.email = ["sub+peerler@gmail.com"]
7
+ gem.description = %q{Simple Wrapper for ruby-aaws}
8
+ gem.summary = %q{Simple Wrapper for ruby-aaws}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "ruby-aaws-simple"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Amazon::AWS::Simple::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-aaws-simple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - kimoto
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-24 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Simple Wrapper for ruby-aaws
15
+ email:
16
+ - sub+peerler@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - README.md
24
+ - Rakefile
25
+ - examples/test.rb
26
+ - lib/amazon/aws/cache.rb
27
+ - lib/amazon/aws/simple.rb
28
+ - lib/amazon/aws/simple_version.rb
29
+ - ruby-aaws-simple.gemspec
30
+ homepage: ''
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.8.24
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: Simple Wrapper for ruby-aaws
54
+ test_files: []