Drawaria gallery library

Library with placeholders for your canvas to the gallery.

Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greasyfork.org/scripts/570679/1781435/Drawaria%20gallery%20library.js

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Drawaria gallery library
// @namespace    http://tampermonkey.net/
// @version      4.1
// @description  Library with placeholders for your canvas to the gallery.
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @connect      picsum.photos
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';
    const COOLDOWN_DURATION = 5 * 1000;
    let lastUploadTime = parseInt(localStorage.getItem('drawariaLastUploadTime') || '0');
    let cooldownDisplayTimeout = null;

    GM_addStyle(`
        .custom-drawaria-btn { margin-bottom: 0.5em; width: 100%; }
        .hidden-btn { display: none !important; }
        #uploadStatusSection { font-size: 0.85em; color: #555; text-align: center; margin-bottom: 0.5em; min-height: 1.2em; font-weight: bold; }
        .cooldown-active-msg { color: orange; }
        .upload-error-msg { color: red; }
        .upload-success-msg { color: green; }
    `);

    function waitForElement(selector, callback, intervalTime = 100) {
        const intervalId = setInterval(() => {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(intervalId);
                callback(element);
            }
        }, intervalTime);
    }

    const getGameModeFlag = (flagConstName) => {
        if (typeof unsafeWindow.Fn !== 'undefined' && typeof unsafeWindow[flagConstName] !== 'undefined') {
            return !!unsafeWindow.Fn[unsafeWindow[flagConstName]];
        }
        return false;
    };

    function setUploadStatusMessage(message, type = '', duration = 3000) {
        const statusSection = document.getElementById('uploadStatusSection');
        if (statusSection) {
            statusSection.innerHTML = message;
            statusSection.className = type;
            if (cooldownDisplayTimeout) clearTimeout(cooldownDisplayTimeout);
            if (duration > 0) {
                cooldownDisplayTimeout = setTimeout(() => {
                    statusSection.innerHTML = '';
                    statusSection.className = '';
                }, duration);
            }
        }
    }

    function startGlobalCooldown() {
        lastUploadTime = Date.now();
        localStorage.setItem('drawariaLastUploadTime', lastUploadTime);
        setUploadStatusMessage(`Cooldown: ${Math.ceil(COOLDOWN_DURATION / 1000)}s`, 'cooldown-active-msg', COOLDOWN_DURATION);
    }

    function checkCooldown() {
        const timeLeft = lastUploadTime + COOLDOWN_DURATION - Date.now();
        if (timeLeft > 0) {
            setUploadStatusMessage(`Espera ${Math.ceil(timeLeft / 1000)}s`, 'cooldown-active-msg', 0);
            return false;
        }
        return true;
    }

    function getRealGameCanvas() {
        let sourceCanvas = document.getElementById('canvas');
        if (typeof unsafeWindow.ze !== 'undefined' && unsafeWindow.ze instanceof HTMLCanvasElement && unsafeWindow.ze.width > 0) {
            sourceCanvas = unsafeWindow.ze;
        }
        return sourceCanvas;
    }

    async function executeUpload(base64ImageData, base64ThumbData, shouldRedirect = true) {
        let roomId = (window.location.pathname.match(/room\/([^/]+)/) || [])[1] || '';
        const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;

        // Sesión (necesaria para evitar 403)
        const rawSid1 = (document.cookie.match(/sid1=([^;]+)/) || [])[1] || "";
        const sessionId = decodeURIComponent(rawSid1);

        const galleryHost = "https://" + (win.qn || "gallery.drawaria.online");
        const postUrl = `${galleryHost}/gallery/uploadimage/?sessionid=${sessionId}`;

        // ── NUEVOS COLABORADORES ── (reemplazados los anteriores)
        const externalCollabs = {
            names: [
                "67 БОГ ДЕПА 67",
                "Д϶ʙид"
            ],
            uids: [
                "69c35590-9565-11f0-8d47-cbcdc07da1cc",
                "a8a95b20-f9ff-11eb-8b3e-bf0e5205a678"
            ]
        };

        // Preparación de datos del POST
        const formData = new URLSearchParams();
        formData.append('imagedata', base64ImageData);
        formData.append('imagedata1', base64ThumbData);
        formData.append('room', roomId);
        formData.append('targetword', '');
        formData.append('guestplayernames', JSON.stringify(externalCollabs.names));
        formData.append('playeruids', JSON.stringify(externalCollabs.uids));
        formData.append('stencils', JSON.stringify(getGameModeFlag('PGMODE_STENCILS')));
        formData.append('pixelart', JSON.stringify(getGameModeFlag('PGMODE_PIXELART')));
        formData.append('advtools', JSON.stringify(getGameModeFlag('PGMODE_ADVTOOLS')));

        try {
            const response = await fetch(postUrl, {
                method: 'POST',
                body: formData
            });

            if (!response.ok) throw new Error(`Servidor rechazó subida: HTTP ${response.status}`);

            const result = await response.json();
            if (result.error) throw new Error(result.error);

            startGlobalCooldown();
            console.log(`%c[Drawaria] Uploaded successfully on ID ${result.imageid}`, "color: #00ff00; font-weight: bold;");
            alert(`Success!\nColaborators: ${externalCollabs.names.join(", ")}\nID de Galería: ${result.imageid}`);

            if (shouldRedirect) window.location.href = `${galleryHost}/gallery/img/${result.imageid}`;
            return true;
        } catch (error) {
            console.error("Fallo interceptado:", error);
            setUploadStatusMessage(`Error: ${error.message}`, 'upload-error-msg');
            return false;
        }
    }

    async function uploadFromCanvas(canvas, shouldRedirect = true) {
        if (!checkCooldown()) return false;
        try {
            const uploadCanvas = document.createElement("canvas");
            const uploadCtx = uploadCanvas.getContext("2d");
            uploadCanvas.width = 1200; uploadCanvas.height = 1000;
            uploadCtx.fillStyle = "#ffffff"; uploadCtx.fillRect(0, 0, uploadCanvas.width, uploadCanvas.height);
            uploadCtx.drawImage(canvas, 0, 0, uploadCanvas.width, uploadCanvas.height);

            const thumbCanvas = document.createElement("canvas");
            const thumbCtx = thumbCanvas.getContext("2d");
            thumbCanvas.width = 300; thumbCanvas.height = 250;
            thumbCtx.fillStyle = "#ffffff"; thumbCtx.fillRect(0, 0, thumbCanvas.width, thumbCanvas.height);
            thumbCtx.drawImage(canvas, 0, 0, thumbCanvas.width, thumbCanvas.height);

            const base64ImageData  = uploadCanvas.toDataURL("image/jpeg", 0.8).split(',')[1];
            const base64ThumbData  = thumbCanvas.toDataURL("image/jpeg", 0.8).split(',')[1];

            return await executeUpload(base64ImageData, base64ThumbData, shouldRedirect);
        } catch (error) {
            setUploadStatusMessage(`Error: ${error.message}`, 'upload-error-msg');
            return false;
        }
    }

    async function uploadLocalFile(file) {
        if (!checkCooldown()) return;
        setUploadStatusMessage('Procesando animación...', '');
        const baseName = file.name.substring(0, file.name.lastIndexOf('.')) || file.name;
        const fileNameJPG = baseName + ".jpg";

        const disguisedFile = new File([file], fileNameJPG, { type: 'image/jpeg' });
        console.log(`[Algorithm] Disguising: ${file.name} → ${disguisedFile.name}`);

        const reader = new FileReader();
        reader.onload = async (e) => {
            const dataUrl = e.target.result;
            const base64ImageData = dataUrl.split(',')[1];

            const img = new Image();
            img.onload = async () => {
                const thumbCanvas = document.createElement("canvas");
                thumbCanvas.width = 300; thumbCanvas.height = 250;
                thumbCanvas.getContext("2d").drawImage(img, 0, 0, 300, 250);
                const base64ThumbData = thumbCanvas.toDataURL("image/jpeg", 0.8).split(',')[1];

                await executeUpload(base64ImageData, base64ThumbData, true);
            };
            img.onerror = () => setUploadStatusMessage('Error al cargar imagen', 'upload-error-msg');
            img.src = dataUrl;
        };
        reader.onerror = () => setUploadStatusMessage('Error leyendo el archivo', 'upload-error-msg');
        reader.readAsDataURL(disguisedFile);
    }

    // Interfaz
    function setupInterface() {
        const rightbar = document.querySelector('#rightbar');
        if (!rightbar || document.getElementById('superSendButton')) return;

        ['sendtogallery', 'downloadcanvas'].forEach(id => {
            const el = document.getElementById(id);
            if (el) el.style.display = 'none';
        });

        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.id = 'hiddenFileInput';
        fileInput.accept = 'image/*';
        fileInput.style.display = 'none';
        fileInput.addEventListener('change', (e) => {
            if (e.target.files[0]) uploadLocalFile(e.target.files[0]);
            e.target.value = '';
        });
        document.body.appendChild(fileInput);

        const uploadLocalBtn = document.createElement('button');
        uploadLocalBtn.className = 'btn btn-warning btn-block custom-drawaria-btn';
        uploadLocalBtn.innerHTML = `<i class="fas fa-cloud-upload-alt"></i> <span>Upload animated JPG GIF</span>`;
        uploadLocalBtn.onclick = () => document.getElementById('hiddenFileInput').click();
        rightbar.prepend(uploadLocalBtn);

        const superSendButton = document.createElement('button');
        superSendButton.id = 'superSendButton';
        superSendButton.className = 'btn btn-primary btn-block custom-drawaria-btn';
        superSendButton.innerHTML = `<i class="fas fa-folder-open"></i> <span>Upload this canvas</span>`;
        superSendButton.onclick = async () => {
            const canvas = getRealGameCanvas();
            if (canvas) await uploadFromCanvas(canvas, true);
            else alert("No se encontró el lienzo del juego.");
        };
        uploadLocalBtn.after(superSendButton);

        const uploadStatusSection = document.createElement('div');
        uploadStatusSection.id = 'uploadStatusSection';
        superSendButton.after(uploadStatusSection);
    }

    waitForElement('#rightbar', setupInterface);

    const observer = new MutationObserver(() => {
        if (!document.getElementById('superSendButton')) setupInterface();
    });
    observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style'] });

})();