Greasy Fork

Greasy Fork is available in English.

Currency Converter

try to take over the world!

当前为 2017-10-06 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Currency Converter
// @namespace    http://tampermonkey.net/
// @version      2.2.1
// @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, games,
    document, location, MutationObserver
*/

// inject swal 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
const 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$'
    }
};

let originalCurrency = 'USD';

// jQuery extension
$.fn.price = function price() {
    return this.eq(0).text().replace(/[^.0-9]/g, '');
};

$.fn.bindPriceData = function bindPriceData() {
    return this.each((index, element) => {
        const $ele = $(element);

        $ele.addClass('CCPrice').attr('data-CCPrice', JSON.stringify({
            currency: originalCurrency,
            price: $ele.text().replace(/[^.0-9]/g, '')
        }));
    });
};

// constructing functions
const has = Object.prototype.hasOwnProperty;
const preferredCurrency = () => has.call(config.exchangeRate.rates, config.preferredCurrency) ? config.preferredCurrency : 'CNY'; // default to CNY
const updateCurrency = (currency = null) => {
    let targetCurrency = currency || preferredCurrency();

    $('.CCPrice').each((index, element) => {
        const $ele = $(element);
        const data = JSON.parse($ele.attr('data-CCPrice'));

        let convertedPrice = 0;

        if (targetCurrency === 'ORI') {
            targetCurrency = data.currency;
            convertedPrice = data.price;
        } else {
            const 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));
    });
};
const constructMenu = () => {
    const $li = $('<li class="Bisko_CC_Menu"><a>Currencies</a></li>');
    const $ul = $('<ul></ul>').appendTo($li);
    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].nameZH}`;

        $ul.append($(`<li class="${currency}">${itemName}</li>`).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':
            originalCurrency = 'RUB';

            GM_addStyle(`
                .games-pricedown span.CCPrice {
                    font-size: 18px;
                }
                .good-title span.CCPrice {
                    margin-right: 3px;
                    font-size: 22px;
                }
            `);

            $('.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((index, node) => {
                const $node = $(node);
                const 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(`
                .Bisko_CC_Menu > a, .Bisko_CC_Menu li {
                    color: white;
                }
                .Bisko_CC_Menu ul {
                    margin: 0;
                }
            `);

            $('#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((i, node) => 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(`
                .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(`
                <svg viewBox="0 0 24 24">
                    <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" />
                </svg>
            `);
            // homepage & product page
            $(`
                .prtag > span,
                .grid-old-price,
                .price_price > span,
                div > span > .bold.white,
                li > .f_right:nth-child(2) > span
            `).bindPriceData();
            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());

            try {
                // product page
                originalCurrency = games.Currency;
                $('price > span').bindPriceData();
            } catch (e) {
                // home page
                new MutationObserver(mutations => {
                    mutations.forEach(mutation => {
                        mutation.addedNodes.forEach(addedNode => {
                            if (addedNode.src && addedNode.src.includes('bam.nr-data.net')) {
                                const currency = decodeURI(addedNode.src).split('currency_code":"').pop().slice(0, 3);

                                if (currency.length > 0) {
                                    originalCurrency = currency;

                                    const $prices = $('.prices > span, .prices > p');
                                    // offset decimal place in Europe (. ,)
                                    if (['EUR', 'RUB'].includes(currency)) $prices.text((i, text) => text.replace(',', '.'));

                                    $prices.bindPriceData();
                                    updateCurrency();
                                }
                            }
                        });
                    });
                }).observe(document.head, {
                    childList: true
                });
            }
            break;
        case 'uk.gamesplanet.com':
        case 'de.gamesplanet.com':
        case 'fr.gamesplanet.com':
            {
                originalCurrency = !location.host.startsWith('uk') ? 'EUR' : 'GBP';

                const GPHandler = () => {
                    const $prices = $('.price_base > strike, .price_current');

                    $('.container > ul').append(constructMenu());
                    // offset decimal place in Europe (. ,)
                    if (!location.host.startsWith('uk')) {
                        $prices.text((i, text) => text.replace(',', '.'));
                    }

                    $prices.bindPriceData();
                    updateCurrency();
                };

                GPHandler(true);

                new MutationObserver(mutations => {
                    mutations.forEach(mutation => {
                        mutation.removedNodes.forEach(removedNode => {
                            if (removedNode.id === 'nprogress') GPHandler();
                        });
                    });
                }).observe(document, {
                    childList: true,
                    subtree: true
                });
                break;
            }
        case 'www.cdkeys.com':
            {
                originalCurrency = $('.currency-switcher:first-child .value').text();
                const currenciesDefault = ['AUD', 'CAD', 'EUR', 'GBP', 'JPY', 'NZD', 'USD'];
                const currenciesAppend = ['CNY', 'HKD', 'KRW', 'MYR', 'NTD', 'RUB'];
                // bind event to default currency switcher to save preferrred currency
                $('.currency-switcher:first-child ul span').each((index, element) => {
                    const $ele = $(element);
                    const currency = $ele.text().slice(0, 3);

                    if (currenciesDefault.includes(currency)) {
                        $ele.parent().click(() => {
                            config.preferredCurrency = currency;

                            GM_setValue('Bisko_CC', JSON.stringify(config));
                        });
                    }
                });
                // append currencies not in the default currency switcher
                currenciesAppend.forEach(currency => {
                    $('.currency-switcher:first-child ul').append($(`<li><a>${currency} - ${currencies[currency].nameEN}</a></li>`).click(() => {
                        config.preferredCurrency = currency;

                        GM_setValue('Bisko_CC', JSON.stringify(config));
                        updateCurrency(currency);
                    }));
                });

                $('.price').bindPriceData();
                break;
            }
        case 'directg.net':
            originalCurrency = 'KRW';

            GM_addStyle(`
                .Bisko_CC_Menu ul {
                    width: 180px;
                    border-top: 3px solid #67c1f5;
                    background-color: #1b2838 !important;
                    opacity: 0.95;
                    color: rgba(255,255,255,0.5) !important;
                }
                .Bisko_CC_Menu ul li {
                    padding: 10px 30px;
                    font-weight: bold;
                }
                .Bisko_CC_Menu ul li:hover, .preferred {
                    background-color: initial !important;
                    color: white;
                }
            `);

            $('.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(`
                .Bisko_CC_Menu {
                    float: left;
                }
                .Bisko_CC_Menu > a {
                    display: block;
                    padding: 15px 20px;
                }
                .Bisko_CC_Menu ul {
                    background-color: #494f5c !important;
                    color: rgba(255, 255, 255, 0.6);
                }
                .Bisko_CC_Menu ul li {
                    padding: 5px 10px;
                }
                .Bisko_CC_Menu ul li:hover, .preferred {
                    background-color: initial !important;
                    color: white;
                }
            `);

            $('.nav:first-child').append(constructMenu());

            new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.removedNodes.forEach(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(`
                .Bisko_CC_Menu ul {
                    transform: translateY(-100%);
                    background-color: #474747 !important;
                    border: 1px solid #272727;
                }
                .Bisko_CC_Menu ul li {
                    padding: 8px 15px;
                    color: #dad6ca;
                }
                .Bisko_CC_Menu ul li:hover, .preferred {
                    background-color: #2E2E2E !important;
                    color: white;
                }
            `);

            $('#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((index, node) => {
                const $node = $(node);
                const 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(`
                .Bisko_CC_Menu ul {
                    background-color: #212121 !important;
                }
                .Bisko_CC_Menu ul li {
                    padding: 8px 15px;
                }
                .Bisko_CC_Menu ul li:hover, .preferred {
                    background-color: #1A1A1A !important;
                }
            `);

            $('.nav').eq(0).append(constructMenu());
            new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.removedNodes.forEach(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(`
                .Bisko_CC_Menu {
                    float: right;
                    margin-top: 5px;
                    padding: 1px 5px;
                    vertical-align: middle;
                    background-image: linear-gradient(#4E4E4E, #101112 40%, #191b1d);
                    font-size: 12px;
                    line-height: 1.5;
                    border-radius: 3px;
                    border-bottom-right-radius: 0;
                    border-top-right-radius: 0;
                }
                .Bisko_CC_Menu > a {
                    color: #f89406;
                }
            `);

            $('.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(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(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();
};
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();
});