// ==UserScript== // @name Currency Converter // @namespace http://tampermonkey.net/ // @version 1.0.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/* // @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 css GM_addStyle(GM_getResourceText('SweetAlert2CSS')); // setup swal swal.setDefaults({ timer: 3000, useRejections: false, }); // load config const config = JSON.parse(GM_getValue('Bisko_CC', '{}')); const interval = 3 * 60 * 60 * 1000; // update exchange rate every 3 hours // constructing functions const has = Object.prototype.hasOwnProperty; const preferredCurrency = () => { const preferred = config.preferredCurrency; if (has.call(config.exchangeRate.rates, preferred)) return preferred; return 'CNY'; }; const updateCurrency = (currency = null) => { const targetCurrency = currency || preferredCurrency(); const symbols = { AUD: 'AU$', CAD: 'CA$', CNY: 'CN¥', EUR: '€', GBP: '£', HKD: 'HK$', JPY: 'JP¥', KRW: '₩', MYR: 'RM', NTD: 'NT$', NZD: 'NZ$', RUB: 'руб', USD: 'US$', }; // converting price $('.currency_price').each((index, element) => { const $ele = $(element); const data = $ele.attr('data-price').split(' '); const originalCurrency = data[0]; const originalPrice = parseFloat(data[1]); let convertedPrice = originalPrice; if (originalCurrency !== targetCurrency && targetCurrency !== 'ORI') { const toBase = originalPrice / config.exchangeRate.rates[originalCurrency]; const toTarget = toBase * config.exchangeRate.rates[targetCurrency]; convertedPrice = toTarget.toFixed(2); } $ele.text(convertedPrice); }); // replacing currency symbol const originalCurrency = $('.currency_name').attr('data-currency'); const symbol = targetCurrency === 'ORI' ? symbols[originalCurrency] : symbols[targetCurrency]; $('.currency_name').text(symbol); }; const constructMenu = () => { const $li = $('
  • Currencies
  • '); const $ul = $('').appendTo($li); const currencies = { ORI: '恢復', AUD: '澳幣', CAD: '加幣', CNY: '人民幣', EUR: '歐元', GBP: '英鎊', HKD: '港幣', JPY: '日圓', KRW: '韓圓', MYR: '令吉', NTD: '台幣', NZD: '紐幣', RUB: '盧布', USD: '美元', }; const preferred = preferredCurrency(); GM_addStyle(` .Bisko_CC_Menu ul { display: none; position: absolute; padding: 0; background-color: #272727; z-index: 9999; } .Bisko_CC_Menu:hover ul { display: block; } .Bisko_CC_Menu li { padding: 2px 10px; list-style-type: none; cursor: pointer; } .Bisko_CC_Menu li:hover, .preferred { background-color: SandyBrown; } `); Object.keys(currencies).forEach((currency) => { const itemName = `${currency} ${currencies[currency]}`; $ul.append( $(`
  • ${itemName}
  • `) .addClass(() => (preferred === currency ? 'preferred' : '')) .click(() => { 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; }; const handler = () => { switch (location.host) { case 'yuplay.ru': GM_addStyle(` .games-pricedown span.currency_price { font-size: 18px; } .good-title span.currency_price { margin-right: 3px; font-size: 22px; } `); $('.header-right').append(constructMenu()); $('.price') .each((index, element) => { $(element).contents().each((i, node) => { const $node = $(node); if (node.tagName === 'S') { // retail price node $node .addClass('currency_price') .attr('data-price', `RUB ${$node.text().trim()}`); } else if (node.nodeType === 3) { // sales price node const price = node.textContent.trim(); if ($.isNumeric(price)) $node.replaceWith(`${price}`); } else if (node.tagName === 'SPAN') { // currency node $node .addClass('currency_name') .attr('data-currency', 'RUB'); } }); }) .prev('.sale').find('s') .each((i, node) => { const $node = $(node); $node .addClass('currency_price') .attr('data-price', `RUB ${$node.text().trim()}`); }); break; // case 'www.gamersgate.com': case 'ru.gamersgate.com': case 'cn.gamersgate.com': { let originalCurrency = ''; if (location.host.startsWith('ru')) originalCurrency = 'RUB'; if (location.host.startsWith('cn')) originalCurrency = 'CNY'; GM_addStyle(` .Bisko_CC_Menu { width: 49px; text-align: center; } .Bisko_CC_Menu svg { width: 36px; height: 36px; background-color: #093745; border: 1px solid #2c7c92; } .Bisko_CC_Menu, .Bisko_CC_Menu li { background-image: none !important; color: white; } .Bisko_CC_Menu li { height: initial !important; float: none !important; padding: 5px 10px !important; } .Bisko_CC_Menu li:hover, .preferred { background-color: SandyBrown !important; } `); $('.btn_menuseparator').replaceWith(constructMenu()); $('.Bisko_CC_Menu a').replaceWith(` `); const prices = $('.price_price, .prtag, li > .f_right:nth-child(2)'); prices.each((index, element) => { $(element) .css('padding-right', '5px') .find('span').each((i, node) => { const $node = $(node); const price = parseFloat($node.text().replace(/[^.0-9]/g, '')); $node .addClass('currency_price') .attr('data-price', `${originalCurrency} ${price}`) .after(``); }); }); prices.prev().prev() .find('.bold.white') .each((index, element) => { const $ele = $(element); const price = parseFloat($ele.text().replace(/[^.0-9]/g, '')); $ele .addClass('currency_price') .attr('data-price', `${originalCurrency} ${price}`); }); prices.closest('.descr_cont').next().find('.grid-old-price').each((index, element) => { const $ele = $(element); const price = parseFloat($ele.text().replace(/[^.0-9]/g, '')); $ele.html(` `); }); break; } case 'www.greenmangaming.com': { GM_addStyle(` .Bisko_CC_Menu > a { margin: 0 !important; padding: 6px 15px !important; font-size: 14px; } .Bisko_CC_Menu > a:hover, .Bisko_CC_Menu li:hover, .preferred { background-color: #494a4f !important; } `); $('.megamenu').append(constructMenu()); let homepage = false; let originalCurrency = $('.currency-code').eq(0).text(); const GMGHandler = (index, element) => { const $ele = $(element); let price = parseFloat($ele.text().replace(/[^.0-9]/g, '')); if (homepage && ['RUB'].includes(originalCurrency)) price /= 100; $ele.html(` `); }; // home page if (originalCurrency.length === 0) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((addedNode) => { if (addedNode.src && addedNode.src.includes('bam.nr-data.net')) { const src = decodeURI(addedNode.src); originalCurrency = src.split('currency_code":"').pop().slice(0, 3) || 'USD'; homepage = true; $('.prices > span').each(GMGHandler); updateCurrency(); observer.disconnect(); } }); }); }); observer.observe(document.head, { childList: true, }); } else $('price > span').each(GMGHandler); // product page break; } default: } updateCurrency(); }; const getExchangeRate = () => { GM_xmlhttpRequest({ method: 'GET', url: 'http://api.fixer.io/latest', onload: (res) => { if (res.status === 200) { try { const 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', ); } }, }); }; $(() => { if (Object.keys(config).length === 0) getExchangeRate(); // first installed else if (Date.now() - interval > config.lastUpdate) getExchangeRate(); // update exchange rate else handler(); });