普通に AWS で ISBN から書籍情報を取得するグリモンのテスト

なんのひねりもないけど、CrossBookSearch から青空文庫とか検索するのに使おうかと思っている。
ASIN = ISBN10 が前提。

// ==UserScript==
// @name           TestAWSECS
// @namespace      http://d.hatena.ne.jp/hetappi
// @include        http://www.amazon.co.jp/*
// ==/UserScript==

var isbn = document.evaluate(
  'normalize-space(//li[b/text()="ISBN-10:"]/text())', document, null, XPathResult.STRING_TYPE, null
).stringValue;
if (!isbn)
  return;

getBook(isbn, function(book) {
  console.log(book);
});

function getBook(isbn, callback) {
  var keyId = 'XXXXXXXXXXXXXXXXXX';
  new AWSECS(keyId).itemLookup(isbn, callback);
}

function AWSECS(accessKeyId) {
  return {
    _util: new Util(),
    _url: 'http://webservices.amazon.co.jp/onca/xml',
    _service: 'AWSECommerceService',
    _accessKeyId: accessKeyId,
    _getUrl: function(args) {
      return this._util.getUrl(
        this._url,
        this._util.merge({ Service: this._service, 'AWSAccessKeyId': this._accessKeyId }, args)
      );
    },
    _request: function(url, callback) {
      var opts = {
        method: 'get',
        url: url,
        onerror: function(resp) {
          callback(null);
        },
        onload: function(resp) {
          var doc = (new DOMParser).parseFromString(resp.responseText, 'text/xml');
          callback(doc);
        }
      };
      GM_xmlhttpRequest(opts);
    },

    itemLookup: function(itemId, callback) {
      this._request(
        this._getUrl({ Operation: 'ItemLookup', ItemId: itemId }), function(doc) {
          callback({
            author: doc.getElementsByTagName('Author')[0].textContent,
            title:  doc.getElementsByTagName('Title')[0].textContent
          });
        }
      );
    }
  }
}

function Util() {
  return {
    keys: function(obj) {
      var keys = [];
      for (var key in obj) {
        if (!obj.hasOwnProperty(key))
          continue;
        keys.push(key);
      }
      return keys;
    },
    getUrl: function(url, params) {
      return url + '?' + this.keys(params).map(function(key) { return key + '=' + params[key] }).join('&');
    },
    merge: function(l, r) {
      this.keys(r).forEach(function(key) { l[key] = r[key] });
      return l;
    }
  }
}