""" 脚本管理模块 管理 Tavern Helper 的脚本,支持三种作用域: - GLOBAL: 全局脚本,对所有聊天可用 - CHARACTER: 角色脚本,绑定到当前角色卡 - PRESET: 预设脚本,绑定到当前预设 每个脚本包含: - 脚本名称 - 脚本内容(JavaScript 代码) - 作者备注 - 变量列表(绑定到脚本的变量) - 按钮配置(配合 getButtonEvent 使用) - 启用状态 """ from enum import Enum from typing import List, Optional, Dict, Any from pydantic import BaseModel, Field from datetime import datetime import uuid class ScriptScope(str, Enum): """脚本作用域""" GLOBAL = 'global' # 全局脚本 CHARACTER = 'character' # 角色脚本 PRESET = 'preset' # 预设脚本 class ScriptVariable(BaseModel): """脚本变量""" name: str = Field(..., description="变量名") value: Any = Field(..., description="变量值") description: Optional[str] = Field(None, description="变量描述") class ScriptButton(BaseModel): """脚本按钮配置""" label: str = Field(..., description="按钮显示文本") event: str = Field(..., description="按钮事件名称(配合 getButtonEvent 使用)") enabled: bool = Field(True, description="是否启用") class ScriptItem(BaseModel): """脚本项""" id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="脚本唯一标识符") name: str = Field(..., description="脚本名称") content: str = Field(..., description="脚本内容(JavaScript 代码)") authorNote: Optional[str] = Field(None, description="作者备注") # 变量列表 variables: List[ScriptVariable] = Field(default_factory=list, description="绑定到脚本的变量") # 按钮配置 buttons: List[ScriptButton] = Field(default_factory=list, description="按钮配置") # 作用域 scope: ScriptScope = Field(ScriptScope.GLOBAL, description="脚本作用域") characterName: Optional[str] = Field(None, description="绑定的角色卡名称") presetName: Optional[str] = Field(None, description="绑定的预设名称") # 启用状态 enabled: bool = Field(True, description="是否启用") # 元数据 createdAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="创建时间戳") updatedAt: int = Field(default_factory=lambda: int(datetime.now().timestamp()), description="更新时间戳") order: int = Field(0, description="执行顺序") class ScriptManager: """脚本管理器""" def __init__(self): self.scripts: List[ScriptItem] = [] def add_script(self, script: ScriptItem): """添加脚本""" self.scripts.append(script) def remove_script(self, script_id: str) -> bool: """删除脚本""" for i, script in enumerate(self.scripts): if script.id == script_id: self.scripts.pop(i) return True return False def update_script(self, script_id: str, updates: Dict[str, Any]) -> bool: """更新脚本""" for script in self.scripts: if script.id == script_id: for key, value in updates.items(): if hasattr(script, key): setattr(script, key, value) script.updatedAt = int(datetime.now().timestamp()) return True return False def get_scripts_by_scope(self, scope: ScriptScope, filter_name: Optional[str] = None) -> List[ScriptItem]: """按作用域获取脚本""" scripts = [s for s in self.scripts if s.scope == scope] if filter_name: scripts = [s for s in scripts if filter_name.lower() in s.name.lower()] return sorted(scripts, key=lambda s: s.order) def get_enabled_scripts(self, scope: ScriptScope) -> List[ScriptItem]: """获取启用的脚本""" return [s for s in self.scripts if s.scope == scope and s.enabled] def get_script(self, script_id: str) -> Optional[ScriptItem]: """获取单个脚本""" for script in self.scripts: if script.id == script_id: return script return None def toggle_script(self, script_id: str) -> bool: """切换脚本启用状态""" for script in self.scripts: if script.id == script_id: script.enabled = not script.enabled script.updatedAt = int(datetime.now().timestamp()) return True return False def get_all_scripts(self) -> List[ScriptItem]: """获取所有脚本""" return self.scripts def export_scripts(self, scope: Optional[ScriptScope] = None) -> List[Dict]: """导出脚本""" if scope: scripts = [s for s in self.scripts if s.scope == scope] else: scripts = self.scripts return [s.dict() for s in scripts] def import_scripts(self, scripts_data: List[Dict], scope: ScriptScope) -> int: """导入脚本""" count = 0 for data in scripts_data: try: script = ScriptItem(**data) script.scope = scope self.scripts.append(script) count += 1 except Exception as e: print(f"导入脚本失败: {e}") return count # 全局脚本管理器实例 script_manager = ScriptManager() if __name__ == '__main__': import json # 测试脚本管理 manager = ScriptManager() # 添加测试脚本 script1 = ScriptItem( name="【骰子系统】-自动更新", content="async function getLatestVersion() {\n try {\n const response = await fetch('/api/version');\n return await response.json();\n } catch (e) {\n return null;\n }\n}", authorNote="感谢a佬开源\n以九颜二改为基础进行三改\n@kousakayou", scope=ScriptScope.GLOBAL, variables=[ ScriptVariable(name="version", value="4.8.4", description="版本号") ], buttons=[ ScriptButton(label="检查更新", event="checkUpdate", enabled=True) ] ) manager.add_script(script1) # 导出测试 print("=== 导出脚本 ===") exported = manager.export_scripts() print(json.dumps(exported, indent=2, ensure_ascii=False)) print("\n✅ 脚本管理测试完成!")