Simple Amazon Shortcuts

Shortcuts for Amazon product price history and review authenticity

// ==UserScript==
// @name     Simple Amazon Shortcuts
// @name:de  Einfache Amazon-Verknüpfungen
// @name:es  Atajos simples de Amazon
// @name:fr  Raccourcis Amazon simples
// @name:hi  सरल अमेज़न शॉर्टकट
// @name:it  Scorciatoie semplici Amazon
// @name:ja  シンプルなAmazonショートカッ
// @namespace   flightless22.SAS
// @description Shortcuts for Amazon product price history and review authenticity
// @description:de  Verknüpfungen für Amazon Product Price History and Review Echtiversität'
// @description:es  Atajos para el Historial de precios del producto de Amazon y de la autenticidad de la revisión
// @description:fr  Raccourcis pour Amazon Historique des prix du produit et révision de l'authenticité
// @description:hi  अमेज़ॅन उत्पाद मूल्य इतिहास के लिए शॉर्टकट और प्रामाणिकता की समीक्षा करें
// @description:it  Scorciatoie per la storia del prezzo del prodotto Amazon e della revisione dell'autenticità
// @description:ja  Amazon製品の価格履歴のショートカットとレビュー信憑性
// @version     2022.05.13.1025
// @author      flightless22
// @homepageURL https://greasyfork.org/en/scripts/427433
// @license 		MIT
// @include		  https://*.amazon.*/*
// @grant       GM.openInTab
// @grant       GM.registerMenuCommand
// @noframes
// ==/UserScript==
(function() {
	"use strict";

	/*<<<<====== User options ======>>>>*/
	// Override system language. For example: "" will use system settings. "en" will use English.
	// Currently supported language code: de, en, es, fr, hi, it and ja.
	const forcedlang = "";
	// Tab behavior. default: open in foreground and insert next to current tab.
	// Note: GreaseMonkey only supports boolean (true = open background | false = open foreground)
	// For full details see: https://violentmonkey.github.io/api/gm/#gm_openintab
	var taboptions = {"active": true, "insert": true};
	// Shortcut access key. set to empty string to disable.
	const accesskey = {"camelcamelcamel": "c", "keepa":"k", "reviewmeta":"r", "fakespot":"f"};
	/*<<<<====== User options ======>>>>*/

	if ((GM_info.scriptHandler === "GreaseMonkey" ) &&
	(typeof taboptions !== "boolean")) taboptions = taboptions["active"] !== undefined ? !taboptions["active"] : false;
	// [1] TLD / [2] ASIN
	const amazonsrc = /^https:\/\/[a-zA-Z]+\.amazon\.([.a-zA-Z]+).*\/([a-zA-Z0-9]{10})/.exec(location.href);
	var babel = {};
	const userlang = getuserlang();
	const service = {
		"Keepa": {
			"cat": translate("price"),
			"tld": {"com":"Default", "co.uk": 2, "de": 3, "fr": 4, "co.jp": 5, "ca": 6, "it": 8, "es": 9, "in": 10,
				"com.mx": 11, "com.br": 12},
			"durl": "https://keepa.com/#!product/1-$asin$",
			"url": "https://keepa.com/#!product/$tld$-$asin$",
			"fn" : function() { getservice("Keepa") },
			"k" : accesskey["keepa"]
		},
		"Camel Camel Camel": {
			"cat": translate("price"),
			"tld": {"au":"au", "ca":"ca", "com":"Default", "co.uk":"uk", "de":"de", "es":"es", "fr":"fr"},
			"durl": "https://camelcamelcamel.com/product/$asin$",
			"url": "https://$tld$.camelcamelcamel.com/product/$asin$",
			"fn" : function() { getservice("Camel Camel Camel") },
			"k" : accesskey["camelcamelcamel"]
		},
		"Review Meta": {
			"cat": translate("review"),
			"tld": {"ca":"ca", "com.au":"au", "com.br":"br","com.mx":"mx", "cn":"cn", "com":"Default", "co.jp":"jp",
				"co.uk":"uk", "de":"de", "es":"es", "fr":"fr", "it":"it", "in":"in", "nl":"nl"},
			"durl": "https://reviewmeta.com/amazon/$asin$",
			"url": "https://reviewmeta.com/amazon-$tld$/$asin$",
			"fn" : function() { getservice("Review Meta") },
			"k" : accesskey["reviewmeta"]
		},
		"Fake Spot": {
			"cat": translate("review"),
			"tld": {"ca":"ca", "com.au":"com.au", "co.jp":"co.jp", "com":"Default", "co.uk":"co.uk", "de":"de",
				"es":"es", "fr":"fr", "in":"in", "it":"it"},
			"durl": "https://www.fakespot.com/analyze?url=http://amazon.com/dp/$asin$",
			"url": "https://www.fakespot.com/analyze?url=http://amazon.$tld$/dp/$asin$",
			"fn" : function() { getservice("Fake Spot") },
			"k" : accesskey["fakespot"]
		}
	};
	function loadbabel(lang) {
		let translations = {
			"en":{ //English
				"price": "Price History",
				"review": "Review Analysis",
				"unsupportedprompt": '$service$: "$amazon$" is unsupported.\nDo you want to continue anyway?',
				"unsupported": '"$amazon$" is unsupported.'
			},
			"de":{ //German / Deutsch
				"price": "Preisverlauf",
				"review": "Bewertungen analysieren",
				"unsupportedprompt": '$service$: "$amazon$" wird nicht unterstützt.\nMöchtest du trotzdem weitermachen?',
				"unsupported": '"$amazon$" wird nicht unterstützt.'
			},
			"es":{ //Spanish / Español
				"price": "Historial de precios",
				"review": "Análisis de revisión",
				"unsupportedprompt": '$service$: "$amazon$" no es compatible.\n¿Quieres continuar de todos modos?',
				"unsupported": '"$amazon$" no es compatible.'
			},
			"fr":{ //French / Français
				"price": "Historique des prix",
				"review": "Analyser l'examen des utilisateurs",
				"unsupportedprompt": '$service$: "$amazon$" n\'est pas pris en charge.\nVoulez-vous continuer quand même?',
				"unsupported": '"$amazon$" n\'est pas pris en charge.'
			},
			"hi":{ //Hindi // हिन्दी
				"price": "मूल्य इतिहास",
				"review": "समीक्षा विश्लेषण",
				"unsupportedprompt": '$service$: $amazon$" समर्थित नहीं है\nक्या आप फिर भी जारी रखना चाहते हैं?',
				"unsupported": '"$amazon$"  समर्थित नहीं है'
			},
			"it":{ //Italian / Italiano
				"price": "Cronologia dei prezzi",
				"review": "Analisi delle recensioni",
				"unsupportedprompt": '$service$: $amazon$" non è supportato.\nVuoi continuare comunque?',
				"unsupported": '"$amazon$" non è supportato.'
			},
			"ja":{ //Japanese / 日本語
				"price": "価格履歴",
				"review": "レビュー分析",
				"unsupportedprompt": '$service$: "$amazon$"はサポートされていません。\n続行しますか?',
				"unsupported": '"$amazon$"はサポートされていません。'
			}
		};
		babel = {"en": translations["en"]}; //fallback language
		if (translations[lang] === undefined) return msg(`Error: '${lang}' translation does not exist. default to 'en' langauge`);
		babel = Object.assign(babel, {[lang]: translations[lang]});
	}
	function getuserlang(){
		let lang = ( forcedlang ? forcedlang : navigator.language.slice(0,2) ); //non region specific
		loadbabel(lang);
		if (babel[lang] === undefined) return "en";
		return lang;
	}
	function translate(name, rep){
		let str = babel[userlang][name];
		if (str === undefined) str = babel["en"][name];
		if (Array.isArray(rep) === true && rep.length % 2 === 0) {
			for (let i = 0; i<= rep.length/2; i+=2) {
				str = str.replace(rep[i], rep[i+1]);
			}
		}
		return str;
	}
	function getservice(name) {
		let p, url, tld = service[name]["tld"][amazonsrc[1]];
		if (tld === "Default") {
			url = service[name]["durl"].replace("$asin$", amazonsrc[2]);
		} else {
			if (tld === undefined) {
				msg(`Error: ${name} does not support amazon.${amazonsrc[1]}`);
				p = confirm( translate("unsupportedprompt", ["$service$", name, "$amazon$", `amazon.${amazonsrc[1]}`]) );
				if (p === false) return;
				tld = amazonsrc[1];
			}
			url = service[name]["url"].replace("$tld$", tld);
			url = url.replace("$asin$", amazonsrc[2]);
		}
		GM.openInTab(url, taboptions);
	}
	function setup() {
		// ignore 404 errors, sometimes product history is still desirable
		if (amazonsrc === null || amazonsrc.length < 2) return msg("ASIN not found, probably not a product page.");
		msg(`Domain: amazon.${amazonsrc[1]} Product ASIN: ${amazonsrc[2]}`);
		let errtxt = translate("unsupported", ["$amazon$", `amazon.${amazonsrc[1]}`]);
		for (let name in service) {
			GM.registerMenuCommand(
				`${name} : ${service[name]["cat"]} ${service[name]["tld"][amazonsrc[1]] === undefined ? `( ${errtxt} )` : ""}`,
				service[name]["fn"],
				service[name]["k"]
			);
		}
	}
	function msg(txt, ret){
		console.log(`[${GM_info.scriptHandler}] ${GM_info.script.name}: ${txt}`);
		return ret;
	}
	setup();
})();