您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds custom URL buttons on Steam pages for cracked and deal sites.
// ==UserScript== // @name Steam Cracked & Deals Hub // @description Adds custom URL buttons on Steam pages for cracked and deal sites. // @version 2.0 // @license MIT // @author 6969RandomGuy6969 // @match https://store.steampowered.com/app/* // @icon https://i.imgur.com/8CoJnwB.png // @namespace https://greasyfork.org/users/1167434 // ==/UserScript== (function () { 'use strict'; const gameName = decodeURIComponent(window.location.pathname.split("/")[3].replace(/_/g, " ")); const ignoreButton = document.querySelector("#ignoreBtn"); // Helpers for local storage function saveCustomSites(key, data) { localStorage.setItem("steam_links_custom_" + key, JSON.stringify(data)); } function loadCustomSites(key) { try { return JSON.parse(localStorage.getItem("steam_links_custom_" + key)) || []; } catch { return []; } } function addCustomSite(key, site) { const current = loadCustomSites(key); current.push(site); saveCustomSites(key, current); } function removeCustomSite(key, site) { const current = loadCustomSites(key); const updated = current.filter(s => s.url !== site.url || s.text !== site.text); saveCustomSites(key, updated); } // UI Component Creators function createContainer() { const container = document.createElement("div"); container.style.marginTop = "50px"; container.style.padding = "20px"; container.style.background = "rgba(0, 0, 0, 0.2)"; container.style.borderRadius = "10px"; container.style.display = "flex"; container.style.flexDirection = "column"; container.style.gap = "30px"; return container; } function createHeader(text) { const header = document.createElement("div"); header.style.fontWeight = "bold"; header.style.fontSize = "21px"; header.style.marginBottom = "15px"; header.style.textTransform = "uppercase"; header.textContent = text; return header; } function createGridContainer() { const grid = document.createElement("div"); grid.style.display = "grid"; grid.style.gridTemplateColumns = "repeat(auto-fit, minmax(160px, 1fr))"; grid.style.gap = "10px"; return grid; } function createButton(url, buttonText, isRemovable = false, onRemove = null, isEditMode = false) { const buttonContainer = document.createElement("div"); buttonContainer.style.display = "flex"; buttonContainer.style.alignItems = "center"; buttonContainer.style.position = "relative"; const button = document.createElement("a"); button.className = "btnv6_blue_hoverfade btn_medium"; button.style.display = "flex"; button.style.alignItems = "center"; button.style.justifyContent = "center"; button.style.minWidth = "160px"; button.style.height = "40px"; button.style.textAlign = "center"; button.style.cursor = "pointer"; button.style.backgroundColor = "rgba(103, 193, 245, 0.2)"; button.style.color = "#67c1f5"; button.style.fontSize = "14px"; button.style.borderRadius = "6px"; const formattedName = gameName.replace(/\s+/g, "+"); const finalURL = url.includes("{{GAME_NAME}}") ? url.replace("{{GAME_NAME}}", formattedName) : url + encodeURIComponent(gameName); button.href = finalURL; button.target = "_blank"; button.textContent = buttonText; buttonContainer.appendChild(button); if (isRemovable) { const deleteButton = document.createElement("button"); deleteButton.textContent = "✖"; deleteButton.style.position = "absolute"; deleteButton.style.top = "-5px"; deleteButton.style.right = "-5px"; deleteButton.style.background = "red"; deleteButton.style.color = "white"; deleteButton.style.border = "none"; deleteButton.style.width = "20px"; deleteButton.style.height = "20px"; deleteButton.style.borderRadius = "50%"; deleteButton.style.cursor = "pointer"; deleteButton.style.display = isEditMode ? "block" : "none"; deleteButton.onclick = () => { buttonContainer.remove(); if (onRemove) onRemove(); }; buttonContainer.appendChild(deleteButton); buttonContainer._deleteButton = deleteButton; // store ref } return buttonContainer; } function createInputSection(category, grid) { let isEditMode = false; const deleteRefs = []; const addButton = document.createElement("button"); addButton.textContent = "+"; addButton.style.background = "#67c1f5"; addButton.style.color = "white"; addButton.style.border = "none"; addButton.style.padding = "5px 10px"; addButton.style.cursor = "pointer"; addButton.style.borderRadius = "4px"; const inputContainer = document.createElement("div"); inputContainer.style.display = "none"; inputContainer.style.flexDirection = "column"; inputContainer.style.gap = "5px"; inputContainer.style.marginTop = "10px"; const inputName = document.createElement("input"); inputName.placeholder = "Site Name"; inputName.style.flex = "1"; const inputURL = document.createElement("input"); inputURL.placeholder = "Paste search URL like https://steamrip.com/?s=red+dead"; inputURL.style.flex = "2"; const confirmButton = document.createElement("button"); confirmButton.textContent = "✅ Save"; confirmButton.style.background = "green"; confirmButton.style.color = "white"; confirmButton.style.border = "none"; confirmButton.style.padding = "5px 10px"; confirmButton.style.cursor = "pointer"; confirmButton.style.borderRadius = "4px"; const cancelButton = document.createElement("button"); cancelButton.textContent = "❌ Cancel"; cancelButton.style.background = "red"; cancelButton.style.color = "white"; cancelButton.style.border = "none"; cancelButton.style.padding = "5px 10px"; cancelButton.style.cursor = "pointer"; cancelButton.style.borderRadius = "4px"; function toggleEditMode(enable) { isEditMode = enable; inputContainer.style.display = isEditMode ? "flex" : "none"; addButton.textContent = isEditMode ? "➕ Add" : "+"; deleteRefs.forEach(btn => { btn.style.display = isEditMode ? "block" : "none"; }); } confirmButton.onclick = () => { const name = inputName.value.trim(); const url = inputURL.value.trim(); if (name && url.includes("?") && url.includes("=")) { const base = url.split("=")[0] + "="; const site = { url: base + "{{GAME_NAME}}", text: name }; const btn = createButton(site.url, site.text, true, () => { removeCustomSite(category, site); }, isEditMode); if (btn._deleteButton) deleteRefs.push(btn._deleteButton); grid.appendChild(btn); addCustomSite(category, site); inputName.value = ""; inputURL.value = ""; toggleEditMode(false); } else { alert("Paste full working search URL like https://steamrip.com/?s=red+dead"); } }; cancelButton.onclick = () => toggleEditMode(false); addButton.onclick = () => toggleEditMode(!isEditMode); inputContainer.appendChild(inputName); inputContainer.appendChild(inputURL); inputContainer.appendChild(confirmButton); inputContainer.appendChild(cancelButton); const section = document.createElement("div"); section.appendChild(addButton); section.appendChild(inputContainer); loadCustomSites(category).forEach(site => { const btn = createButton(site.url, site.text, true, () => { removeCustomSite(category, site); }, isEditMode); if (btn._deleteButton) { btn._deleteButton.style.display = "none"; deleteRefs.push(btn._deleteButton); } grid.appendChild(btn); }); return section; } // Main UI const categoryContainer = createContainer(); const crackedHeader = createHeader("CRACKED:"); const crackedGrid = createGridContainer(); const crackedSites = [ { url: "https://www.skidrowreloaded.com/?s={{GAME_NAME}}", text: "SkidrowReloaded" }, { url: "https://igg-games.com/?s={{GAME_NAME}}", text: "IGG-Games" }, { url: "https://x1337x.ws/srch?search={{GAME_NAME}}", text: "x1337x" }, { url: "https://game3rb.com/?s={{GAME_NAME}}", text: "Game3rb" }, { url: "https://online-fix.me/index.php?do=search&subaction=search&story={{GAME_NAME}}", text: "Onlinefix" }, { url: "https://fitgirl-repacks.site/?s={{GAME_NAME}}", text: "Fitgirl Repacks" }, { url: "https://dodi-repacks.site/?s={{GAME_NAME}}", text: "Dodi Repack" } ]; crackedSites.forEach(site => crackedGrid.appendChild(createButton(site.url, site.text))); const crackedInputSection = createInputSection("cracked", crackedGrid); const dealsHeader = createHeader("DEALS:"); const dealsGrid = createGridContainer(); const dealsSites = [ { url: "https://store.epicgames.com/en-US/browse?q={{GAME_NAME}}", text: "Epic Games" }, { url: "https://www.gog.com/en/games?query={{GAME_NAME}}", text: "GOG" }, { url: "https://www.humblebundle.com/store/search?sort=discount&search={{GAME_NAME}}", text: "Humble Store" }, { url: "https://www.gamestop.com/search/?q={{GAME_NAME}}", text: "GameStop" }, { url: "https://www.cdkeys.com/catalogsearch/result/?q={{GAME_NAME}}", text: "CDKeys" }, { url: "https://store.ubi.com/us/search?q={{GAME_NAME}}", text: "UPlay" }, { url: "https://www.origin.com/store/search?fq=search&searchString={{GAME_NAME}}", text: "Origin" }, { url: "https://www.greenmangaming.com/search?query={{GAME_NAME}}", text: "Green Man Gaming" }, { url: "https://www.fanatical.com/en/search?search={{GAME_NAME}}", text: "Fanatical" }, { url: "https://www.microsoft.com/en-us/store/search/games?q={{GAME_NAME}}", text: "Microsoft Store" } ]; dealsSites.forEach(site => dealsGrid.appendChild(createButton(site.url, site.text))); const dealsInputSection = createInputSection("deals", dealsGrid); categoryContainer.appendChild(crackedHeader); categoryContainer.appendChild(crackedGrid); categoryContainer.appendChild(crackedInputSection); categoryContainer.appendChild(dealsHeader); categoryContainer.appendChild(dealsGrid); categoryContainer.appendChild(dealsInputSection); if (ignoreButton) { ignoreButton.parentNode.insertBefore(categoryContainer, ignoreButton.nextSibling); } })();