Raw Source
g31w0fw0rldgmail.com / Steam to SteamDB Button

// ==UserScript==
// @name         Steam to SteamDB Button
// @namespace    https://store.steampowered.com/
// @version      1.1.8
// @description  Adds a SteamDB button to Steam app, bundle, or sub pages in the appropriate action container.
// @author       g31w0fw0rld
// @license      MIT
// @match        https://store.steampowered.com/app/*
// @match        https://store.steampowered.com/bundle/*
// @match        https://store.steampowered.com/sub/*
// @downloadURL  https://github.com/g31w0fw0rld/steam-to-steamdb-button/raw/main/steam-to-steamdb-button.user.js
// @updateURL    https://github.com/g31w0fw0rld/steam-to-steamdb-button/raw/main/steam-to-steamdb-button.user.js
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // =============================================
    // CONSTANTES
    // =============================================
    const STEAMDB_BASE_URL = 'https://steamdb.info/';
    const PATH_REGEX = /\/(app|bundle|sub)\/(\d+)/;
    const STEAMDB_BUTTON_ID = 'steamdbButtonContainer';

    // Icono SVG oficial de SteamDB
    const STEAMDB_SVG = '<svg width="16" height="16" viewBox="0 0 128 128" class="octicon octicon-steamdb" aria-hidden="true" style="margin-right: 8px; vertical-align: middle;"><path fill="currentColor" fill-rule="evenodd" d="M63.9 0C30.5 0 3.1 11.9.1 27.1l35.6 6.7c2.9-.9 6.2-1.3 9.6-1.3l16.7-10c-.2-2.5 1.3-5.1 4.7-7.2 4.8-3.1 12.3-4.8 19.9-4.8 5.2-.1 10.5.7 15 2.2 11.2 3.8 13.7 11.1 5.7 16.3-5.1 3.3-13.3 5-21.4 4.8l-22 7.9c-.2 1.6-1.3 3.1-3.4 4.5-5.9 3.8-17.4 4.7-25.6 1.9-3.6-1.2-6-3-7-4.8L2.5 38.4c2.3 3.6 6 6.9 10.8 9.8C5 53 0 59 0 65.5c0 6.4 4.8 12.3 12.9 17.1C4.8 87.3 0 93.2 0 99.6 0 115.3 28.6 128 64 128c35.3 0 64-12.7 64-28.4 0-6.4-4.8-12.3-12.9-17 8.1-4.8 12.9-10.7 12.9-17.1 0-6.5-5-12.6-13.4-17.4 8.3-5.1 13.3-11.4 13.3-18.2 0-16.5-28.7-29.9-64-29.9zm22.8 14.2c-5.2.1-10.2 1.2-13.4 3.3-5.5 3.6-3.8 8.5 3.8 11.1 7.6 2.6 18.1 1.8 23.6-1.8s3.8-8.5-3.8-11c-3.1-1-6.7-1.5-10.2-1.5zm.3 1.7c7.4 0 13.3 2.8 13.3 6.2 0 3.4-5.9 6.2-13.3 6.2s-13.3-2.8-13.3-6.2c0-3.4 5.9-6.2 13.3-6.2zM45.3 34.4c-1.6.1-3.1.2-4.6.4l9.1 1.7a10.8 5 0 1 1-8.1 9.3l-8.9-1.7c1 .9 2.4 1.7 4.3 2.4 6.4 2.2 15.4 1.5 20-1.5s3.2-7.2-3.2-9.3c-2.6-.9-5.7-1.3-8.6-1.3zM109 51v9.3c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-9.2c11.5 5.3 27.4 8.6 44.9 8.6 17.6 0 33.6-3.3 45.2-8.7zm0 34.6v8.8c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-8.8c11.6 5.1 27.4 8.2 45 8.2s33.5-3.1 45-8.2z"></path></svg>';

    // Mapa de contenedores según el tipo de página de Steam
    // - app: usa 'queueActionsCtn' (se clona para crear sección separada)
    // - bundle/sub: usa 'game_area_purchase_top' (se añade directamente)
    const CONTAINER_IDS = {
        app: 'queueActionsCtn',
        bundle: 'game_area_purchase_top',
        sub: 'game_area_purchase_top'
    };

    // =============================================
    // FUNCIONES
    // =============================================

    /**
     * Extrae el tipo de página (app, bundle, sub) y el ID numérico
     * desde la URL actual de Steam.
     * @returns {{ type: string, id: string } | null} Objeto con tipo e ID, o null si no coincide.
     */
    function extractPageType() {
        const match = window.location.pathname.match(PATH_REGEX);
        if (!match) return null;
        return { type: match[1], id: match[2] };
    }

    /**
     * Crea un botón con el estilo nativo de Steam (btn_black btn_medium)
     * que abre la página correspondiente de SteamDB en una nueva pestaña.
     * @param {string} type - Tipo de página (app, bundle, sub).
     * @param {string} id - ID numérico del producto en Steam.
     * @returns {HTMLButtonElement} El botón listo para insertar.
     */
    function createSteamDBButton(type, id) {
        const url = `${STEAMDB_BASE_URL}${type}/${id}/`;
        const button = document.createElement('button');
        button.className = 'btn_black btn_medium';
        button.innerHTML = `<span>${STEAMDB_SVG}SteamDB</span>`;
        button.addEventListener('click', () => window.open(url, '_blank'));
        return button;
    }

    /**
     * Obtiene el contenedor DOM donde debe insertarse el botón,
     * según el tipo de página de Steam.
     * @param {string} type - Tipo de página (app, bundle, sub).
     * @returns {HTMLElement|null} El contenedor encontrado o null.
     */
    function getContainer(type) {
        const containerId = CONTAINER_IDS[type];
        return containerId ? document.getElementById(containerId) : null;
    }

    /**
     * Inserta el botón de SteamDB en el contenedor apropiado.
     * Para páginas de tipo 'app', se clona el contenedor original para crear
     * una sección visual separada debajo. Para 'bundle' y 'sub',
     * el botón se añade directamente al contenedor existente.
     * @param {HTMLButtonElement} button - El botón a insertar.
     * @param {HTMLElement} container - El contenedor DOM de destino.
     * @param {string} type - Tipo de página (app, bundle, sub).
     */
    function insertButton(button, container, type) {
        if (type === 'app') {
            // Clonar contenedor para crear sección separada debajo
            const newContainer = container.cloneNode(true);
            newContainer.id = STEAMDB_BUTTON_ID;
            newContainer.innerHTML = '';
            newContainer.style.paddingTop = 'unset';
            container.parentNode.insertBefore(newContainer, container.nextSibling);
            newContainer.appendChild(button);
        } else {
            container.appendChild(button);
        }
    }

    /**
     * Punto de entrada: extrae el tipo de página, crea el botón
     * y lo inserta en el contenedor correspondiente.
     */
    function init() {
        const pageInfo = extractPageType();
        if (!pageInfo) return;

        const { type, id } = pageInfo;
        const container = getContainer(type);
        if (!container) return;

        const button = createSteamDBButton(type, id);
        insertButton(button, container, type);
    }

    // =============================================
    // INICIALIZACIÓN
    // =============================================
    try {
        init();
    } catch (e) {
        console.error('(steam2steamdb): Error al crear el botón SteamDB:', e);
    }
})();