Steam IGG Games Search Button

Adds a button to Steam game pages to search the game on igg-games.com

// ==UserScript==
// @name         Steam IGG Games Search Button
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Adds a button to Steam game pages to search the game on igg-games.com
// @match        https://store.steampowered.com/app/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==
(function() {
    'use strict';

    const BUTTON_ID = 'igg-games-search-btn';
    const SEARCH_BASE_URL = 'https://igg-games.com/?s=';
    const IGG_FAVICON_URL = 'https://igg-games.com/favicon.ico';

    function getGameTitle() {
        const selectors = [
            '.apphub_AppName',
            '.game_title_area .pageheader',
            'h2.pageheader',
            '#appHubAppName',
            '.game_title_area h2',
            '[itemprop="name"]'
        ];

        for (const selector of selectors) {
            const element = document.querySelector(selector);
            if (element && element.textContent.trim()) {
                return element.textContent.trim();
            }
        }

        const pageTitle = document.title;
        if (pageTitle) {
            const match = pageTitle.match(/^(.+?)(?:\son\ssteam)?$/i);
            if (match && match[1]) {
                return match[1].trim();
            }
        }

        const urlMatch = window.location.pathname.match(/\/app\/\d+\/([^\/]+)/);
        if (urlMatch && urlMatch[1]) {
            return urlMatch[1].replace(/_/g, ' ');
        }

        return null;
    }

    async function getFaviconUrl() {
        try {
            // Try to fetch the favicon directly
            const response = await fetch(IGG_FAVICON_URL, { method: 'HEAD' });
            if (response.ok) {
                return IGG_FAVICON_URL;
            }
        } catch (error) {
            console.log('Direct favicon fetch failed, trying alternative methods');
        }

        try {
            // Try to parse favicon from the main page
            const response = await fetch('https://igg-games.com/');
            const html = await response.text();

            // Look for favicon link tags
            const faviconMatches = html.match(/<link[^>]*rel=['"](shortcut )?icon['"][^>]*href=['"]([^'"]+)['"]/i);
            if (faviconMatches && faviconMatches[2]) {
                let faviconUrl = faviconMatches[2];
                // Convert relative URLs to absolute
                if (faviconUrl.startsWith('/')) {
                    faviconUrl = 'https://igg-games.com' + faviconUrl;
                } else if (!faviconUrl.startsWith('http')) {
                    faviconUrl = 'https://igg-games.com/' + faviconUrl;
                }
                return faviconUrl;
            }
        } catch (error) {
            console.log('Failed to parse favicon from main page');
        }

        // Fallback to default favicon.ico
        return IGG_FAVICON_URL;
    }

    function createIGGButton(gameTitle, faviconUrl) {
        const searchUrl = `${SEARCH_BASE_URL}${encodeURIComponent(gameTitle)}`;

        const button = document.createElement('a');
        button.id = BUTTON_ID;
        button.className = 'btnv6_blue_hoverfade btn_medium btn_steamdb';
        button.href = searchUrl;
        button.target = '_blank';
        button.rel = 'noopener noreferrer';

        const span = document.createElement('span');
        span.setAttribute('data-tooltip-text', 'View on IGG Games');
        span.setAttribute('aria-describedby', 'tooltip-35');

        const iconSpan = document.createElement('span');
        iconSpan.className = 'ico16';
        iconSpan.style.cssText = `
            background: url('${faviconUrl}') no-repeat center;
            background-size: 16px 16px;
            width: 16px;
            height: 16px;
            display: inline-block;
        `;

        span.appendChild(iconSpan);
        button.appendChild(span);

        return button;
    }

    async function addIGGGamesButton() {
        if (document.getElementById(BUTTON_ID)) return false;

        const gameTitle = getGameTitle();
        if (!gameTitle) return false;

        const faviconUrl = await getFaviconUrl();
        const button = createIGGButton(gameTitle, faviconUrl);

        const otherSiteInfo = document.querySelector('.apphub_OtherSiteInfo');
        if (otherSiteInfo) {
            try {
                otherSiteInfo.appendChild(button.cloneNode(true));
                return true;
            } catch (e) {
                console.error('Failed to add to OtherSiteInfo:', e);
            }
        }

        const gameActions = document.querySelector('.game_area_purchase_game_wrapper, .game_purchase_action');
        if (gameActions) {
            try {
                const buttonContainer = document.createElement('div');
                buttonContainer.style.cssText = 'margin: 10px 0; clear: both;';
                buttonContainer.appendChild(button.cloneNode(true));

                gameActions.parentNode.insertBefore(buttonContainer, gameActions.nextSibling);
                return true;
            } catch (e) {
                console.error('Failed to add near purchase area:', e);
            }
        }

        const gameDetails = document.querySelector('.game_details_section, .rightcol');
        if (gameDetails) {
            try {
                const buttonContainer = document.createElement('div');
                buttonContainer.style.cssText = 'margin: 10px 0; padding: 10px 0; border-top: 1px solid rgba(255,255,255,0.1);';
                buttonContainer.appendChild(button.cloneNode(true));

                gameDetails.insertBefore(buttonContainer, gameDetails.firstChild);
                return true;
            } catch (e) {
                console.error('Failed to add to game details:', e);
            }
        }

        const mainContent = document.querySelector('.page_content_ctn, .game_page_content');
        if (mainContent) {
            try {
                const buttonContainer = document.createElement('div');
                buttonContainer.style.cssText = `
                    position: fixed;
                    top: 100px;
                    right: 20px;
                    z-index: 1000;
                    background: rgba(0,0,0,0.8);
                    padding: 10px;
                    border-radius: 5px;
                    box-shadow: 0 4px 8px rgba(0,0,0,0.3);
                `;
                buttonContainer.appendChild(button.cloneNode(true));

                document.body.appendChild(buttonContainer);
                return true;
            } catch (e) {
                console.error('Failed to add floating button:', e);
            }
        }

        return false;
    }

    async function attemptToAddButton(retries = 5, delay = 500) {
        if (retries <= 0) return;

        const success = await addIGGGamesButton();
        if (!success) {
            setTimeout(() => attemptToAddButton(retries - 1, delay * 1.2), delay);
        }
    }

    function setupObserver() {
        if (document.getElementById(BUTTON_ID)) return;

        const observer = new MutationObserver(async (mutations) => {
            if (document.getElementById(BUTTON_ID)) {
                observer.disconnect();
                return;
            }

            let shouldTryAddButton = false;

            for (const mutation of mutations) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    for (const node of mutation.addedNodes) {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            const element = node;
                            const className = element.className || '';

                            if (typeof className === 'string' && (
                                className.includes('apphub_OtherSiteInfo') ||
                                className.includes('external_link') ||
                                className.includes('block_content_inner') ||
                                element.querySelector('a[href*="steamcommunity.com"]')
                            )) {
                                shouldTryAddButton = true;
                                break;
                            }
                        }
                    }
                    if (shouldTryAddButton) break;
                }
            }

            if (shouldTryAddButton) {
                setTimeout(() => addIGGGamesButton(), 100);
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        setTimeout(() => observer.disconnect(), 15000);
    }

    async function init() {
        const success = await addIGGGamesButton();
        if (!success) {
            attemptToAddButton();
            setupObserver();
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 100);
    }

    window.addEventListener('load', () => {
        setTimeout(async () => {
            if (!document.getElementById(BUTTON_ID)) {
                await addIGGGamesButton();
            }
        }, 500);
    });

    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            if (url.includes('/app/')) {
                setTimeout(async () => {
                    if (!document.getElementById(BUTTON_ID)) {
                        await init();
                    }
                }, 1000);
            }
        }
    }).observe(document, { subtree: true, childList: true });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址