Greasy Fork

Currency Converter

try to take over the world!

目前为 2017-08-04 提交的版本。查看 最新版本

// ==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
// ==/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 = $('<li class="Bisko_CC_Menu"><a>Currencies</a></li>');
    var $ul = $('<ul></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($('<li class="' + currency + '">' + itemName + '</li>').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($('<span>' + text + '<span>').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('<div class="Bisko_CC_Menu top_menu"></div>').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                <svg viewBox="0 0 24 24">\n                    <path fill="#a9ebea" d="M11.8,10.9C9.53,10.31 8.8,9.7 8.8,8.75C8.8,7.66 9.81,6.9 11.5,6.9C13.28,6.9 13.94,7.75 14,9H16.21C16.14,7.28 15.09,5.7 13,5.19V3H10V5.16C8.06,5.58 6.5,6.84 6.5,8.77C6.5,11.08 8.41,12.23 11.2,12.9C13.7,13.5 14.2,14.38 14.2,15.31C14.2,16 13.71,17.1 11.5,17.1C9.44,17.1 8.63,16.18 8.5,15H6.32C6.44,17.19 8.08,18.42 10,18.83V21H13V18.85C14.95,18.5 16.5,17.35 16.5,15.3C16.5,12.46 14.07,11.5 11.8,10.9Z" />\n                </svg>\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($('<li><a>' + currency + ' - ' + currencies[currency].nameEN + '</a></li>').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($('<a>' + text + '</a>').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('<div class="Bisko_CC_Menu top_menu"></div>').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();
});