Sync between Sexy.AI and SillyTavern

banquyy

目前为 2024-11-20 提交的版本。查看 最新版本

// ==UserScript==
// @name         Sync between Sexy.AI and SillyTavern
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  banquyy
// @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) {
           const messageText = node.querySelector('.mes_text');
           if (!messageText) return;

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

           if (hasImagePrompt && !messageText.querySelector('.button-container')) {
               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);

                       // Remove image###prompt### from message
                       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);
           }
       }

       document.querySelectorAll('.mes').forEach(addButtonsToMessage);

       const observer = new MutationObserver((mutations) => {
           mutations.forEach((mutation) => {
               mutation.addedNodes.forEach((node) => {
                   if (node.classList?.contains('mes')) {
                       addButtonsToMessage(node);
                   }
               });
           });
       });

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

QingJ © 2025

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