您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Combined Background Changer and Color Customizer for Character.AI
// ==UserScript== // @name Character.ai Changer // @namespace http://tampermonkey // @version 1.00.1V3 // @description Combined Background Changer and Color Customizer for Character.AI // @author NotYou // @match https://character.ai/* // @match https://*.character.ai/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @run-at document-start // ==/UserScript== (function() { 'use strict'; // ========================================== // SCRIPT 1: Character.AI Background Changer // ========================================== (function() { 'use strict'; // Initialize logging console.log('Character.AI Background Changer initialized'); function log(message) { console.log(`[BG Changer]: ${message}`); } // Create UI elements const controlPanel = document.createElement('div'); const btnToggle = document.createElement('button'); const statusIndicator = document.createElement('div'); // Set up control panel function setupControlPanel() { controlPanel.id = 'cai-bg-control-panel'; controlPanel.style.position = 'fixed'; controlPanel.style.bottom = '60px'; controlPanel.style.right = '20px'; controlPanel.style.width = '250px'; controlPanel.style.backgroundColor = 'rgba(30, 30, 30, 0.9)'; controlPanel.style.color = 'white'; controlPanel.style.padding = '15px'; controlPanel.style.borderRadius = '8px'; controlPanel.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)'; controlPanel.style.zIndex = '9999999'; controlPanel.style.fontFamily = 'Arial, sans-serif'; controlPanel.style.fontSize = '14px'; controlPanel.style.display = 'none'; controlPanel.innerHTML = ` <div id="panel-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h3 style="margin: 0; font-size: 16px;">Background Changer</h3> <button id="close-panel" style="background: none; border: none; color: white; cursor: pointer; font-size: 18px;">×</button> </div> <div id="panel-content"> <div style="margin-bottom: 15px;"> <label for="bg-url" style="display: block; margin-bottom: 5px;">Image URL:</label> <input type="text" id="bg-url" placeholder="https://example.com/image.jpg" style="width: 100%; padding: 5px; box-sizing: border-box; margin-bottom: 5px;"> <button id="apply-url" style="padding: 5px 10px; background: #4a4a4a; border: none; color: white; cursor: pointer; border-radius: 3px;">Apply URL</button> </div> <div style="margin-bottom: 15px;"> <label for="bg-upload" style="display: block; margin-bottom: 5px;">Upload Image:</label> <input type="file" id="bg-upload" accept="image/*" style="width: 100%; margin-bottom: 5px;"> </div> <div style="margin-bottom: 15px;"> <label for="bg-color" style="display: block; margin-bottom: 5px;">Background Color:</label> <div style="display: flex; align-items: center;"> <input type="color" id="bg-color" value="#1a1a1a" style="margin-right: 10px;"> <button id="apply-color" style="padding: 5px 10px; background: #4a4a4a; border: none; color: white; cursor: pointer; border-radius: 3px;">Apply Color</button> </div> </div> <div style="text-align: center; margin-top: 20px;"> <button id="reset-bg" style="padding: 8px 15px; background: #cc3333; border: none; color: white; cursor: pointer; border-radius: 3px;">Reset Background</button> </div> </div> `; } // Set up toggle button function setupToggleButton() { btnToggle.id = 'cai-bg-toggle'; btnToggle.textContent = 'Change BG'; btnToggle.style.position = 'fixed'; btnToggle.style.bottom = '20px'; btnToggle.style.right = '20px'; btnToggle.style.padding = '8px 12px'; btnToggle.style.backgroundColor = '#3a3'; btnToggle.style.color = 'white'; btnToggle.style.border = 'none'; btnToggle.style.borderRadius = '5px'; btnToggle.style.fontSize = '14px'; btnToggle.style.fontWeight = 'bold'; btnToggle.style.cursor = 'pointer'; btnToggle.style.zIndex = '9999997'; btnToggle.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.2)'; } // Set up status indicator function setupStatusIndicator() { statusIndicator.id = 'cai-bg-status'; statusIndicator.style.position = 'fixed'; statusIndicator.style.bottom = '20px'; statusIndicator.style.left = '20px'; statusIndicator.style.padding = '8px 12px'; statusIndicator.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; statusIndicator.style.color = 'white'; statusIndicator.style.borderRadius = '4px'; statusIndicator.style.fontSize = '14px'; statusIndicator.style.zIndex = '9999998'; statusIndicator.style.opacity = '0'; statusIndicator.style.transition = 'opacity 0.5s'; statusIndicator.textContent = 'Background changer ready'; } // Toggle panel visibility function togglePanel() { const isVisible = controlPanel.style.display === 'block'; if (isVisible) { controlPanel.style.display = 'none'; btnToggle.style.backgroundColor = '#3a3'; } else { controlPanel.style.display = 'block'; btnToggle.style.backgroundColor = '#555'; } } // Show status message function showStatus(message, duration = 2000) { statusIndicator.textContent = message; statusIndicator.style.opacity = '1'; setTimeout(() => { statusIndicator.style.opacity = '0'; }, duration); } // Apply background from URL function applyUrlBackground() { const url = document.getElementById('bg-url').value.trim(); if (!url) { showStatus('Please enter a valid URL'); return; } applyBackground(`url(${url}) no-repeat center center fixed`, 'cover'); showStatus('Background applied from URL'); } // Apply background from color picker function applyColorBackground() { const color = document.getElementById('bg-color').value; applyBackground(color); showStatus('Background color applied'); } // Apply background image from file upload function handleImageUpload(event) { const file = event.target.files[0]; if (!file) return; // Check if file is an image if (!file.type.startsWith('image/')) { showStatus('Please select an image file'); return; } const reader = new FileReader(); reader.onload = function(e) { const imageUrl = e.target.result; applyBackground(`url(${imageUrl}) no-repeat center center fixed`, 'cover'); showStatus('Background image applied'); // Save the image data to GM storage GM_setValue('bgImageData', imageUrl); }; reader.readAsDataURL(file); } // Apply background function applyBackground(style, size = null) { document.body.style.background = style; if (size) { document.body.style.backgroundSize = size; } // Save settings GM_setValue('bgStyle', style); GM_setValue('bgSize', size || ''); } // Reset background function resetBackground() { document.body.style.background = ''; document.body.style.backgroundSize = ''; // Clear saved values GM_setValue('bgStyle', ''); GM_setValue('bgSize', ''); GM_setValue('bgImageData', ''); // Reset form inputs const urlInput = document.getElementById('bg-url'); const uploadInput = document.getElementById('bg-upload'); if (urlInput) urlInput.value = ''; if (uploadInput) uploadInput.value = ''; showStatus('Background reset to default'); } // Restore saved background function restoreBackground() { const bgStyle = GM_getValue('bgStyle', ''); const bgSize = GM_getValue('bgSize', ''); if (bgStyle) { document.body.style.background = bgStyle; if (bgSize) { document.body.style.backgroundSize = bgSize; } log('Restored saved background'); } } // Setup event listeners function setupEventListeners() { // Toggle button btnToggle.addEventListener('click', togglePanel); // Close panel button document.getElementById('close-panel')?.addEventListener('click', () => { togglePanel(); }); // Apply URL background document.getElementById('apply-url')?.addEventListener('click', applyUrlBackground); // Apply color background document.getElementById('apply-color')?.addEventListener('click', applyColorBackground); // Handle file upload document.getElementById('bg-upload')?.addEventListener('change', handleImageUpload); // Reset background document.getElementById('reset-bg')?.addEventListener('click', resetBackground); log('Event listeners set up'); } // DOM Ready helper function function domReady(callback) { if (document.readyState === "complete" || document.readyState === "interactive") { setTimeout(callback, 1); } else { document.addEventListener("DOMContentLoaded", callback); } } // Initialize everything when DOM is ready function init() { if (!document.body) { setTimeout(init, 100); return; } try { // Setup UI elements setupControlPanel(); setupToggleButton(); setupStatusIndicator(); // Add elements to the page document.body.appendChild(controlPanel); document.body.appendChild(btnToggle); document.body.appendChild(statusIndicator); // Setup event listeners setupEventListeners(); // Restore saved background restoreBackground(); // Show initial status showStatus('Background changer ready'); log('Initialization complete'); } catch (error) { console.error('[BG Changer Error]:', error); } } // Run initialization when DOM is ready domReady(() => { init(); // Additional safety check setTimeout(() => { if (!document.getElementById('cai-bg-control-panel')) { log('Panel not found, retrying initialization'); init(); } }, 3000); }); // Backup initialization on window load window.addEventListener('load', () => { if (!document.getElementById('cai-bg-control-panel')) { log('Panel not found on window load, reinitializing'); init(); } }); })(); // ========================================== // SCRIPT 2: Enhanced Color Customizer // ========================================== (function() { 'use strict'; // Helper function to get the current theme function getCurrentTheme() { return document.documentElement.classList.contains('dark') ? 'dark' : 'light'; } // Default colors based on theme function getDefaultColors(theme) { const darkColors = { 'italic': '#E0DF7F', 'quotationmarks': '#FFFFFF', 'plaintext': '#A2A2AC', 'custom': '#E0DF7F', 'charbubble': '#26272B', 'userbubble': '#303136', 'guide': '#131316', 'input': '#202024', 'body': '#18181B', 'accent': '#26272B' }; const lightColors = { 'italic': '#4F7AA6', 'quotationmarks': '#000000', 'plaintext': '#374151', 'custom': '#4F7AA6', 'charbubble': '#E4E4E7', 'userbubble': '#D9D9DF', 'guide': '#FAFAFA', 'input': '#F4F4F5', 'body': '#ECECEE', 'accent': '#26272B' }; return theme === 'dark' ? darkColors : lightColors; } // Load Comic Sans MS and other web fonts function loadWebFonts() { // Add Comic Sans MS GM_addStyle(` @import url('https://fonts.cdnfonts.com/css/comic-sans'); @font-face { font-family: 'Comic Sans MS'; src: local('Comic Sans MS'), url('https://fonts.cdnfonts.com/s/11177/comici.woff') format('woff'), url('https://fonts.cdnfonts.com/s/11177/comicbd.woff') format('woff'); font-display: swap; } `); // Add Google Fonts const googleFontsLink = document.createElement('link'); googleFontsLink.rel = 'stylesheet'; googleFontsLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Open+Sans:wght@400;700&family=Lato:wght@400;700&family=Montserrat:wght@400;700&display=swap'; document.head.appendChild(googleFontsLink); } // Create main customization menu function createCustomizationMenu() { const theme = getCurrentTheme(); const menuContainer = document.createElement('div'); menuContainer.id = 'cai-color-customizer'; menuContainer.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 900px; background-color: ${theme === 'dark' ? 'rgba(19, 19, 22, 0.95)' : 'rgba(214, 214, 221, 0.95)'}; border-radius: 10px; padding: 20px; z-index: 9999; display: none; `; // Tabs container const tabContainer = document.createElement('div'); tabContainer.style.cssText = ` display: flex; margin-bottom: 15px; `; // Content container const contentContainer = document.createElement('div'); // Create tabs const tabs = [ { name: 'Colors', id: 'colors' }, { name: 'Typography', id: 'typography' }, { name: 'Layout', id: 'layout' } ]; tabs.forEach(tab => { const tabButton = document.createElement('button'); tabButton.textContent = tab.name; tabButton.style.cssText = ` flex-grow: 1; padding: 10px; background-color: ${theme === 'dark' ? '#26272B' : '#E4E4E7'}; border: none; margin-right: 5px; cursor: pointer; `; tabButton.addEventListener('click', () => { // Hide all content contentContainer.innerHTML = ''; // Show specific tab content switch(tab.id) { case 'colors': renderColorTab(contentContainer); break; case 'typography': renderTypographyTab(contentContainer); break; case 'layout': renderLayoutTab(contentContainer); break; } }); tabContainer.appendChild(tabButton); }); // Add close button const closeButton = document.createElement('button'); closeButton.textContent = '×'; closeButton.style.cssText = ` position: absolute; top: 10px; right: 10px; background: none; border: none; font-size: 20px; cursor: pointer; `; closeButton.addEventListener('click', () => { menuContainer.style.display = 'none'; }); menuContainer.appendChild(closeButton); menuContainer.appendChild(tabContainer); menuContainer.appendChild(contentContainer); document.body.appendChild(menuContainer); // Auto-select the first tab on creation tabContainer.firstChild.click(); return menuContainer; } // Render color customization tab function renderColorTab(container) { const theme = getCurrentTheme(); const categories = ['italic', 'quotationmarks', 'plaintext', 'custom', 'charbubble', 'userbubble', 'guide', 'input', 'body', 'accent']; categories.forEach(category => { const colorWrapper = document.createElement('div'); colorWrapper.style.cssText = ` display: flex; align-items: center; margin-bottom: 10px; `; const label = document.createElement('label'); label.textContent = category.charAt(0).toUpperCase() + category.slice(1); label.style.marginRight = '10px'; const colorPicker = document.createElement('input'); colorPicker.type = 'color'; colorPicker.value = GM_getValue(`${category}_color`, getDefaultColors(theme)[category]); colorPicker.addEventListener('input', () => { GM_setValue(`${category}_color`, colorPicker.value); applyCustomColors(); }); colorWrapper.appendChild(label); colorWrapper.appendChild(colorPicker); container.appendChild(colorWrapper); }); } // Render typography tab function renderTypographyTab(container) { // Typography container const typographyContainer = document.createElement('div'); typographyContainer.style.cssText = ` display: flex; flex-direction: column; gap: 15px; `; // Font selector const fontSelectContainer = document.createElement('div'); fontSelectContainer.style.cssText = ` display: flex; flex-direction: column; gap: 5px; `; const fontSelectLabel = document.createElement('label'); fontSelectLabel.textContent = 'Font Family:'; const fontSelect = document.createElement('select'); fontSelect.style.width = '100%'; // Common fonts including Comic Sans MS const fonts = [ 'Comic Sans MS', 'Inter', 'Arial', 'Helvetica', 'Verdana', 'Tahoma', 'Times New Roman', 'Georgia', 'Garamond', 'Courier New', 'Consolas', 'Monaco', 'Roboto', 'Open Sans', 'Lato', 'Montserrat' ]; // Add default option const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = 'Default'; fontSelect.appendChild(defaultOption); // Add font options fonts.forEach(font => { const option = document.createElement('option'); option.value = font; option.textContent = font; option.style.fontFamily = font; fontSelect.appendChild(option); }); // Set selected value from saved preference fontSelect.value = GM_getValue('selected_font', ''); fontSelect.addEventListener('change', () => { GM_setValue('selected_font', fontSelect.value); applyTypographySettings(); }); fontSelectContainer.appendChild(fontSelectLabel); fontSelectContainer.appendChild(fontSelect); typographyContainer.appendChild(fontSelectContainer); // Font Style const fontStyleContainer = document.createElement('div'); fontStyleContainer.style.cssText = ` display: flex; flex-direction: column; gap: 5px; margin-top: 10px; `; const fontStyleLabel = document.createElement('label'); fontStyleLabel.textContent = 'Font Style:'; const fontStyleOptions = document.createElement('div'); fontStyleOptions.style.cssText = ` display: flex; gap: 10px; `; // Bold checkbox const boldContainer = document.createElement('div'); const boldCheckbox = document.createElement('input'); boldCheckbox.type = 'checkbox'; boldCheckbox.id = 'font-bold'; boldCheckbox.checked = GM_getValue('fontBold', false); const boldLabel = document.createElement('label'); boldLabel.textContent = 'Bold'; boldLabel.htmlFor = 'font-bold'; boldCheckbox.addEventListener('change', () => { GM_setValue('fontBold', boldCheckbox.checked); applyTypographySettings(); }); boldContainer.appendChild(boldCheckbox); boldContainer.appendChild(boldLabel); // Italic checkbox const italicContainer = document.createElement('div'); const italicCheckbox = document.createElement('input'); italicCheckbox.type = 'checkbox'; italicCheckbox.id = 'font-italic'; italicCheckbox.checked = GM_getValue('fontItalic', false); const italicLabel = document.createElement('label'); italicLabel.textContent = 'Italic'; italicLabel.htmlFor = 'font-italic'; italicCheckbox.addEventListener('change', () => { GM_setValue('fontItalic', italicCheckbox.checked); applyTypographySettings(); }); italicContainer.appendChild(italicCheckbox); italicContainer.appendChild(italicLabel); fontStyleOptions.appendChild(boldContainer); fontStyleOptions.appendChild(italicContainer); fontStyleContainer.appendChild(fontStyleLabel); fontStyleContainer.appendChild(fontStyleOptions); typographyContainer.appendChild(fontStyleContainer); // Font Size Slider const fontSizeContainer = document.createElement('div'); fontSizeContainer.style.cssText = ` display: flex; flex-direction: column; gap: 5px; `; const fontSizeLabel = document.createElement('label'); fontSizeLabel.textContent = 'Font Size: ' + GM_getValue('fontSize', 16) + 'px'; const fontSizeSlider = document.createElement('input'); fontSizeSlider.type = 'range'; fontSizeSlider.min = 10; fontSizeSlider.max = 30; fontSizeSlider.value = GM_getValue('fontSize', 16); fontSizeSlider.style.width = '100%'; fontSizeSlider.addEventListener('input', () => { const newSize = fontSizeSlider.value; fontSizeLabel.textContent = 'Font Size: ' + newSize + 'px'; GM_setValue('fontSize', newSize); applyTypographySettings(); }); fontSizeContainer.appendChild(fontSizeLabel); fontSizeContainer.appendChild(fontSizeSlider); typographyContainer.appendChild(fontSizeContainer); container.appendChild(typographyContainer); } // Render layout tab function renderLayoutTab(container) { const layoutContainer = document.createElement('div'); layoutContainer.style.cssText = ` display: flex; flex-direction: column; gap: 15px; `; // Avatar size control const avatarSizeContainer = document.createElement('div'); avatarSizeContainer.style.cssText = ` display: flex; align-items: center; gap: 10px; `; const sizeLabel = document.createElement('label'); sizeLabel.textContent = 'Avatar Image Size (px):'; const sizeInput = document.createElement('input'); sizeInput.type = 'number'; sizeInput.value = GM_getValue('image_size', '24'); sizeInput.min = '16'; sizeInput.max = '64'; sizeInput.style.width = '60px'; sizeInput.addEventListener('change', () => { GM_setValue('image_size', sizeInput.value); applyLayoutSettings(); }); avatarSizeContainer.appendChild(sizeLabel); avatarSizeContainer.appendChild(sizeInput); layoutContainer.appendChild(avatarSizeContainer); // Chat bubble spacing control const spacingContainer = document.createElement('div'); spacingContainer.style.cssText = ` display: flex; align-items: center; gap: 10px; `; const spacingLabel = document.createElement('label'); spacingLabel.textContent = 'Message Spacing (px):'; const spacingInput = document.createElement('input'); spacingInput.type = 'number'; spacingInput.value = GM_getValue('message_spacing', '10'); spacingInput.min = '0'; spacingInput.max = '30'; spacingInput.style.width = '60px'; spacingInput.addEventListener('change', () => { GM_setValue('message_spacing', spacingInput.value); applyLayoutSettings(); }); spacingContainer.appendChild(spacingLabel); spacingContainer.appendChild(spacingInput); layoutContainer.appendChild(spacingContainer); container.appendChild(layoutContainer); } // Apply color customizations dynamically function applyCustomColors() { const theme = getCurrentTheme(); const defaultColors = getDefaultColors(theme); const categories = ['italic', 'quotationmarks', 'plaintext', 'custom', 'charbubble', 'userbubble', 'guide', 'input', 'body', 'accent']; // Remove any existing style element const existingStyle = document.getElementById('cai-custom-colors'); if (existingStyle) { existingStyle.remove(); } const styleElement = document.createElement('style'); styleElement.id = 'cai-custom-colors'; let css = ''; categories.forEach(category => { const color = GM_getValue(`${category}_color`, defaultColors[category]); switch(category) { case 'italic': css += `em { color: ${color} !important; } `; break; case 'quotationmarks': css += `blockquote { color: ${color} !important; } `; break; case 'plaintext': css += `p[node='[object Object]'] { color: ${color} !important; } `; break; case 'charbubble': css += `.mt-1.bg-surface-elevation-2 { background-color: ${color} !important; } `; break; case 'userbubble': css += `.mt-1.bg-surface-elevation-3 { background-color: ${color} !important; } `; break; case 'guide': css += `.overflow-y-auto { background-color: ${color} !important; } `; break; case 'input': css += `.w-full.border-none.bg-surface-elevation-1 { background-color: ${color} !important; } `; break; case 'body': css += `body { background-color: ${color} !important; } `; break; case 'accent': css += `.text-primary-600 { color: ${color} !important; } `; break; case 'custom': css += `code, pre { color: ${color} !important; } `; break; } }); styleElement.textContent = css; document.head.appendChild(styleElement); } // Apply typography settings function applyTypographySettings() { // Remove any existing style element const existingStyle = document.getElementById('cai-custom-typography'); if (existingStyle) { existingStyle.remove(); } const font = GM_getValue('selected_font', ''); const fontSize = GM_getValue('fontSize', 16) + 'px'; const isBold = GM_getValue('fontBold', false); const isItalic = GM_getValue('fontItalic', false); const fontWeight = isBold ? 'bold' : 'normal'; const fontStyle = isItalic ? 'italic' : 'normal'; const styleElement = document.createElement('style'); styleElement.id = 'cai-custom-typography'; // Make sure we properly handle Comic Sans MS and other fonts with spaces const fontFamily = font ? `'${font}', ` : ''; styleElement.textContent = ` p, textarea, button, div.text-sm, .markdown-content, .message-content, div[class*="text-base"], div[class*="text-md"], div[class*="text-lg"], span[class*="text-base"], span[class*="text-md"], span[class*="text-lg"] { font-family: ${fontFamily}'Noto Sans', sans-serif !important; font-size: ${fontSize} !important; font-weight: ${fontWeight} !important; font-style: ${fontStyle} !important; } `; document.head.appendChild(styleElement); } // Apply layout settings function applyLayoutSettings() { // Remove any existing style element const existingStyle = document.getElementById('cai-custom-layout'); if (existingStyle) { existingStyle.remove(); } const imageSize = GM_getValue('image_size', '24') + 'px'; const messageSpacing = GM_getValue('message_spacing', '10') + 'px'; const styleElement = document.createElement('style'); styleElement.id = 'cai-custom-layout'; styleElement.textContent = ` .mt-0.hidden.md\\:flex.flex-col.gap-3.items-center img { width: ${imageSize} !important; height: ${imageSize} !important; } .mt-1.flex.w-full { margin-bottom: ${messageSpacing} !important; } `; document.head.appendChild(styleElement); } // Apply all settings at once function applySettings() { applyCustomColors(); applyTypographySettings(); applyLayoutSettings(); } // Create global customization button function createCustomizationButton() { // Check if button already exists if (document.getElementById('cai-customizer-button')) { return; } const button = document.createElement('button'); button.id = 'cai-customizer-button'; button.style.cssText = ` position: fixed; top: 10px; right: 10px; width: 24px; height: 24px; background-image: url('https://i.imgur.com/yBgJ3za.png'); background-size: cover; z-index: 9998; border: none; cursor: pointer; border-radius: 4px; `; // Create menu only if it doesn't exist let menu = document.getElementById('cai-color-customizer'); if (!menu) { menu = createCustomizationMenu(); } button.addEventListener('click', () => { menu.style.display = menu.style.display === 'none' ? 'block' : 'none'; }); document.body.appendChild(button); } // Global keyboard shortcut handler function handleKeyboardShortcut(event) { if (event.key === '`' && event.ctrlKey) { event.preventDefault(); const menu = document.getElementById('cai-color-customizer'); if (menu) { menu.style.display = menu.style.display === 'none' ? 'block' : 'none'; } } } // Wait for page to load before initialization function waitForPageLoad() { // Load web fonts first loadWebFonts(); // Check if we're on Character.AI or Discord if (window.location.hostname.includes('character.ai')) { // For Character.AI if (document.readyState === 'complete' || document.readyState === 'interactive') { initializeForCAI(); } else { window.addEventListener('DOMContentLoaded', initializeForCAI); } } else if (window.location.hostname.includes('discord.com')) { // For Discord const checkInterval = setInterval(() => { if (document.querySelector('#app-mount')) { clearInterval(checkInterval); initializeForDiscord(); } }, 500); } } // Initialize for Character.AI function initializeForCAI() { // Ensure the button is created createCustomizationButton(); // Apply settings applySettings(); // Add keyboard shortcut listener document.addEventListener('keydown', handleKeyboardShortcut); // Re-apply settings when theme changes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName === 'class' && mutation.target === document.documentElement) { applySettings(); } }); }); observer.observe(document.documentElement, { attributes: true }); // Make sure button stays visible with periodic check setInterval(() => { if (!document.getElementById('cai-customizer-button')) { createCustomizationButton(); } }, 5000); } // Initialize for Discord function initializeForDiscord() { // Apply font settings if exists const savedFont = GM_getValue('discordFont', GM_getValue('selected_font', '')); const fontSize = GM_getValue('discordFontSize', GM_getValue('fontSize', 16)); const fontWeight = GM_getValue('discordFontWeight', GM_getValue('fontBold', false) ? 'bold' : 'normal'); const fontStyle = GM_getValue('fontItalic', false) ? 'italic' : 'normal'; const fontColor = GM_getValue('discordFontColor', '#ffffff'); // Create style for Discord font customization const styleElement = document.createElement('style'); styleElement.id = 'discord-font-customizer'; styleElement.textContent = ` .markup-eYLPri, .contents-2MsGLg, [class*="messageContent-"], [class*="channelName-"] { font-family: ${savedFont ? `'${savedFont}',` : ''} 'Whitney', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; font-size: ${fontSize}px !important; font-weight: ${fontWeight} !important; font-style: ${fontStyle} !important; color: ${fontColor} !important; } `; document.head.appendChild(styleElement); // Create customization button for Discord createCustomizationButton(); // Add keyboard shortcut listener for Discord document.addEventListener('keydown', handleKeyboardShortcut); // Make sure button stays visible with periodic check setInterval(() => { if (!document.getElementById('cai-customizer-button')) { createCustomizationButton(); } }, 5000); } // Start initialization waitForPageLoad(); // Fallback initialization to ensure script runs setTimeout(() => { if (!document.getElementById('cai-customizer-button')) { loadWebFonts(); createCustomizationButton(); applySettings(); document.addEventListener('keydown', handleKeyboardShortcut); } }, 3000); })(); // ========================================== // SHARED INITIALIZATION // ========================================== function initializeAll() { // Call the initialization functions from both scripts if they exist // For example: // if (typeof initBackgroundChanger === 'function') { // initBackgroundChanger(); // } // // if (typeof initColorCustomizer === 'function') { // initColorCustomizer(); // } } // Run on page load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializeAll); } else { initializeAll(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址