YouTube SuperChat货币转换器

将各种国际货币金额转为你所在地区的币种(如CNY,HKD,NTD,USD,JPY等)

目前为 2024-07-22 提交的版本。查看 最新版本

// ==UserScript==
// @name         YouTube SuperChat货币转换器
// @name:zh-CN   YouTube SuperChat货币转换器
// @name:zh-TW   YouTube SuperChat貨幣轉換器
// @name:zh-HK   YouTube SuperChat貨幣轉換器

// @description         将各种国际货币金额转为你所在地区的币种(如CNY,HKD,NTD,USD,JPY等)
// @description:zh-CN   将各种国际货币金额转为你所在地区的币种(如CNY,HKD,NTD,USD,JPY等)
// @description:zh-TW   將各種國際貨幣金額轉為你所在地區的幣種(如CNY,HKD,NTD,USD,JPY等)
// @description:zh-HK   將各種國際貨幣金額轉為你所在地區的幣種(如CNY,HKD,NTD,USD,JPY等)

// @namespace    http://tampermonkey.net/
// @version      1.2
// @author       kksskkoopp
// @match        https://www.youtube.com/*
// @grant        GM_xmlhttpRequest
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @connect      v6.exchangerate-api.com
// @license      MIT
// @run-at       document-end
// ==/UserScript==
/* globals  $ */
(function() {
    'use strict';

    console.log('脚本信息');
    console.log(GM.info);

    // 汇率API信息
    let targetCurrencyCode = 'CNY'; // 目标币种
    let targetCurrencyPrecision = 2 // 目标币种保留的小数位数;
    // API密钥请在 https://www.exchangerate-api.com/ 免费获取:邮箱注册->一键激活->获得API密钥->替换下面的API_KEY
    let API_KEY = '0c719520222e5b86cf26f479'; // API密钥
    let API_URL = `https://v6.exchangerate-api.com/v6/${API_KEY}/latest/${targetCurrencyCode}`; // API地址

    // YoutubeSuperChat货币符号 : ISO-4217货币码
    let currencyMap = {
        '$': { code: 'USD', chinese_name: '美元' },
        '¥': { code: 'JPY', chinese_name: '日元' },
        '₱': { code: 'PHP', chinese_name: '菲律宾比索' },
        '£': { code: 'GBP', chinese_name: '英镑' },
        '€': { code: 'EUR', chinese_name: '欧元' },
        '₩': { code: 'KRW', chinese_name: '韩元' },
        '₽': { code: 'RUB', chinese_name: '卢布' },
        '₹': { code: 'INR', chinese_name: '卢比' },
        '฿': { code: 'THB', chinese_name: '泰铢' },
        '₣': { code: 'FRF', chinese_name: '法郎' },
        '₫': { code: 'VND', chinese_name: '越南盾' },

        'A$': { code: 'AUD', chinese_name: '澳大利亚元' },
        'NZ$': { code: 'NZD', chinese_name: '新西兰元' },
        'R$': { code: 'BRL', chinese_name: '巴西雷亚尔' },
        'HK$': { code: 'HKD', chinese_name: '港币' },
        'NT$': { code: 'TWD', chinese_name: '新台币' },
        'CA$': { code: 'CAD', chinese_name: '加拿大元' },
        'US$': { code: 'USD', chinese_name: '美元' },

        'AED': { code: 'AED', chinese_name: '阿联酋迪拉姆' },
        'ARS': { code: 'ARS', chinese_name: '阿根廷比索' },
        'SGD': { code: 'SGD', chinese_name: '新加坡元' },
        'MYR': { code: 'MYR', chinese_name: '马来西亚林吉特' }



    };

    let exchangeRates = {};
    /*
        计算公式
        targetCurrencyAmount = fromCurrencyAmount * exchangeRates[fromCurrenyCode]
    */

    // 获取汇率信息
    function fetchExchangeRates(callback) {
        console.log(`开始请求汇率${API_URL}`);
        GM_xmlhttpRequest({
            method: 'GET',
            url: API_URL,
            onload: function(response) {
                let data = JSON.parse(response.responseText);
                if (data.result == 'success')
                {
                    exchangeRates = data.conversion_rates;
                    let datetime = new Date();
                    console.log(`汇率 ${datetime.toLocaleDateString()} ${datetime.toLocaleTimeString()}`);
                    console.log(exchangeRates);
                    console.log('汇率请求完毕');
                    callback();
                }
                else if (data.result == 'error')
                {
                    console.error(`错误:响应:${data}`);
                    console.error(`详情见https://www.exchangerate-api.com/docs/standard-requests`);
                }
            },
            onerror: function() {
                console.error('无法获取汇率');
            }
        });
    }


    // 解析金额和货币类型
    function parseAmountAndCurrency(text) {
        // 去除空白字符
        text = text.replace(/\s+/g, '');
        // 遍历currencyMap字典,找到匹配的货币符号
        for (const [symbol, info] of Object.entries(currencyMap)) {
            if (text.startsWith(symbol)) {
                const amount = parseFloat(text.replace(symbol, '').replace(/,/g, '')); // 提取金额并去除千位分隔符
                return { amount, fromCurrencyCode: info.code, chinese_name: info.chinese_name };
            }
        }
        console.error(`新的币种${text}.`);
        return null; // 如果未找到匹配的货币符号,返回null
    }

    // 观察DOM变化并转换SuperChat金额
    function observeSuperChat() {

        let targetNode = document.body;
        let config = { childList: true, subtree: true };

        let callback = function(mutationsList, observer) {
            for(let mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    // 遍历新增的节点,检查是否包含SuperChat消息
                    $(mutation.addedNodes).each(function() {
                        let element = $(this).find('yt-formatted-string.style-scope.yt-live-chat-paid-message-renderer, yt-formatted-string.style-scope.yt-live-chat-paid-sticker-renderer').not('#deleted-state, #dashboard-deleted-state');
                        if (element.length > 0) {
                            // 处理每个SuperChat消息
                            element.each(function() {
                                if (!$(this).attr('YoutubeSuperChatCurrencyConverter-converted')) {



                                    let message = $(this).text().trim();
                                    console.log(`捕获到超级留言[${message}]`);
                                    let parsed = parseAmountAndCurrency(message);
                                    if (parsed) {
                                        console.log(`解析成功${message}:${parsed.fromCurrencyCode} ${parsed.amount}`);
                                        // 获取汇率并计算转换后的金额
                                        let targetCurrencyAmount = parsed.amount / exchangeRates[parsed.fromCurrencyCode];
                                        let targetCurrencyAmount_str = targetCurrencyAmount.toFixed(targetCurrencyPrecision);
                                        //let newText = `${message}=${targetCurrencyCode} ${targetCurrencyAmount_str}`;

                                        const additionalInfo = `
                                            <div class="split-text" style="display: inline-block; white-space: no-wrap; text-align: left;">
                                                <div style="font-size: 7px;">${parsed.chinese_name}</div>
                                                <div style="font-size: 11px;">=${targetCurrencyCode} ${targetCurrencyAmount_str}</div>
                                            </div>`;

                                        $(this).html(message + additionalInfo);


                                        //$(this).text(newText);

                                        $(this).attr('YoutubeSuperChatCurrencyConverter-converted', 'true'); // 标记为已处理

                                    } else {
                                        console.log(`解析失败[${message}]`);
                                    }
                                }
                            });
                        }
                    });
                }
            }
        };

        // 创建并启动MutationObserver
        let observer = new MutationObserver(callback);
        observer.observe(targetNode, config);
    }

    // 启动观察器
    $(document).ready(function() {
        fetchExchangeRates(observeSuperChat);
    });
})();