// ==UserScript== // @name Currency Converter // @namespace http://tampermonkey.net/ // @version 2.2.0 // @description try to take over the world! // @icon http://store.steampowered.com/favicon.ico // @author Bisumaruko // @include http*://yuplay.ru/* // @include http*://*.gamersgate.com/* // @include http*://www.greenmangaming.com/* // @include http*://gama-gama.ru/* // @include http*://*.gamesplanet.com/* // @include http*://www.cdkeys.com/* // @include http*://directg.net/* // @include http*://www.humblebundle.com/* // @include http*://www.indiegala.com/* // @include http*://www.bundlestars.com/* // @include http*://www.opiumpulses.com/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.6/sweetalert2.min.js // @resource SweetAlert2CSS https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.6/sweetalert2.min.css // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_getResourceText // @run-at document-start // @connect api.fixer.io // @downloadURL none // ==/UserScript== /* global GM_xmlhttpRequest, GM_setValue, GM_getValue, GM_addStyle, GM_getResourceText, $, swal, document, location, MutationObserver */ // inject swal css GM_addStyle(GM_getResourceText('SweetAlert2CSS')); // setup swal swal.setDefaults({ timer: 3000, useRejections: false }); // load config var config = JSON.parse(GM_getValue('Bisko_CC', '{}')); var interval = 3 * 60 * 60 * 1000; // update exchange rate every 3 hours var currencies = { ORI: { nameEN: '', nameZH: '恢復', symbol: '' }, AUD: { nameEN: 'Australian Dollar', nameZH: '澳幣', symbol: 'AU$' }, CAD: { nameEN: 'Canadian Dollar', nameZH: '加幣', symbol: 'CA$' }, CNY: { nameEN: 'Chinese Yuan', nameZH: '人民幣', symbol: 'CN¥' }, EUR: { nameEN: 'Euro', nameZH: '歐元', symbol: '€' }, GBP: { nameEN: 'Great Britain Pound', nameZH: '英鎊', symbol: '£' }, HKD: { nameEN: 'Hong Kong Dollar', nameZH: '港幣', symbol: 'HK$' }, JPY: { nameEN: 'Japanese Yen', nameZH: '日圓', symbol: 'JP¥' }, KRW: { nameEN: 'South Korean Won', nameZH: '韓圓', symbol: '₩' }, MYR: { nameEN: 'Malaysian Ringgit', nameZH: '令吉', symbol: 'RM' }, NTD: { nameEN: 'New Taiwan Dollar', nameZH: '台幣', symbol: 'NT$' }, NZD: { nameEN: 'New Zealand Dollar', nameZH: '紐幣', symbol: 'NZ$' }, RUB: { nameEN: 'Russian Ruble', nameZH: '盧布', symbol: 'руб' }, USD: { nameEN: 'United States Dollar', nameZH: '美元', symbol: 'US$' } }; var originalCurrency = 'USD'; // jQuery extension $.fn.price = function price() { return this.eq(0).text().replace(/[^.0-9]/g, ''); }; $.fn.bindPriceData = function bindPriceData() { return this.each(function (index, element) { var $ele = $(element); $ele.addClass('CCPrice').attr('data-CCPrice', JSON.stringify({ currency: originalCurrency, price: $ele.text().replace(/[^.0-9]/g, '') })); }); }; // constructing functions var has = Object.prototype.hasOwnProperty; var preferredCurrency = function preferredCurrency() { return has.call(config.exchangeRate.rates, config.preferredCurrency) ? config.preferredCurrency : 'CNY'; }; // default to CNY var updateCurrency = function updateCurrency() { var currency = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var targetCurrency = currency || preferredCurrency(); $('.CCPrice').each(function (index, element) { var $ele = $(element); var data = JSON.parse($ele.attr('data-CCPrice')); var convertedPrice = 0; if (targetCurrency === 'ORI') { targetCurrency = data.currency; convertedPrice = data.price; } else { var rates = config.exchangeRate.rates; convertedPrice = data.price * (rates[targetCurrency] / rates[data.currency]); } $ele.text(convertedPrice.toLocaleString('en', { style: 'currency', currency: targetCurrency, maximumFractionDigits: 2 }).replace('MYR', currencies.MYR.symbol).replace('NTD', currencies.NTD.symbol)); }); }; var constructMenu = function constructMenu() { var $li = $('
  • Currencies
  • '); var $ul = $('').appendTo($li); var preferred = preferredCurrency(); GM_addStyle('\n .Bisko_CC_Menu ul {\n display: none;\n position: absolute;\n padding: 0;\n background-color: #272727;\n z-index: 9999;\n }\n .Bisko_CC_Menu:hover ul {\n display: block;\n }\n .Bisko_CC_Menu li {\n padding: 2px 10px;\n list-style-type: none;\n cursor: pointer;\n }\n .Bisko_CC_Menu li:hover, .preferred {\n background-color: SandyBrown;\n }\n '); Object.keys(currencies).forEach(function (currency) { var itemName = currency + ' ' + currencies[currency].nameZH; $ul.append($('
  • ' + itemName + '
  • ').addClass(function () { return preferred === currency ? 'preferred' : ''; }).click(function () { config.preferredCurrency = currency; GM_setValue('Bisko_CC', JSON.stringify(config)); updateCurrency(currency); $('.Bisko_CC_Menu .preferred').removeClass('preferred'); $('.Bisko_CC_Menu .' + currency).addClass('preferred'); })); }); return $li; }; var handler = function handler() { switch (location.host) { case 'yuplay.ru': originalCurrency = 'RUB'; GM_addStyle('\n .games-pricedown span.CCPrice {\n font-size: 18px;\n }\n .good-title span.CCPrice {\n margin-right: 3px;\n font-size: 22px;\n }\n '); $('.header-right').append(constructMenu()); // homepage games-pricedown $('.games-pricedown .sale > s, .games-pricedown .price').bindPriceData(); // homepage game box & product page $('.games-box .price, .good-title .price').contents().each(function (index, node) { var $node = $(node); var text = $node.text().trim(); if (node.tagName === 'S') $node.bindPriceData(); // retail price if (node.tagName === 'SPAN') $node.remove(); // currency else if (node.nodeType === 3 && text.length > 0) { // sales price $node.replaceWith($('' + text + '').bindPriceData()); } }); break; case 'gama-gama.ru': originalCurrency = 'RUB'; GM_addStyle('\n .Bisko_CC_Menu > a, .Bisko_CC_Menu li {\n color: white;\n }\n .Bisko_CC_Menu ul {\n margin: 0;\n }\n '); $('#top_back').append(constructMenu().wrapInner('
    ').children().unwrap()); // homepage $('.price_1, .old_price, .promo_price').bindPriceData(); // product page $('.card-info-oldprice > span, .card-info-price > span').bindPriceData(); $('.card-info-oldprice, .card-info-price').contents().filter(function (i, node) { return node.nodeType !== 1; }).remove(); break; // case 'www.gamersgate.com': case 'ru.gamersgate.com': case 'cn.gamersgate.com': if (location.host.startsWith('ru')) originalCurrency = 'RUB'; if (location.host.startsWith('cn')) originalCurrency = 'CNY'; GM_addStyle('\n .Bisko_CC_Menu {\n width: 49px;\n text-align: center;\n }\n .Bisko_CC_Menu svg {\n width: 36px;\n height: 36px;\n background-color: #093745;\n border: 1px solid #2c7c92;\n }\n .Bisko_CC_Menu, .Bisko_CC_Menu li {\n background-image: none !important;\n color: white;\n }\n .Bisko_CC_Menu li {\n height: initial !important;\n float: none !important;\n padding: 5px 10px !important;\n }\n .Bisko_CC_Menu li:hover, .preferred {\n background-color: SandyBrown !important;\n }\n '); $('.btn_menuseparator').replaceWith(constructMenu()); $('.Bisko_CC_Menu a').replaceWith('\n \n \n \n '); // homepage & product page $('\n .prtag > span,\n .grid-old-price,\n .price_price > span,\n div > span > .bold.white,\n li > .f_right:nth-child(2) > span\n ').bindPriceData(); break; case 'www.greenmangaming.com': originalCurrency = $('.currency-code').eq(0).text(); GM_addStyle('\n .Bisko_CC_Menu > a {\n margin: 0 !important;\n padding: 6px 15px !important;\n font-size: 14px;\n }\n .Bisko_CC_Menu > a:hover, .Bisko_CC_Menu li:hover, .preferred {\n background-color: #494a4f !important;\n }\n '); $('.megamenu').append(constructMenu()); // home page new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.addedNodes.forEach(function (addedNode) { if (addedNode.src && addedNode.src.includes('bam.nr-data.net')) { var $prices = $('.prices > span'); var src = decodeURI(addedNode.src); originalCurrency = src.split('currency_code":"').pop().slice(0, 3) || 'USD'; // offset decimal place in Europe (. ,) if (['EUR', 'RUB'].includes(originalCurrency)) { $prices.text(function (i, text) { return text.replace(',', '.'); }); } $prices.bindPriceData(); updateCurrency(); } }); }); }).observe(document.head, { childList: true }); // product page $('price > span').bindPriceData(); break; case 'uk.gamesplanet.com': case 'de.gamesplanet.com': case 'fr.gamesplanet.com': { originalCurrency = !location.host.startsWith('uk') ? 'EUR' : 'GBP'; var GPHandler = function GPHandler() { var $prices = $('.price_base > strike, .price_current'); $('.container > ul').append(constructMenu()); // offset decimal place in Europe (. ,) if (!location.host.startsWith('uk')) { $prices.text(function (i, text) { return text.replace(',', '.'); }); } $prices.bindPriceData(); updateCurrency(); }; GPHandler(true); new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.removedNodes.forEach(function (removedNode) { if (removedNode.id === 'nprogress') GPHandler(); }); }); }).observe(document, { childList: true, subtree: true }); break; } case 'www.cdkeys.com': { originalCurrency = $('.currency-switcher:first-child .value').text(); var currenciesDefault = ['AUD', 'CAD', 'EUR', 'GBP', 'JPY', 'NZD', 'USD']; var currenciesAppend = ['CNY', 'HKD', 'KRW', 'MYR', 'NTD', 'RUB']; // bind event to default currency switcher to save preferrred currency $('.currency-switcher:first-child ul span').each(function (index, element) { var $ele = $(element); var currency = $ele.text().slice(0, 3); if (currenciesDefault.includes(currency)) { $ele.parent().click(function () { config.preferredCurrency = currency; GM_setValue('Bisko_CC', JSON.stringify(config)); }); } }); // append currencies not in the default currency switcher currenciesAppend.forEach(function (currency) { $('.currency-switcher:first-child ul').append($('
  • ' + currency + ' - ' + currencies[currency].nameEN + '
  • ').click(function () { config.preferredCurrency = currency; GM_setValue('Bisko_CC', JSON.stringify(config)); updateCurrency(currency); })); }); $('.price').bindPriceData(); break; } case 'directg.net': originalCurrency = 'KRW'; GM_addStyle('\n .Bisko_CC_Menu ul {\n width: 180px;\n border-top: 3px solid #67c1f5;\n background-color: #1b2838 !important;\n opacity: 0.95;\n color: rgba(255,255,255,0.5) !important;\n }\n .Bisko_CC_Menu ul li {\n padding: 10px 30px;\n font-weight: bold;\n }\n .Bisko_CC_Menu ul li:hover, .preferred {\n background-color: initial !important;\n color: white;\n }\n '); $('.nav').append(constructMenu()); $('span.PricebasePrice, span.PricesalesPrice').bindPriceData().next('span[itemprop="priceCurrency"]').remove(); break; /* case 'www.origin.com': { const region = location.pathname.split('/')[1]; const currencyRegion = { twn: 'NTD', jpn: 'JPY', rus: 'RUB', usa: 'USD', nzl: 'NZD', irl: 'EUR', kor: 'KRW', }; }*/ case 'www.humblebundle.com': originalCurrency = 'USD'; GM_addStyle('\n .Bisko_CC_Menu {\n float: left;\n }\n .Bisko_CC_Menu > a {\n display: block;\n padding: 15px 20px;\n }\n .Bisko_CC_Menu ul {\n background-color: #494f5c !important;\n color: rgba(255, 255, 255, 0.6);\n }\n .Bisko_CC_Menu ul li {\n padding: 5px 10px;\n }\n .Bisko_CC_Menu ul li:hover, .preferred {\n background-color: initial !important;\n color: white;\n }\n '); $('.nav:first-child').append(constructMenu()); new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.removedNodes.forEach(function (removedNode) { if (removedNode.data === 'The Humble Store: Loading') { $('.price, .store-price, .full-price, .current-price').bindPriceData(); updateCurrency(); } }); }); }).observe(document.head, { childList: true, subtree: true }); break; case 'www.indiegala.com': originalCurrency = 'USD'; GM_addStyle('\n .Bisko_CC_Menu ul {\n transform: translateY(-100%);\n background-color: #474747 !important;\n border: 1px solid #272727;\n }\n .Bisko_CC_Menu ul li {\n padding: 8px 15px;\n color: #dad6ca;\n }\n .Bisko_CC_Menu ul li:hover, .preferred {\n background-color: #2E2E2E !important;\n color: white;\n }\n '); $('#libdContainer > ul:not(:first-child)').append(constructMenu()); $('.Bisko_CC_Menu > a').addClass('libd-group-item libd-bounce'); // homepage & product page $('.inner-info, .inner, .price-container').contents().each(function (index, node) { var $node = $(node); var text = $node.text().trim(); $node.parent().parent().css('overflow', 'hidden'); if (node.nodeType === 1 && node.tagName !== 'BR') $node.bindPriceData();else if (node.nodeType === 3 && text.length) { $node.replaceWith($('' + text + '').bindPriceData()); } }); // search result $('.price-cont').bindPriceData(); break; case 'www.bundlestars.com': originalCurrency = 'USD'; GM_addStyle('\n .Bisko_CC_Menu ul {\n background-color: #212121 !important;\n }\n .Bisko_CC_Menu ul li {\n padding: 8px 15px;\n }\n .Bisko_CC_Menu ul li:hover, .preferred {\n background-color: #1A1A1A !important;\n }\n '); $('.nav').eq(0).append(constructMenu()); new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.removedNodes.forEach(function (removedNode) { if (removedNode.id === 'loading-bar-spinner') { $('.bs-price, .bs-currency-discount > span, .bs-currency-price').bindPriceData(); $('.bs-card-meta > .bs-pricing, .bs-card-meta > .bs-currency-discount').css({ position: 'absolute', right: '19px' }); updateCurrency(); } }); }); }).observe(document.body, { childList: true }); break; case 'www.opiumpulses.com': originalCurrency = 'USD'; GM_addStyle('\n .Bisko_CC_Menu {\n float: right;\n margin-top: 5px;\n padding: 1px 5px;\n vertical-align: middle;\n background-image: linear-gradient(#4E4E4E, #101112 40%, #191b1d);\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n }\n .Bisko_CC_Menu > a {\n color: #f89406;\n }\n '); $('.top-bar > .container > form').after(constructMenu().wrapInner('
    ').children().unwrap()); // homepage $('.album__container p > span:first-of-type').bindPriceData(); // store page $('.product-box s, .product-box .text-danger').bindPriceData(); new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.addedNodes.forEach(function (addedNode) { if (addedNode.id === 'productlistview') { $(addedNode).find('.product-box s, .product-box .text-danger').bindPriceData(); updateCurrency(); } }); }); }).observe(document.body, { childList: true, subtree: true }); break; default: } // only update prices when appended currencies are selected if (originalCurrency !== preferredCurrency()) updateCurrency(); }; var getExchangeRate = function getExchangeRate() { GM_xmlhttpRequest({ method: 'GET', url: 'http://api.fixer.io/latest', onload: function onload(res) { if (res.status === 200) { try { var exchangeRate = JSON.parse(res.response); config.exchangeRate = exchangeRate; config.lastUpdate = Date.now(); // add EUR, NTD config.exchangeRate.rates.EUR = 1; config.exchangeRate.rates.NTD = config.exchangeRate.rates.HKD * 3.9; GM_setValue('Bisko_CC', JSON.stringify(config)); handler(); } catch (e) { swal('Parsing Failed', 'An error occured when parsing exchange rate data, please reload to try again', 'error'); } } else { swal('Loading Failed', 'Unable to fetch exchange rate data, please reload to try again', 'error'); } } }); }; $(function () { if (Object.keys(config).length === 0) getExchangeRate(); // first installed else if (Date.now() - interval > config.lastUpdate) getExchangeRate(); // update exchange rate else handler(); });