Listing 3. xmlrpc-lookup.rb #!/usr/bin/ruby require 'net/http' require 'rexml/document' require 'xmlrpc/server' # Set our regular expressions not_in_collection_re = /class="yourEntryWouldBeHereData"/ix on_shelf_re = /CHECK\s+SHELF/ix checked_out_re = /DUE /ix # ------------------------------------------------------------ # XML-RPC # ------------------------------------------------------------ # Start an HTTP server on port 8080, to listen for clients server = XMLRPC::Server.new(8080) server.add_handler(name="atf.books", signature=['array', 'array']) do |isbns| output = [ ] # Iterate through each of our arguments isbns.each do |isbn| isbn_output = {'ISBN' => isbn} # Ignore non-ISBN arguments if not isbn.match(/^[0-9xX]{10}$/) isbn_output['message'] = "ISBN #{isbn} is invalid." output << isbn_output next end # ------------------------------------------------------------ # Amazon # ------------------------------------------------------------ # Put together an Amazon parameter string amazon_params = {'Service' => 'AWSECommerceService', 'Operation' => 'ItemLookup', 'AWSAccessKeyId' => 'XXX', 'ItemId' => isbn, 'ResponseGroup' => 'Medium,OfferFull', 'MerchantId' => 'All'}.map {|key,value| "#{key}=#{value}"}.join("&") # Ask Amazon what it knows about our ISBN amazon_response = Net::HTTP.get_response('webservices.amazon.com', '/onca/xml?' << amazon_params) xml = REXML::Document.new(amazon_response.body) # Get the lowest new, used, and collectible prices new_price = xml.root.elements["Items/Item/OfferSummary/LowestNewPrice/FormattedPrice"] if new_price.nil? isbn_output['New'] = "None available" else isbn_output['New'] = new_price.text end used_price = xml.root.elements["Items/Item/OfferSummary/LowestUsedPrice/FormattedPrice"] if used_price.nil? isbn_output['Used'] = "None available" else isbn_output['Used'] = used_price.text end collectible_price = xml.root.elements["Items/Item/OfferSummary/LowestCollectiblePrice/FormattedPrice"] if collectible_price.nil? isbn_output['Collectible'] = "None available" else isbn_output['Collectible'] = collectible_price.text end # ------------------------------------------------------------ # Library # ------------------------------------------------------------ # Ask the library what it knows about our ISBN library_response = Net::HTTP.get_response('catalog.skokie.lib.il.us', "/search~S4/i?SEARCH=#{isbn}") # Check our regular expressions against the HTML response if not_in_collection_re.match(library_response.body) isbn_output['Library'] = "Library: Not in the Skokie collection." elsif checked_out_re.match(library_response.body) isbn_output['Library'] = "Checked out." elsif on_shelf_re.match(library_response.body) isbn_output['Library'] = "On the shelf." else isbn_output['Library'] = "Unparseable response." end output << isbn_output end output end server.serve