// ==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.6
// @author kksskkoopp
// @match https://www.youtube.com/live_chat_replay*
// @match https://www.youtube.com/live_chat*
// @grant GM_xmlhttpRequest
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @connect v6.exchangerate-api.com
// @license MIT
// @run-at document-start
// ==/UserScript==
/* globals $ */
(function() {
'use strict';
// 汇率API信息
let chinese_name_font_size = 7; // 中文货币名 字体大小
let converted_currency_font_size = 10; // 转换后的货币金额 字体大小
let targetCurrencyCode = 'CNY'; // 目标币种
let targetCurrencyPrecision = 2 // 目标币种保留的小数位数;
// API密钥请在 https://www.exchangerate-api.com/ 免费获取:邮箱注册->一键激活->复制API密钥->添加到下面的的API_KEY
let API_KEY = [
'0c719520222e5b86cf26f479',
'd6aa54b3dd223922e629fcc8',
'064bacfc0b0c5d7fe525b541',
'35d768f3c2f9e84a00116085',
'975287c29230eca269117358'
]; // *** API密钥 *** (将API_KEY添加到方括号内,不要替换下面API_URL中的API_KEY)
let rand = Math.floor(Math.random() * API_KEY.length);
let API_URL = `https://v6.exchangerate-api.com/v6/${API_KEY[rand]}/latest/${targetCurrencyCode}`; // API地址
let API_QUOTA_URL = `https://v6.exchangerate-api.com/v6/${API_KEY[rand]}/quota` // 剩余额度查询地址
// YoutubeSuperChat货币符号 : ISO-4217货币码
let currencyMap = {
'$': { ISO_code: 'USD', chinese_name: '美元' },
'¥': { ISO_code: 'JPY', chinese_name: '日元' },
'₱': { ISO_code: 'PHP', chinese_name: '菲律宾比索' },
'£': { ISO_code: 'GBP', chinese_name: '英镑' },
'€': { ISO_code: 'EUR', chinese_name: '欧元' },
'₩': { ISO_code: 'KRW', chinese_name: '韩元' },
'₽': { ISO_code: 'RUB', chinese_name: '俄罗斯卢布' },
'₹': { ISO_code: 'INR', chinese_name: '印度卢比' },
'฿': { ISO_code: 'THB', chinese_name: '泰铢' },
'₫': { ISO_code: 'VND', chinese_name: '越南盾' },
'A$': { ISO_code: 'AUD', chinese_name: '澳大利亚元' },
'AU$': { ISO_code: 'AUD', chinese_name: '澳大利亚元' },
'NZ$': { ISO_code: 'NZD', chinese_name: '新西兰元' },
'R$': { ISO_code: 'BRL', chinese_name: '巴西雷亚尔' },
'HK$': { ISO_code: 'HKD', chinese_name: '港币' },
'NT$': { ISO_code: 'TWD', chinese_name: '新台币' },
'CA$': { ISO_code: 'CAD', chinese_name: '加拿大元' },
'US$': { ISO_code: 'USD', chinese_name: '美元' },
'JP¥': { ISO_code: 'JPY', chinese_name: '日元' },
'AED': { ISO_code: 'AED', chinese_name: '阿联酋迪拉姆' },
'AFN': { ISO_code: 'AFN', chinese_name: '阿富汗尼' },
'ALL': { ISO_code: 'ALL', chinese_name: '阿尔巴尼亚列克' },
'AMD': { ISO_code: 'AMD', chinese_name: '亚美尼亚德拉姆' },
'ANG': { ISO_code: 'ANG', chinese_name: '荷属安的列斯盾' },
'AOA': { ISO_code: 'AOA', chinese_name: '安哥拉宽扎' },
'ARS': { ISO_code: 'ARS', chinese_name: '阿根廷比索' },
'AUD': { ISO_code: 'AUD', chinese_name: '澳大利亚元' },
'AWG': { ISO_code: 'AWG', chinese_name: '阿鲁巴弗罗林' },
'AZN': { ISO_code: 'AZN', chinese_name: '阿塞拜疆马纳特' },
'BAM': { ISO_code: 'BAM', chinese_name: '波斯尼亚和黑塞哥维那马克' },
'BBD': { ISO_code: 'BBD', chinese_name: '巴巴多斯元' },
'BDT': { ISO_code: 'BDT', chinese_name: '孟加拉塔卡' },
'BGN': { ISO_code: 'BGN', chinese_name: '保加利亚列弗' },
'BHD': { ISO_code: 'BHD', chinese_name: '巴林第纳尔' },
'BIF': { ISO_code: 'BIF', chinese_name: '布隆迪法郎' },
'BMD': { ISO_code: 'BMD', chinese_name: '百慕大元' },
'BND': { ISO_code: 'BND', chinese_name: '文莱元' },
'BOB': { ISO_code: 'BOB', chinese_name: '玻利维亚诺' },
'BRL': { ISO_code: 'BRL', chinese_name: '巴西雷亚尔' },
'BSD': { ISO_code: 'BSD', chinese_name: '巴哈马元' },
'BTN': { ISO_code: 'BTN', chinese_name: '不丹努扎姆' },
'BWP': { ISO_code: 'BWP', chinese_name: '博茨瓦纳普拉' },
'BYN': { ISO_code: 'BYN', chinese_name: '白俄罗斯卢布' },
'BZD': { ISO_code: 'BZD', chinese_name: '伯利兹元' },
'CAD': { ISO_code: 'CAD', chinese_name: '加拿大元' },
'CDF': { ISO_code: 'CDF', chinese_name: '刚果法郎' },
'CHF': { ISO_code: 'CHF', chinese_name: '瑞士法郎' },
'CLP': { ISO_code: 'CLP', chinese_name: '智利比索' },
'CNY': { ISO_code: 'CNY', chinese_name: '人民币' },
'COP': { ISO_code: 'COP', chinese_name: '哥伦比亚比索' },
'CRC': { ISO_code: 'CRC', chinese_name: '哥斯达黎加科朗' },
'CUP': { ISO_code: 'CUP', chinese_name: '古巴比索' },
'CVE': { ISO_code: 'CVE', chinese_name: '佛得角埃斯库多' },
'CZK': { ISO_code: 'CZK', chinese_name: '捷克克朗' },
'DJF': { ISO_code: 'DJF', chinese_name: '吉布提法郎' },
'DKK': { ISO_code: 'DKK', chinese_name: '丹麦克朗' },
'DOP': { ISO_code: 'DOP', chinese_name: '多米尼加比索' },
'DZD': { ISO_code: 'DZD', chinese_name: '阿尔及利亚第纳尔' },
'EGP': { ISO_code: 'EGP', chinese_name: '埃及镑' },
'ERN': { ISO_code: 'ERN', chinese_name: '厄立特里亚纳克法' },
'ETB': { ISO_code: 'ETB', chinese_name: '埃塞俄比亚比尔' },
'EUR': { ISO_code: 'EUR', chinese_name: '欧元' },
'FJD': { ISO_code: 'FJD', chinese_name: '斐济元' },
'FKP': { ISO_code: 'FKP', chinese_name: '福克兰群岛镑' },
'FOK': { ISO_code: 'FOK', chinese_name: '法罗克朗' },
'GBP': { ISO_code: 'GBP', chinese_name: '英镑' },
'GEL': { ISO_code: 'GEL', chinese_name: '格鲁吉亚拉里' },
'GGP': { ISO_code: 'GGP', chinese_name: '根西镑' },
'GHS': { ISO_code: 'GHS', chinese_name: '加纳塞地' },
'GIP': { ISO_code: 'GIP', chinese_name: '直布罗陀镑' },
'GMD': { ISO_code: 'GMD', chinese_name: '冈比亚达拉西' },
'GNF': { ISO_code: 'GNF', chinese_name: '几内亚法郎' },
'GTQ': { ISO_code: 'GTQ', chinese_name: '危地马拉格查尔' },
'GYD': { ISO_code: 'GYD', chinese_name: '圭亚那元' },
'HKD': { ISO_code: 'HKD', chinese_name: '港币' },
'HNL': { ISO_code: 'HNL', chinese_name: '洪都拉斯伦皮拉' },
'HRK': { ISO_code: 'HRK', chinese_name: '克罗地亚库纳' },
'HTG': { ISO_code: 'HTG', chinese_name: '海地古德' },
'HUF': { ISO_code: 'HUF', chinese_name: '匈牙利福林' },
'IDR': { ISO_code: 'IDR', chinese_name: '印尼卢比' },
'ILS': { ISO_code: 'ILS', chinese_name: '以色列新谢克尔' },
'IMP': { ISO_code: 'IMP', chinese_name: '马恩岛镑' },
'INR': { ISO_code: 'INR', chinese_name: '印度卢比' },
'IQD': { ISO_code: 'IQD', chinese_name: '伊拉克第纳尔' },
'IRR': { ISO_code: 'IRR', chinese_name: '伊朗里亚尔' },
'ISK': { ISO_code: 'ISK', chinese_name: '冰岛克朗' },
'JEP': { ISO_code: 'JEP', chinese_name: '泽西镑' },
'JMD': { ISO_code: 'JMD', chinese_name: '牙买加元' },
'JOD': { ISO_code: 'JOD', chinese_name: '约旦第纳尔' },
'JPY': { ISO_code: 'JPY', chinese_name: '日元' },
'KES': { ISO_code: 'KES', chinese_name: '肯尼亚先令' },
'KGS': { ISO_code: 'KGS', chinese_name: '吉尔吉斯斯坦索姆' },
'KHR': { ISO_code: 'KHR', chinese_name: '柬埔寨瑞尔' },
'KID': { ISO_code: 'KID', chinese_name: '基里巴斯元' },
'KMF': { ISO_code: 'KMF', chinese_name: '科摩罗法郎' },
'KRW': { ISO_code: 'KRW', chinese_name: '韩元' },
'KWD': { ISO_code: 'KWD', chinese_name: '科威特第纳尔' },
'KYD': { ISO_code: 'KYD', chinese_name: '开曼群岛元' },
'KZT': { ISO_code: 'KZT', chinese_name: '哈萨克斯坦坚戈' },
'LAK': { ISO_code: 'LAK', chinese_name: '老挝基普' },
'LBP': { ISO_code: 'LBP', chinese_name: '黎巴嫩镑' },
'LKR': { ISO_code: 'LKR', chinese_name: '斯里兰卡卢比' },
'LRD': { ISO_code: 'LRD', chinese_name: '利比里亚元' },
'LSL': { ISO_code: 'LSL', chinese_name: '莱索托洛蒂' },
'LYD': { ISO_code: 'LYD', chinese_name: '利比亚第纳尔' },
'MAD': { ISO_code: 'MAD', chinese_name: '摩洛哥迪拉姆' },
'MDL': { ISO_code: 'MDL', chinese_name: '摩尔多瓦列伊' },
'MGA': { ISO_code: 'MGA', chinese_name: '马达加斯加阿里亚里' },
'MKD': { ISO_code: 'MKD', chinese_name: '马其顿第纳尔' },
'MMK': { ISO_code: 'MMK', chinese_name: '缅元' },
'MNT': { ISO_code: 'MNT', chinese_name: '蒙古图格里克' },
'MOP': { ISO_code: 'MOP', chinese_name: '澳门元' },
'MRU': { ISO_code: 'MRU', chinese_name: '毛里塔尼亚乌吉亚' },
'MUR': { ISO_code: 'MUR', chinese_name: '毛里求斯卢比' },
'MVR': { ISO_code: 'MVR', chinese_name: '马尔代夫拉菲亚' },
'MWK': { ISO_code: 'MWK', chinese_name: '马拉维克瓦查' },
'MXN': { ISO_code: 'MXN', chinese_name: '墨西哥比索' },
'MYR': { ISO_code: 'MYR', chinese_name: '马来西亚林吉特' },
'MZN': { ISO_code: 'MZN', chinese_name: '莫桑比克梅蒂卡尔' },
'NAD': { ISO_code: 'NAD', chinese_name: '纳米比亚元' },
'NGN': { ISO_code: 'NGN', chinese_name: '尼日利亚奈拉' },
'NIO': { ISO_code: 'NIO', chinese_name: '尼加拉瓜科多巴' },
'NOK': { ISO_code: 'NOK', chinese_name: '挪威克朗' },
'NPR': { ISO_code: 'NPR', chinese_name: '尼泊尔卢比' },
'NZD': { ISO_code: 'NZD', chinese_name: '新西兰元' },
'OMR': { ISO_code: 'OMR', chinese_name: '阿曼里亚尔' },
'PAB': { ISO_code: 'PAB', chinese_name: '巴拿马巴波亚' },
'PEN': { ISO_code: 'PEN', chinese_name: '秘鲁新索尔' },
'PGK': { ISO_code: 'PGK', chinese_name: '巴布亚新几内亚基那' },
'PHP': { ISO_code: 'PHP', chinese_name: '菲律宾比索' },
'PKR': { ISO_code: 'PKR', chinese_name: '巴基斯坦卢比' },
'PLN': { ISO_code: 'PLN', chinese_name: '波兰兹罗提' },
'PYG': { ISO_code: 'PYG', chinese_name: '巴拉圭瓜拉尼' },
'QAR': { ISO_code: 'QAR', chinese_name: '卡塔尔里亚尔' },
'RON': { ISO_code: 'RON', chinese_name: '罗马尼亚列伊' },
'RSD': { ISO_code: 'RSD', chinese_name: '塞尔维亚第纳尔' },
'RUB': { ISO_code: 'RUB', chinese_name: '俄罗斯卢布' },
'RWF': { ISO_code: 'RWF', chinese_name: '卢旺达法郎' },
'SAR': { ISO_code: 'SAR', chinese_name: '沙特里亚尔' },
'SBD': { ISO_code: 'SBD', chinese_name: '所罗门群岛元' },
'SCR': { ISO_code: 'SCR', chinese_name: '塞舌尔卢比' },
'SDG': { ISO_code: 'SDG', chinese_name: '苏丹镑' },
'SEK': { ISO_code: 'SEK', chinese_name: '瑞典克朗' },
'SGD': { ISO_code: 'SGD', chinese_name: '新加坡元' },
'SHP': { ISO_code: 'SHP', chinese_name: '圣赫勒拿镑' },
'SLE': { ISO_code: 'SLE', chinese_name: '塞拉利昂利昂' },
'SOS': { ISO_code: 'SOS', chinese_name: '索马里先令' },
'SRD': { ISO_code: 'SRD', chinese_name: '苏里南元' },
'SSP': { ISO_code: 'SSP', chinese_name: '南苏丹镑' },
'STN': { ISO_code: 'STN', chinese_name: '圣多美和普林西比多布拉' },
'SYP': { ISO_code: 'SYP', chinese_name: '叙利亚镑' },
'SZL': { ISO_code: 'SZL', chinese_name: '斯威士兰里兰吉尼' },
'THB': { ISO_code: 'THB', chinese_name: '泰铢' },
'TJS': { ISO_code: 'TJS', chinese_name: '塔吉克斯坦索莫尼' },
'TMT': { ISO_code: 'TMT', chinese_name: '土库曼斯坦马纳特' },
'TND': { ISO_code: 'TND', chinese_name: '突尼斯第纳尔' },
'TOP': { ISO_code: 'TOP', chinese_name: '汤加潘加' },
'TRY': { ISO_code: 'TRY', chinese_name: '土耳其里拉' },
'TTD': { ISO_code: 'TTD', chinese_name: '特立尼达和多巴哥元' },
'TVD': { ISO_code: 'TVD', chinese_name: '图瓦卢元' },
'TWD': { ISO_code: 'TWD', chinese_name: '新台币' },
'TZS': { ISO_code: 'TZS', chinese_name: '坦桑尼亚先令' },
'UAH': { ISO_code: 'UAH', chinese_name: '乌克兰格里夫纳' },
'UGX': { ISO_code: 'UGX', chinese_name: '乌干达先令' },
'USD': { ISO_code: 'USD', chinese_name: '美元' },
'UYU': { ISO_code: 'UYU', chinese_name: '乌拉圭比索' },
'UZS': { ISO_code: 'UZS', chinese_name: '乌兹别克斯坦苏姆' },
'VES': { ISO_code: 'VES', chinese_name: '委内瑞拉主权玻利瓦尔' },
'VND': { ISO_code: 'VND', chinese_name: '越南盾' },
'VUV': { ISO_code: 'VUV', chinese_name: '瓦努阿图瓦图' },
'WST': { ISO_code: 'WST', chinese_name: '萨摩亚塔拉' },
'XAF': { ISO_code: 'XAF', chinese_name: '中非法郎' },
'XCD': { ISO_code: 'XCD', chinese_name: '东加勒比元' },
'XDR': { ISO_code: 'XDR', chinese_name: '特别提款权' },
'XOF': { ISO_code: 'XOF', chinese_name: '西非法郎' },
'XPF': { ISO_code: 'XPF', chinese_name: '太平洋法郎' },
'YER': { ISO_code: 'YER', chinese_name: '也门里亚尔' },
'ZAR': { ISO_code: 'ZAR', chinese_name: '南非兰特' },
'ZMW': { ISO_code: 'ZMW', chinese_name: '赞比亚克瓦查' },
'ZWL': { ISO_code: 'ZWL', chinese_name: '津巴布韦元' }
};
let exchangeRates = {};
// 计算公式: targetCurrencyAmount = fromCurrencyAmount * exchangeRates[fromCurrenyCode]
// 获取汇率信息
function fetchExchangeRates(callback) {
// 查询剩余额度
GM_xmlhttpRequest({
method: 'GET',
url: API_QUOTA_URL,
onload: function(response) {
let data = JSON.parse(response.responseText);
if (data['result'] == 'success')
{
console.log(`每月计划额度:${data['plan_quota']}, 剩余额度:${data['requests_remaining']}`);
}
else if (data['result'] == 'error')
{
// 详情见 https://www.exchangerate-api.com/docs/request-quota-endpoint
if (data['error-type'] === 'invalid-key') {
console.log("错误:无效的API密钥。");
} else if (data['error-type'] === 'inactive-account') {
console.log("错误:账户未激活,请在您的电子邮件激活。");
} else if (data['error-type'] === 'quota-reached') {
console.log("错误:无剩余查询额度,您的全部查询额度已使用完毕。");
}
}
},
onerror: function() {
console.error('错误:脚本无法连接到汇率接口 https://www.exchangerate-api.com/');
}
});
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')
{
// 详情见 https://www.exchangerate-api.com/docs/standard-requests
if (data['error-type'] === 'unsupported-code') {
console.log("错误:不支持的币种。");
} else if (data['error-type'] === 'malformed-request') {
console.log("错误:请求格式错误。");
} else if (data['error-type'] === 'invalid-key') {
console.log("错误:无效的API密钥。");
} else if (data['error-type'] === 'inactive-account') {
console.log("错误:账户未激活,请在您的电子邮件激活。");
} else if (data['error-type'] === 'quota-reached') {
console.log("错误:无剩余查询额度,您的全部查询额度已使用完毕。");
}
}
},
onerror: function() {
console.error('错误:脚本无法连接到汇率接口 https://www.exchangerate-api.com/');
}
});
}
// 解析金额和货币类型
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.ISO_code, chinese_name: info.chinese_name };
}
}
console.error(`不支持的币种${text}.`);
return 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);
const additionalInfo = `
<div class="split-text" style="display: inline-block; white-space: no-wrap; text-align: left;">
<div style="font-size: ${chinese_name_font_size}px; margin-bottom: 1px;">${parsed.chinese_name}</div>
<div style="font-size: ${converted_currency_font_size}px; margin-top: 1px;">=${targetCurrencyCode} ${targetCurrencyAmount_str}</div>
</div>`;
$(this).html(message + additionalInfo);
$(this).attr('YoutubeSuperChatCurrencyConverter-converted', 'true'); // 标记为已处理
} else {
console.log(`解析失败[${message}]`);
}
}
});
}
});
}
}
};
// 创建并启动MutationObserver
let observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
// 启动观察器
$(document).ready(fetchExchangeRates(observeSuperChat));
})();