您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhanced integration between SillyTavern and Sexy.AI with translation support
当前为
// ==UserScript== // @name Sync between Sexy.AI and SillyTavern old // @namespace http://tampermonkey.net/ // @version 3.0 // @description Enhanced integration between SillyTavern and Sexy.AI with translation support // @author You // @match https://sexy.ai/workflow* // @match https://staticui.sexy.ai/* // @match http://ducninh.top:8000/* // @match http://127.0.0.1:8000/* // @match http://*/*:8000/* // @grant GM_setValue // @grant GM_getValue // @grant unsafeWindow // ==/UserScript== (function() { 'use strict'; console.log("Script started on URL:", window.location.href); const isSexyAI = window.location.href.includes('sexy.ai') || window.location.href.includes('staticui.sexy.ai'); const isSillyTavern = window.location.href.includes(':8000'); // Utility Functions function createStyledButton(text, onClick) { const button = document.createElement('button'); button.textContent = text; button.style.cssText = ` padding: 5px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px; opacity: 0.8; transition: all 0.3s; margin-left: 5px; `; button.addEventListener('mouseover', () => button.style.opacity = '1'); button.addEventListener('mouseout', () => button.style.opacity = '0.8'); button.addEventListener('click', onClick); return button; } // Extract original text from message function extractOriginalText(messageNode) { // Try to get original text from data attribute first const originalText = messageNode.getAttribute('data-original-text'); if (originalText) { return originalText; } // If no stored original text, get current text const messageText = messageNode.querySelector('.mes_text'); if (!messageText) return ''; // Clone the message text element to work with const clone = messageText.cloneNode(true); // Remove any button containers if they exist const buttonContainer = clone.querySelector('.button-container'); if (buttonContainer) { buttonContainer.remove(); } return clone.textContent.trim(); } // Store original text before translation function storeOriginalText(messageNode) { const messageText = messageNode.querySelector('.mes_text'); if (messageText && !messageNode.hasAttribute('data-original-text')) { messageNode.setAttribute('data-original-text', messageText.textContent); } } // SexyAI Implementation if (isSexyAI) { if (window.location.href.includes('staticui.sexy.ai')) { const promptButton = createStyledButton('Get Prompt', () => { const prompt = GM_getValue('st_prompt', null); if (prompt) { const positiveInput = document.querySelector('textarea') || document.querySelector('input[type="text"]'); if (positiveInput) { positiveInput.value = prompt; const event = new Event('input', { bubbles: true }); positiveInput.dispatchEvent(event); GM_setValue('st_prompt', null); promptButton.style.backgroundColor = '#2196F3'; promptButton.textContent = 'Prompt Added'; setTimeout(() => { promptButton.style.backgroundColor = '#4CAF50'; promptButton.textContent = 'Get Prompt'; }, 2000); } } }); promptButton.style.cssText += 'position: fixed; right: 20px; top: 80px;'; document.body.appendChild(promptButton); } document.addEventListener('click', (e) => { if (e.target.tagName === 'IMG') { // Lấy tất cả ảnh hiện tại const allImages = document.querySelectorAll('img'); const latestImages = Array.from(allImages) .slice(-4) // Lấy 4 ảnh cuối cùng .map(img => ``); console.log('Saving latest images:', latestImages); GM_setValue('sexyai_images', latestImages.join('\n')); // Visual feedback const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 10px; right: 10px; background-color: #4CAF50; color: white; padding: 8px; border-radius: 4px; z-index: 10000; opacity: 0; transition: opacity 0.3s; `; overlay.textContent = 'Images Synced'; document.body.appendChild(overlay); setTimeout(() => { overlay.style.opacity = '1'; setTimeout(() => { overlay.style.opacity = '0'; setTimeout(() => overlay.remove(), 300); }, 1500); }, 0); } }, true); } else if (isSillyTavern) { function showImageModal(imageUrl) { const existingModal = document.querySelector('.image-modal-container'); if (existingModal) { existingModal.remove(); } const container = document.createElement('div'); container.className = 'image-modal-container'; container.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 10000; background: rgba(0, 0, 0, 0.8); padding: 10px; border-radius: 10px; max-width: 300px; `; // Tải trước tất cả các ảnh const images = GM_getValue('sexyai_images', '').split('\n').filter(url => url); const imageElements = images.map(url => { const img = new Image(); img.src = url.replace('.replace(')', ''); img.style.cssText = ` width: 100%; height: auto; max-height: 400px; object-fit: contain; border-radius: 5px; display: none; `; return img; }); let currentIndex = images.findIndex(url => url === imageUrl); if (currentIndex === -1) currentIndex = 0; // Hiển thị ảnh hiện tại imageElements[currentIndex].style.display = 'block'; // Thêm tất cả ảnh vào container imageElements.forEach(img => container.appendChild(img)); const navigationContainer = document.createElement('div'); navigationContainer.style.cssText = ` display: flex; justify-content: space-between; margin-top: 10px; `; const prevButton = document.createElement('button'); const nextButton = document.createElement('button'); [prevButton, nextButton].forEach(button => { button.style.cssText = ` background: #4CAF50; border: none; color: white; padding: 5px 15px; border-radius: 3px; cursor: pointer; margin: 0 5px; font-size: 16px; transition: background-color 0.2s; `; }); prevButton.textContent = '←'; nextButton.textContent = '→'; // Tối ưu hàm chuyển ảnh function switchImage(newIndex) { imageElements[currentIndex].style.display = 'none'; currentIndex = (newIndex + images.length) % images.length; imageElements[currentIndex].style.display = 'block'; } prevButton.onclick = () => switchImage(currentIndex - 1); nextButton.onclick = () => switchImage(currentIndex + 1); // Thêm phím tắt để điều hướng document.addEventListener('keydown', function(e) { if (container.isConnected) { // Chỉ xử lý khi modal đang hiển thị if (e.key === 'ArrowLeft') { prevButton.click(); } else if (e.key === 'ArrowRight') { nextButton.click(); } else if (e.key === 'Escape') { closeButton.click(); } } }); // Cải thiện nút đóng const closeButton = document.createElement('button'); closeButton.textContent = '×'; closeButton.style.cssText = ` position: absolute; top: -10px; right: -10px; background: #4CAF50; border: none; color: white; width: 20px; height: 20px; border-radius: 50%; font-size: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; transition: background-color 0.2s; `; closeButton.onmouseover = () => closeButton.style.backgroundColor = '#45a049'; closeButton.onmouseout = () => closeButton.style.backgroundColor = '#4CAF50'; closeButton.onclick = () => { container.remove(); const showImageButton = document.querySelector('#show_image_button'); if (showImageButton) { showImageButton.style.color = ''; showImageButton.style.opacity = '0.7'; } }; container.appendChild(closeButton); navigationContainer.appendChild(prevButton); navigationContainer.appendChild(nextButton); container.appendChild(navigationContainer); document.body.appendChild(container); // Tải trước ảnh kế tiếp images.forEach((url, index) => { if (index !== currentIndex) { const preloadImg = new Image(); preloadImg.src = url.replace('.replace(')', ''); } }); } function addControlButtons() { // Kiểm tra cả hai nút để tránh nhân bản if (document.querySelector('#show_image_button') || document.querySelector('#send_prompt_button')) { return; // Nếu đã tồn tại nút thì không thêm nữa } const extensionsButton = document.querySelector('#extensionsMenuButton'); const optionsButton = document.querySelector('#options_button'); if (extensionsButton && optionsButton) { // Nút Show Image const showImageButton = document.createElement('div'); showImageButton.id = 'show_image_button'; showImageButton.className = 'fa-solid fa-eye interactable'; showImageButton.title = 'Show/Hide Images'; showImageButton.style.cssText = ` display: flex; cursor: pointer; opacity: 0.7; margin: 0 5px; font-size: 18px; transition: all 0.3s; `; showImageButton.tabIndex = "0"; // Nút Send Prompt const sendPromptButton = document.createElement('div'); sendPromptButton.id = 'send_prompt_button'; sendPromptButton.className = 'fa-solid fa-paper-plane interactable'; sendPromptButton.title = 'Send Prompt'; sendPromptButton.style.cssText = ` display: flex; cursor: pointer; opacity: 0.7; margin: 0 5px; font-size: 18px; transition: all 0.3s; `; sendPromptButton.tabIndex = "0"; // Logic xử lý sự kiện cho Show Image Button let isShowingImages = false; let currentImageIndex = 0; let images = []; showImageButton.addEventListener('click', () => { isShowingImages = !isShowingImages; showImageButton.style.color = isShowingImages ? 'var(--accent-color, #4CAF50)' : ''; showImageButton.style.opacity = isShowingImages ? '1' : '0.7'; if (isShowingImages) { const markdownUrls = GM_getValue('sexyai_images', '').split('\n').filter(url => url); images = markdownUrls; if (images.length > 0) { showImageModal(images[currentImageIndex]); } } else { const existingModal = document.querySelector('.image-modal-container'); if (existingModal) { existingModal.remove(); } } }); // Logic xử lý sự kiện cho Send Prompt Button sendPromptButton.addEventListener('click', () => { const messages = document.getElementsByClassName('mes'); const lastMessage = messages[messages.length - 1]; if (lastMessage) { const text = extractOriginalText(lastMessage); const match = text.match(/image###([^#]+)###/); if (match) { const prompt = match[1].trim(); GM_setValue('st_prompt', prompt); sendPromptButton.style.color = 'var(--accent-color, #4CAF50)'; setTimeout(() => { sendPromptButton.style.color = ''; }, 2000); } } }); // Chèn các nút vào vị trí phù hợp optionsButton.parentNode.insertBefore(showImageButton, optionsButton.nextSibling); extensionsButton.parentNode.insertBefore(sendPromptButton, extensionsButton.nextSibling); } } // Thay đổi cách gọi hàm addControlButtons let checkInterval = setInterval(() => { if (document.querySelector('#options_button') && document.querySelector('#extensionsMenuButton')) { addControlButtons(); // Sau khi thêm nút thành công, clear interval if (document.querySelector('#show_image_button') && document.querySelector('#send_prompt_button')) { clearInterval(checkInterval); } } }, 1000); // Thêm một observer để xử lý trường hợp giao diện bị reload const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.removedNodes.length > 0) { // Nếu các nút bị xóa, thêm lại chúng if (!document.querySelector('#show_image_button') || !document.querySelector('#send_prompt_button')) { addControlButtons(); } } } }); // Bắt đầu quan sát DOM observer.observe(document.body, { childList: true, subtree: true }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址