Greasy Fork

Greasy Fork is available in English.

Currency Converter

try to take over the world!

当前为 2017-07-29 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==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
// ==/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 = $('<li class="Bisko_CC_Menu"><a>Currencies</a></li>');
    const $ul = $('<ul></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(
            $(`<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':
            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(`<span class="currency_price" data-price="RUB ${price}">${price}</span>`);
                        } 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(`
                <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>
            `);
            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(`<span class="currency_name" data-currency="${originalCurrency}"></span>`);
                    });
            });

            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(`
                    <span class="currency_price" data-price="${originalCurrency} ${price}"></span>
                    <span class="currency_name" data-currency="${originalCurrency}"></span>
                `);
            });
            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(`
                    <span class="currency_name" data-currency="${originalCurrency}"></span>
                    <span class="currency_price" data-price="${originalCurrency} ${price}"></span>
                `);
            };
            // 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();
});