Last active
May 12, 2016 00:00
-
-
Save satyr/29674 to your computer and use it in GitHub Desktop.
amazon.co.jp (Ubiquity 0.5.4+)
This file contains hidden or 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
var Name = 'jamazon', | |
Jamazon = 'http://www.amazon.co.jp/', | |
ItemMax = 35, | |
Logo = '<a class="logo" href="'+ Jamazon +'" accesskey="0">' | |
+ '<img border="0" width="126" height="28" align="middle" src="' | |
+ 'http://g-ecx.images-amazon.com/images/G/09/gno/images/general/' | |
+ 'navAmazonLogoFooter._V28243234_.gif' | |
+ '"/></a>', | |
Base = '<style>\ | |
.head {padding:0 0.4em}\ | |
.results, .features {margin:0; padding:0; list-style:none}\ | |
.item img {float:right; border:none; margin:0 0.2em 0.2em 0}\ | |
.query, .num, .price {font-weight:bold}\ | |
.num, li {margin:0 0 0.2em}\ | |
.price, .author, .label, .features {font-size:92%}\ | |
.query::before, .query::after {content:\'"\'}\ | |
.num::before {content:"Total: "}\ | |
.num {float:right}\ | |
.price {white-space:nowrap}\ | |
.features li:before {content:"\\2022 "}\ | |
.button {padding:0; border-width:1px; font:bold 92% monospace}\ | |
.item {clear:both}\ | |
.error {font-style:oblique; line-height:1.8}\ | |
.loading {opacity:0.9}\ | |
.loading + .logo {opacity:0.4}\ | |
.error + .logo {opacity:0.7}\ | |
</style>'+ | |
'<div class='+ Name +'><div id='+ Name +'></div>'+ Logo +'</div>', | |
Categories = { | |
'All すべて': ['All', 'aps', ['u', 'default']], | |
'Apparel 服&ファッション小物': ['Apparel', 'apparel'], | |
'Automotive カー&バイク用品': ['Automotive', 'automotive'], | |
'Baby ベビー&マタニティ': ['Baby', 'baby'], | |
'Beauty コスメ': ['Beauty', 'beauty'], | |
'Books 和書': ['Books', 'stripbooks'], | |
'Classical クラシック音楽': ['Classical', 'classical'], | |
'DVD DVD': ['DVD', 'dvd'], | |
'Electronics 家電&カメラ': ['Electronics', 'electronics'], | |
'ForeignBooks 洋書': ['ForeignBooks', 'english-books'], | |
'Grocery 食品&飲料': ['Grocery', 'food-beverage'], | |
'HealthPersonalCare ヘルス&ビューティー': ['HealthPersonalCare', 'hpc'], | |
'Hobbies ホビー': ['Hobbies', 'hobby'], | |
'Jewelry ジュエリー': ['Jewelry', 'jewelry'], | |
'KindleStore Kindleストア': ['KindleStore', 'digital-text'], | |
'Kitchen ホーム&キッチン': ['Kitchen', 'kitchen'], | |
'MobileApps Androidアプリ': ['MobileApps', 'mobile-apps'], | |
'MP3Downloads MP3ミュージック': ['MP3Downloads', 'digital-music'], | |
'Music ミュージック': ['Music', 'popular'], | |
'MusicalInstruments 楽器': ['MusicalInstruments', 'mi'], | |
'OfficeProducts 文房具・オフィス用品': ['OfficeProducts', 'office-products'], | |
'Shoes&Bags シューズ&バッグ': ['Shoes', 'shoes'], | |
'Software PCソフト': ['Software', 'software'], | |
'SportingGoods スポーツ&アウトドア': ['SportingGoods', 'sporting'], | |
'Toys おもちゃ': ['Toys', 'toys'], | |
'VHS ビデオ': ['VHS', 'vhs'], | |
'VideoGames TVゲーム': ['VideoGames', 'videogames'], | |
'Watches 時計': ['Watches', 'watch'], | |
}, | |
CategoList = (function(){ | |
var xml = '<ul id="jamazon-categories" style="-moz-column-count:2">' | |
for(var [c, [k,, x]] in new Iterator(Categories)) | |
xml += '<li class="'+ k +'">' | |
+ [x && '<'+ x[0] +' title="'+ x[1] +'">'] | |
+ Utils.escapeHtml(c) | |
+ [x && '</'+ x[0] +'>'] | |
+ '</li>' | |
return xml +'</ul>' | |
}()), | |
H = Utils.escapeHtml | |
function ng(c){ | |
c.textContent = Array.slice(arguments, 1).join(' '); | |
c.className = 'error'; | |
} | |
function joinq($_, sel, delim){ | |
return $_.find(sel).map((_, x) => x.textContent).get().join(delim || ' ') | |
} | |
function onclick(e){ | |
var b = e.target; | |
if(b.type !== "button") return; | |
e.preventDefault(); | |
b.disabled = true; | |
Utils.openUrlInBrowser(b.title); | |
} | |
var amazEnc = (str) => | |
encodeURIComponent(str).replace(/[!\'()*]+/g, (s) => escape(s, 0)) | |
function amazSig(endp, reqp, params){ | |
var ps = $.extend({ | |
Timestamp: new Date().toISOString().slice(0, -5) +'Z', | |
AssociateTag: 'matyr-22', | |
AWSAccessKeyId: '0SP5F78NM10ZVNWWG482', | |
SignatureMethod: 'HmacSHA256', | |
SignatureVersion: 2, | |
}, params); | |
var sps = Object.keys(ps).map(k => k +'='+ amazEnc(ps[k])).sort().join('&'); | |
return ('http://'+ endp + reqp +'?'+ sps +'&Signature='+ | |
amazEnc(Utils.signHMAC( | |
'SHA256', 'DlSRkBtC3WDAMjA5fVJO4Fg04omvXYVXs49oNPlo', | |
['GET', endp, reqp, sps].join('\n')))); | |
} | |
function qst(lmn, slc){ | |
var child = lmn && lmn.querySelector(slc) | |
return child ? child.textContent : '' | |
} | |
var qsat = (lmn, slc) => | |
Array.map(lmn.querySelectorAll(slc), x => x.textContent) | |
CmdUtils.CreateCommand({ | |
names: [Name, 'amazon.co.jp'], | |
icon: Jamazon +'favicon.ico', | |
description: Logo, | |
help: '<h3>Categories カテゴリーリスト</h3>'+ CategoList, | |
arguments: { | |
object: noun_arb_text, | |
format: CmdUtils.NounType('category カテゴリー', Categories, '^All '), | |
}, | |
execute: function jam_execute({object: {text}, format: {data}}){ | |
Utils.openUrlInBrowser( | |
(text = text.trim()) | |
? Jamazon +'s/?tag=matyr-22&__mk_ja_JP='+ | |
'%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&search-alias='+ data[1] + | |
'&field-keywords='+ encodeURIComponent(text) | |
: Jamazon); | |
}, | |
preview: function jam_preview(pb, {object: {text, html}, format: {data}}){ | |
do var cn = pb.ownerDocument.getElementById(Name); | |
while(!cn && (pb.innerHTML = Base)); | |
if(!text){ | |
cn.innerHTML = CategoList; | |
cn.querySelector('.'+ data[0]).style.fontWeight = 'bold'; | |
return; | |
} | |
cn.className = 'loading'; | |
CmdUtils.previewAjax(pb, { | |
url: amazSig('xml-jp.amznxslt.com', '/onca/xml', { | |
Service: 'AWSECommerceService', | |
Version: "2011-08-01", | |
Operation: 'ItemSearch', | |
Condition: 'All', | |
Merchant: 'All', | |
ResponseGroup: 'ItemAttributes,Images,Offers', | |
AssociateTag: "matyr-22", | |
SearchIndex: data[0], | |
Keywords: text, | |
}), | |
dataType: 'xml', | |
success: function jam_success(xml){ | |
var em = xml.querySelector('Error > Message') | |
if(em) return ng(cn, em.textContent) | |
var ol = '<ol class=results>', i = 1 | |
for(let it of Array.slice(xml.querySelectorAll('Items > Item'))){ | |
let img = it.querySelector('SmallImage') | |
, attr = it.querySelector('ItemAttributes') | |
, price = it.querySelector('OfferSummary > LowestNewPrice') | |
|| attr.querySelector('ListPrice') | |
, label = qst(attr, 'Label') | |
, key = i.toString(ItemMax + 1).toUpperCase() | |
, author = qsat(attr, 'Author' ).join(', ') | |
, feats = qsat(attr, 'Feature') | |
let hu = H(qst(it, 'DetailPageURL')) | |
, li = '<li class=item><input type=button class=button' | |
+ ' value='+ key +' accesskey='+ key | |
+ ' title="'+ hu +'">' | |
+ ' <a href="'+ hu +'">' | |
+ '<span class=title>'+ H(qst(attr, 'Title')) +'</span>' | |
+ '</a>' | |
+ ' <span class=price>' | |
+ H(qst(price, 'FormattedPrice')) +'</span>' | |
if(img) li += '<img src="' + H(qst(img, 'URL' )) | |
+ '" width="' + qst(img, 'Width' ) | |
+ '" height="' + qst(img, 'Height') +'">' | |
if(author) | |
li += '<div class=author>'+ H(author) +'</div>' | |
if(label) | |
li += '<div class=label>'+ H(label) +'</div>' | |
if(feats.length) | |
li += feats.reduce((ul, f) => ul +'<li>'+ f, | |
'<ul class=features>') + '</ul>' | |
ol += li | |
if(++i > ItemMax) break | |
} | |
cn.innerHTML = '<div class=head>' | |
+ '<span class=query>'+ html +'</span>' | |
+ '<span class=num>' | |
+ qst(xml, 'Items > TotalResults') +'</span>' | |
+ '</div>' | |
+ ol + '</ol><br clear=all>' | |
cn.addEventListener('click', onclick, false) | |
cn.className = '' | |
cn.ownerDocument.defaultView.scrollTo(0, 0) | |
}, | |
error: function jam_error(x, s){ | |
if(x.status) ng(cn, x.status, x.statusText, '('+ s +')') | |
}, | |
}); | |
}, | |
author: { | |
name: 'satyr', email: 'murky.satyr\x40gmail.com', | |
homepage: 'http://satyr.github.io', | |
}, | |
license: 'MIT', | |
homepage: 'http://d.hatena.ne.jp/murky-satyr/20081129/1227893155', | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment