Steam Pirate Links Dropdown

Adds a dropdown menu with links to game download/forum sites on Steam app pages, next to Community Hub. Includes loading/error indication and smarter title sanitization. Use responsibly and legally.

目前為 2025-04-09 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Steam Pirate Links Dropdown
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Adds a dropdown menu with links to game download/forum sites on Steam app pages, next to Community Hub. Includes loading/error indication and smarter title sanitization. Use responsibly and legally.
// @author       AndreyUA
// @match        https://store.steampowered.com/app/*
// @icon         https://store.steampowered.com/favicon.ico
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const sites = [
        { name: "Rutracker", searchUrl: "https://rutracker.org/forum/tracker.php?nm={searchTerm}" },
        { name: "CS.RIN.RU", searchUrl: "https://cs.rin.ru/forum/search.php?keywords={searchTerm}&terms=all&author=&sc=1&sf=titleonly&sr=topics&sk=t&sd=d&st=0&ch=300&t=0&submit=Search" },
        { name: "Online-Fix.me", searchUrl: "https://online-fix.me/index.php?do=search&subaction=search&story={searchTerm}" },
        { name: "FitGirl Repacks", searchUrl: "https://fitgirl-repacks.site/?s={searchTerm}" },
        { name: "DODI Repacks", searchUrl: "https://dodi-repacks.site/?s={searchTerm}" },
        { name: "GOG-Games", searchUrl: "https://gog-games.to/?s={searchTerm}" },
        { name: "SteamRIP", searchUrl: "https://steamrip.com/?s={searchTerm}" },
        { name: "Torrminatorr Forum", searchUrl: "https://forum.torrminatorr.com/search.php?keywords={searchTerm}&terms=all&author=&sc=1&sf=titleonly&sr=topics&sk=t&sd=d&st=0&ch=300&t=0&submit=Search" },
        { name: "SteamGG", searchUrl: "https://steamgg.net/?s={searchTerm}" },
        { name: "KaosKrew", searchUrl: "https://www.kaoskrew.org/search.php?keywords={searchTerm}&terms=all&author=&sc=1&sf=titleonly&sr=topics&sk=t&sd=d&st=0&ch=300&t=0&submit=Search" },
    ];

    function sanitizeGameTitle(title) {
        if (!title) return '';
        let cleanTitle = title.replace(/™|®|©/g, '').trim();

        const suffixPatterns = [
             /\s*[:\-–—]?\s+(Remastered|Remake|Definitive|Ultimate|Deluxe|GOTY|Game of the Year|Anniversary|Enhanced|Complete|Gold|Premium|Collectors|Extended|Legacy)\s+(Collection|Edition|Cut)?\s*$/i,
             /\s*\(?(VR)\)?\s*$/i,
             /\s+-\s+(Remastered|Definitive|etc...)\s*$/i,
             /\s+\d{4}\s*$/
        ];

        suffixPatterns.forEach(pattern => {
            cleanTitle = cleanTitle.replace(pattern, '').trim();
        });

        return cleanTitle;
    }

    const button = document.createElement('a');
    button.href = '#';
    button.className = 'btnv6_blue_hoverfade btn_medium pirate-links-button';
    button.innerHTML = '<span>Loading...</span>';

    const insertionPoint = document.querySelector('.apphub_OtherSiteInfo');
    if (!insertionPoint) {
        console.error("Steam Pirate Links: Could not find insertion point (.apphub_OtherSiteInfo). Steam UI might have changed.");
        button.innerHTML = '<span>Error</span>';
        button.classList.add('pirate-links-error');
        const tempContainer = document.createElement('div');
        tempContainer.style.display = 'inline-block';
        tempContainer.style.marginRight = '4px';
        tempContainer.appendChild(button);
        (document.querySelector('.page_title_area .apphub_HeaderStandardTop') || document.body).appendChild(tempContainer);
        return;
    }

    let originalGameTitle = '';
    const titleElement = document.getElementById('appHubAppName');
    if (titleElement) {
        originalGameTitle = titleElement.textContent.trim();
    } else {
        const pageTitle = document.title;
        const match = pageTitle.match(/^(.*)\s+on Steam$/);
        if (match && match[1]) {
            originalGameTitle = match[1].trim();
        }
    }

    if (!originalGameTitle) {
        console.error("Steam Pirate Links: Could not reliably determine game title.");
        button.innerHTML = '<span>Error</span>';
        button.classList.add('pirate-links-error');
        insertionPoint.insertAdjacentElement('afterbegin', button);
        return;
    }

    const sanitizedGameTitle = sanitizeGameTitle(originalGameTitle);
    console.log("Steam Pirate Links | Original Title:", originalGameTitle, "| Sanitized:", sanitizedGameTitle);


    const container = document.createElement('div');
    container.className = 'pirate-links-container';
    container.style.position = 'relative';
    container.style.display = 'inline-block';
    container.style.marginRight = '4px';
    container.style.verticalAlign = 'top';

    button.innerHTML = '<span>Find...</span>';

    const dropdownPanel = document.createElement('div');
    dropdownPanel.className = 'popup_block_new pirate-links-dropdown';
    dropdownPanel.style.display = 'none';
    dropdownPanel.style.position = 'absolute';
    dropdownPanel.style.zIndex = '1500';
    dropdownPanel.style.minWidth = '150px';
    dropdownPanel.style.right = '0';
    dropdownPanel.style.marginTop = '2px';

    const dropdownContent = document.createElement('div');
    dropdownContent.className = 'popup_body popup_menu';

    sites.forEach(site => {
        const link = document.createElement('a');
        link.className = 'popup_menu_item';
        link.href = site.searchUrl.replace('{searchTerm}', encodeURIComponent(sanitizedGameTitle));
        link.textContent = site.name;
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        dropdownContent.appendChild(link);
    });

    dropdownPanel.appendChild(dropdownContent);
    container.appendChild(button);
    container.appendChild(dropdownPanel);

    const communityHubButton = insertionPoint.querySelector('a[href*="steamcommunity.com/app/"]');
    if (communityHubButton) {
        insertionPoint.insertBefore(container, communityHubButton);
    } else {
        insertionPoint.insertAdjacentElement('afterbegin', container);
    }

    button.addEventListener('click', (event) => {
        if (button.classList.contains('pirate-links-error')) {
            event.preventDefault();
            return;
        }
        event.preventDefault();
        event.stopPropagation();
        const isVisible = dropdownPanel.style.display === 'block';
        const otherPopups = insertionPoint.querySelectorAll('.popup_block_new:not(.pirate-links-dropdown)');
        otherPopups.forEach(p => p.style.display = 'none');
        dropdownPanel.style.display = isVisible ? 'none' : 'block';
    });

    document.addEventListener('click', (event) => {
        if (!container.contains(event.target) && dropdownPanel.style.display === 'block') {
            dropdownPanel.style.display = 'none';
        }
    });

    GM_addStyle(`
        .pirate-links-button span { vertical-align: middle; }

        .pirate-links-button.pirate-links-error {
            background-color: #5c6b7c !important;
            color: #acb2b8 !important;
            cursor: not-allowed !important;
            opacity: 0.7;
        }
         .pirate-links-button.pirate-links-error:hover {
             background-color: #5c6b7c !important;
             color: #acb2b8 !important;
         }

        .pirate-links-dropdown {
            background-color: #171d25;
            border: 1px solid #000;
            box-shadow: 0 0 8px rgba(0,0,0,0.6);
            color: #c7d5e0;
            border-radius: 3px;
        }
        .pirate-links-dropdown .popup_menu_item {
            display: block;
            padding: 6px 12px;
            color: #c7d5e0;
            text-decoration: none;
            font-size: 13px;
            white-space: nowrap;
        }
        .pirate-links-dropdown .popup_menu_item:hover {
            background-color: #c7d5e0;
            color: #1b2838;
            border-radius: 2px;
        }
    `);

    console.log("Steam Pirate Links Dropdown loaded successfully (v1.5).");

})();

QingJ © 2025

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