// ==UserScript== // @name Steam历史最低价格查询 // @namespace SteamHistoryLowestPrice // @description 在steam商店页显示当前app历史最低价格及进包次数(此脚本需要勾选Steam商店加速才会生效) // @include https://store.steampowered.com/app/* // @include https://store.steampowered.com/bundle/* // @include https://store.steampowered.com/sub/* // @author 软妹币玩家、byzod // @license GPL version 3 or any later version // @version 1.2 // @grant GM_xmlhttpRequest // @enable true // jshint esversion:6 // @downloadURL https://update.greasyfork.icu/scripts/504441/Steam%E5%8E%86%E5%8F%B2%E6%9C%80%E4%BD%8E%E4%BB%B7%E6%A0%BC%E6%9F%A5%E8%AF%A2.user.js // @updateURL https://update.greasyfork.icu/scripts/504441/Steam%E5%8E%86%E5%8F%B2%E6%9C%80%E4%BD%8E%E4%BB%B7%E6%A0%BC%E6%9F%A5%E8%AF%A2.meta.js // ==/UserScript== // 显示样式 // 0 = 显示在购买按钮上面 // 1 = 显示在购买信息框上面 const INFO_STYLE = 1; // 货币区域覆盖,两个字母的国家代号,大小写均可 // 空字符("")代表不覆盖,使用steam的cookie中steamCountry的值 // 见 https://zh.wikipedia.org/wiki/ISO_3166-1 或 https://en.wikipedia.org/wiki/ISO_3166-1 // 常用 美国USD:"us", 中国CNY: "cn", 英国GBP: "uk", 日本JPY: "jp", 俄国RUS: "ru" const CC_OVERRIDE = ""; // 货币符号 const CURRENCY_SYMBOLS = { 'AED': 'DH', 'AUD': 'A$', 'BRL': 'R$', 'CAD': 'CDN$', 'CHF': 'CHF', 'CLP': 'CLP$', 'CNY': '¥', // Chines Yuan 'COP': 'COL$', 'CRC': '₡', // Costa Rican Colón 'EUR': '€', // Euro 'GBP': '£', // British Pound Sterling 'HKD': 'HK$', 'IDR': 'Rp', 'ILS': '₪', // Israeli New Sheqel 'INR': '₹', // Indian Rupee 'JPY': '¥', // Japanese Yen 'KRW': '₩', // South Korean Won 'MXN': 'Mex$', 'MYR': 'RM', 'NGN': '₦', // Nigerian Naira 'NOK': 'kr', 'NZD': 'NZ$', 'PEN': 'S/.', 'PHP': '₱', // Philippine Peso 'PLN': 'zł', // Polish Zloty 'PYG': '₲', // Paraguayan Guarani 'RUB': 'pуб', 'SAR': 'SR', 'SGD': 'S$', 'THB': '฿', // Thai Baht 'TRY': 'TL', 'TWD': 'NT$', 'UAH': '₴', // Ukrainian Hryvnia 'USD': '$', // US Dollar 'VND': '₫', // Vietnamese Dong 'ZAR': 'R ', }; // 查询历史低价包括的商店 const STORES = [ "steam", // "amazonus", // "impulse", // "gamersgate", // "direct2drive", // "origin", // "uplay", // "indiegalastore", // "gamesplanet", // "indiegamestand", // "gog", // "nuuvem", // "dlgamer", // "humblestore", // "squenix", // "bundlestars", // "fireflower", // "humblewidgets", // "newegg", // "coinplay", // "wingamestore", // "macgamestore", // "gamebillet", // "silagames", // "itchio", // "gamejolt", // "paradox" ]; // 在app页和愿望单页显示史低价格 let urlMatch = location.href.match(/(app|sub|bundle)\/(\d+)/); let appId = ""; let type = ""; let subIds = []; let bundleids = []; if (urlMatch && urlMatch.length == 3) { type = urlMatch[1] appId = urlMatch[2]; } // console.log('[史低]: ' + type + ' : ' + appId + ', requesting data info...'); // DEBUG // 获取subs document.querySelectorAll("input[name=subid]") .forEach(sub => subIds.push(sub.value)); // 获取bundles document.querySelectorAll("input[name=bundleid]") .forEach(sub => bundleids.push(sub.value)); let cc = "cn"; if (CC_OVERRIDE.length > 0) { // 使用覆盖的货币区域 cc = CC_OVERRIDE; } else { // 使用默认的的货币区域 let ccMatch = document.cookie.match(/steamCountry=([a-z]{2})/i); if (ccMatch !== null && ccMatch.length == 2) { cc = ccMatch[1]; } } AddLowestPriceTag(appId, type, subIds, bundleids, STORES.join(","), cc, location.protocol); // 在商店页添加史低信息 async function AddLowestPriceTag(appId, type = "app", subIds = [], bundleids = [], stores = "steam", cc = "cn", protocol = "https") { // 史低信息容器们 let lowestPriceNodes = {}; // 统计subid let findSubIds = []; if (type == "bundle") { // bundle就一个, 视作subid findSubIds.push(appId); } else if (type == "app" || type == "sub") { // app/sub/bundle 可能有好多 findSubIds = subIds.slice(); if (bundleids.length > 0) { findSubIds.push.apply(findSubIds, bundleids); } } // 寻找每一个subid的购买按钮,生成史低信息容器们 findSubIds.forEach(subId => { let gameWrapper = null; try { gameWrapper = document.querySelector('.game_area_purchase_game input[value="' + subId + '"]'); switch (INFO_STYLE) { case 0: gameWrapper = gameWrapper.parentNode.parentNode.querySelector('.game_purchase_action'); break; case 1: gameWrapper = gameWrapper.parentNode.parentNode; break; } } catch (ex) { gameWrapper = null; } if (gameWrapper) { let lowestInfo = document.createElement("div"); lowestInfo.className = "game_lowest_price"; lowestInfo.innerText = "正在读取历史最低价格..."; switch (INFO_STYLE) { case 0: gameWrapper.prepend(lowestInfo); break; case 1: gameWrapper.append(lowestInfo); break; } lowestPriceNodes[subId] = lowestInfo; } }); // 获取sub们的数据 let data = null; try { data = await GettingSteamDBAppInfo(appId, type, subIds, stores, cc, protocol); if ((typeof data == 'string')) data = JSON.parse(data); } catch (err) { console.log('[史低]: ' + err); } // console.log('[史低]: app ' + appId + ' data : %o', data); // DEBUG // 解析data let appInfos = []; // 如果是bundle, 除了.meta外只有一个bundle/xxx,否则是一大堆xxx if (type == "bundle") { appInfos.push({ Id: appId, Info: data["bundle/" + appId] }); } else if (type == "app" || type == "sub") { data = data.prices; for (let key in data) { let appid = key.replace(new RegExp('(app|sub|bundle)/'), ""); if (!isNaN(appid)) { appInfos.push({ Id: appid, Info: data[key] }); } } } // console.log('[史低]: app ' + appId + ' metaInfo: %o', metaInfo); // DEBUG // console.log('[史低]: app ' + appId + ' appInfos: %o', appInfos); // DEBUG // 如果查到info,塞到购买按钮上面去 if (appInfos.length > 0) { // 为每一个sub或bundle添加史低 appInfos.forEach(app => { let lowestInfo = lowestPriceNodes[app.Id]; if (lowestInfo) { lowestInfo.innerHTML = // 历史最低 '历史最低价是 ' + '' + new Date(app.Info.lowest.timestamp).toLocaleDateString() + ' 时在 ' + ' ' + app.Info.lowest.shop.name + ' 中的 ' + '-' + app.Info.lowest.cut + '%' + ' ' + GETSymbol(app.Info.lowest.price.currency) + ' ' + app.Info.lowest.price.amount + '' // 第二行 + '
' // // 进包次数 // + '进包  0 // ? ' style="color:#0d0" title="' + app.Info.bundles.live.length + ' 个正在销售的慈善包"' // : '') // + '> ' // + app.Info.bundles.count // + '  次,' // 当前最低 + (app.Info.current.price.amount <= app.Info.lowest.price.amount ? '当前为历史最低价,' : '当前最低价是') + '在 ' + ' ' + app.Info.current.shop.name + ' 中的 ' + '-' + app.Info.current.cut + '%' + ' ' + GETSymbol(app.Info.current.price.currency) + ' ' + app.Info.current.price.amount + ''; } }); } else { // metaInfo为空,或者appInfos无内容 console.log('[史低]: get lowest price failed, data = %o', data); for (let id in lowestPriceNodes) { lowestPriceNodes[id].innerHTML = ""; } } // 返回史低info return Promise.resolve(lowestPriceNodes); } function GETSymbol(currency) { return currency in CURRENCY_SYMBOLS ? CURRENCY_SYMBOLS[currency] : currency; } // 获取史低信息 async function GettingSteamDBAppInfo(appId, type = "app", subIds = [], stores = "steam", cc = "cn", protocol = "https") { let requestPromise = null; let bundleId = []; if (type == "bundle") { bundleId = [appId]; } else if (type == "app" || type == "sub") { bundleId = bundleids?.map(x => parseInt(x)).filter(x => !isNaN(x)); } if (!isNaN(appId) && parseInt(appId) > 0) { let requestUrl = protocol + "//api.augmentedsteam.com/prices/v2"; // console.log('[史低]: requestUrl: ' + requestUrl); // DEBUG //shops 61 = steam requestPromise = new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", headers: { 'Content-Type': 'application/json' }, url: requestUrl, data: JSON.stringify({ "country": cc, "apps": [], "subs": subIds.map(x => parseInt(x)).filter(x => !isNaN(x)), "bundles": bundleId, "voucher": true, "shops": [61] }), onload: function (response) { resolve(response.response); }, onerror: function (error) { reject(error); } }); }); } else { requestPromise = Promise.reject("Invalid appid"); } return requestPromise; }