Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rework initilizaton for cleaner public API.
- Loading branch information
Showing
10 changed files
with
184 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# RemoteBook | ||
|
||
RemoteBook is a gem for searching Amazon & B&N for books. Returned links have associate information in the links. | ||
|
||
## Installation | ||
|
||
It's a gem. Either run `gem install remote_book` at the command line, or add `gem 'remote_book'` to your Gemfile. | ||
|
||
## Usage | ||
|
||
Get your affiliate digits: | ||
|
||
https://affiliate-program.amazon.com/ | ||
http://affiliates.barnesandnoble.com/ - sign up with LinkShare | ||
|
||
for rails, run the install generator: | ||
|
||
add something like this to an initializer | ||
|
||
RemoteBook::Amazon.associate_keys = {:associates_id => "me", | ||
:key_id => "digits", | ||
:secret_key => "secret_digits"} | ||
|
||
Right now it just searches by ISBN, so: | ||
|
||
a = RemoteBook::Amazon.find_by_isbn("somedigits") | ||
a.large_image | ||
a.medium_image | ||
a.small_image | ||
a.link | ||
a.author | ||
a.title | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,12 @@ | ||
require "remote_book/version" | ||
require "remote_book/remote_book" | ||
require "remote_book/amazon_book" | ||
require "rubygems" | ||
require "uri" | ||
require "openssl" | ||
require "typhoeus" | ||
require "nokogiri" | ||
|
||
require "remote_book/base" | ||
require "remote_book/amazon" | ||
|
||
module RemoteBook | ||
# Your code goes here... | ||
VERSION = File.read(File.dirname(__FILE__) + "/../VERSION").chomp | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
module RemoteBook | ||
class Amazon < RemoteBook::Base | ||
# mac os 10.5 does not ship with SHA256 support built into ruby, 10.6 does. | ||
DIGEST_SUPPORT = ::OpenSSL::Digest.constants.include?('SHA256') || ::OpenSSL::Digest.constants.include?(:SHA256) | ||
DIGEST = ::OpenSSL::Digest::Digest.new('sha256') if DIGEST_SUPPORT | ||
|
||
def self.find(options) | ||
a = new | ||
# unless DIGEST_SUPPORT raise "no digest sup" | ||
if options[:isbn] | ||
req = build_isbn_lookup_query(options[:isbn]) | ||
response = Typhoeus::Request.get(req) | ||
|
||
if 200 == response.code | ||
xml_doc = Nokogiri.XML(response.body) | ||
else | ||
return false | ||
end | ||
|
||
if 1 == xml_doc.xpath("//xmlns:Items").size | ||
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:LargeImage/xmlns:URL") | ||
a.large_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:LargeImage/xmlns:URL").inner_text | ||
end | ||
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:MediumImage/xmlns:URL") | ||
a.medium_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:MediumImage/xmlns:URL").inner_text | ||
end | ||
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:SmallImage/xmlns:URL") | ||
a.small_image = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:SmallImage/xmlns:URL") | ||
end | ||
a.title = xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemAttributes/xmlns:Title").inner_text | ||
a.authors = [] | ||
xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemAttributes/xmlns:Author").each do |author| | ||
a.authors << author.inner_text | ||
end | ||
# ewww | ||
if xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemLinks/xmlns:ItemLink/xmlns:Description='Technical Details'") | ||
xml_doc.xpath("//xmlns:Items/xmlns:Item/xmlns:ItemLinks/xmlns:ItemLink").each do |item_link| | ||
if "Technical Details" == item_link.xpath("xmlns:Description").inner_text | ||
a.link = item_link.xpath("xmlns:URL").inner_text | ||
end | ||
end | ||
end | ||
end | ||
end | ||
return a | ||
end | ||
|
||
private | ||
def self.build_isbn_lookup_query(item_id) | ||
base = "http://ecs.amazonaws.com/onca/xml" | ||
query = "Service=AWSECommerceService&" | ||
query << "AWSAccessKeyId=#{associate_keys[:key_id]}&" | ||
query << "AssociateTag=#{associate_keys[:associates_id]}&" | ||
query << "Operation=ItemLookup&" | ||
query << "ItemId=#{item_id}&" | ||
query << "ResponseGroup=ItemAttributes,Offers,Images&" | ||
# query << "ResponseGroup=ItemAttributes&" | ||
query << "Version=2009-07-01" | ||
sig_query = sign_query base, query, associate_keys[:secret_key] | ||
base + "?" + sig_query | ||
end | ||
# most of this is from http://www.justinball.com/2009/09/02/amazon-ruby-and-signing_authenticating-your-requests/ | ||
# which is actually from the ruby-aaws gem | ||
def self.sign_query(uri, query, amazon_secret_access_key = "", locale = :us) | ||
uri = URI.parse(uri) | ||
# only add current timestamp if it's not in the query, a timestamp passed in via query takes precedence | ||
# I'm only doing this so the checksum comes out correctly with the example from the amazon documentation | ||
query << "&Timestamp=#{Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')}" unless query.include?("Timestamp") | ||
new_query = query.split('&').collect{|param| "#{param.split('=')[0]}=#{url_encode(param.split('=')[1])}"}.sort.join('&') | ||
# puts new_query | ||
to_sign = "GET\n%s\n%s\n%s" % [uri.host, uri.path, new_query] | ||
# step 7 of http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html | ||
hmac = OpenSSL::HMAC.digest(DIGEST, amazon_secret_access_key, to_sign) | ||
base64_hmac = [hmac].pack('m').chomp | ||
signature = url_encode(base64_hmac) | ||
|
||
new_query << "&Signature=#{signature}" | ||
end | ||
|
||
# Shamelessly plagiarised from Wakou Aoyama's cgi.rb, but then altered slightly to please AWS. | ||
def self.url_encode(str) | ||
str.gsub( /([^a-zA-Z0-9_.~-]+)/ ) do | ||
'%' + $1.unpack( 'H2' * $1.bytesize ).join( '%' ).upcase | ||
end | ||
end | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module RemoteBook | ||
class Base | ||
attr_accessor :large_image, :medium_image, :small_image, :link, :authors, :title, :isbn, :digital_link | ||
|
||
def author | ||
@authors.join(", ") | ||
end | ||
|
||
class << self | ||
def associate_keys | ||
@@associate_keys ||= {} | ||
end | ||
|
||
def associate_keys=(obj) | ||
@@associate_keys = obj | ||
end | ||
|
||
def setup | ||
yield self | ||
end | ||
|
||
def find_by_isbn(isbn) | ||
self.find(:isbn => isbn) | ||
end | ||
|
||
def find(options) | ||
|
||
end | ||
end | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,35 @@ | ||
# -*- encoding: utf-8 -*- | ||
$:.push File.expand_path("../lib", __FILE__) | ||
require "remote_book/version" | ||
require "remote_book" | ||
|
||
Gem::Specification.new do |s| | ||
s.name = "remote_book" | ||
s.version = RemoteBook::VERSION | ||
s.authors = ["Seth Faxon"] | ||
s.email = ["seth.faxon@gmail.com"] | ||
s.homepage = "" | ||
s.summary = %q{TODO: Write a gem summary} | ||
s.description = %q{TODO: Write a gem description} | ||
s.summary = %q{Pull book affiliate links and images from Amazon, Barns & Noble} | ||
s.description = %q{Pull book affiliate links and images from Amazon, Barns & Noble} | ||
|
||
s.rubyforge_project = "remote_book" | ||
|
||
s.files = `git ls-files`.split("\n") | ||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") | ||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } | ||
s.require_paths = ["lib"] | ||
|
||
if s.respond_to? :specification_version then | ||
s.specification_version = 3 | ||
|
||
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then | ||
s.add_runtime_dependency(%q<typhoeus>) | ||
s.add_runtime_dependency(%q<nokogiri>) | ||
else | ||
s.add_dependency(%q<typhoeus>) | ||
s.add_dependency(%q<nokogiri>) | ||
end | ||
else | ||
s.add_dependency(%q<typhoeus>) | ||
s.add_dependency(%q<nokogiri>) | ||
end | ||
end |