您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Check every web page for game, dlc and package links to the steam store and mark using icons whether it's owned, unowned, wishlisted, ignored (not interested), removed/delisted (decommissioned), has cards, or is bundled.
当前为
// ==UserScript== // @name Steam Web Integration // @icon https://store.steampowered.com/favicon.ico // @namespace Royalgamer06 // @author Royalgamer06 // @contributor Black3ird // @contributor Lex // @contributor Luckz // @version 1.7.5 // @description Check every web page for game, dlc and package links to the steam store and mark using icons whether it's owned, unowned, wishlisted, ignored (not interested), removed/delisted (decommissioned), has cards, or is bundled. // @include /^https?\:\/\/.+/ // @exclude /^https?\:\/\/(.+.steampowered|steamcommunity).com\/(?!groups\/groupbuys).*/ // @grant GM_xmlhttpRequest // @grant GM_openInTab // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @connect store.steampowered.com // @connect steam-tracker.com // @connect bartervg.com // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js // @supportURL https://www.steamgifts.com/discussion/y9vVm/ // ==/UserScript== // ==Configuration== const prefix = false; // Prefix (true) instead of suffix (false) position icon. const wantIgnores = true; // Whether (true) or not (false) you want to display an extra icon for ignored (not interested) apps. const wantDecommissioned = true; // Whether (true) or not (false) you want to display an extra icon for removed or delisted (decommissioned) apps. const wantCards = true; // Whether (true) or not (false) you want to display an extra icon for apps with cards. const wantBundles = true; // Whether (true) or not (false) you want to display an extra icon for previously bundled apps. const linkCardIcon = true; // Link the card icon to SteamCardExchange.net const ignoredIcon = "🚫︎"; // HTML entity code for '🛇' (default). const ignoredColor = "grey"; // Color of the icon for ignored (not interested) apps. const wishlistIcon = "❤"; // HTML entity code for '❤' (default). const wishlistColor = "hotpink"; // Color of the icon for wishlisted apps. const ownedIcon = "✔"; // HTML entity code for '✔' (default). const ownedColor = "green"; // Color of the icon for owned apps and subs. const unownedIcon = "✘"; // HTML entity code for '✘' (default). const unownedColor = "red"; // Color of the icon for unowned apps and subs. const decommissionedIcon = "🗑"; // HTML entity code for '🗑' (default). The symbol '☠' ("☠") is a good alternative if the default symbol is unavailable. const decommissionedColor = "initial"; // Color of the icon for removed or delisted apps and subs. const cardIcon = "🂡"; // HTML entity code for '🂡' (default). ♠ ("♠") is an alternative if this symbol is unavailable. const cardColor = "blue"; // Color of the icon for cards. const bundleIcon = "🎁︎"; // HTML entity code for '🎁︎' (default). Barter.vg uses the symbol '✽' ("✽"). const bundleColor = "yellow"; // Color of the icon for bundled apps. const userRefreshInterval = 0; // Number of minutes to wait to refresh cached userdata. 0 = always stay up-to-date. const decommissionedRefreshInterval = 60 * 24; // Number of minutes to wait to refresh cached userdata. 0 = always stay up-to-date, but not recommended. const cardsRefreshInterval = 60 * 24 * 2; // Number of minutes to wait to refresh cached trading card data. 0 = always stay up-to-date, but not recommended. const bundlesRefreshInterval = 60 * 24 * 2; // Number of minutes to wait to refresh cached bundle data. 0 = always stay up-to-date, but not recommended. const dateOverride = false; // Force date display in the YYYY-MM-DD HH:MM:SS style; otherwise matches system locale. // ==/Configuration== // ==Code== this.$ = this.jQuery = jQuery.noConflict(true); $.expr[":"].regex = function(elem, index, match) { var matchParams = match[3].split(","), validLabels = /^(data|css):/, attr = { method: matchParams[0].match(validLabels) ? matchParams[0].split(":")[0] : "attr", property: matchParams.shift().replace(validLabels, "") }, regexFlags = "ig", regex = new RegExp(matchParams.join("").replace(/^\s+|\s+$/g, ""), regexFlags); return regex.test(jQuery(elem)[attr.method](attr.property)); }; refresh(); function refresh() { const cachedJson = GM_getValue("swi_data", null); const lastCached = GM_getValue("swi_last", 0); if (Date.now() - lastCached >= userRefreshInterval * 60000 || !cachedJson) { var v = parseInt(GM_getValue("swi_v", "1")) + 1; GM_xmlhttpRequest({ method: "GET", url: "https://store.steampowered.com/dynamicstore/userdata/?v=" + v, onload: function(response) { GM_setValue("swi_v", v); refreshDecommissioned(function(decommissioned) { refreshCards(function(cards) { refreshBundles(function(bundles) { init(JSON.parse(response.responseText), decommissioned, cards, bundles); }); }); }); } }); } else { refreshDecommissioned(function(decommissioned) { refreshCards(function(cards) { refreshBundles(function(bundles) { init(JSON.parse(cachedJson), decommissioned, cards, bundles); }); }); }); } } function refreshDecommissioned(callback) { const cachedDecommissioned = JSON.parse(GM_getValue("swi_decommissioned", null)); const lastCachedDecommissioned = GM_getValue("swi_decommissioned_last", 0); if (wantDecommissioned && (Date.now() - lastCachedDecommissioned >= decommissionedRefreshInterval * 60000 || !cachedDecommissioned)) { GM_xmlhttpRequest({ method: "GET", url: "https://steam-tracker.com/api?action=GetAppListV3", timeout: 30000, onload: function(response) { var json = null; try { json = JSON.parse(response.responseText); if (json.success) { GM_setValue("swi_decommissioned", JSON.stringify(json.removed_apps)); GM_setValue("swi_decommissioned_last", Date.now()); } callback(json.removed_apps); } catch (e) { console.log("Unable to parse removed steam games data. Using cached data...", e); callback(cachedDecommissioned); } }, onerror: function() { console.log("An error occurred while refreshing removed steam games data. Using cached data..."); callback(cachedDecommissioned); }, ontimeout: function() { console.log("It took too long to refresh removed steam games data. Using cached data..."); callback(cachedDecommissioned); } }); } else { callback(cachedDecommissioned); } } function refreshCards(callback) { const cachedCards = JSON.parse(GM_getValue("swi_tradingcards", null)); const lastCachedCards = parseInt(GM_getValue("swi_tradingcards_last", 0)) || 1; if (wantCards && (Date.now() - lastCachedCards >= cardsRefreshInterval * 60000 || !cachedCards || Object.keys(cachedCards).length < 7000) || Object.values(cachedCards)[0].marketable === undefined) { GM_xmlhttpRequest({ method: "GET", url: "https://bartervg.com/browse/cards/json/", timeout: 30000, onload: function(response) { var json = null; try { json = JSON.parse(response.responseText); if (Object.keys(json).length > 7000) { // sanity check GM_setValue("swi_tradingcards", JSON.stringify(json)); GM_setValue("swi_tradingcards_last", Date.now()); } callback(json); } catch (error) { console.log("Unable to parse Barter.vg trading cards data. Using cached data...", error); callback(cachedCards); } }, onerror: function(response) { console.log("An error occurred while refreshing Barter.vg trading cards data. Using cached data...", response); callback(cachedCards); }, ontimeout: function() { console.log("It took too long to refresh Barter.vg trading cards data. Using cached data..."); callback(cachedCards); } }); } else { callback(cachedCards); } } function refreshBundles(callback) { const cachedBundles = JSON.parse(GM_getValue("swi_bundles", null)); const lastCachedBundles = parseInt(GM_getValue("swi_bundles_last", 0)) || 1; if (wantBundles && (Date.now() - lastCachedBundles >= bundlesRefreshInterval * 60000 || !cachedBundles || Object.keys(cachedBundles).length < 7000) || Object.values(cachedBundles)[0].bundles === undefined) { GM_xmlhttpRequest({ method: "GET", url: "https://bartervg.com/browse/bundles/json/", timeout: 30000, onload: function(response) { var json = null; try { json = JSON.parse(response.responseText); if (Object.keys(json).length > 7000) { // sanity check GM_setValue("swi_bundles", JSON.stringify(json)); GM_setValue("swi_bundles_last", Date.now()); } callback(json); } catch (error) { console.log("Unable to parse Barter.vg bundles data. Using cached data...", error); callback(cachedBundles); } }, onerror: function(response) { console.log("An error occurred while refreshing Barter.vg bundles data. Using cached data...", response); callback(cachedBundles); }, ontimeout: function() { console.log("It took too long to refresh Barter.vg bundles data. Using cached data..."); callback(cachedBundles); } }); } else { callback(cachedBundles); } } function init(userdata, decommissioned, cards, bundles) { var ignoredApps = userdata.rgIgnoredApps; var ownedApps = userdata.rgOwnedApps; var ownedPackages = userdata.rgOwnedPackages; var wishlist = userdata.rgWishlist; var lastCached = GM_getValue("swi_last", 0); if (ownedApps.length === 0 && ownedPackages.length === 0 && ignoredApps.length === 0 && wishlist.length === 0) { const parsedCachedJson = JSON.parse(GM_getValue("swi_data", null)); ignoredApps = parsedCachedJson.rgIgnoredApps; ownedApps = parsedCachedJson.rgOwnedApps; ownedPackages = parsedCachedJson.rgOwnedPackages; wishlist = parsedCachedJson.rgWishlist; } else { lastCached = Date.now(); GM_setValue("swi_last", lastCached); GM_setValue("swi_data", JSON.stringify(userdata)); } const lcs = dateOverride ? (new Date(lastCached)).toLocaleString("sv-SE") : (new Date(lastCached)).toLocaleString(); const dlcs = (new Date(GM_getValue("swi_decommissioned_last", 0))).toLocaleString(dateOverride ? "sv-SE" : undefined); const clcs = (new Date(GM_getValue("swi_tradingcards_last", 0))).toLocaleString(dateOverride ? "sv-SE" : undefined); const blcs = (new Date(GM_getValue("swi_bundles_last", 0))).toLocaleString(dateOverride ? "sv-SE" : undefined); const appSelector = ":regex(href, ^(https?:)?\/\/(store\.steampowered\.com|steamcommunity\.com|steamdb\.info)\/(agecheck\/)?app\/[0-9]+), img[src*='cdn.akamai.steamstatic.com/steam/apps/'], img[src*='steamcdn-a.akamaihd.net/steam/apps/'], " + "img[src*='cdn.edgecast.steamstatic.com/steam/apps/'], img[src*='steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/'], img[src*='steamdb.info/static/camo/apps/']"; const subSelector = ":regex(href, ^(https?:)?\/\/(store\.steampowered\.com|steamdb\.info)\/sub\/[0-9]+)"; $(document).on("DOMSubtreeModified", appSelector, function() { doApp(this, wishlist, ownedApps, ignoredApps, decommissioned, cards, bundles, lcs, dlcs, clcs, blcs); }).on("DOMSubtreeModified", subSelector, function() { doSub(this, wishlist, ownedPackages, lcs); }).ready(function() { $(appSelector).each(function() { doApp(this, wishlist, ownedApps, ignoredApps, decommissioned, cards, bundles, lcs, dlcs, clcs, blcs); }); $(subSelector).each(function() { doSub(this, wishlist, ownedPackages, lcs); }); }); } function doApp(elem, wishlist, ownedApps, ignoredApps, decommissioned, cards, bundles, lcs, dlcs, clcs, blcs) { if (!$(elem).hasClass("swi")) { $(elem).addClass("swi"); let appID = elem.href ? parseInt(elem.href.split("app/")[1].split("/")[0].split("?")[0].split("#")[0]) : parseInt(elem.src.split("apps/")[1].split("/")[0].split("?")[0].split("#")[0]); if (!isNaN(appID)) setTimeout(function() { let html; if (ownedApps.includes(appID)) { //if owned html = "<span style='color: " + ownedColor + "; cursor: help;' title='Game or DLC (" + appID + ") owned on Steam\nLast updated: " + lcs + "'> " + ownedIcon + "</span>"; //✔ } else { //else not owned if (wishlist.includes(appID)) { //if wishlisted html = "<span style='color: " + wishlistColor + "; cursor: help;' title='Game or DLC (" + appID + ") wishlisted on Steam\nLast updated: " + lcs + "'> " + wishlistIcon + "</span>"; //❤ } else { //else not wishlisted html = "<span style='color: " + unownedColor + "; cursor: help;' title='Game or DLC (" + appID + ") not owned on Steam\nLast updated: " + lcs + "'> " + unownedIcon + "</span>"; //✘ } } if (ignoredApps.includes(appID) && wantIgnores) { //if ignored and enabled html += "<span style='color: " + ignoredColor + "; cursor: help;' title='Game or DLC (" + appID + ") ignored on Steam\nLast updated: " + lcs + "'> " + ignoredIcon + "</span>"; //🛇 } if (wantDecommissioned && decommissioned) { //if decommissioned and have cache or new data var app = decommissioned.filter(function(obj) { return obj.appid === appID.toString(); })[0]; if (app) { //if decommissioned? html += "<span style='color: " + decommissionedColor + "; cursor: help;' title='The " + app.type + " \"" + app.name.replace(/'/g, "") + "\" (" + appID + ") is " + app.category.toLowerCase() + " and has only " + app.count + " confirmed owners on Steam\nLast updated: " + dlcs + "'> " + decommissionedIcon + "</span>"; //🗑 } } if (wantCards && cards[appID] !== undefined && cards[appID].cards !== undefined && cards[appID].cards > 0) { //if has cards and enabled html += "<span style='color: " + cardColor + "; cursor: help;' title='Game (" + appID + ") has " + cards[appID].cards + (cards[appID].marketable ? " " : " un") + "marketable cards\nLast updated: " + clcs + "'> " + (linkCardIcon ? "<a href='https://www.steamcardexchange.net/index.php?gamepage-appid-" + appID + "' target='_blank'>" + cardIcon + "</a>" : cardIcon) + "</span>"; } if (wantBundles && bundles[appID] !== undefined && bundles[appID].bundles !== undefined && bundles[appID].bundles > 0) { //if is bundled and enabled html += "<span style='color: " + bundleColor + "; cursor: help;' title='Game (" + appID + ") has been in " + bundles[appID].bundles + " bundles\nLast updated: " + blcs + "'> " + "<a href='https://barter.vg/steam/app/" + appID + "' target='_blank'>" + bundleIcon + "</a></span>"; } if (prefix) { $(elem).before(html); } else { $(elem).after(html); } $(elem).parent().css("overflow", "visible"); }, 0); } } function doSub(elem, wishlist, ownedPackages, lcs) { if (!$(elem).hasClass("swi")) { $(elem).addClass("swi"); setTimeout(function() { var subID = parseInt(elem.href.split("sub/")[1].split("/")[0].split("?")[0].split("#")[0]); var html; if ($.inArray(subID, ownedPackages) > -1) { //if owned html = "<span style='color: " + ownedColor + "; cursor: help;' title='Package owned on Steam\nLast updated: " + lcs + "'> " + ownedIcon + "</span>"; //✔ } else { //else not owned html = "<span style='color: " + unownedColor + "; cursor: help;' title='Package not owned on Steam\nLast updated: " + lcs + "'> " + unownedIcon + "</span>"; //✖ } if (prefix) { $(elem).before(html); } else { $(elem).after(html); } $(elem).parent().css("overflow", "visible"); }, 0); } } // ==/Code==
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址