Drawaria gallery library

Library with placeholders for your canvas to the gallery.

このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @require https://update.greasyfork.org/scripts/570679/1781435/Drawaria%20gallery%20library.js

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==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'] });

})();