Steam Workshop Copy SteamCMD Button

Adds a button to copy SteamCMD workshop download commands

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Steam Workshop Copy SteamCMD Button
// @namespace    http://steamcommunity.com/
// @version      1.0
// @description  Adds a button to copy SteamCMD workshop download commands
// @author       TheFantasticLoki
// @match        https://steamcommunity.com/sharedfiles/filedetails/*
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    
    // Function to extract item ID from URL
    function getWorkshopItemIdFromUrl() {
        const urlParams = new URLSearchParams(window.location.search);
        return urlParams.get('id');
    }
    
    // Function to find game ID
    function getGameId() {
        // Look for game ID in breadcrumbs
        const breadcrumbs = document.querySelectorAll('.breadcrumbs a');
        for (const crumb of breadcrumbs) {
            const href = crumb.getAttribute('href');
            if (href && href.includes('/app/')) {
                const match = href.match(/\/app\/(\d+)/);
                if (match && match[1]) {
                    return match[1];
                }
            }
        }
        
        // Alternative method: look for game app link
        const appLinks = document.querySelectorAll('a[href*="/app/"]');
        for (const link of appLinks) {
            const match = link.href.match(/\/app\/(\d+)/);
            if (match && match[1]) {
                return match[1];
            }
        }
        
        return null;
    }
    
    function createCopyButton(gameId, workshopItemId) {
        // Create styles for our custom elements
        const styleEl = document.createElement('style');
        styleEl.textContent = `
            .steam_cmd_copy_btn {
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                width: 33px;
                height: 33px;
                background: #3d6c8d;
                border-radius: 4px;
                margin: 0 5px;
                transition: background 0.2s;
                position: relative;
            }
            .steam_cmd_copy_btn:hover {
                background: #67c1f5;
            }
            .steam_cmd_copy_btn svg {
                width: 25px;
                height: 25px;
                vertical-align: middle;
                fill: white;
            }
            .steam_cmd_copy_tooltip {
                display: none;
                position: fixed;
                background-color: #171a21;
                color: #fff;
                text-align: center;
                border-radius: 3px;
                padding: 8px 12px;
                z-index: 9999;
                border: 1px solid #4d4d4d;
                white-space: nowrap;
                font-size: 12px;
                box-shadow: 0 0 5px rgba(0,0,0,0.3);
                pointer-events: none;
            }
            .steam_cmd_command {
                font-family: monospace;
                background: #32353c;
                padding: 4px 6px;
                border-radius: 2px;
                margin-top: 5px;
                display: block;
            }
        `;
        document.head.appendChild(styleEl);
        
        // Create the button element
        const copyButton = document.createElement('div');
        copyButton.className = 'steam_cmd_copy_btn';
        
        // Create SVG icon for clipboard
        copyButton.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
            </svg>
        `;
        
        // Create tooltip as a separate element attached to body
        const tooltip = document.createElement('div');
        tooltip.className = 'steam_cmd_copy_tooltip';
        tooltip.innerHTML = `Copy SteamCMD<span class="steam_cmd_command">workshop_download_item ${gameId} ${workshopItemId}</span>`;
        document.body.appendChild(tooltip);
        
        // Handle tooltip positioning
        copyButton.addEventListener('mouseenter', function(e) {
            const rect = copyButton.getBoundingClientRect();
            tooltip.style.display = 'block';
            
            // Position tooltip above the button
            tooltip.style.left = rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2) + 'px';
            tooltip.style.top = rect.top - tooltip.offsetHeight - 10 + 'px';
            
            // If tooltip would go off the top, show it below instead
            if (rect.top - tooltip.offsetHeight < 0) {
                tooltip.style.top = rect.bottom + 10 + 'px';
            }
        });
        
        copyButton.addEventListener('mouseleave', function() {
            tooltip.style.display = 'none';
        });
        
        // Add click event to copy the command
        copyButton.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            
            const command = `workshop_download_item ${gameId} ${workshopItemId}`;
            GM_setClipboard(command);
            
            // Visual feedback
            tooltip.innerHTML = 'Copied!';
            setTimeout(function() {
                tooltip.innerHTML = `Copy SteamCMD<span class="steam_cmd_command">workshop_download_item ${gameId} ${workshopItemId}</span>`;
            }, 2000);
        });
        
        // Clean up tooltip when button is removed
        const cleanupTooltip = new MutationObserver(function(mutations) {
            if (!document.body.contains(copyButton)) {
                tooltip.remove();
                cleanupTooltip.disconnect();
            }
        });
        cleanupTooltip.observe(document.body, { childList: true, subtree: true });
        
        return copyButton;
    }
    
    
    // Main function to run when page is loaded
    function addCopyButtons() {
        // Check if we've already run
        if (document.querySelector('.steam_cmd_copy_btn')) {
            return; // Skip if buttons already exist
        }
        
        const gameId = getGameId();
        if (!gameId) {
            console.log('Could not find game ID');
            return;
        }
        
        // First check for single item page
        const singleSubscribeButton = document.getElementById('SubscribeItemBtn');
        if (singleSubscribeButton) {
            const workshopItemId = getWorkshopItemIdFromUrl();
            if (workshopItemId) {
                // Find the parent div of the subscribe button
                const subscribeButtonContainer = singleSubscribeButton.closest('div');
                if (subscribeButtonContainer && subscribeButtonContainer.parentNode) {
                    // Create a new container div for our button
                    const copyButtonContainer = document.createElement('div');
                    copyButtonContainer.style.display = 'inline-block';
                    copyButtonContainer.style.marginLeft = '5px';
                    
                    // Add the copy button to its container
                    const copyButton = createCopyButton(gameId, workshopItemId);
                    copyButtonContainer.appendChild(copyButton);
                    
                    // Insert after the subscribe button's container
                    subscribeButtonContainer.parentNode.insertBefore(
                        copyButtonContainer, 
                        subscribeButtonContainer.nextSibling
                    );
                }
            }
            return;
        }
        
        // Collection page handling - targeting the exact structure seen in collections
        const subscriptionControls = document.querySelectorAll('.subscriptionControls');
        subscriptionControls.forEach(controlsDiv => {
            // Check if we already added a button here
            if (controlsDiv.querySelector('.steam_cmd_copy_btn')) {
                return;
            }

            // Find the subscribe button inside this controls div
            const subscribeButton = controlsDiv.querySelector('[id^="SubscribeItemBtn"]');
            if (subscribeButton) {
                // Extract workshop ID from button ID (format: SubscribeItemBtn###)
                const match = subscribeButton.id.match(/SubscribeItemBtn(\d+)/);
                if (match && match[1]) {
                    const workshopItemId = match[1];

                    // Create copy button
                    const copyButton = createCopyButton(gameId, workshopItemId);

                    // Directly append to the controls div instead of creating a new container
                    controlsDiv.appendChild(copyButton);
                }
            }
        });
    }
    
    // Use mutation observer to run when content changes (for dynamic loading)
    function initObserver() {
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.addedNodes.length) {
                    addCopyButtons();
                }
            }
        });
        
        observer.observe(document.body, { childList: true, subtree: true });
    }
    
    // Check if the page is already loaded
    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        addCopyButtons();
        initObserver();
    } else {
        // Wait for page to load
        window.addEventListener('DOMContentLoaded', () => {
            addCopyButtons();
            initObserver();
        });
    }
})();