Skip to content

Instantly share code, notes, and snippets.

@xtravar
Created August 20, 2020 01:53
Show Gist options
  • Save xtravar/2690fb86d02e8b45d5b7577b61674dd7 to your computer and use it in GitHub Desktop.
Save xtravar/2690fb86d02e8b45d5b7577b61674dd7 to your computer and use it in GitHub Desktop.
A Tampermonkey script that converts currencies and whatnot on Amazon sites. WIP.
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://*.amazon.de/*
// @match https://*.amazon.co.jp/*
// @match https://*.amazon.co.uk/*
// @match https://*.amazon.it/*
// @grant none
// ==/UserScript==
function convertUnit(value, unit) {
let multiplier = null;
let dest = null;
switch(unit.toLowerCase()){
case 'kg':
case 'kilograms':
multiplier = 2.20462;
dest = 'lbs';
break;
case 'g':
multiplier = 0.220462;
dest = 'lbs';
break;
case 'cm':
multiplier = 0.393701;
dest = 'in';
break;
case 'mm':
multiplier = 0.0393701;
dest = 'in';
break;
case '€':
multiplier = 1.19;
dest = '$';
break;
case '¥':
multiplier = 0.14;
dest = '$';
break;
case '$':
multiplier = 1;
dest = '$';
break;
default:
alert(unit);
break;
}
if(multiplier == null) { return {value: 'wtf', unit: 'wtf' }; }
if(value instanceof Array) {
value = value.map(v => v * multiplier);
} else {
value = value * multiplier;
}
return {value: value, unit: dest};
}
function convertValueStr(str, unit) {
var input;
if(str instanceof Array) {
input = str.map(e => new Number(e.replace(',', '')));
} else {
input = new Number(str.replace(',', ''));
}
let result = convertUnit(input, unit);
var format;
var appendUnit = true;
if(result.unit == '$') {
appendUnit = false;
let formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
});
format = v => formatter.format(v);
} else {
format = v => v.toFixed(2);
}
if(result.value instanceof Array) {
let oldFormat = format;
format = v => v.map(e => oldFormat(e)).join(' x ')
}
if(appendUnit) {
return format(result.value) + ' ' + result.unit;
} else {
return format(result.value);
}
}
function queryXpathRoot(root, path) {
//"//*[@id='prodDetails']//span[@class='value']"
return [document.evaluate(path, root, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)].map(e => Array(e.snapshotLength).fill().map((a, i) => e.snapshotItem(i)))[0]
}
function iterXpathRoot(root, path, cb) {
let elems = queryXpathRoot(root, path);
for(const elem of elems) {
cb(elem);
}
}
function iterXpath(path, cb) {
return iterXpathRoot(document, path, cb);
}
function indiscriminateValue(text) {
const numreg = /(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)/g
var found = false;
text = text.replace(/(?:\b|^)([\d,]+(?:\.\d+)?)\s*x\s*(\d+(?:\.\d+)?)\s*x\s*(\d+(?:\.\d+)?)\s*(mm|cm)(?:\b|$)/g, (matched, p1Value, p2Value, p3Value, p4Unit) => {
found = true;
return convertValueStr([p1Value, p2Value, p3Value], p4Unit);
});
text = text.replace(/(?:\b|^)([€¥])\s*(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)(?:\b|$)/g, (matched, p1Unit, p2Value) => {
found = true;
return convertValueStr(p2Value, p1Unit);
});
text = text.replace(/(?:\b|^)(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)\s*(mm|cm|g|[Kk](?:ilo)?[Gg](?:rams)?)(?:\b|$)/g, (matched, p1Value, p2Unit) => {
found = true;
return convertValueStr(p1Value, p2Unit);
});
text = text.replace(/(?:\b|^)(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)\s*x\s*(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)\s*x\s*(\d\d?\d?(?:,?\d\d\d)*(?:\.\d+)?)\s*(mm|cm)(?:\b|$)/g, (matched, p1Value, p2Value, p3Value, p4Unit) => {
found = true;
return convertValueStr([p1Value, p2Value, p3Value], p4Unit);
});
return text;
}
function indiscriminate() {
let list = [
"//*[@id='prodDetails']//*[@class='value']",
"//*[@id='prodDetails']//td",
"//*[starts-with(@class, 'comparison_baseitem_column')]/span",
"//*[starts-with(@class, 'comparison_sim_items_column')]/span",
"//span[contains(@class, 'a-color-price')]",
"//*[@id='price-shipping-message']/*[starts-with(text(), '+')]",
"//*[@id='price_inside_buybox' or @id='priceblock_ourprice']",
"//*[@id='price-shipping-message']/*[starts-with(text(), '+')]",
"//span[contains(text(), ' delivery')]"
];
let xpath = list.join(" | ")
iterXpath(xpath, e => {
let oldText = e.innerText;
let newText = indiscriminateValue(e.innerText);
if(oldText != newText) {
e.innerText = indiscriminateValue(e.innerText);
}
});
iterXpath("//*[@class='a-price']", e => {
let unitNode = e.getElementsByClassName('a-price-symbol')[0];
let valueNode = e.getElementsByClassName('a-price-whole')[0];
if(unitNode.innerText == '') {
let newText = indiscriminateValue(valueNode.innerText);
if(newText != valueNode.innerText) {
valueNode.innerText = newText;
}
} else {
let result = convertUnit(new Number(valueNode.innerText), unitNode.innerText);
if(unitNode.innerText != result.unit) {
unitNode.innerText = result.unit;
valueNode.innerText = result.value.toFixed(2);
}
}
});
}
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
(function() {
'use strict';
var timerId;
var debounceFunction = function (func, delay) {
// Cancels the setTimeout method execution
clearTimeout(timerId);
// Executes the func after delay time.
timerId = setTimeout(indiscriminate, delay);
};
var mutated = debounce(indiscriminate, 100);
new MutationObserver(function(mutations) {
debounceFunction(300);
}).observe(document, {childList: true, subtree: true});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment