您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
查询不同区域的Fanatical游戏/慈善包的价格
// ==UserScript== // @name Fanatical Price Checker // @name:zh-CN Fanatical 跨区价格查询 // @name:zh-TW Fanatical 跨區價格查詢 // @namespace https://www.fanatical.com/ // @version 0.3.1 // @description Check the price of different regions for Fanatical. // @description:zh-CN 查询不同区域的Fanatical游戏/慈善包的价格 // @description:zh-TW 查詢不同區域的Fanatical遊戲/慈善包的價格 // @icon https://cdn.fanatical.com/production/icons/android-chrome-192x192.png // @author Thesharing // @license MIT // @include /^https?://www\.fanatical\.com/en/bundle/.+$ // @include /^https?://www\.fanatical\.com/en/game/.+$ // @include /^https?://www\.fanatical\.com/en/dlc/.+$ // @grant GM_xmlhttpRequest // @run-at document-idle // ==/UserScript== var totalNum = 0; var priceList = []; var regionList = ["USD", "CAD", "EUR", "GBP"]; var curList = {}; var urlType = document.URL.split('/')[4]; var targetCur = "CNY"; (function () { 'use strict'; var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var target = document.querySelector('#root'); var config = { attributes: true, childList: true, characterData: true }; var continuousObserver = new MutationObserver(function (mutations, me) { var normalPageContainer = document.getElementsByClassName('product-commerce-container'); var starDealPageContainer = document.getElementsByClassName('purchase-info-container'); if (starDealPageContainer.length > 0){ console.log('STARDEAL'); addStarDealButton(starDealPageContainer[0]); } if (normalPageContainer.length > 0) { console.log('NORMAL'); addNormalButton(normalPageContainer[0]); } }); var subObserver = new MutationObserver(function (mutations, me) { var normalPageContainer = document.getElementsByClassName('product-commerce-container'); if (normalPageContainer.length > 0) { addNormalButton(normalPageContainer[0]); var subContent = document.querySelector('.content').querySelector('div'); continuousObserver.observe(subContent, config); me.disconnect(); } }); var observer = new MutationObserver(function (mutations, me) { var content = document.querySelector('.content'); if (content) { subObserver.observe(content, config); me.disconnect(); } }); observer.observe(target, config); })(); function addNormalButton(container) { var outsideContainer = document.createElement('div'); outsideContainer.className = 'col-12 col-md-6 col-lg-12'; container.appendChild(outsideContainer); var priceContainer = document.createElement('div'); priceContainer.className = 'p-3 pl-md-1 pl-lg-3 card-block'; priceContainer.id = 'checkPrice'; outsideContainer.appendChild(priceContainer); var button = document.createElement('button'); button.className = 'mt-3 cart-btn btn btn-primary btn-lg btn-block'; button.id = 'checkPriceButton'; button.onclick = checkPrice; var buttonText = document.createElement('b'); buttonText.id = 'checkPriceButtonText'; buttonText.appendChild(document.createTextNode('Check Price')); button.appendChild(buttonText); priceContainer.appendChild(button); var checkPriceList = document.createElement('div'); checkPriceList.id = 'checkPriceList'; checkPriceList.className = 'mt-3'; priceContainer.appendChild(checkPriceList); } function addStarDealButton(container) { var priceContainer = document.createElement('div'); priceContainer.id = 'checkPrice'; container.appendChild(priceContainer); var button = document.createElement('button'); button.className = 'cart-btn btn btn-primary btn-lg'; button.id = 'checkPriceButton'; button.onclick = checkPrice; button.style = 'height: 48px; margin-left: 10px;'; var buttonText = document.createElement('b'); buttonText.id = 'checkPriceButtonText'; buttonText.appendChild(document.createTextNode('Check Price')); button.appendChild(buttonText); priceContainer.appendChild(button); var checkPriceList = document.createElement('div'); checkPriceList.id = 'checkPriceList'; var title = document.getElementsByClassName('purchase-info-title')[0]; title.appendChild(checkPriceList); } function checkPrice() { var buttonText = document.getElementById('checkPriceButtonText'); buttonText.innerText = 'Checking Price...'; if (urlType == 'bundle') { var bundleName = document.URL.split('/')[5]; GM_xmlhttpRequest({ method: "GET", url: "https://api.fanatical.com/api/products/" + bundleName, onload: function (response) { var bundleData = JSON.parse(response.responseText); priceList.length = 0; for (var i = 0; i < bundleData.bundles.length; i++) { var bundlePrice = {}; for (var j = 0; j < regionList.length; j++) { var priceItem = { 'price': bundleData.bundles[i].price[regionList[j]] / 100, 'targetCur': 0 }; bundlePrice[regionList[j]] = priceItem; } priceList.push(bundlePrice); } fetchCurrency(buttonText); } }); } else if (urlType == 'game' || urlType == 'dlc') { var gameName = document.URL.split('/')[5]; GM_xmlhttpRequest({ method: "GET", url: "https://api.fanatical.com/api/products/" + gameName, onload: function (response) { var gameData = JSON.parse(response.responseText); var discount = 1.0; if('current_discount' in gameData && 'percent'in gameData.current_discount){ discount = 1 - gameData.current_discount.percent; } priceList.length = 0; gamePrice = {}; for (var i = 0; i < regionList.length; i++) { var priceItem = { 'price': gameData.price[regionList[i]] * discount / 100, 'targetCur': 0 }; gamePrice[regionList[i]] = priceItem; } priceList.push(gamePrice); fetchCurrency(buttonText); } }); } } function fetchCurrency(buttonText) { for (var k = 0; k < regionList.length; k++) { GM_xmlhttpRequest({ method: "GET", url: "https://finance.google.cn/finance/converter?a=1&from=" + regionList[k] + "&to=" + targetCur, context: { 'region': regionList[k], }, onload: function (response) { var responseDocument = new DOMParser().parseFromString(response.responseText, "text/html"); var result = responseDocument.getElementById('currency_converter_result').innerText; curList[response.context.region] = extractCurrency(result); if (Object.keys(curList).length >= regionList.length) { buttonText.innerText = 'Finished!'; if (urlType == 'bundle') { displayBundleResult(); } else if (urlType == 'game' || urlType == 'dlc') { displayGameResult(); } } } }); } } function extractCurrency(str) { return parseFloat(str.trim().split(' ')[3]); } function displayBundleResult() { var cheapList = []; for (var i = 0; i < priceList.length; i++) { var cheapPrice = 10000.0; var cheapRegion = 'USD'; for (var j = 0; j < regionList.length; j++) { var priceItem = priceList[i][regionList[j]]; priceItem.targetCur = (curList[regionList[j]] * priceItem.price); if (priceItem.targetCur < cheapPrice) { cheapPrice = priceItem.targetCur; cheapRegion = regionList[j]; } } cheapList.push(cheapRegion); } // RENDER var c = document.getElementById('checkPriceList'); while (c.firstChild) { c.removeChild(c.firstChild); } for (var k = 0; k < priceList.length; k++) { var container = document.createElement('div'); container.className = 'mt-3'; c.appendChild(container); var titleText = document.createElement('b'); titleText.appendChild(document.createTextNode('Tier ' + (k + 1).toString())); var title = document.createElement('h4'); title.appendChild(titleText); container.appendChild(title); for (var l = 0; l < regionList.length; l++) { var priceText; if (regionList[l] == cheapList[k]) { priceText = document.createElement('b'); } else { priceText = document.createElement('span'); } var priceValue = priceList[k][regionList[l]]; priceText.appendChild(document.createTextNode(priceValue.price.toFixed(2) + ' ' + regionList[l] + ' = ' + priceValue.targetCur.toFixed(2) + ' ' + targetCur)); container.appendChild(priceText); container.appendChild(document.createElement('br')); } } } function displayGameResult() { var cheapPrice = 10000.0; var cheapRegion = 'USD'; for (var j = 0; j < regionList.length; j++) { var priceItem = priceList[0][regionList[j]]; priceItem.targetCur = (curList[regionList[j]] * priceItem.price); if (priceItem.targetCur < cheapPrice) { cheapPrice = priceItem.targetCur; cheapRegion = regionList[j]; } } // RENDER var c = document.getElementById('checkPriceList'); while (c.firstChild) { c.removeChild(c.firstChild); } var container = document.createElement('div'); container.className = 'mt-3'; c.appendChild(container); for (var l = 0; l < regionList.length; l++) { var priceText; if (regionList[l] == cheapRegion) { priceText = document.createElement('b'); } else { priceText = document.createElement('span'); } var priceValue = priceList[0][regionList[l]]; priceText.appendChild(document.createTextNode(priceValue.price.toFixed(2) + ' ' + regionList[l] + ' = ' + priceValue.targetCur.toFixed(2) + ' ' + targetCur)); container.appendChild(priceText); container.appendChild(document.createElement('br')); } }