fassbinder 0.0.8 → 0.0.9
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/Gemfile +5 -0
- data/Rakefile +1 -0
- data/bin/rainer +3 -0
- data/fassbinder.gemspec +4 -7
- data/lib/fassbinder/book_builder.rb +35 -0
- data/lib/fassbinder/cli.rb +52 -0
- data/lib/fassbinder/errors.rb +4 -0
- data/lib/fassbinder/item_builder.rb +46 -0
- data/lib/fassbinder/offer_builder.rb +47 -0
- data/lib/fassbinder/request.rb +10 -1
- data/lib/fassbinder/response.rb +26 -51
- data/lib/fassbinder/seller_builder.rb +28 -0
- data/lib/fassbinder/shipping_builder.rb +27 -0
- data/lib/fassbinder/version.rb +1 -1
- data/lib/fassbinder.rb +0 -8
- data/spec/fassbinder/request_spec.rb +38 -8
- data/spec/fassbinder/response_spec.rb +14 -7
- metadata +19 -44
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/bin/rainer
ADDED
data/fassbinder.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ['Paper Cavalier']
|
10
10
|
s.email = 'code@papercavalier.com'
|
11
11
|
s.homepage = 'https://rubygems.org/gems/fassbinder'
|
12
|
-
s.summary = %q{
|
13
|
-
s.description = %q{Fassbinder
|
12
|
+
s.summary = %q{Crawls book offers on Amazon}
|
13
|
+
s.description = %q{Fassbinder crawls book offers on Amazon.}
|
14
14
|
|
15
15
|
s.rubyforge_project = 'fassbinder'
|
16
16
|
|
@@ -19,10 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ['lib']
|
21
21
|
|
22
|
-
s.add_dependency('kosher', '~> 0.2.
|
22
|
+
s.add_dependency('kosher', '~> 0.2.23')
|
23
23
|
s.add_dependency('sucker', '~> 1.4.0')
|
24
|
-
s.
|
25
|
-
s.add_development_dependency('ruby-debug19', '~> 0.11.6')
|
26
|
-
s.add_development_dependency('vcr', '~> 1.7.0')
|
27
|
-
s.add_development_dependency('webmock', '~> 1.6.2')
|
24
|
+
s.add_dependency('thor', '~> 0.14.6')
|
28
25
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'kosher'
|
2
|
+
require 'fassbinder/offer_builder'
|
3
|
+
|
4
|
+
module Fassbinder
|
5
|
+
class BookBuilder
|
6
|
+
attr_reader :book
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@book = Kosher::Book.new
|
10
|
+
@book.offers = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_offer(hash)
|
14
|
+
builder = OfferBuilder.new
|
15
|
+
builder.id = hash['OfferListing']['OfferListingId']
|
16
|
+
builder.venue = @book.venue
|
17
|
+
builder.add_item(hash)
|
18
|
+
builder.add_seller(hash['Merchant'])
|
19
|
+
builder.add_shipping(hash)
|
20
|
+
@book.offers << builder.offer
|
21
|
+
end
|
22
|
+
|
23
|
+
def asin=(asin)
|
24
|
+
@book.asin = asin
|
25
|
+
end
|
26
|
+
|
27
|
+
def venue=(venue)
|
28
|
+
@book.venue = venue
|
29
|
+
end
|
30
|
+
|
31
|
+
def offers_total=(count)
|
32
|
+
@book.offers_total = count.to_i
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'thor'
|
3
|
+
require 'fassbinder'
|
4
|
+
|
5
|
+
module Fassbinder
|
6
|
+
class CLI < Thor
|
7
|
+
desc 'all', 'Looks up all offers for an ASIN'
|
8
|
+
method_option :locale, :required => true, :aliases => '-l'
|
9
|
+
def all(asin)
|
10
|
+
locale = options[:locale] || :us
|
11
|
+
lookup(asin, locale)
|
12
|
+
end
|
13
|
+
map 'a' => 'all'
|
14
|
+
|
15
|
+
desc 'kosher', 'Looks up kosher offers for an ASIN'
|
16
|
+
method_option :locale, :required => true, :aliases => '-l'
|
17
|
+
def kosher(asin)
|
18
|
+
locale = options[:locale] || :us
|
19
|
+
lookup(asin, locale, true)
|
20
|
+
end
|
21
|
+
map 'k' => 'kosher'
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def lookup(asin, locale, kosher_only=false)
|
26
|
+
request = Request.new(credentials)
|
27
|
+
request.locale = locale
|
28
|
+
request.batchify(asin)
|
29
|
+
offers = request.get.to_a.first.offers
|
30
|
+
|
31
|
+
offers.select!(&:kosher?) if kosher_only
|
32
|
+
|
33
|
+
offers.each do |offer|
|
34
|
+
puts offer.kosher? ? 'kosher' : 'unkosher'
|
35
|
+
|
36
|
+
offer.id = offer.id[0, 24] + '...'
|
37
|
+
|
38
|
+
description = offer.item.description.text
|
39
|
+
if description.size > 77
|
40
|
+
offer.item.description.text = description[0, 77] + '...'
|
41
|
+
end
|
42
|
+
|
43
|
+
pp offer
|
44
|
+
puts
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def credentials
|
48
|
+
{ 'key' => ENV['AMAZON_KEY'],
|
49
|
+
'secret' => ENV['AMAZON_SECRET'] }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Fassbinder
|
2
|
+
class ItemBuilder
|
3
|
+
attr_reader :item
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@item = Kosher::Item.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def price=(price)
|
10
|
+
cents = price['Amount'].to_i
|
11
|
+
currency = price['CurrencyCode']
|
12
|
+
|
13
|
+
cents *= 100 if currency == 'JPY'
|
14
|
+
|
15
|
+
@item.cents = cents
|
16
|
+
@item.currency = currency
|
17
|
+
end
|
18
|
+
|
19
|
+
def quantity=(quantity)
|
20
|
+
@item.quantity = quantity.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_condition(grade)
|
24
|
+
condition = Kosher::Condition.new
|
25
|
+
condition.grade =
|
26
|
+
case grade
|
27
|
+
when 'new' then 1
|
28
|
+
when 'mint' then 2
|
29
|
+
when 'verygood' then 3
|
30
|
+
when 'good' then 4
|
31
|
+
when 'acceptable' then 5
|
32
|
+
else 6
|
33
|
+
end
|
34
|
+
|
35
|
+
@item.condition = condition
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_description(text)
|
39
|
+
text ||= ''
|
40
|
+
description = Kosher::Description.new
|
41
|
+
description.text = text
|
42
|
+
|
43
|
+
@item.description = description
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fassbinder/item_builder'
|
2
|
+
require 'fassbinder/seller_builder'
|
3
|
+
require 'fassbinder/shipping_builder'
|
4
|
+
|
5
|
+
module Fassbinder
|
6
|
+
class OfferBuilder
|
7
|
+
attr_reader :offer
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@offer = Kosher::Offer.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_item(hash)
|
14
|
+
builder = ItemBuilder.new
|
15
|
+
builder.price = hash['OfferListing']['Price']
|
16
|
+
builder.quantity = hash['OfferListing']['Quantity']
|
17
|
+
builder.add_condition(hash['OfferAttributes']['SubCondition'])
|
18
|
+
builder.add_description(hash['OfferAttributes']['ConditionNote'])
|
19
|
+
@offer.item = builder.item
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_seller(hash)
|
23
|
+
builder = SellerBuilder.new
|
24
|
+
builder.id = hash['MerchantId']
|
25
|
+
builder.name = hash['Name']
|
26
|
+
builder.rating = hash['AverageFeedbackRating']
|
27
|
+
builder.add_location(hash['Location']) if hash['Location']
|
28
|
+
@offer.seller = builder.seller
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_shipping(hash)
|
32
|
+
builder = ShippingBuilder.new
|
33
|
+
builder.add_availability(hash['OfferListing']['AvailabilityAttributes']['MaximumHours'])
|
34
|
+
is_free = (hash['OfferListing']['IsEligibleForSuperSaverShipping'] == '1')
|
35
|
+
builder.calculate_price(is_free, @offer.venue, hash['OfferListing']['Price']['CurrencyCode'])
|
36
|
+
@offer.shipping = builder.shipping
|
37
|
+
end
|
38
|
+
|
39
|
+
def id=(id)
|
40
|
+
@offer.id = id
|
41
|
+
end
|
42
|
+
|
43
|
+
def venue=(venue)
|
44
|
+
@offer.venue = venue
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/fassbinder/request.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'sucker'
|
2
|
+
require 'fassbinder/response'
|
3
|
+
|
1
4
|
module Fassbinder
|
2
5
|
class Request < Sucker::Request
|
3
6
|
def initialize(args = {})
|
@@ -7,10 +10,16 @@ module Fassbinder
|
|
7
10
|
'ItemLookup.Shared.IdType' => 'ASIN',
|
8
11
|
'ItemLookup.Shared.Condition' => 'All',
|
9
12
|
'ItemLookup.Shared.MerchantId' => 'All',
|
10
|
-
'ItemLookup.Shared.ResponseGroup' => ['OfferFull'
|
13
|
+
'ItemLookup.Shared.ResponseGroup' => ['OfferFull'] })
|
11
14
|
end
|
12
15
|
|
13
16
|
def batchify(asins)
|
17
|
+
asins = [asins].flatten
|
18
|
+
|
19
|
+
if asins.size > 20
|
20
|
+
raise ArgumentError, 'You cannot add more than 20 ASINs to a batch'
|
21
|
+
end
|
22
|
+
|
14
23
|
self.<<({ 'ItemLookup.1.ItemId' => asins[0, 10] })
|
15
24
|
self.<<({ 'ItemLookup.2.ItemId' => asins[10, 10] }) if asins.size > 10
|
16
25
|
end
|
data/lib/fassbinder/response.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
|
-
|
1
|
+
require 'fassbinder/book_builder'
|
2
|
+
require 'fassbinder/errors'
|
2
3
|
|
3
|
-
|
4
|
-
# be taken absolutely seriously.
|
5
|
-
#
|
4
|
+
module Fassbinder
|
6
5
|
class Response
|
7
6
|
include Enumerable
|
8
7
|
|
9
|
-
DEFAULT_SHIPPING_CENTS = { :us => 399,
|
10
|
-
:uk => 280,
|
11
|
-
:de => 299,
|
12
|
-
:ca => 649,
|
13
|
-
:fr => 300,
|
14
|
-
:jp => 25000 }
|
15
|
-
|
16
8
|
def initialize(response, locale)
|
17
|
-
|
9
|
+
unless response.valid?
|
10
|
+
message =
|
11
|
+
if response.has_errors?
|
12
|
+
response.errors.first['Message']
|
13
|
+
else
|
14
|
+
response.code
|
15
|
+
end
|
16
|
+
|
17
|
+
raise InvalidResponse, message
|
18
|
+
end
|
18
19
|
|
19
20
|
@response = response
|
20
|
-
@locale = locale
|
21
|
+
@locale = locale.to_sym
|
21
22
|
end
|
22
23
|
|
23
24
|
# Yields each snapshot to given block.
|
24
25
|
#
|
25
26
|
def each(&block)
|
26
|
-
@response.each('Item') { |doc| block.call(
|
27
|
+
@response.each('Item') { |doc| block.call(build_book(doc)) }
|
27
28
|
end
|
28
29
|
|
29
30
|
def errors
|
@@ -34,44 +35,18 @@ module Fassbinder
|
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
38
|
+
def build_book(doc)
|
39
|
+
builder = BookBuilder.new
|
40
|
+
|
41
|
+
builder.asin = doc['ASIN']
|
42
|
+
builder.offers_total = doc['Offers']['TotalOffers']
|
43
|
+
host = Sucker::Request::HOSTS[@locale]
|
44
|
+
builder.venue = "amazon.#{host.match(/[^.]+$/)}"
|
45
|
+
|
46
|
+
offers = doc['Offers']['Offer']
|
47
|
+
offers.each { |offer| builder.add_offer(offer) }
|
48
48
|
|
49
|
-
|
50
|
-
doc['OfferListing']['OfferListingId'],
|
51
|
-
Kosher::Item.new(doc['OfferListing']['Price']['Amount'].to_i,
|
52
|
-
doc['OfferListing']['Price']['CurrencyCode'],
|
53
|
-
doc['OfferListing']['Quantity'].to_i,
|
54
|
-
Kosher::Condition.new(case doc['OfferAttributes']['SubCondition']
|
55
|
-
when 'new' then 1
|
56
|
-
when 'mint' then 2
|
57
|
-
when 'verygood' then 3
|
58
|
-
when 'good' then 4
|
59
|
-
when 'acceptable' then 5
|
60
|
-
else 6
|
61
|
-
end),
|
62
|
-
Kosher::Description.new(doc['OfferAttributes']['ConditionNote'].to_s)),
|
63
|
-
Kosher::Seller.new(doc['Merchant']['MerchantId'],
|
64
|
-
doc['Merchant']['Name'],
|
65
|
-
doc['Merchant']['AverageFeedbackRating'].to_f,
|
66
|
-
Kosher::Location.new((doc['Merchant']['Location']['CountryCode'] rescue nil),
|
67
|
-
(doc['Merchant']['Location']['StateCode'] rescue nil))),
|
68
|
-
Kosher::Shipping.new(doc['OfferListing']['IsEligibleForSuperSaverShipping'] == '1' ?
|
69
|
-
0 : DEFAULT_SHIPPING_CENTS[@locale],
|
70
|
-
doc['OfferListing']['Price']['CurrencyCode'],
|
71
|
-
Kosher::Availability.new(doc['OfferListing']['AvailabilityAttributes']['MaximumHours'].to_i))
|
72
|
-
)
|
73
|
-
end
|
74
|
-
)
|
49
|
+
builder.book
|
75
50
|
end
|
76
51
|
end
|
77
52
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Fassbinder
|
2
|
+
class SellerBuilder
|
3
|
+
attr_reader :seller
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@seller = Kosher::Seller.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def id=(id)
|
10
|
+
@seller.id = id
|
11
|
+
end
|
12
|
+
|
13
|
+
def name=(name)
|
14
|
+
@seller.name = name
|
15
|
+
end
|
16
|
+
|
17
|
+
def rating=(rating)
|
18
|
+
@seller.rating = rating.to_f
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_location(hash)
|
22
|
+
location = Kosher::Location.new
|
23
|
+
location.country = hash['CountryCode']
|
24
|
+
location.state = hash['StateCode']
|
25
|
+
@seller.location = location
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Fassbinder
|
2
|
+
class ShippingBuilder
|
3
|
+
DEFAULT_SHIPPING_CENTS = { 'amazon.com' => 399,
|
4
|
+
'amazon.co.uk' => 280,
|
5
|
+
'amazon.de' => 299,
|
6
|
+
'amazon.ca' => 649,
|
7
|
+
'amazon.fr' => 300,
|
8
|
+
'amazon.co.jp' => 25000 }
|
9
|
+
|
10
|
+
attr_reader :shipping
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@shipping = Kosher::Shipping.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_availability(hours)
|
17
|
+
availability = Kosher::Availability.new
|
18
|
+
availability.hours = hours.to_i
|
19
|
+
@shipping.availability = availability
|
20
|
+
end
|
21
|
+
|
22
|
+
def calculate_price(is_free, venue, currency)
|
23
|
+
@shipping.cents = is_free ? 0 : DEFAULT_SHIPPING_CENTS[venue]
|
24
|
+
@shipping.currency = currency
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/fassbinder/version.rb
CHANGED
data/lib/fassbinder.rb
CHANGED
@@ -5,22 +5,52 @@ module Fassbinder
|
|
5
5
|
let(:request) { Request.new(credentials) }
|
6
6
|
|
7
7
|
describe ".new" do
|
8
|
-
it "
|
8
|
+
it "sets up an item request" do
|
9
9
|
request.parameters['Operation'].should eql 'ItemLookup'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "looks up ASINs" do
|
10
13
|
request.parameters['ItemLookup.Shared.IdType'].should eql 'ASIN'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "looks up all conditions" do
|
11
17
|
request.parameters['ItemLookup.Shared.Condition'].should eql 'All'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "looks up all merchants" do
|
12
21
|
request.parameters['ItemLookup.Shared.MerchantId'].should eql 'All'
|
13
|
-
|
22
|
+
end
|
23
|
+
|
24
|
+
it "looks up full offers" do
|
25
|
+
request.parameters['ItemLookup.Shared.ResponseGroup'].should eql ['OfferFull']
|
14
26
|
end
|
15
27
|
end
|
16
28
|
|
17
29
|
describe "#batchify" do
|
18
|
-
|
19
|
-
|
20
|
-
|
30
|
+
context "when passed one ASIN" do
|
31
|
+
it "adds the ASIN to the batch" do\
|
32
|
+
request.batchify('foo')
|
33
|
+
request.parameters['ItemLookup.1.ItemId'].should eql ['foo']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when passed up to 20 ASINs" do
|
38
|
+
it "adds the ASINs to the batch" do
|
39
|
+
asins = (0..19).to_a
|
40
|
+
request.batchify(asins)
|
41
|
+
|
42
|
+
request.parameters['ItemLookup.1.ItemId'].should eql (0..9).to_a
|
43
|
+
request.parameters['ItemLookup.2.ItemId'].should eql (10..19).to_a
|
44
|
+
end
|
45
|
+
end
|
21
46
|
|
22
|
-
|
23
|
-
|
47
|
+
context "when passed over 20 ASINs" do
|
48
|
+
it "raises an error" do
|
49
|
+
expect do
|
50
|
+
asins = (0..20).to_a
|
51
|
+
request.batchify(asins)
|
52
|
+
end.to raise_error ArgumentError
|
53
|
+
end
|
24
54
|
end
|
25
55
|
end
|
26
56
|
|
@@ -29,7 +59,7 @@ module Fassbinder
|
|
29
59
|
VCR.http_stubbing_adapter.http_connections_allowed = true
|
30
60
|
end
|
31
61
|
|
32
|
-
it "returns
|
62
|
+
it "returns a response" do
|
33
63
|
Request.stub!(:get)
|
34
64
|
|
35
65
|
request.locale = :us
|
@@ -21,13 +21,20 @@ module Fassbinder
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe ".new" do
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
context "when response is not valid" do
|
25
|
+
it "raises an error" do
|
26
|
+
response = mock('Response')
|
27
|
+
response.stub!(:valid?).and_return(false)
|
28
|
+
response.stub!(:has_errors?).and_return(true)
|
29
|
+
response.stub!(:errors).and_return([{
|
30
|
+
'Code' => 'AccountLimitExceeded',
|
31
|
+
'Message' => 'YOU FAIL'
|
32
|
+
}])
|
33
|
+
|
34
|
+
expect do
|
35
|
+
Response.new(response, :us)
|
36
|
+
end.to raise_error InvalidResponse, 'YOU FAIL'
|
37
|
+
end
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: fassbinder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.9
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Paper Cavalier
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-04-15 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - ~>
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.2.
|
24
|
+
version: 0.2.23
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -36,53 +36,20 @@ dependencies:
|
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
39
|
+
name: thor
|
40
40
|
prerelease: false
|
41
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
47
|
-
type: :
|
46
|
+
version: 0.14.6
|
47
|
+
type: :runtime
|
48
48
|
version_requirements: *id003
|
49
|
-
|
50
|
-
name: ruby-debug19
|
51
|
-
prerelease: false
|
52
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
|
-
requirements:
|
55
|
-
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: 0.11.6
|
58
|
-
type: :development
|
59
|
-
version_requirements: *id004
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: vcr
|
62
|
-
prerelease: false
|
63
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
-
none: false
|
65
|
-
requirements:
|
66
|
-
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 1.7.0
|
69
|
-
type: :development
|
70
|
-
version_requirements: *id005
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
|
-
name: webmock
|
73
|
-
prerelease: false
|
74
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
|
-
requirements:
|
77
|
-
- - ~>
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: 1.6.2
|
80
|
-
type: :development
|
81
|
-
version_requirements: *id006
|
82
|
-
description: Fassbinder wraps Amazon in a loving embrace.
|
49
|
+
description: Fassbinder crawls book offers on Amazon.
|
83
50
|
email: code@papercavalier.com
|
84
|
-
executables:
|
85
|
-
|
51
|
+
executables:
|
52
|
+
- rainer
|
86
53
|
extensions: []
|
87
54
|
|
88
55
|
extra_rdoc_files: []
|
@@ -93,11 +60,19 @@ files:
|
|
93
60
|
- LICENSE
|
94
61
|
- README.md
|
95
62
|
- Rakefile
|
63
|
+
- bin/rainer
|
96
64
|
- fassbinder.gemspec
|
97
65
|
- fassbinder.jpg
|
98
66
|
- lib/fassbinder.rb
|
67
|
+
- lib/fassbinder/book_builder.rb
|
68
|
+
- lib/fassbinder/cli.rb
|
69
|
+
- lib/fassbinder/errors.rb
|
70
|
+
- lib/fassbinder/item_builder.rb
|
71
|
+
- lib/fassbinder/offer_builder.rb
|
99
72
|
- lib/fassbinder/request.rb
|
100
73
|
- lib/fassbinder/response.rb
|
74
|
+
- lib/fassbinder/seller_builder.rb
|
75
|
+
- lib/fassbinder/shipping_builder.rb
|
101
76
|
- lib/fassbinder/version.rb
|
102
77
|
- spec/fassbinder/request_spec.rb
|
103
78
|
- spec/fassbinder/response_spec.rb
|
@@ -128,10 +103,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
103
|
requirements: []
|
129
104
|
|
130
105
|
rubyforge_project: fassbinder
|
131
|
-
rubygems_version: 1.
|
106
|
+
rubygems_version: 1.6.2
|
132
107
|
signing_key:
|
133
108
|
specification_version: 3
|
134
|
-
summary:
|
109
|
+
summary: Crawls book offers on Amazon
|
135
110
|
test_files:
|
136
111
|
- spec/fassbinder/request_spec.rb
|
137
112
|
- spec/fassbinder/response_spec.rb
|