Comentário "Um comentário sobre a discussão "A review on Janitor AI - Automatic Message Formatting Corrector (Settings Menu)"" de caret foi denunciado em 13/11/2025 pelo motivo: Spam

caret disse:

My homemade fix:

// ==UserScript==
// @name         Janitor AI - Automatic Message Formatting Corrector (Drag & Drop button)
// @namespace    http://tampermonkey.net/
// @version      7.1
// @description  Draggable button with visual feedback! Remembers its position, adapts to screen size, and can't be dragged off-screen. Formats narration/dialogues.
// @author       accforfaciet
// @match        *://janitorai.com/chats/*
// @grant        GM_addStyle
// @run-at       document-idle
// @license      MIT
// @downloadURL  https://update.greasyfork.org/scripts/551458/Janitor%20AI%20-%20Automatic%20Message%20Formatting%20Corrector%20%28Drag%20%20Drop%20button%29.user.js
// @updateURL    https://update.greasyfork.org/scripts/551458/Janitor%20AI%20-%20Automatic%20Message%20Formatting%20Corrector%20%28Drag%20%20Drop%20button%29.meta.js
// ==/UserScript==
(function() {
    'use strict';
    // --- SCRIPT SETTINGS ---
    const DEBUG_MODE = true;
    const BUTTON_POSITION_KEY = 'formatterButtonPosition';
    // --- UNIVERSAL SELECTORS ---
    const EDIT_BUTTON_SELECTOR = 'button[title="Edit Message"], button[aria-label="Edit"]';
    const TEXT_AREA_SELECTOR = 'textarea[style*="font-size:16px"], textarea[style*="font-size: 16px"], textarea[class*="_autoResizeTextarea"]';
    const CONFIRM_BUTTON_SELECTOR = 'button[aria-label="Confirm"], button[aria-label="Save"], button[aria-label*="Confirm"], button[aria-label*="Save"]';
    // --- DEBUGGING TOOLS ---
    function debugLog(...args) { if (DEBUG_MODE) console.log('[DEBUG]', ...args); }
    function waitForElement(selector, timeoutMs = 10000) {
        return new Promise(resolve => {
            let el = document.querySelector(selector);
            if (el) {
                debugLog(`Element found immediately: ${selector}`);
                return resolve(el);
            }
            debugLog(`Waiting for element: ${selector}`);
            const startTime = Date.now();
            const observer = new MutationObserver(() => {
                const elapsed = Date.now() - startTime;
                if (elapsed > timeoutMs) {
                    observer.disconnect();
                    debugLog(`Timeout (${timeoutMs}ms) waiting for: ${selector}`);
                    return resolve(null);
                }
                el = document.querySelector(selector);
                if (el) {
                    observer.disconnect();
                    debugLog(`Element found after ${elapsed}ms: ${selector}`);
                    return resolve(el);
                }
            });
            observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
        });
    }
    // --- CORE TEXT PROCESSING FUNCTIONS ---
    function removeThinkTags(text) {
        text = text.replace(/\n?\s*<(thought|thoughts)>[\s\S]*?<\/(thought|thoughts)>\s*\n?/g, '');
        text = text.replace(/<(system|response)>|<\/response>/g, '');
        text = text.replace(/\n?\s*<think>[\s\S]*?<\/think>\s*\n?/g, '');
        text = text.replace('</think>', '');
        return removeSystemPrompt(text);
    }
    function formatNarrationAndDialogue(text) {
        text = removeThinkTags(text);
        const normalizedText = text.replace(/[«“”„‟⹂❞❝]/g, '"');
        const lines = normalizedText.split('\n');
        return lines.map(line => {
            const trimmedLine = line.trim();
            if (trimmedLine === '') return '';
            const cleanLine = trimmedLine.replace(/\*/g, '');
            if (cleanLine.includes('"') || cleanLine.includes('`')) {
                return cleanLine.split(/("[\s\S]*?"|`[\s\S]*?`)/)
                    .map(frag => {
                        if ((frag.startsWith('"') && frag.endsWith('"')) || (frag.startsWith('`') && frag.endsWith('`'))) return frag;
                        return frag.trim() !== '' ? `*${frag.trim()}*` : '';
                    }).filter(Boolean).join(' ');
            }
            return `*${cleanLine}*`;
        }).join('\n');
    }
    function removeSystemPrompt(text) {
        if (!text.trim().toLowerCase().includes('theuser')) return text;
        const splitPointIndex = text.search(/[^\s\*]\*[^\s\*]/);
        if (splitPointIndex !== -1) {
            debugLog(`System prompt found. Text trimmed.`);
            return text.substring(splitPointIndex + 1);
        }
        return text;
    }
    // --- MAIN ACTION SEQUENCE ---
    async function processLastMessage(textProcessor) {
        debugLog('--- STARTING EDIT PROCESS ---');
        try {
            const allEditButtons = document.querySelectorAll(EDIT_BUTTON_SELECTOR);
            debugLog(`Found ${allEditButtons.length} edit buttons`);
            if (allEditButtons.length === 0) {
                debugLog('STOP: No edit buttons found.');
                return;
            }
            const lastEditButton = allEditButtons[allEditButtons.length - 1];
            debugLog('Clicking last edit button');
            lastEditButton.click();
            debugLog('Edit button clicked, waiting 800ms for modal');
            await new Promise(resolve => setTimeout(resolve, 800));
            const textField = await waitForElement(TEXT_AREA_SELECTOR);
            if (!textField) {
                debugLog('STOP: Text field not found');
                return;
            }
            debugLog('Text field found');
            const originalText = textField.value;
            debugLog(`Original text length: ${originalText.length}`);
            const newText = textProcessor(originalText);
            debugLog(`New text length: ${newText.length}`);
            textField.value = newText;
            textField.dispatchEvent(new Event('input', { bubbles: true }));
            textField.dispatchEvent(new Event('change', { bubbles: true }));
            debugLog('Text updated, events dispatched');
            const confirmButton = await waitForElement(CONFIRM_BUTTON_SELECTOR, 5000);
            if (!confirmButton) {
                debugLog('STOP: Confirm button not found');
                return;
            }
            debugLog('Confirm button found, clicking');
            confirmButton.click();
            debugLog('--- PROCESS COMPLETED SUCCESSFULLY ---');
        } catch (error) {
            debugLog('ERROR in process:', error.message);
            console.error('CRITICAL ERROR during edit process:', error);
        }
    }
    // --- DRAGGABLE BUTTON ---
    function makeButtonDraggable(button) {
        let isDragging = false;
        let wasDragged = false;
        let offsetX, offsetY;
        const savedPosition = localStorage.getItem(BUTTON_POSITION_KEY);
        if (savedPosition) {
            const { top, left } = JSON.parse(savedPosition);
            button.style.top = top;
            button.style.left = left;
            button.style.right = 'auto';
            button.style.bottom = 'auto';
        }
        function dragStart(e) {
            e.preventDefault();
            isDragging = true;
            wasDragged = false;
            button.classList.add('is-dragging');
            const clientX = e.type === 'touchstart' ? e.touches[0].clientX : e.clientX;
            const clientY = e.type === 'touchstart' ? e.touches[0].clientY : e.clientY;
            offsetX = clientX - button.getBoundingClientRect().left;
            offsetY = clientY - button.getBoundingClientRect().top;
            document.addEventListener('mousemove', dragMove);
            document.addEventListener('touchmove', dragMove, { passive: false });
            document.addEventListener('mouseup', dragEnd);
            document.addEventListener('touchend', dragEnd);
        }
        function dragMove(e) {
            if (!isDragging) return;
            e.preventDefault();
            wasDragged = true;
            const clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
            const clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY;
            let newLeft = clientX - offsetX;
            let newTop = clientY - offsetY;
            const buttonRect = button.getBoundingClientRect();
            newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - buttonRect.width));
            newTop = Math.max(0, Math.min(newTop, window.innerHeight - buttonRect.height));
            button.style.right = 'auto';
            button.style.bottom = 'auto';
            button.style.left = `${newLeft}px`;
            button.style.top = `${newTop}px`;
        }
        function dragEnd() {
            if (!isDragging) return;
            isDragging = false;
            button.classList.remove('is-dragging');
            document.removeEventListener('mousemove', dragMove);
            document.removeEventListener('touchmove', dragMove);
            document.removeEventListener('mouseup', dragEnd);
            document.removeEventListener('touchend', dragEnd);
            if (wasDragged) {
                const pos = { top: button.style.top, left: button.style.left };
                localStorage.setItem(BUTTON_POSITION_KEY, JSON.stringify(pos));
            } else {
                processLastMessage(formatNarrationAndDialogue);
            }
        }
        button.addEventListener('mousedown', dragStart);
        button.addEventListener('touchstart', dragStart, { passive: false });
    }
    function createTriggerButton() {
        const buttonContainer = document.createElement('div');
        buttonContainer.id = 'janitor-editor-buttons';
        document.body.appendChild(buttonContainer);
        const formatButton = document.createElement('button');
        formatButton.innerHTML = '✏️';
        formatButton.id = 'formatterTrigger';
        formatButton.title = 'Format asterisks (Click) or Move Button (Drag)';
        buttonContainer.appendChild(formatButton);
        makeButtonDraggable(formatButton);
    }
    // --- MOBILE KEYBOARD FIX ---
    async function initKeyboardBugFix() {
        try {
            const mainInput = await waitForElement('textarea[placeholder^="Type a message"]', 10000);
            const buttonContainer = document.getElementById('janitor-editor-buttons');
            if (!mainInput || !buttonContainer) return;
            mainInput.addEventListener('focus', () => { buttonContainer.style.display = 'none'; });
            mainInput.addEventListener('blur', () => { setTimeout(() => { buttonContainer.style.display = 'block'; }, 200); });
        } catch (e) {}
    }
    // --- ADAPTIVE STYLES ---
    GM_addStyle(`
        #janitor-editor-buttons button {
            position: fixed;
            z-index: 9999;
            color: white;
            border: none;
            border-radius: 50%;
            box-shadow: 0 4px 8px rgba(0,0,0,0.3);
            cursor: pointer;
            transition: transform 0.2s, opacity 0.2s, box-shadow 0.2s;
            user-select: none;
        }
        #janitor-editor-buttons button:active {
            transform: scale(0.95);
        }
        #formatterTrigger {
            background-color: #c9226e;
        }
        #janitor-editor-buttons button.is-dragging {
            transform: scale(1.1);
            opacity: 0.8;
            box-shadow: 0 8px 16px rgba(0,0,0,0.4);
            transition: none;
        }
        @media (min-width: 769px) {
            #formatterTrigger {
                width: 50px; height: 50px; font-size: 24px;
                right: 27%; bottom: 12%;
            }
        }
        @media (max-width: 768px) {
            #formatterTrigger {
                width: 40px; height: 40px; font-size: 16px;
                right: 28%; bottom: 20%;
            }
        }
    `);
    // --- LAUNCH ---
    createTriggerButton();
    initKeyboardBugFix();
    console.log('Script "Janitor AI - Automatic Message Formatting Corrector" (v7.1) launched.');
})();

caret (o usuário denunciado) fez as seguintes alterações:

Esta denúncia foi arquivada por um moderador.