kosher 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +1 -2
- data/LICENSE +13 -22
- data/README.md +2 -4
- data/kosher.gemspec +19 -11
- data/lib/kosher/algorithm.rb +19 -0
- data/lib/kosher/condition.rb +32 -0
- data/lib/kosher/description.rb +59 -0
- data/lib/kosher/item.rb +26 -0
- data/lib/kosher/offer.rb +34 -0
- data/lib/kosher/request.rb +28 -0
- data/lib/kosher/seller.rb +28 -0
- data/lib/kosher/version.rb +1 -1
- data/lib/kosher.rb +10 -5
- data/spec/fabricators/condition_fabricator.rb +7 -0
- data/spec/fabricators/offer_fabricator.rb +8 -0
- data/spec/fabricators/seller_fabricator.rb +15 -0
- data/spec/fixtures/cassette_library/0143105825.yml +112 -0
- data/spec/fixtures/cassette_library/batch-request.yml +22388 -0
- data/spec/kosher/algorithm_spec.rb +38 -0
- data/spec/kosher/condition_spec.rb +31 -0
- data/spec/kosher/{string_spec.rb → description_spec.rb} +8 -4
- data/spec/kosher/item_spec.rb +35 -0
- data/spec/kosher/offer_spec.rb +123 -0
- data/spec/kosher/request_spec.rb +42 -0
- data/spec/kosher/seller_spec.rb +65 -0
- data/spec/spec_helper.rb +5 -4
- data/spec/support/credentials.rb +3 -0
- data/spec/support/faker.rb +19 -0
- data/spec/support/vcr.rb +12 -0
- metadata +114 -32
- data/.rspec +0 -2
- data/.rvmrc +0 -1
- data/lib/kosher/regexps.rb +0 -7
- data/lib/kosher/string.rb +0 -50
- data/spec/kosher_spec.rb +0 -9
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
@@ -1,22 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
2
|
+
Version 2, December 2004
|
3
|
+
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
5
|
+
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
7
|
+
copies of this license document, and changing it is allowed as long
|
8
|
+
as the name is changed.
|
9
|
+
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
12
|
+
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
Kosher
|
2
2
|
======
|
3
3
|
|
4
|
-
|
4
|
+
Kosher wraps Amazon in a loving embrace.
|
5
5
|
|
6
|
-
|
7
|
-
description.kosher?
|
8
|
-
=> false
|
6
|
+
![Walter Benjamin](https://github.com/papercavalier/kosher/raw/master/walter_benjamin.jpg)
|
data/kosher.gemspec
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path(
|
3
|
-
require
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'kosher/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'kosher'
|
7
7
|
s.version = Kosher::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = [
|
10
|
-
s.email =
|
11
|
-
s.homepage =
|
12
|
-
s.summary = %q{
|
13
|
-
s.description = %q{
|
9
|
+
s.authors = ['Paper Cavalier']
|
10
|
+
s.email = 'code@papercavalier.com'
|
11
|
+
s.homepage = 'https://rubygems.org/gems/kosher'
|
12
|
+
s.summary = %q{Wraps Amazon in a loving embrace.}
|
13
|
+
s.description = %q{Kosher wraps Amazon in a loving embrace.}
|
14
14
|
|
15
|
-
s.rubyforge_project =
|
15
|
+
s.rubyforge_project = 'kosher'
|
16
16
|
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
-
s.require_paths = [
|
20
|
+
s.require_paths = ['lib']
|
21
21
|
|
22
|
-
s.
|
22
|
+
s.add_dependency('sucker', '~> 1.3.1')
|
23
|
+
s.add_dependency('throttler', '~> 0.2.4')
|
24
|
+
s.add_development_dependency('fabrication', '~> 0.9.5')
|
25
|
+
s.add_development_dependency('rspec', '~> 2.5.0')
|
26
|
+
if RUBY_VERSION.include? '1.9'
|
27
|
+
s.add_development_dependency('ruby-debug19', '~> 0.11.6')
|
28
|
+
end
|
29
|
+
s.add_development_dependency('vcr', '~> 1.7.0')
|
30
|
+
s.add_development_dependency('webmock', '~> 1.6.2')
|
23
31
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Algorithm
|
3
|
+
def initialize(response)
|
4
|
+
@response = response
|
5
|
+
end
|
6
|
+
|
7
|
+
def items
|
8
|
+
@response.map('Item') do |item|
|
9
|
+
Item.build(item)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
@response.errors.map do |error|
|
15
|
+
error['Message'].scan(/[0-9A-Z]{10}/).first rescue nil
|
16
|
+
end.compact
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Condition < Struct.new(:in_words)
|
3
|
+
def to_i
|
4
|
+
case in_words
|
5
|
+
when 'new'
|
6
|
+
1
|
7
|
+
when 'mint'
|
8
|
+
2
|
9
|
+
when 'verygood'
|
10
|
+
3
|
11
|
+
when 'good'
|
12
|
+
4
|
13
|
+
when 'acceptable'
|
14
|
+
5
|
15
|
+
else
|
16
|
+
6
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def kosher?
|
21
|
+
to_i <= 4
|
22
|
+
end
|
23
|
+
|
24
|
+
def new?
|
25
|
+
in_words == 'new'
|
26
|
+
end
|
27
|
+
|
28
|
+
def used?
|
29
|
+
!new?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Description < String
|
3
|
+
DAMAGED = "\\b(?:missing|torn|broken|split|discard|withdrawn|rent|stain|school|damaged|water)"
|
4
|
+
EXLIB = "(?:e?x|discarded|retired|former|has|have)[\\s._-]*lib"
|
5
|
+
MARKED = "(highlight|hilit|underlin)"
|
6
|
+
MISSING_VOL = "(vols?|volume) only"
|
7
|
+
REVIEW_COPY = "\\b(?:uncorrected|advanced?\\sreview|arc)\\b"
|
8
|
+
|
9
|
+
def kosher?
|
10
|
+
!(present? && bad?)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def bad?
|
16
|
+
damaged? ||
|
17
|
+
ex_library? ||
|
18
|
+
marked? ||
|
19
|
+
missing_volume? ||
|
20
|
+
review_copy?
|
21
|
+
end
|
22
|
+
|
23
|
+
def damaged?
|
24
|
+
matches(DAMAGED)
|
25
|
+
end
|
26
|
+
|
27
|
+
def does_not_match(value)
|
28
|
+
!match(Regexp.new(value, true))
|
29
|
+
end
|
30
|
+
|
31
|
+
def ex_library?
|
32
|
+
matches(EXLIB) && does_not_match(negation_of(EXLIB))
|
33
|
+
end
|
34
|
+
|
35
|
+
def marked?
|
36
|
+
matches(MARKED) && does_not_match(negation_of(MARKED))
|
37
|
+
end
|
38
|
+
|
39
|
+
def matches(value)
|
40
|
+
!does_not_match(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def missing_volume?
|
44
|
+
matches(MISSING_VOL)
|
45
|
+
end
|
46
|
+
|
47
|
+
def negation_of(value)
|
48
|
+
"(?:no|not an?)\\s+#{value}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def present?
|
52
|
+
self != ''
|
53
|
+
end
|
54
|
+
|
55
|
+
def review_copy?
|
56
|
+
matches(REVIEW_COPY)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/kosher/item.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Item < Struct.new(:asin, :offers)
|
3
|
+
|
4
|
+
def self.build(doc)
|
5
|
+
asin = doc['ASIN']
|
6
|
+
offers = build_offers(doc['Offers']['Offer'])
|
7
|
+
|
8
|
+
new(asin, offers)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def self.build_offers(offers)
|
14
|
+
[offers].flatten.compact.map do |offer|
|
15
|
+
|
16
|
+
# Senify Yen because Ruby Money says so
|
17
|
+
price = offer['OfferListing']['Price']
|
18
|
+
if price['CurrencyCode'] == 'JPY'
|
19
|
+
price['Amount'] = price['Amount'].to_i * 100
|
20
|
+
end
|
21
|
+
|
22
|
+
Offer.build(offer)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/kosher/offer.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Offer < Struct.new(
|
3
|
+
:seller,
|
4
|
+
:condition,
|
5
|
+
:description,
|
6
|
+
:ships_in,
|
7
|
+
:ships_free,
|
8
|
+
:cents)
|
9
|
+
|
10
|
+
def self.build(doc)
|
11
|
+
offer = new
|
12
|
+
offer.seller = Seller.build(doc['Merchant'])
|
13
|
+
|
14
|
+
attributes = doc['OfferAttributes']
|
15
|
+
offer.condition = Condition.new(attributes['SubCondition'])
|
16
|
+
offer.description = Description.new(attributes['ConditionNote'].to_s)
|
17
|
+
|
18
|
+
listing = doc['OfferListing']
|
19
|
+
offer.ships_in = listing['AvailabilityAttributes']['MaximumHours'].to_i
|
20
|
+
offer.ships_free = listing['IsEligibleForSuperSaverShipping'] == '1'
|
21
|
+
offer.cents = listing['Price']['Amount'].to_i
|
22
|
+
|
23
|
+
offer
|
24
|
+
end
|
25
|
+
|
26
|
+
def kosher?
|
27
|
+
condition.kosher? && seller.kosher? && description.kosher? && ships_now?
|
28
|
+
end
|
29
|
+
|
30
|
+
def ships_now?
|
31
|
+
ships_in.to_i <= 48
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Request < Sucker::Request
|
3
|
+
def initialize(args={})
|
4
|
+
super
|
5
|
+
add_parameters
|
6
|
+
end
|
7
|
+
|
8
|
+
def batchify(asins)
|
9
|
+
self.<<({ 'ItemLookup.1.ItemId' => asins[0, 10] })
|
10
|
+
self.<<({ 'ItemLookup.2.ItemId' => asins[10, 10] }) if asins.size > 10
|
11
|
+
end
|
12
|
+
|
13
|
+
def get
|
14
|
+
Algorithm.new(super)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def add_parameters
|
20
|
+
self.<<({
|
21
|
+
'Operation' => 'ItemLookup',
|
22
|
+
'ItemLookup.Shared.IdType' => 'ASIN',
|
23
|
+
'ItemLookup.Shared.Condition' => 'All',
|
24
|
+
'ItemLookup.Shared.MerchantId' => 'All',
|
25
|
+
'ItemLookup.Shared.ResponseGroup' => ['OfferFull', 'SalesRank'] })
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Kosher
|
2
|
+
class Seller < Struct.new(:merchant_id, :average_rating)
|
3
|
+
class << self
|
4
|
+
attr_accessor :blacklist
|
5
|
+
|
6
|
+
def build(doc)
|
7
|
+
merchant_id = doc['MerchantId']
|
8
|
+
average_rating = doc['AverageFeedbackRating'].to_f
|
9
|
+
|
10
|
+
new(merchant_id, average_rating)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def blacklist
|
15
|
+
self.class.blacklist
|
16
|
+
end
|
17
|
+
|
18
|
+
def blacklisted?
|
19
|
+
blacklist.include? merchant_id rescue false
|
20
|
+
end
|
21
|
+
|
22
|
+
def kosher?
|
23
|
+
return false if blacklisted?
|
24
|
+
|
25
|
+
average_rating == 0.0 || average_rating > 4.7
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/kosher/version.rb
CHANGED
data/lib/kosher.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'sucker'
|
2
|
+
require 'kosher/algorithm'
|
3
|
+
require 'kosher/condition'
|
4
|
+
require 'kosher/description'
|
5
|
+
require 'kosher/item'
|
6
|
+
require 'kosher/offer'
|
7
|
+
require 'kosher/request'
|
8
|
+
require 'kosher/seller'
|
3
9
|
|
4
10
|
module Kosher
|
5
|
-
def self.new(
|
6
|
-
|
11
|
+
def self.new(args={})
|
12
|
+
Request.new(args)
|
7
13
|
end
|
8
14
|
end
|
9
|
-
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Fabricator(:seller, :class_name => 'kosher/seller') do
|
2
|
+
merchant_id Faker::Amazon.merchant_id
|
3
|
+
end
|
4
|
+
|
5
|
+
Fabricator(:new_seller, :from => :seller) do
|
6
|
+
average_rating 0.0
|
7
|
+
end
|
8
|
+
|
9
|
+
Fabricator(:good_seller, :from => :seller) do
|
10
|
+
average_rating 5.0
|
11
|
+
end
|
12
|
+
|
13
|
+
Fabricator(:bad_seller, :from => :seller) do
|
14
|
+
average_rating 4.5
|
15
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://ecs.amazonaws.com:80/onca/xml?AWSAccessKeyId=0ZVSQ33MDFPQS8H2PM02&AssociateTag=papecava-20&ItemLookup.1.ItemId=0143105825&ItemLookup.Shared.Condition=All&ItemLookup.Shared.IdType=ASIN&ItemLookup.Shared.MerchantId=All&ItemLookup.Shared.ResponseGroup=OfferFull,SalesRank&Operation=ItemLookup&Service=AWSECommerceService&Signature=x3dZXO/H7AvZ7x/bt6P1iTAx13QatyVbMyc1v9yKtzc=&Timestamp=2011-03-02T19:25:56Z&Version=2010-11-01
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
accept-encoding:
|
9
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
10
|
+
response: !ruby/struct:VCR::Response
|
11
|
+
status: !ruby/struct:VCR::ResponseStatus
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
date:
|
16
|
+
- Wed, 02 Mar 2011 19:25:56 GMT
|
17
|
+
server:
|
18
|
+
- Server
|
19
|
+
content-type:
|
20
|
+
- text/xml;charset=UTF-8
|
21
|
+
vary:
|
22
|
+
- Accept-Encoding,User-Agent
|
23
|
+
content-encoding:
|
24
|
+
- gzip
|
25
|
+
content-length:
|
26
|
+
- "3620"
|
27
|
+
nncoection:
|
28
|
+
- close
|
29
|
+
body: !binary |
|
30
|
+
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
|
110
|
+
tnT+E+jS5/89Q+XfeGWzi8lBAAA=
|
111
|
+
|
112
|
+
http_version: "1.1"
|