Character.AI Filtered Message Editor

Permanently enables the Edit button on filtered messages by stripping safety flags from all data (JSON.parse intercept).

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

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

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Character.AI Filtered Message Editor
// @namespace    https://greasyfork.org/users/YOUR_USER_ID
// @version      1.0
// @description  Permanently enables the Edit button on filtered messages by stripping safety flags from all data (JSON.parse intercept).
// @author       You
// @match        https://character.ai/*
// @match        https://neo.character.ai/*
// @grant        none
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Inject directly into the page to bypass sandbox limitations
    const inject = function() {
        // Override JSON.parse to catch data from Network, Cache, AND HTML
        const originalParse = JSON.parse;

        JSON.parse = function(text, reviver) {
            const data = originalParse(text, reviver);

            try {
                // Recursive function to find and flip the safety flag
                const clean = (obj) => {
                    if (!obj || typeof obj !== 'object') return;

                    if (obj.safety_truncated === true) {
                        obj.safety_truncated = false;
                    }

                    if (Array.isArray(obj)) {
                        obj.forEach(clean);
                    } else {
                        Object.values(obj).forEach(clean);
                    }
                };

                // Clean the data before the website sees it
                clean(data);

            } catch (e) {
                // Silently fail on errors to keep the site running smoothly
            }

            return data;
        };
    };

    const script = document.createElement('script');
    script.textContent = `(${inject.toString()})();`;
    (document.head || document.documentElement).appendChild(script);
    script.remove();

})();