remote_book 0.1.0
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 +5 -0
- data/Gemfile +10 -0
- data/README.rdoc +38 -0
- data/Rakefile +6 -0
- data/VERSION +1 -0
- data/lib/remote_book.rb +35 -0
- data/lib/remote_book/amazon.rb +89 -0
- data/lib/remote_book/barnes_and_noble.rb +46 -0
- data/lib/remote_book/base.rb +31 -0
- data/remote_book.gemspec +36 -0
- data/spec/fixtures/amazon_1433506254.xml +1 -0
- data/spec/lib/amazon_spec.rb +21 -0
- data/spec/lib/barnes_and_noble_spec.rb +16 -0
- data/spec/spec_helper.rb +30 -0
- data/tasks/spec.rake +33 -0
- metadata +78 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= RemoteBook
|
2
|
+
|
3
|
+
RemoteBook is a gem for creating affiliate links to Amazon & B&N for books.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
It's a gem. Either run `gem install remote_book` at the command line, or add `gem 'remote_book'` to your Gemfile.
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
Get your affiliate digits:
|
12
|
+
|
13
|
+
https://affiliate-program.amazon.com/
|
14
|
+
http://affiliates.barnesandnoble.com/ - sign up with LinkShare, wonder why Amazon is more popular
|
15
|
+
|
16
|
+
for rails, add something like this to an initializer
|
17
|
+
|
18
|
+
RemoteBook::Amazon.associate_keys = {:associates_id => "me",
|
19
|
+
:key_id => "digits",
|
20
|
+
:secret_key => "secret_digits"}
|
21
|
+
|
22
|
+
RemoteBook::BarnesAndNoble.associate_keys = {:web_service_token => "token"}
|
23
|
+
To get the token, login to LinkShare, Links => Web Services (something like: http://cli.linksynergy.com/cli/publisher/links/webServices.php)
|
24
|
+
|
25
|
+
Right now it just searches by ISBN, so:
|
26
|
+
|
27
|
+
a = RemoteBook::Amazon.find_by_isbn("somedigits")
|
28
|
+
a.large_image
|
29
|
+
a.medium_image
|
30
|
+
a.small_image
|
31
|
+
a.link
|
32
|
+
a.author
|
33
|
+
a.title
|
34
|
+
|
35
|
+
b = RemoteBook::BarnesAndNoble.find_by_isbn("digits")
|
36
|
+
b.link
|
37
|
+
|
38
|
+
Barnes And Noble's LinkShare api isn't really much of an API, so all the BN class returns is a link. The Barnes And Noble API is very slow, everything returned from these classes should be cached on your end. You have been warned.
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/remote_book.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "uri"
|
3
|
+
require "net/http"
|
4
|
+
require "openssl"
|
5
|
+
require "typhoeus"
|
6
|
+
require "nokogiri"
|
7
|
+
|
8
|
+
require "remote_book/base"
|
9
|
+
require "remote_book/amazon"
|
10
|
+
require "remote_book/barnes_and_noble"
|
11
|
+
|
12
|
+
module RemoteBook
|
13
|
+
VERSION = File.read(File.dirname(__FILE__) + "/../VERSION").chomp
|
14
|
+
|
15
|
+
def self.get_url(url, options = {:read_timeout => 2, :open_timeout => 2})
|
16
|
+
uri = URI.parse(url)
|
17
|
+
|
18
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
19
|
+
http.read_timeout = options[:read_timeout]
|
20
|
+
http.open_timeout = options[:open_timeout]
|
21
|
+
# this return structure is pretty ugly
|
22
|
+
begin
|
23
|
+
res = http.start { |web|
|
24
|
+
g = Net::HTTP::Get.new(uri.request_uri)
|
25
|
+
web.request(g)
|
26
|
+
}
|
27
|
+
rescue Timeout::Error
|
28
|
+
return {:body => "error: timeout", :status => :error}
|
29
|
+
rescue Exception => e
|
30
|
+
return {:body => "error: #{e}", :status => :error}
|
31
|
+
else
|
32
|
+
return res
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module RemoteBook
|
2
|
+
class Amazon < RemoteBook::Base
|
3
|
+
attr_accessor :large_image, :medium_image, :small_image, :authors, :title, :isbn, :digital_link
|
4
|
+
|
5
|
+
# FIXME: failed digest support should raise exception.
|
6
|
+
# mac os 10.5 does not ship with SHA256 support built into ruby, 10.6 does.
|
7
|
+
DIGEST_SUPPORT = ::OpenSSL::Digest.constants.include?('SHA256') || ::OpenSSL::Digest.constants.include?(:SHA256)
|
8
|
+
DIGEST = ::OpenSSL::Digest::Digest.new('sha256') if DIGEST_SUPPORT
|
9
|
+
|
10
|
+
def self.find(options)
|
11
|
+
a = new
|
12
|
+
# unless DIGEST_SUPPORT raise "no digest sup"
|
13
|
+
if options[:isbn]
|
14
|
+
req = build_isbn_lookup_query(options[:isbn])
|
15
|
+
response = RemoteBook.get_url(req)
|
16
|
+
|
17
|
+
if response.respond_to?(:code) && "200" == response.code
|
18
|
+
xml_doc = Nokogiri.XML(response.body)
|
19
|
+
else
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
if 1 == xml_doc.xpath("//xmlns:Items").size
|
24
|
+
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:LargeImage/xmlns:URL")
|
25
|
+
a.large_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:LargeImage/xmlns:URL").inner_text
|
26
|
+
end
|
27
|
+
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:MediumImage/xmlns:URL")
|
28
|
+
a.medium_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:MediumImage/xmlns:URL").inner_text
|
29
|
+
end
|
30
|
+
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:SmallImage/xmlns:URL")
|
31
|
+
a.small_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:SmallImage/xmlns:URL")
|
32
|
+
end
|
33
|
+
a.title = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemAttributes/xmlns:Title").inner_text
|
34
|
+
a.authors = []
|
35
|
+
xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemAttributes/xmlns:Author").each do |author|
|
36
|
+
a.authors << author.inner_text
|
37
|
+
end
|
38
|
+
# ewww
|
39
|
+
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemLinks/xmlns:ItemLink/xmlns:Description='Technical Details'")
|
40
|
+
xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemLinks/xmlns:ItemLink").each do |item_link|
|
41
|
+
if "Technical Details" == item_link.xpath("xmlns:Description").inner_text
|
42
|
+
a.link = item_link.xpath("xmlns:URL").inner_text
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return a
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def self.build_isbn_lookup_query(item_id)
|
53
|
+
base = "http://ecs.amazonaws.com/onca/xml"
|
54
|
+
query = "Service=AWSECommerceService&"
|
55
|
+
query << "AWSAccessKeyId=#{associate_keys[:key_id]}&"
|
56
|
+
query << "AssociateTag=#{associate_keys[:associates_id]}&"
|
57
|
+
query << "Operation=ItemLookup&"
|
58
|
+
query << "ItemId=#{item_id}&"
|
59
|
+
query << "ResponseGroup=ItemAttributes,Offers,Images&"
|
60
|
+
# query << "ResponseGroup=ItemAttributes&"
|
61
|
+
query << "Version=2009-07-01"
|
62
|
+
sig_query = sign_query base, query, associate_keys[:secret_key]
|
63
|
+
base + "?" + sig_query
|
64
|
+
end
|
65
|
+
# most of this is from http://www.justinball.com/2009/09/02/amazon-ruby-and-signing_authenticating-your-requests/
|
66
|
+
# which is actually from the ruby-aaws gem
|
67
|
+
def self.sign_query(uri, query, amazon_secret_access_key = "", locale = :us)
|
68
|
+
uri = URI.parse(uri)
|
69
|
+
# only add current timestamp if it's not in the query, a timestamp passed in via query takes precedence
|
70
|
+
# I'm only doing this so the checksum comes out correctly with the example from the amazon documentation
|
71
|
+
query << "&Timestamp=#{Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')}" unless query.include?("Timestamp")
|
72
|
+
new_query = query.split('&').collect{|param| "#{param.split('=')[0]}=#{url_encode(param.split('=')[1])}"}.sort.join('&')
|
73
|
+
to_sign = "GET\n%s\n%s\n%s" % [uri.host, uri.path, new_query]
|
74
|
+
# step 7 of http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html
|
75
|
+
hmac = OpenSSL::HMAC.digest(DIGEST, amazon_secret_access_key, to_sign)
|
76
|
+
base64_hmac = [hmac].pack('m').chomp
|
77
|
+
signature = url_encode(base64_hmac)
|
78
|
+
|
79
|
+
new_query << "&Signature=#{signature}"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Shamelessly plagiarised from Wakou Aoyama's cgi.rb, but then altered slightly to please AWS.
|
83
|
+
def self.url_encode(str)
|
84
|
+
str.gsub( /([^a-zA-Z0-9_.~-]+)/ ) do
|
85
|
+
'%' + $1.unpack( 'H2' * $1.bytesize ).join( '%' ).upcase
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module RemoteBook
|
2
|
+
class BarnesAndNoble < RemoteBook::Base
|
3
|
+
ISBN_SEARCH_BASE_URI = "http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?ISBSRC=Y&ISBN="
|
4
|
+
LINK_SHARE_DEEP_LINK_BASE = "http://getdeeplink.linksynergy.com/createcustomlink.shtml"
|
5
|
+
BN_LINK_SHARE_MID = "36889"
|
6
|
+
|
7
|
+
def self.find(options)
|
8
|
+
b = new
|
9
|
+
if options[:isbn]
|
10
|
+
bn_page = barnes_and_noble_page_link_for(options[:isbn])
|
11
|
+
return nil unless bn_page
|
12
|
+
|
13
|
+
b.link = link_share_deep_link_for(bn_page)
|
14
|
+
end
|
15
|
+
b
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def self.build_isbn_lookup_query(isbn)
|
20
|
+
ISBN_SEARCH_BASE_URI + isbn
|
21
|
+
end
|
22
|
+
# pass the ISBN to the search service, read the redirect information, and use that as store link
|
23
|
+
def self.barnes_and_noble_page_link_for(isbn)
|
24
|
+
search_path = build_isbn_lookup_query(isbn)
|
25
|
+
response = RemoteBook.get_url(search_path, :read_timeout => 6, :open_timeout => 4)
|
26
|
+
if response.respond_to?(:each_header)
|
27
|
+
response.each_header do |name, value|
|
28
|
+
return value if "location" == name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
false
|
32
|
+
end
|
33
|
+
# based on a pdf linked at the bottom of this page: http://helpcenter.linkshare.com/publisher/questions.php?questionid=61
|
34
|
+
# direct pdf link (working 20 aug 2011):
|
35
|
+
# http://helpcenter.linkshare.com/publisher/getattachment.php?data=NjF8QXV0b21hdGVkIExpbmtHZW5lcmF0b3IgMi4xLS1NYXkgMjAxMS5wZGY%3D
|
36
|
+
def self.link_share_deep_link_for(url)
|
37
|
+
token = associate_keys[:web_service_token]
|
38
|
+
deep_link_lookup = LINK_SHARE_DEEP_LINK_BASE + "?token=" + token + "&mid=" + BN_LINK_SHARE_MID + "&murl=" + url
|
39
|
+
a = RemoteBook.get_url(deep_link_lookup, :read_timeout => 6, :open_timeout => 4)
|
40
|
+
if a.response.respond_to?(:code) && "200" == a.response.code
|
41
|
+
return a.response.body
|
42
|
+
end
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RemoteBook
|
2
|
+
class Base
|
3
|
+
attr_accessor :link, :isbn
|
4
|
+
|
5
|
+
def author
|
6
|
+
@authors.join(", ")
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def associate_keys
|
11
|
+
@@associate_keys ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def associate_keys=(obj)
|
15
|
+
@@associate_keys = obj
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup
|
19
|
+
yield self
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_by_isbn(isbn)
|
23
|
+
find(:isbn => isbn)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find(options)
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/remote_book.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "remote_book"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "remote_book"
|
7
|
+
s.version = RemoteBook::VERSION
|
8
|
+
s.authors = ["Seth Faxon"]
|
9
|
+
s.email = ["seth.faxon@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/sfaxon/remote_book"
|
11
|
+
s.summary = %q{Pull book affiliate links and images from Amazon, Barns & Noble}
|
12
|
+
s.description = %q{Pull book affiliate links and images from Amazon, Barns & Noble}
|
13
|
+
|
14
|
+
s.rubyforge_project = "remote_book"
|
15
|
+
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
s.specification_version = 3
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<nokogiri>)
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<nokogiri>)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<nokogiri>)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0" ?><ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2009-07-01"><OperationRequest><HTTPHeaders><Header Name="UserAgent" Value="Typhoeus - http://github.com/dbalatero/typhoeus/tree/master"></Header></HTTPHeaders><RequestId>463d3e16-ef6a-4ed0-b4f5-300b26e1aad7</RequestId><Arguments><Argument Name="Operation" Value="ItemLookup"></Argument><Argument Name="Service" Value="AWSECommerceService"></Argument><Argument Name="Signature" Value="usV9ajvcYWKBk4NWIS7STUtvelKgBlWJGGxWhQAhIGQ="></Argument><Argument Name="AssociateTag" Value="theresurgence-20"></Argument><Argument Name="Version" Value="2009-07-01"></Argument><Argument Name="ItemId" Value="1433506254"></Argument><Argument Name="AWSAccessKeyId" Value="1A7ETSHYVGJVYADTM6G2"></Argument><Argument Name="Timestamp" Value="2011-08-20T03:56:30Z"></Argument><Argument Name="ResponseGroup" Value="ItemAttributes,Offers,Images"></Argument></Arguments><RequestProcessingTime>0.0422470000000000</RequestProcessingTime></OperationRequest><Items><Request><IsValid>True</IsValid><ItemLookupRequest><Condition>New</Condition><DeliveryMethod>Ship</DeliveryMethod><IdType>ASIN</IdType><MerchantId>Amazon</MerchantId><OfferPage>1</OfferPage><ItemId>1433506254</ItemId><ResponseGroup>ItemAttributes</ResponseGroup><ResponseGroup>Offers</ResponseGroup><ResponseGroup>Images</ResponseGroup><ReviewPage>1</ReviewPage><ReviewSort>-SubmissionDate</ReviewSort><VariationPage>All</VariationPage></ItemLookupRequest></Request><Item><ASIN>1433506254</ASIN><DetailPageURL>http://www.amazon.com/Doctrine-What-Christians-Should-Believe/dp/1433506254%3FSubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1433506254</DetailPageURL><ItemLinks><ItemLink><Description>Technical Details</Description><URL>http://www.amazon.com/Doctrine-What-Christians-Should-Believe/dp/tech-data/1433506254%3FSubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>Add To Baby Registry</Description><URL>http://www.amazon.com/gp/registry/baby/add-item.html%3Fasin.0%3D1433506254%26SubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>Add To Wedding Registry</Description><URL>http://www.amazon.com/gp/registry/wedding/add-item.html%3Fasin.0%3D1433506254%26SubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>Add To Wishlist</Description><URL>http://www.amazon.com/gp/registry/wishlist/add-item.html%3Fasin.0%3D1433506254%26SubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>Tell A Friend</Description><URL>http://www.amazon.com/gp/pdp/taf/1433506254%3FSubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>All Customer Reviews</Description><URL>http://www.amazon.com/review/product/1433506254%3FSubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink><ItemLink><Description>All Offers</Description><URL>http://www.amazon.com/gp/offer-listing/1433506254%3FSubscriptionId%3D1A7ETSHYVGJVYADTM6G2%26tag%3Dtheresurgence-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3D1433506254</URL></ItemLink></ItemLinks><SmallImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL75_.jpg</URL><Height Units="pixels">75</Height><Width Units="pixels">47</Width></SmallImage><MediumImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL160_.jpg</URL><Height Units="pixels">160</Height><Width Units="pixels">100</Width></MediumImage><LargeImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL.jpg</URL><Height Units="pixels">500</Height><Width Units="pixels">313</Width></LargeImage><ImageSets><ImageSet Category="primary"><SwatchImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL30_.jpg</URL><Height Units="pixels">30</Height><Width Units="pixels">19</Width></SwatchImage><SmallImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL75_.jpg</URL><Height Units="pixels">75</Height><Width Units="pixels">47</Width></SmallImage><ThumbnailImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL75_.jpg</URL><Height Units="pixels">75</Height><Width Units="pixels">47</Width></ThumbnailImage><TinyImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL110_.jpg</URL><Height Units="pixels">110</Height><Width Units="pixels">69</Width></TinyImage><MediumImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL._SL160_.jpg</URL><Height Units="pixels">160</Height><Width Units="pixels">100</Width></MediumImage><LargeImage><URL>http://ecx.images-amazon.com/images/I/41xMfBAsMnL.jpg</URL><Height Units="pixels">500</Height><Width Units="pixels">313</Width></LargeImage></ImageSet></ImageSets><ItemAttributes><Author>Mark Driscoll</Author><Author>Gerry Breshears</Author><Binding>Hardcover</Binding><DeweyDecimalNumber>230</DeweyDecimalNumber><EAN>9781433506253</EAN><Feature>ISBN13: 9781433506253</Feature><Feature>Condition: New</Feature><Feature>Notes: BRAND NEW FROM PUBLISHER! 100% Satisfaction Guarantee. Tracking provided on most orders. Buy with Confidence! Millions of books sold!</Feature><ISBN>1433506254</ISBN><Label>Crossway Books</Label><Languages><Language><Name>English</Name><Type>Unknown</Type></Language><Language><Name>English</Name><Type>Original Language</Type></Language><Language><Name>English</Name><Type>Published</Type></Language></Languages><ListPrice><Amount>2299</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$22.99</FormattedPrice></ListPrice><Manufacturer>Crossway Books</Manufacturer><NumberOfItems>1</NumberOfItems><NumberOfPages>464</NumberOfPages><PackageDimensions><Height Units="hundredths-inches">118</Height><Length Units="hundredths-inches">858</Length><Weight Units="hundredths-pounds">163</Weight><Width Units="hundredths-inches">575</Width></PackageDimensions><ProductGroup>Book</ProductGroup><ProductTypeName>ABIS_BOOK</ProductTypeName><PublicationDate>2010-03-18</PublicationDate><Publisher>Crossway Books</Publisher><SKU>ST1433506254</SKU><Studio>Crossway Books</Studio><Title>Doctrine: What Christians Should Believe (RE: Lit)</Title></ItemAttributes><OfferSummary><LowestNewPrice><Amount>1417</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$14.17</FormattedPrice></LowestNewPrice><LowestUsedPrice><Amount>1401</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$14.01</FormattedPrice></LowestUsedPrice><TotalNew>51</TotalNew><TotalUsed>17</TotalUsed><TotalCollectible>0</TotalCollectible><TotalRefurbished>0</TotalRefurbished></OfferSummary><Offers><TotalOffers>1</TotalOffers><TotalOfferPages>1</TotalOfferPages><Offer><Merchant><MerchantId>ATVPDKIKX0DER</MerchantId><GlancePage>http://www.amazon.com/gp/help/seller/home.html?seller=ATVPDKIKX0DER</GlancePage><AverageFeedbackRating>0.0</AverageFeedbackRating><TotalFeedback>0</TotalFeedback></Merchant><OfferAttributes><Condition>New</Condition><SubCondition>new</SubCondition></OfferAttributes><OfferListing><OfferListingId>EDEpY3kBcSJkX8ndCQNbHcnumz1mrH3F8xPIujEqFichzusTRh3rVJUdhhGrfe8uT14X%2BoEWy4PRueVjhcDpA9pREsiD%2BUqm8BNGILgpLbGw1OunCi792Q%3D%3D</OfferListingId><Price><Amount>1503</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$15.03</FormattedPrice></Price><AmountSaved><Amount>796</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$7.96</FormattedPrice></AmountSaved><PercentageSaved>35</PercentageSaved><Availability>Usually ships in 24 hours</Availability><AvailabilityAttributes><AvailabilityType>now</AvailabilityType><MinimumHours>0</MinimumHours><MaximumHours>0</MaximumHours></AvailabilityAttributes><Quantity>-1</Quantity><IsEligibleForSuperSaverShipping>1</IsEligibleForSuperSaverShipping></OfferListing></Offer></Offers></Item></Items></ItemLookupResponse>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RemoteBook::Amazon do
|
4
|
+
before(:each) do
|
5
|
+
RemoteBook::Amazon.associate_keys = {:associates_id => 'foo',
|
6
|
+
:key_id => 'bar',
|
7
|
+
:secret_key => 'baz'}
|
8
|
+
end
|
9
|
+
it "should set large_image on successful get" do
|
10
|
+
FakeWeb.register_uri(:get, %r|http://ecs\.amazonaws\.com/(.*)|, :body => load_file("amazon_1433506254.xml"))
|
11
|
+
a = RemoteBook::Amazon.find_by_isbn("1433506254")
|
12
|
+
a.large_image.should == "http://ecx.images-amazon.com/images/I/41xMfBAsMnL.jpg"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "find_by_isbn should return false when error code returned by web service" do
|
16
|
+
FakeWeb.register_uri(:get, %r|http://ecs\.amazonaws\.com/(.*)|, :body => "Error", :status => ["404", "not found"])
|
17
|
+
a = RemoteBook::Amazon.find_by_isbn("unicorn")
|
18
|
+
a.should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RemoteBook::BarnesAndNoble do
|
4
|
+
before(:each) do
|
5
|
+
RemoteBook::BarnesAndNoble.associate_keys = {:web_service_token => 'doesntmatterfortest'}
|
6
|
+
end
|
7
|
+
it "should set link on successful get" do
|
8
|
+
dest = "http://click.linksynergy.com/fs-bin/some_ugly_path"
|
9
|
+
FakeWeb.register_uri(:get, RemoteBook::BarnesAndNoble::ISBN_SEARCH_BASE_URI+"1433506254",
|
10
|
+
:body => "redirect",
|
11
|
+
:location => "http://search.barnesandnoble.com/bookpath/")
|
12
|
+
FakeWeb.register_uri(:get, %r|http://getdeeplink\.linksynergy\.com/(.*)|, :body => dest)
|
13
|
+
a = RemoteBook::BarnesAndNoble.find_by_isbn("1433506254")
|
14
|
+
a.link.should == dest
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
2
|
+
# in spec/support/ and its subdirectories.
|
3
|
+
# Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
4
|
+
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
|
5
|
+
|
6
|
+
require 'fakeweb'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
# == Mock Framework
|
10
|
+
#
|
11
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
12
|
+
#
|
13
|
+
# config.mock_with :mocha
|
14
|
+
# config.mock_with :flexmock
|
15
|
+
# config.mock_with :rr
|
16
|
+
config.mock_with :rspec
|
17
|
+
|
18
|
+
FakeWeb.allow_net_connect = false
|
19
|
+
|
20
|
+
config.before(:each) do
|
21
|
+
FakeWeb.clean_registry
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_file(name)
|
26
|
+
file = File.open("spec/fixtures/#{name}", "rb")
|
27
|
+
contents = file.read
|
28
|
+
file.close
|
29
|
+
return contents
|
30
|
+
end
|
data/tasks/spec.rake
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
ENV['BUNDLE_GEMFILE'] = File.dirname(__FILE__) + '/../Gemfile'
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rspec'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
desc "Run the test suite"
|
9
|
+
task :spec => ['spec:setup', 'spec:remote_book_lib', 'spec:cleanup']
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
desc "Setup the test environment"
|
13
|
+
task :setup do
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Cleanup the test environment"
|
17
|
+
task :cleanup do
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Test the remote_book library"
|
21
|
+
RSpec::Core::RakeTask.new(:remote_book_lib) do |task|
|
22
|
+
remote_book_root = File.expand_path(File.dirname(__FILE__) + '/..')
|
23
|
+
task.pattern = remote_book_root + '/spec/lib/**/*_spec.rb'
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Run the coverage report"
|
27
|
+
RSpec::Core::RakeTask.new(:rcov) do |task|
|
28
|
+
remote_book_root = File.expand_path(File.dirname(__FILE__) + '/..')
|
29
|
+
task.pattern = remote_book_root + '/spec/lib/**/*_spec.rb'
|
30
|
+
task.rcov=true
|
31
|
+
task.rcov_opts = %w{--rails --exclude osx\/objc,gems\/,spec\/,features\/}
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remote_book
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Seth Faxon
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-20 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
requirement: &70195227487660 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70195227487660
|
26
|
+
description: Pull book affiliate links and images from Amazon, Barns & Noble
|
27
|
+
email:
|
28
|
+
- seth.faxon@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README.rdoc
|
37
|
+
- Rakefile
|
38
|
+
- VERSION
|
39
|
+
- lib/remote_book.rb
|
40
|
+
- lib/remote_book/amazon.rb
|
41
|
+
- lib/remote_book/barnes_and_noble.rb
|
42
|
+
- lib/remote_book/base.rb
|
43
|
+
- remote_book.gemspec
|
44
|
+
- spec/fixtures/amazon_1433506254.xml
|
45
|
+
- spec/lib/amazon_spec.rb
|
46
|
+
- spec/lib/barnes_and_noble_spec.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- tasks/spec.rake
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: https://github.com/sfaxon/remote_book
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project: remote_book
|
70
|
+
rubygems_version: 1.6.2
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Pull book affiliate links and images from Amazon, Barns & Noble
|
74
|
+
test_files:
|
75
|
+
- spec/fixtures/amazon_1433506254.xml
|
76
|
+
- spec/lib/amazon_spec.rb
|
77
|
+
- spec/lib/barnes_and_noble_spec.rb
|
78
|
+
- spec/spec_helper.rb
|