自动连接LLM API和AllTalkTTS API
当前为
// ==UserScript==
// @name SillyTavern Auto Connect
// @namespace http://tampermonkey.net/
// @version 1.4
// @description 自动连接LLM API和AllTalkTTS API
// @match *://127.0.0.1:8000/*
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// ==/UserScript==
if (
window.location.href !== 'http://127.0.0.1:8000/' &&
!window.location.href.startsWith('http://127.0.0.1:8000/#')
) {
console.log('非目标页面,脚本终止');
return;
}
(function() {
'use strict';
// 配置中心
const CONFIG = {
buttons: [
{
selector: '#api_button_textgenerationwebui',
name: 'API连接',
status: {
element: '.online_status_indicator',
successCondition: el => el.classList.contains('success')
}
},
{
selector: '#tts_refresh',
name: 'TTS刷新',
status: {
element: '.at-settings-option.status-option #status_info',
successCondition: el => el.innerText.trim() === 'Ready'
}
}
],
timing: {
interval: 1000, // 检测间隔(ms),改为1.5秒加快检查速度
retryLimit: 30 // 最大尝试次数
}
};
// 获取界面显示设置,默认为显示(true)
let showInterface = GM_getValue('showInterface', true);
// 注册(不可用)Tampermonkey菜单命令
function registerMenuCommands() {
GM_registerMenuCommand(`${showInterface ? '✓ 已启用' : '✗ 已禁用'} 界面显示`, () => {
showInterface = !showInterface;
GM_setValue('showInterface', showInterface);
// 如果面板已创建,则更新其显示状态
if (statusPanel) {
statusPanel.style.display = showInterface ? 'block' : 'none';
}
// 刷新菜单
registerMenuCommands();
});
}
// 初始注册(不可用)菜单
registerMenuCommands();
// 创建增强状态面板
const statusPanel = createStatusPanel();
let isRunning = true;
// 状态面板模板
function createStatusPanel() {
const panel = document.createElement('div');
panel.style = `
position: fixed;
top: 20px;
right: 20px;
background: rgba(0,0,0,0.85);
color: white;
padding: 15px;
border-radius: 8px;
z-index: 99999;
font-family: Arial;
min-width: 220px;
backdrop-filter: blur(5px);
display: ${showInterface ? 'block' : 'none'};
`;
panel.innerHTML = `
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<h3 style="margin:0;color:#4CAF50;font-size:16px;">连接状态监控</h3>
<div>
<button id="stopConnectBtn" style="background:#ff4444;color:white;border:none;border-radius:4px;padding:3px 8px;cursor:pointer;font-size:12px;">停止</button>
</div>
</div>
<div id="statusContent" style="line-height:1.6;font-size:14px;"></div>
`;
document.body.appendChild(panel);
// 添加停止按钮事件监听
panel.querySelector('#stopConnectBtn').addEventListener('click', () => {
isRunning = false;
const statusContent = panel.querySelector('#statusContent');
statusContent.innerHTML += `
<div style="color:#ff9800;margin-top:10px;border-top:1px solid #333;padding-top:8px;">
已手动停止连接尝试
</div>
`;
// 3秒后关闭面板
setTimeout(() => {
statusPanel.remove();
}, 3000);
});
return panel;
}
// 状态检测器
function checkConnectionStatus(buttonConfig) {
const statusElement = document.querySelector(buttonConfig.status.element);
if (!statusElement) return false;
return buttonConfig.status.successCondition(statusElement);
}
// 增强点击方法
async function performEnhancedClick(selector) {
const btn = document.querySelector(selector);
if (!btn) return false;
// 使用更温和的方式触发点击,避免干扰用户操作
try {
// 直接调用按钮的原生click方法,而不是分发多个鼠标事件
btn.click();
await new Promise(resolve => setTimeout(resolve, 1000));
return true;
} catch (error) {
console.error(`点击按钮 ${selector} 时出错:`, error);
return false;
}
}
// 更新状态显示
function updateStatusDisplay(attempts) {
const statusContent = statusPanel.querySelector('#statusContent');
let html = CONFIG.buttons.map(btn => {
const isConnected = checkConnectionStatus(btn);
return `
<div style="margin-bottom:8px;">
<span style="color:${isConnected ? '#4CAF50' : '#ff4444'}">${isConnected ? '✓' : '✗'}</span>
${btn.name}:
<span style="color:${isConnected ? '#4CAF50' : '#ff4444'}">
${isConnected ? '已连接' : '未连接'}
</span>
</div>
`;
}).join('');
html += `
<div style="border-top:1px solid #333;padding-top:8px;margin-top:8px;">
尝试次数:${attempts}/${CONFIG.timing.retryLimit}<br>
下次检测:${new Date(Date.now() + CONFIG.timing.interval).toLocaleTimeString()}
</div>
`;
statusContent.innerHTML = html;
}
// 主控制器
async function controlLoop() {
let attempts = 0;
// 先检查是否已全部连接
let initialCheck = true;
let allConnected = true;
const connectionStatus = {};
// 检查每个按钮的连接状态
for (const btn of CONFIG.buttons) {
const isConnected = checkConnectionStatus(btn);
connectionStatus[btn.selector] = isConnected;
if (!isConnected) allConnected = false;
}
// 如果已全部连接,直接显示成功并3秒后关闭
if (allConnected) {
updateStatusDisplay(0);
const statusContent = statusPanel.querySelector('#statusContent');
statusContent.innerHTML += `
<div style="color:#4CAF50;margin-top:10px;border-top:1px solid #333;padding-top:8px;">
所有连接已成功!无需重连
</div>
`;
setTimeout(() => {
statusPanel.remove();
}, 3000);
return;
}
// 如果有未连接的,开始重连流程
const timer = setInterval(async () => {
if (!isRunning) {
clearInterval(timer);
return;
}
attempts++;
allConnected = true;
// 只对未连接的按钮进行点击操作
for (const btn of CONFIG.buttons) {
const isConnected = checkConnectionStatus(btn);
connectionStatus[btn.selector] = isConnected;
if (!isConnected) {
// 只点击未连接的按钮
const clicked = await performEnhancedClick(btn.selector);
if (!clicked) console.warn(`找不到按钮:${btn.name}`);
allConnected = false;
}
}
updateStatusDisplay(attempts);
if (allConnected || attempts >= CONFIG.timing.retryLimit) {
clearInterval(timer);
isRunning = false;
const statusContent = statusPanel.querySelector('#statusContent');
statusContent.innerHTML += `
<div style="color:#${allConnected ? '4CAF50' : 'ff4444'};margin-top:10px;border-top:1px solid #333;padding-top:8px;">
${allConnected ? '所有连接已成功!' : '达到最大尝试次数'}
</div>
`;
// 添加3秒后移除面板逻辑
if (allConnected) {
setTimeout(() => {
statusPanel.remove();
}, 3000);
}
}
}, CONFIG.timing.interval);
}
// 启动系统
window.addEventListener('load', () => {
setTimeout(controlLoop, 2000); // 等待页面初始化
});
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址