Greasy Fork is available in English.

DDSteam for IGDB and Steam

Add download/search links for games on IGDB and Steam pages. Includes configurable shortcuts and game name formatting.

// ==UserScript==
// @name         DDSteam for IGDB and Steam
// @name:es      DDSteam para IGDB y Steam
// @version      5.1
// @description  Add download/search links for games on IGDB and Steam pages. Includes configurable shortcuts and game name formatting.
// @description:es  Añadir enlaces de descarga/búsqueda de juegos en las páginas de IGDB y Steam. Incluye accesos directos configurables y formato de nombre de juego.
// @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';

    // --- Global Keys for Settings ---
    const SETTINGS_SHORTCUT_ENABLED_KEY = 'ddsteam_show_settings_shortcut';
    const GAME_FORMATTING_ENABLED_KEY = 'ddsteam_game_formatting_enabled';
    const DEFAULT_SETTINGS_SHORTCUT_ENABLED = true;
    const DEFAULT_GAME_FORMATTING_ENABLED = false;

    // --- Configuration: Define each site's info and default enabled state ---
    const siteConfigs = [
        {
            id: "steamgg",
            name: "SteamGG",
            tooltip: "Search on SteamGG\nDLL Site. Portable Games.",
            icon: "https://i.ibb.co/XCj45HD/1728102863385.png",
            urlTemplate: "https://steamgg.net/?s={game}",
            defaultEnabled: true
        },
      {
            id: "games4u",
            name: "Games4U",
            tooltip: "Search on Games4U\nDLL Site. Portable Games.",
            icon: "https://games4u.org/wp-content/uploads/2024/07/Games4u.webp",
            urlTemplate: "https://games4u.org/?s={game}",
            defaultEnabled: false
        },
      {
            id: "gamedrive",
            name: "GameDrive",
            tooltip: "Search on GameDrive\nDLL Site.",
            icon: "https://gamedrive.org/wp-content/uploads/2023/06/logo.png",
            urlTemplate: "https://gamedrive.org/?s={game}",
            defaultEnabled: true
        },
      {
            id: "anker",
            name: "AnkerGames",
            tooltip: "Search on AnkerGames\nDLL Site. Portable Games. Direct Links. No filehosters.",
            icon: "https://ankergames.net/static/img/logo-1734270270.webp",
            urlTemplate: "https://ankergames.net/search/{game}",
            defaultEnabled: true
        },
      {
            id: "onlinefix",
            name: "Online-Fix",
            tooltip: "Search on Online-Fix\nDLL Site. Games with online patches",
            icon: "https://i.ibb.co/rRZfn6Wp/logo1.png",
            urlTemplate: "https://online-fix.me/index.php?do=search&subaction=search&story={game}",
            defaultEnabled: true
        },
        {
            id: "steamrip",
            name: "SteamRIP",
            tooltip: "Search on SteamRIP\nDLL Site. Portable Games.",
            icon: "https://i.imgur.com/tmvOT86.png",
            urlTemplate: "https://steamrip.com/?s={game}",
            defaultEnabled: true
        },
        {
            id: "compupc",
            name: "CompuPC",
            tooltip: "Search on CompuPC\nDLL Spanish Site.",
            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\nDLL Spanish Site.",
            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) \nThe origin of everything. Good for download clean steam files and latest updates.",
            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\nDLL Site. Focus in GOG games.",
            icon: "https://i.imgur.com/wXfz72C.png",
            urlTemplate: "https://www.gog-games.to/?search={game}",
            defaultEnabled: true
        },
      {
            id: "blizzboygames",
            name: "BlizzBoyGames",
            tooltip: "Search on BlizzBoyGames\nDLL Spanish Site. Good for old games.",
            icon: "https://www.blizzboygames.net/wp-content/uploads/2016/07/logo.png",
            urlTemplate: "https://www.blizzboygames.net/?s={game}",
            defaultEnabled: true
        },
        {
            id: "fitgirl",
            name: "FitGirl",
            tooltip: "Search on FitGirl\nThe Torrent Site.",
            icon: "https://i.imgur.com/GOFbweI.png",
            urlTemplate: "https://fitgirl-repacks.site/?s={game}",
            defaultEnabled: true
        },
      {
            id: "byxatab",
            name: "ByXatab",
            tooltip: "Search on ByXatab\nTorrent Site. Newer games are portable.",
            icon: "https://i.ibb.co/x8CsZ8GP/1314800.jpg",
            urlTemplate: "https://byxatab.com/search/{game}",
            defaultEnabled: true
        },
        {
            id: "ovagames",
            name: "OvaGames",
            tooltip: "Search on OvaGames\nDLL Site in multiple parts.",
            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\nROMs DDL Site. Clean and fast.",
            icon: "https://crocdb.net/static/img/croc_logo.png",
            urlTemplate: "https://crocdb.net/search/?title={game}",
            defaultEnabled: true
        },
      {
            id: "retrogametalk",
            name: "RetroGameTalk",
            tooltip: "Search on RetroGameTalk (Login required) \nROMs DDL Site. Good for patched, modded and translated games.",
            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\nROMs DDL Site.",
            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\nSwitch Games.",
            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\nPS3/PSVita PKG games files.",
            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\nGame Fixes & Workarounds.",
            icon: "https://i.ibb.co/h1FZcbV1/images-Photoroom.png",
            urlTemplate: "https://www.pcgamingwiki.com/w/index.php?search={game}",
            defaultEnabled: true
        },
      {
            id: "steamdb",
            name: "SteamDB",
            tooltip: "Search on SteamDB",
            icon: "https://i.ibb.co/nNNjwvpQ/Picsart-25-03-23-03-58-16-581.png",
            urlTemplate: "https://steamdb.info/search/?a=all&q={game}",
            defaultEnabled: true
        },
      {
            id: "hltb",
            name: "HowLongToBeat",
            tooltip: "Search on HowLongToBeat\nFind Average Game Lengths.",
            icon: "https://howlongtobeat.com/img/icons/apple-touch-icon-72x72.png",
            urlTemplate: "https://howlongtobeat.com/?q={game}",
            defaultEnabled: true
        },
      {
            id: "igdbsearch",
            name: "IGDB",
            tooltip: "Search on IGDB",
            icon: "https://www.igdb.com/packs/static/igdbLogo-bcd49db90003ee7cd4f4.svg",
            urlTemplate: "https://www.igdb.com/search?utf8=%E2%9C%93&q={game}",
            defaultEnabled: true
        },
        {
            id: "ggdeals",
            name: "GGDeals",
            tooltip: "Search on GGDeals",
            icon: "https://gg.deals/images/logo/logo-white.svg?v=c4392aa2",
            urlTemplate: "https://gg.deals/search/?title={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 ? site.defaultEnabled : false);
    }

    function setSiteEnabled(siteId, platform, enabled) {
        const key = `ddsteam_${platform}_${siteId}`;
        GM_setValue(key, enabled);
    }

    // --- Popup Menu ---
    let ddsteamSettingsModal = null;
    let ddsteamSettingsModalClickListener = null;

    function closeDdsteamSettingsModal() {
        if (ddsteamSettingsModal && ddsteamSettingsModal.parentNode) {
            ddsteamSettingsModal.parentNode.removeChild(ddsteamSettingsModal);
            document.body.style.overflow = '';
            if (ddsteamSettingsModalClickListener) {
                document.removeEventListener('click', ddsteamSettingsModalClickListener);
                ddsteamSettingsModalClickListener = null;
            }
            ddsteamSettingsModal = null;
        }
    }

    function createPopupMenu() {
        if (ddsteamSettingsModal) {
            return;
        }

        const modal = document.createElement('div');
        ddsteamSettingsModal = modal;

        modal.style.position = 'fixed';
        modal.style.top = '50%';
        modal.style.left = '50%';
        modal.style.transform = 'translate(-50%, -50%)';
        modal.style.backgroundColor = '#1a1a1a';
        modal.style.padding = '20px';
        modal.style.zIndex = '10001';
        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';

        document.body.style.overflow = 'hidden';

        const title = document.createElement('h2');
        title.textContent = 'DDSteam Configuration';
        title.style.marginTop = '0';
        title.style.color = '#fff';
        modal.appendChild(title);

        // --- TABS (UNCHANGED) ---
        const tabs = document.createElement('div');
        tabs.style.display = 'flex';
        tabs.style.marginBottom = '10px';
        const steamTab = document.createElement('button');
        steamTab.textContent = 'Steam';
        steamTab.style.cssText = 'flex: 1; padding: 5px; background-color: white; color: black; border: none; cursor: pointer;';
        const igdbTab = document.createElement('button');
        igdbTab.textContent = 'IGDB';
        igdbTab.style.cssText = 'flex: 1; padding: 5px; background-color: #ccc; color: black; border: none; cursor: pointer;';
        tabs.appendChild(steamTab);
        tabs.appendChild(igdbTab);
        modal.appendChild(tabs);
        const steamContainer = document.createElement('div');
        const igdbContainer = document.createElement('div');
        igdbContainer.style.display = 'none';

        // --- POPULATE CONTAINERS (UNCHANGED) ---
        function populateContainer(container, platform) {
            container.innerHTML = '';
            const order = getSiteOrder(platform);
            order.forEach(siteId => {
                const site = siteConfigs.find(s => s.id === siteId);
                if (!site) return;
                const item = document.createElement('div');
                item.draggable = true;
                item.style.cssText = 'display: flex; align-items: center; margin: 5px 0; cursor: move; padding: 5px; background-color: #2a2a2a; border-radius: 4px; color: #fff;';

                const img = new Image();
                img.src = site.icon;
                img.style.cssText = 'width: 56px; height: 28px; object-fit: contain; margin-right: 10px;';
                img.title = site.tooltip;

                const status = document.createElement('span');
                const isEnabled = isSiteEnabled(site.id, platform);
                status.textContent = isEnabled ? '✔' : '✘';
                status.style.cssText = `font-size: 20px; margin-left: 10px; cursor: pointer; color: ${isEnabled ? '#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 targetId = site.id;
                    let currentOrderList = [...order];
                    currentOrderList = currentOrderList.filter(id => id !== draggedId);
                    const dropIndex = currentOrderList.indexOf(targetId);
                    const rect = item.getBoundingClientRect();
                    currentOrderList.splice(e.clientY < rect.top + rect.height / 2 ? dropIndex : dropIndex + 1, 0, draggedId);
                    setSiteOrder(platform, currentOrderList);
                    populateContainer(container, platform);
                });
            });
        }
        populateContainer(steamContainer, 'steam');
        populateContainer(igdbContainer, 'igdb');
        modal.appendChild(steamContainer);
        modal.appendChild(igdbContainer);

        // --- TAB SWITCHING (UNCHANGED) ---
        steamTab.addEventListener('click', () => {
            steamContainer.style.display = 'block'; igdbContainer.style.display = 'none';
            steamTab.style.backgroundColor = 'white'; igdbTab.style.backgroundColor = '#ccc';
        });
        igdbTab.addEventListener('click', () => {
            igdbContainer.style.display = 'block'; steamContainer.style.display = 'none';
            igdbTab.style.backgroundColor = 'white'; steamTab.style.backgroundColor = '#ccc';
        });

        // --- GENERAL OPTIONS (MODIFIED) ---
        const optionsContainer = document.createElement('div');
        optionsContainer.style.marginTop = '15px';
        optionsContainer.style.paddingTop = '10px';
        optionsContainer.style.borderTop = '1px solid #444';

        // Shortcut Option
        const shortcutOptionContainer = document.createElement('div');
        shortcutOptionContainer.style.cssText = 'display: flex; align-items: center; margin-bottom: 5px;';
        const shortcutCheckbox = document.createElement('input');
        shortcutCheckbox.type = 'checkbox';
        shortcutCheckbox.id = 'ddsteam_show_shortcut_checkbox';
        shortcutCheckbox.checked = GM_getValue(SETTINGS_SHORTCUT_ENABLED_KEY, DEFAULT_SETTINGS_SHORTCUT_ENABLED);
        shortcutCheckbox.style.cssText = 'margin-right: 8px; cursor: pointer;';
        const shortcutLabel = document.createElement('label');
        shortcutLabel.htmlFor = 'ddsteam_show_shortcut_checkbox';
        shortcutLabel.textContent = 'Show settings shortcut in link lists';
        shortcutLabel.style.cursor = 'pointer';
        shortcutCheckbox.addEventListener('change', () => GM_setValue(SETTINGS_SHORTCUT_ENABLED_KEY, shortcutCheckbox.checked));
        shortcutOptionContainer.appendChild(shortcutCheckbox);
        shortcutOptionContainer.appendChild(shortcutLabel);
        optionsContainer.appendChild(shortcutOptionContainer);

        // Formatting Option
        const formattingOptionContainer = document.createElement('div');
        formattingOptionContainer.style.cssText = 'display: flex; align-items: center;';
        const formattingCheckbox = document.createElement('input');
        formattingCheckbox.type = 'checkbox';
        formattingCheckbox.id = 'ddsteam_format_game_name_checkbox';
        formattingCheckbox.checked = GM_getValue(GAME_FORMATTING_ENABLED_KEY, DEFAULT_GAME_FORMATTING_ENABLED);
        formattingCheckbox.style.cssText = 'margin-right: 8px; cursor: pointer;';
        const formattingLabel = document.createElement('label');
        formattingLabel.htmlFor = 'ddsteam_format_game_name_checkbox';
        formattingLabel.textContent = 'Enable game name formatting';
        formattingLabel.style.cursor = 'pointer';
        formattingCheckbox.addEventListener('change', () => GM_setValue(GAME_FORMATTING_ENABLED_KEY, formattingCheckbox.checked));
        formattingOptionContainer.appendChild(formattingCheckbox);
        formattingOptionContainer.appendChild(formattingLabel);
        optionsContainer.appendChild(formattingOptionContainer);

        modal.appendChild(optionsContainer);


        // --- BUTTONS (UNCHANGED) ---
        const resetButton = document.createElement('button');
        resetButton.textContent = 'Reset to Defaults';
        resetButton.style.cssText = 'margin-top: 10px; padding: 5px 10px; background-color: #444; border: none; color: #fff; 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));
            if (platform === 'steam') populateContainer(steamContainer, 'steam'); else populateContainer(igdbContainer, 'igdb');
        });
        modal.appendChild(resetButton);

        const okButton = document.createElement('button');
        okButton.textContent = 'OK';
        okButton.style.cssText = 'margin-top: 10px; margin-left: 10px; padding: 5px 10px; background-color: #444; border: none; color: #fff; cursor: pointer;';
        okButton.addEventListener('click', () => { closeDdsteamSettingsModal(); window.location.reload(); });
        modal.appendChild(okButton);

        ddsteamSettingsModalClickListener = (e) => {
            if (ddsteamSettingsModal && !ddsteamSettingsModal.contains(e.target) && !e.target.closest('.ddsteam-settings-shortcut-btn')) {
                closeDdsteamSettingsModal();
            }
        };
        setTimeout(() => document.addEventListener('click', ddsteamSettingsModalClickListener), 0);

        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 => site && isSiteEnabled(site.id, platform))
            .map(site => ({
                name: site.name,
                tooltip: site.tooltip,
                icon: site.icon,
                url: site.urlTemplate.replace('{game}', encodeURIComponent(formattedGameName))
            }));
    }

    function createLinkButton(searchLink, buttonText, tooltipText, iconPath, iconWidth, iconHeight) {
        const linkButton = document.createElement("a");
        linkButton.href = searchLink;
        linkButton.target = "_blank";
        linkButton.title = tooltipText;
        const img = new Image();
        img.src = iconPath;
        img.alt = buttonText;
        img.style.cssText = `width: ${iconWidth}; height: ${iconHeight}; object-fit: contain; border-radius: 8px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); background-color: rgba(0, 0, 0, 0.2);`;
        linkButton.appendChild(img);
        return linkButton;
    }

    function createSettingsShortcutButtonElement(targetHeightStr) {
        const settingsButton = document.createElement("button");
        settingsButton.className = 'ddsteam-settings-shortcut-btn';
        settingsButton.textContent = "⚙️";
        settingsButton.title = "Open DDSteam Settings";
        const numericHeight = parseInt(targetHeightStr);
        settingsButton.style.cssText = `display: inline-flex; align-items: center; justify-content: center; width: ${targetHeightStr}; height: ${targetHeightStr}; font-size: ${numericHeight * 0.65}px; padding: 0; border: none; background-color: rgba(0, 0, 0, 0.2); color: #fff; border-radius: 8px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); cursor: pointer; transition: transform 0.3s ease-in-out;`;
        settingsButton.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); createPopupMenu(); });
        settingsButton.addEventListener('mouseover', () => settingsButton.style.transform = 'scale(1.1)');
        settingsButton.addEventListener('mouseout', () => settingsButton.style.transform = 'scale(1)');
        return settingsButton;
    }

    function formatGameName(gameName) {
        const useFormatting = GM_getValue(GAME_FORMATTING_ENABLED_KEY, DEFAULT_GAME_FORMATTING_ENABLED);
        if (useFormatting) {
            // Full formatting logic
            return gameName.trim().toLowerCase().replace(/'/g, '').replace(/_/g, ' ').replace(/[^a-zA-Z0-9 ]/g, '');
        } else {
            // Minimal formatting: just trim whitespace
            return gameName.trim();
        }
    }

    // --- Processing Functions ---
    function addLinksToContainer(container, gameName, platformKey, iconHeight, iconWidth) {
        const formattedGameName = formatGameName(gameName);
        const sites = getSites(formattedGameName, platformKey.startsWith('igdb') ? 'igdb' : 'steam');
        sites.forEach(site => {
            const btn = createLinkButton(site.url, site.name, site.tooltip, site.icon, iconWidth, iconHeight);
            container.appendChild(btn);
        });
        if (GM_getValue(SETTINGS_SHORTCUT_ENABLED_KEY, DEFAULT_SETTINGS_SHORTCUT_ENABLED)) {
            const settingsBtn = createSettingsShortcutButtonElement(iconHeight);
            container.appendChild(settingsBtn);
        }
    }

    function processSearchResults() {
        document.querySelectorAll("a.overflow-wrap.link-dark.h4.mt-0").forEach(link => {
            if (!link.href.includes('/games/') || (link.nextElementSibling && link.nextElementSibling.classList.contains("ddsteam-container"))) return;
            const gameName = link.firstChild?.nodeType === Node.TEXT_NODE ? link.firstChild.textContent.trim() : link.textContent.trim();
            const container = document.createElement('div');
            container.className = "ddsteam-container";
            container.style.cssText = 'margin-top: 5px; display: flex; flex-wrap: wrap; gap: 5px;';
            addLinksToContainer(container, gameName, 'igdb', '28px', '56px');
            link.insertAdjacentElement('afterend', container);
        });
    }

    function processGameInfoPage() {
        const linksContainerTarget = document.querySelector('.MuiGrid2-grid-xs-12');
        if (!linksContainerTarget || linksContainerTarget.querySelector('.ddsteam-game-links')) return;
        const container = document.createElement('div');
        container.className = 'ddsteam-game-links';
        container.style.cssText = 'margin-top: 8px; margin-bottom: 8px; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;';
        const gameTitleElement = document.querySelector("h1.MuiTypography-h3, h1");
        if (!gameTitleElement) return;
        const gameName = gameTitleElement.textContent.trim();
        addLinksToContainer(container, gameName, 'igdb', '48px', '48px');
        const hrElem = linksContainerTarget.querySelector('hr');
        if (hrElem) hrElem.insertAdjacentElement('beforebegin', container);
        else linksContainerTarget.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 container = document.createElement('div');
        container.className = "ddsteam-container";
        container.style.cssText = 'margin-top: 10px; display: flex; flex-wrap: wrap; gap: 5px;';
        addLinksToContainer(container, gameName, 'steam', '28px', '56px');
        parent.appendChild(container);
    }

    // --- Styles ---
    const styleSheet = document.createElement("style");
    styleSheet.textContent = `.ddsteam-container a:hover img, .ddsteam-game-links a:hover img { transform: scale(1.1); }`;
    document.head.appendChild(styleSheet);

    // --- Initialization ---
    const url = window.location.href;
    if (url.includes('igdb.com/search')) {
        setTimeout(processSearchResults, 500);
        const observer = new MutationObserver(() => processSearchResults());
        observer.observe(document.body, { childList: true, subtree: true });
    } else if (url.includes('igdb.com/games/')) {
        const checkExist = setInterval(() => {
            if (document.querySelector("h1.MuiTypography-h3, h1") && document.querySelector('.MuiGrid2-grid-xs-12')) {
                processGameInfoPage();
                // We don't clear interval here to catch potential re-renders on the page, but we prevent re-adding.
            }
        }, 1000);
    } else if (url.includes('store.steampowered.com/app/')) {
        const checkSteamExist = setInterval(() => {
            if (document.querySelector('.apphub_AppName')) {
                processGamePage();
                // We don't clear interval here to catch potential re-renders on the page, but we prevent re-adding.
            }
        }, 1000);
    }
})();