Drawaria gallery library

Library with placeholders for your canvas to the gallery.

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/570679/1781435/Drawaria%20gallery%20library.js

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

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

})();