Drawaria gallery library

Library with placeholders for your canvas to the gallery.

Dette scriptet burde ikke installeres direkte. Det er et bibliotek for andre script å inkludere med det nye metadirektivet // @require https://update.greasyfork.org/scripts/570679/1781435/Drawaria%20gallery%20library.js

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

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

})();