Sync between Sexy.AI and SillyTavern

bqy

目前為 2024-11-20 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Sync between Sexy.AI and SillyTavern
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  bqy
// @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');

   function createStyledButton(text, onClick, isFixed = false) {
       const button = document.createElement('button');
       button.textContent = text;
       let baseStyle = `
           padding: 5px 8px;
           background-color: #4CAF50;
           color: white;
           border: none;
           border-radius: 3px;
           cursor: pointer;
           font-size: 12px;
           opacity: 0.8;
           transition: opacity 0.3s;
           z-index: 9999;
       `;

       if(isFixed) {
           baseStyle += `
               position: fixed;
               right: 20px;
           `;
       } else {
           baseStyle += `
               margin-left: 5px;
           `;
       }

       button.style.cssText = baseStyle;
       button.addEventListener('mouseover', () => button.style.opacity = '1');
       button.addEventListener('mouseout', () => button.style.opacity = '0.8');
       button.addEventListener('click', onClick);
       return button;
   }

   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);
                       alert('Prompt added!');
                   } else {
                       console.error('Available inputs:', document.querySelectorAll('input, textarea'));
                       alert('Input field not found.');
                   }
               } else {
                   alert('No prompt found. Copy from SillyTavern first.');
               }
           }, true);

           promptButton.style.top = '80px';
           document.body.appendChild(promptButton);
       }

       document.addEventListener('click', (e) => {
           if (e.target.tagName === 'IMG') {
               const markdownUrls = [`![alt-text](${e.target.src})`];
               GM_setValue('sexyai_images', markdownUrls.join('\n'));
               alert('Image copied! Switch to SillyTavern tab.');
           }
       }, true);

   } else if (isSillyTavern) {
       function addButtonsToMessage(node) {
           setTimeout(() => {
               if (!node || !node.querySelector) return;

               const messageText = node.querySelector('.mes_text');
               if (!messageText) return;

               // Check if buttons already exist
               if (messageText.querySelector('.button-container')) return;

               const text = messageText.innerHTML;
               const hasImagePrompt = text.match(/image###([^#]+)###/);

               if (hasImagePrompt) {
                   const buttonContainer = document.createElement('div');
                   buttonContainer.className = 'button-container';
                   buttonContainer.style.display = 'flex';
                   buttonContainer.style.gap = '5px';
                   buttonContainer.style.marginTop = '5px';

                   const syncButton = createStyledButton('📥 Sync Image', () => {
                       const markdownUrls = GM_getValue('sexyai_images', null);
                       if (!markdownUrls) {
                           alert('No images found. Click an image in Sexy.AI first.');
                           return;
                       }

                       const editButton = node.querySelector('.mes_edit');
                       if (editButton) {
                           editButton.click();
                           setTimeout(() => {
                               const textarea = document.getElementById('curEditTextarea');
                               if (textarea) {
                                   textarea.value = textarea.value + '\n' + markdownUrls;
                                   setTimeout(() => {
                                       const confirmButton = node.querySelector('.mes_edit_done');
                                       if (confirmButton) {
                                           confirmButton.click();
                                           GM_setValue('sexyai_images', null);
                                           alert('Images added successfully!');
                                       }
                                   }, 100);
                               }
                           }, 100);
                       }
                   });

                   const sendPromptButton = createStyledButton('📤 Send Prompt', () => {
                       const text = messageText.textContent;
                       const match = text.match(/image###([^#]+)###/);
                       if (match) {
                           const prompt = match[1].trim();
                           GM_setValue('st_prompt', prompt);
                           messageText.innerHTML = messageText.innerHTML.replace(/(image###[^#]+###)/g, '');
                           alert('Prompt copied! Click "Get Prompt" in Sexy.AI tab');
                       } else {
                           alert('No valid prompt found. Message should contain image###prompt###');
                       }
                   });

                   buttonContainer.appendChild(syncButton);
                   buttonContainer.appendChild(sendPromptButton);
                   messageText.appendChild(buttonContainer);
               }
           }, 500);
       }

       // Initial scan for existing messages
       document.querySelectorAll('.mes').forEach(addButtonsToMessage);

       // Watch for new messages
       const observer = new MutationObserver((mutations) => {
           mutations.forEach((mutation) => {
               mutation.addedNodes.forEach((node) => {
                   if (node.nodeType === 1) { // Check if it's an element node
                       if (node.classList?.contains('mes')) {
                           addButtonsToMessage(node);
                       }
                       // Also check children for .mes classes
                       const mesElements = node.getElementsByClassName('mes');
                       Array.from(mesElements).forEach(addButtonsToMessage);
                   }
               });
           });
       });

       observer.observe(document.body, {
           childList: true,
           subtree: true
       });
   }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址