// ==UserScript==
// @name DDSteam for IGDB and Steam
// @name:es DDSteam para IGDB y Steam
// @version 4.0
// @description Add download/search links for games on IGDB and Steam pages.
// @description:es Añadir enlaces de descarga/búsqueda de juegos en las páginas de IGDB y Steam.
// @author johnromerobot
// @license MIT
// @match https://www.igdb.com/search*
// @match https://www.igdb.com/games/*
// @match https://store.steampowered.com/app/*
// @namespace https://greasyfork.org/users/1243768
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
// --- Configuration: Define each site's info and default enabled state ---
const siteConfigs = [
{
id: "steamgg",
name: "SteamGG",
tooltip: "Search on SteamGG",
icon: "https://i.ibb.co/XCj45HD/1728102863385.png",
urlTemplate: "https://steamgg.net/?s={game}",
defaultEnabled: true
},
{
id: "games4u",
name: "Games4U",
tooltip: "Search on Games4U",
icon: "https://games4u.org/wp-content/uploads/2024/07/Games4u.webp",
urlTemplate: "https://games4u.org/?s={game}",
defaultEnabled: true
},
{
id: "steamrip",
name: "SteamRIP",
tooltip: "Search on SteamRIP",
icon: "https://i.imgur.com/tmvOT86.png",
urlTemplate: "https://steamrip.com/?s={game}",
defaultEnabled: true
},
{
id: "compupc",
name: "CompuPC",
tooltip: "Search on CompuPC",
icon: "https://img.compu-pc.com/i/a5bbf162b8926d1eff5cdbec5ee6e09a/logo.png",
urlTemplate: "https://compu-pc.com/?s={game}",
defaultEnabled: true
},
{
id: "juegosdepcfull",
name: "JuegosdePCFull",
tooltip: "Search on JuegosdePCFull",
icon: "https://www.gamezfull.com/wp-content/themes/MystiqueR3/favicon_gf.ico",
urlTemplate: "https://juegosdepcfull.com/?s={game}",
defaultEnabled: true
},
{
id: "csrinru",
name: "CS.RIN.RU",
tooltip: "Search on CS.RIN.RU (Login required)",
icon: "https://i.ibb.co/RYQkz8t/site-logo-2.png",
urlTemplate: "https://cs.rin.ru/forum/search.php?keywords={game}&terms=all&author=&sc=1&sf=titleonly&sk=t&sd=d&sr=topics&st=0&ch=300&t=0&submit=Search",
defaultEnabled: true
},
{
id: "gog",
name: "GOG",
tooltip: "Search on GOGGames",
icon: "https://i.imgur.com/wXfz72C.png",
urlTemplate: "https://www.gog-games.to/?q={game}",
defaultEnabled: true
},
{
id: "fitgirl",
name: "FitGirl",
tooltip: "Search on FitGirl",
icon: "https://i.imgur.com/GOFbweI.png",
urlTemplate: "https://fitgirl-repacks.site/?s={game}",
defaultEnabled: true
},
{
id: "ovagames",
name: "OvaGames",
tooltip: "Search on OvaGames",
icon: "https://i.ibb.co/MxtCWQxG/ovagames-logo-Photoroom.png",
urlTemplate: "https://www.ovagames.com/?s={game}",
defaultEnabled: true
},
{
id: "crocdb",
name: "CrocDB",
tooltip: "Search on CrocDB",
icon: "https://crocdb.net/static/img/croc-512x512.png",
urlTemplate: "https://crocdb.net/search/?title={game}",
defaultEnabled: true
},
{
id: "retrogametalk",
name: "RetroGameTalk",
tooltip: "Search on RetroGameTalk",
icon: "https://retrogametalk.com/repository/wp-content/uploads/2025/02/rgt-logo.png",
urlTemplate: "https://retrogametalk.com/repository/?s={game}",
defaultEnabled: true
},
{
id: "romsfun",
name: "RomsFun",
tooltip: "Search on RomsFun",
icon: "https://romsfun.com/wp-content/uploads/2023/08/LOGO.png",
urlTemplate: "https://romsfun.com/?s={game}",
defaultEnabled: true
},
{
id: "nxbrew",
name: "NXBrew",
tooltip: "Search on NXBrew",
icon: "https://nxbrew.net/wp-content/uploads/2019/05/cropped-NXbrewlogo-1.png",
urlTemplate: "https://nxbrew.net/?s={game}",
defaultEnabled: true
},
{
id: "nopaystation",
name: "NoPayStation",
tooltip: "Search on NoPayStation",
icon: "https://i.ibb.co/22msVjw/87ef1b4993784afe5a15d20e5936253b.webp",
urlTemplate: "https://nopaystation.com/search?query={game}&limit=50&orderBy=completionDate&sort=DESC&missing=Show",
defaultEnabled: true
},
{
id: "pcgamingwiki",
name: "PCGamingWiki",
tooltip: "Search on PCGamingWiki",
icon: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwZgcgIYqscsLY6OnFI3sC7ZRYui2OghZWIg&s",
urlTemplate: "https://www.pcgamingwiki.com/w/index.php?search={game}",
defaultEnabled: true
}
];
// --- Configuration Storage ---
function getSiteOrder(platform) {
const key = `ddsteam_order_${platform}`;
return GM_getValue(key, siteConfigs.map(site => site.id));
}
function setSiteOrder(platform, order) {
const key = `ddsteam_order_${platform}`;
GM_setValue(key, order);
}
function isSiteEnabled(siteId, platform) {
const key = `ddsteam_${platform}_${siteId}`;
const site = siteConfigs.find(s => s.id === siteId);
return GM_getValue(key, site.defaultEnabled);
}
function setSiteEnabled(siteId, platform, enabled) {
const key = `ddsteam_${platform}_${siteId}`;
GM_setValue(key, enabled);
}
// --- Popup Menu ---
function createPopupMenu() {
const modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '50%';
modal.style.left = '50%';
modal.style.transform = 'translate(-50%, -50%)';
modal.style.backgroundColor = '#1a1a1a'; // Dark background
modal.style.padding = '20px';
modal.style.zIndex = '10000';
modal.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
modal.style.borderRadius = '8px';
modal.style.maxHeight = '80vh';
modal.style.overflowY = 'auto';
modal.style.color = '#fff'; // White text for contrast
const title = document.createElement('h2');
title.textContent = 'DDSteam Configuration';
title.style.marginTop = '0';
title.style.color = '#fff';
modal.appendChild(title);
const tabs = document.createElement('div');
tabs.style.display = 'flex';
tabs.style.marginBottom = '10px';
const steamTab = document.createElement('button');
steamTab.textContent = 'Steam';
steamTab.style.flex = '1';
steamTab.style.padding = '5px';
steamTab.style.backgroundColor = '#333'; // Darker gray for inactive tab
steamTab.style.border = 'none';
steamTab.style.cursor = 'pointer';
steamTab.style.color = '#fff';
const igdbTab = document.createElement('button');
igdbTab.textContent = 'IGDB';
igdbTab.style.flex = '1';
igdbTab.style.padding = '5px';
igdbTab.style.backgroundColor = '#444'; // Slightly lighter gray for active tab
igdbTab.style.border = 'none';
igdbTab.style.cursor = 'pointer';
igdbTab.style.color = '#fff';
tabs.appendChild(steamTab);
tabs.appendChild(igdbTab);
modal.appendChild(tabs);
const steamContainer = document.createElement('div');
const igdbContainer = document.createElement('div');
igdbContainer.style.display = 'none';
function populateContainer(container, platform) {
container.innerHTML = '';
const order = getSiteOrder(platform);
order.forEach(siteId => {
const site = siteConfigs.find(s => s.id === siteId);
const item = document.createElement('div');
item.draggable = true;
item.style.display = 'flex';
item.style.alignItems = 'center';
item.style.margin = '5px 0';
item.style.cursor = 'move';
item.style.padding = '5px';
item.style.backgroundColor = '#2a2a2a'; // Dark background for items
item.style.borderRadius = '4px';
item.style.color = '#fff';
const img = new Image();
img.src = site.icon;
img.style.width = '56px';
img.style.height = '28px';
img.style.objectFit = 'contain';
img.style.marginRight = '10px';
img.title = site.tooltip;
const status = document.createElement('span');
status.textContent = isSiteEnabled(site.id, platform) ? '✔' : '✘';
status.style.fontSize = '20px';
status.style.marginLeft = '10px';
status.style.cursor = 'pointer';
status.style.color = isSiteEnabled(site.id, platform) ? '#00ff00' : '#ff0000';
status.addEventListener('click', () => {
const newState = !isSiteEnabled(site.id, platform);
setSiteEnabled(site.id, platform, newState);
status.textContent = newState ? '✔' : '✘';
status.style.color = newState ? '#00ff00' : '#ff0000';
});
item.appendChild(img);
item.appendChild(document.createTextNode(site.name));
item.appendChild(status);
container.appendChild(item);
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', site.id);
item.style.opacity = '0.5';
});
item.addEventListener('dragend', () => {
item.style.opacity = '1';
});
item.addEventListener('dragover', (e) => e.preventDefault());
item.addEventListener('drop', (e) => {
e.preventDefault();
const draggedId = e.dataTransfer.getData('text/plain');
const newOrder = order.filter(id => id !== draggedId);
const dropIndex = order.indexOf(site.id);
newOrder.splice(dropIndex, 0, draggedId);
setSiteOrder(platform, newOrder);
populateContainer(container, platform);
});
});
}
populateContainer(steamContainer, 'steam');
populateContainer(igdbContainer, 'igdb');
modal.appendChild(steamContainer);
modal.appendChild(igdbContainer);
steamTab.addEventListener('click', () => {
steamContainer.style.display = 'block';
igdbContainer.style.display = 'none';
steamTab.style.backgroundColor = '#444';
igdbTab.style.backgroundColor = '#333';
});
igdbTab.addEventListener('click', () => {
igdbContainer.style.display = 'block';
steamContainer.style.display = 'none';
igdbTab.style.backgroundColor = '#444';
steamTab.style.backgroundColor = '#333';
});
const resetButton = document.createElement('button');
resetButton.textContent = 'Reset to Defaults';
resetButton.style.marginTop = '10px';
resetButton.style.padding = '5px 10px';
resetButton.style.backgroundColor = '#444';
resetButton.style.border = 'none';
resetButton.style.color = '#fff';
resetButton.style.cursor = 'pointer';
resetButton.addEventListener('click', () => {
const platform = steamContainer.style.display === 'block' ? 'steam' : 'igdb';
setSiteOrder(platform, siteConfigs.map(site => site.id));
siteConfigs.forEach(site => setSiteEnabled(site.id, platform, site.defaultEnabled));
populateContainer(steamContainer, 'steam');
populateContainer(igdbContainer, 'igdb');
});
modal.appendChild(resetButton);
const okButton = document.createElement('button');
okButton.textContent = 'OK';
okButton.style.marginTop = '10px';
okButton.style.marginLeft = '10px';
okButton.style.padding = '5px 10px';
okButton.style.backgroundColor = '#444';
okButton.style.border = 'none';
okButton.style.color = '#fff';
okButton.style.cursor = 'pointer';
okButton.addEventListener('click', () => {
document.body.removeChild(modal);
window.location.reload(); // Refresh the page
});
modal.appendChild(okButton);
// Add click outside handler
document.addEventListener('click', (e) => {
if (!modal.contains(e.target)) {
document.body.removeChild(modal);
}
});
document.body.appendChild(modal);
}
GM_registerMenuCommand("Configure DDSteam Links", createPopupMenu);
// --- Utility Functions ---
function getSites(formattedGameName, platform) {
const order = getSiteOrder(platform);
return order
.map(siteId => siteConfigs.find(site => site.id === siteId))
.filter(site => isSiteEnabled(site.id, platform))
.map(site => ({
name: site.name,
tooltip: site.tooltip,
icon: site.icon,
url: site.urlTemplate.replace('{game}', formattedGameName)
}));
}
function createButton(searchLink, buttonText, tooltipText, iconPath, iconWidth, iconHeight) {
const linkButton = document.createElement("a");
linkButton.href = searchLink;
linkButton.target = "_blank";
linkButton.title = tooltipText;
linkButton.style.display = 'inline-block';
linkButton.style.marginRight = '10px';
linkButton.style.marginTop = '5px';
const img = new Image();
img.src = iconPath;
img.alt = buttonText;
img.style.width = iconWidth;
img.style.height = iconHeight;
img.style.objectFit = 'contain';
img.style.transition = 'transform 0.3s ease-in-out';
img.style.borderRadius = '8px';
img.style.boxShadow = '0 0 5px rgba(0, 0, 0, 0.3)';
img.style.backgroundColor = 'rgba(0, 0, 0, 0.2)';
linkButton.appendChild(img);
return linkButton;
}
function formatGameName(gameName) {
return gameName.trim().toLowerCase().replace(/'/g, '').replace(/_/g, ' ').replace(/[^a-zA-Z0-9 ]/g, '');
}
// --- Processing Functions ---
function processSearchResults() {
const gameLinks = document.querySelectorAll("a.overflow-wrap.link-dark.h4.mt-0");
gameLinks.forEach(link => {
if (!link.href.includes('/games/')) return;
let gameName = link.firstChild && link.firstChild.nodeType === Node.TEXT_NODE ?
link.firstChild.textContent.trim() : link.textContent.trim();
if (link.nextElementSibling && link.nextElementSibling.classList.contains("ddsteam-container")) return;
const container = document.createElement('div');
container.classList.add("ddsteam-container");
container.style.marginTop = '5px';
container.style.display = 'flex';
container.style.flexWrap = 'wrap';
container.style.gap = '5px';
const formattedGameName = formatGameName(gameName);
const sites = getSites(formattedGameName, 'igdb');
sites.forEach(site => {
const btn = createButton(site.url, site.name, site.tooltip, site.icon, '56px', '28px');
container.appendChild(btn);
});
link.insertAdjacentElement('afterend', container);
});
}
function processGameInfoPage() {
const linksContainer = document.querySelector('.MuiGrid2-grid-xs-12');
if (!linksContainer || linksContainer.querySelector('.ddsteam-game-links')) return;
const container = document.createElement('div');
container.classList.add('ddsteam-game-links');
container.style.marginTop = '8px';
container.style.display = 'flex';
container.style.flexWrap = 'wrap';
container.style.gap = '8px';
container.style.justifyContent = 'center';
const gameTitleElement = document.querySelector("h1.MuiTypography-h3") || document.querySelector("h1");
if (!gameTitleElement) return;
const gameName = gameTitleElement.textContent.trim();
const formattedGameName = formatGameName(gameName);
const sites = getSites(formattedGameName, 'igdb');
sites.forEach(site => {
const btn = createButton(site.url, site.name, site.tooltip, site.icon, '48px', '48px');
container.appendChild(btn);
});
const hrElem = linksContainer.querySelector('hr');
if (hrElem) hrElem.insertAdjacentElement('beforebegin', container);
else linksContainer.appendChild(container);
}
function processGamePage() {
const gameTitleElement = document.querySelector('.apphub_AppName');
if (!gameTitleElement) return;
const parent = gameTitleElement.parentElement;
if (!parent || parent.querySelector('.ddsteam-container')) return;
const gameName = gameTitleElement.textContent.trim();
const formattedGameName = formatGameName(gameName);
const sites = getSites(formattedGameName, 'steam');
const container = document.createElement('div');
container.classList.add("ddsteam-container");
container.style.marginTop = '10px';
container.style.display = 'flex';
container.style.flexWrap = 'wrap';
container.style.gap = '5px';
sites.forEach(site => {
const btn = createButton(site.url, site.name, site.tooltip, site.icon, '56px', '28px');
container.appendChild(btn);
});
parent.appendChild(container);
}
// --- Styles ---
const styles = `
a:hover img {
transform: scale(1.1);
}
`;
const styleSheet = document.createElement("style");
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
// --- Initialization ---
const url = window.location.href;
if (url.includes('igdb.com/search')) {
processSearchResults();
const observer = new MutationObserver(() => processSearchResults());
observer.observe(document.body, { childList: true, subtree: true });
} else if (url.includes('igdb.com/games/')) {
setTimeout(processGameInfoPage, 1000);
} else if (url.includes('store.steampowered.com/app/')) {
processGamePage();
}
})();