Drawaria gallery library

Library with placeholders for your canvas to the gallery.

Este script não deve ser instalado diretamente. Este script é uma biblioteca de outros scripts para incluir com o diretório meta // @require https://update.greasyfork.org/scripts/570679/1781435/Drawaria%20gallery%20library.js

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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'] });

})();