VWED_server/tests/test.py

320 lines
11 KiB
Python
Raw Normal View History

2025-09-20 16:50:45 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
2025-09-25 10:52:52 +08:00
WebSocket 脚本日志订阅测试
用于监控 VWED 脚本日志推送
2025-09-20 16:50:45 +08:00
"""
2025-07-14 10:29:37 +08:00
2025-09-25 10:52:52 +08:00
import asyncio
2025-09-20 16:50:45 +08:00
import json
2025-07-14 10:29:37 +08:00
from datetime import datetime
2025-09-25 10:52:52 +08:00
import signal
import sys
2025-07-14 10:29:37 +08:00
2025-09-25 10:52:52 +08:00
try:
import websockets
except ImportError:
print("❌ 缺少 websockets 依赖,请运行: pip install websockets")
sys.exit(1)
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
class VWEDWebSocketLogMonitor:
"""VWED WebSocket 日志监控器"""
def __init__(self, host="localhost", port=8000, client_id="monitor_test", client_type="monitor"):
2025-09-20 16:50:45 +08:00
self.host = host
self.port = port
2025-09-25 10:52:52 +08:00
self.client_id = client_id
self.client_type = client_type
self.websocket = None
self.running = False
self.subscribed_scripts = set()
async def connect(self):
"""连接到 WebSocket 服务器"""
uri = f"ws://{self.host}:{self.port}/api/script/ws/script-logs?client_id={self.client_id}&client_type={self.client_type}"
2025-07-14 10:29:37 +08:00
try:
2025-09-25 10:52:52 +08:00
print(f"正在连接到 WebSocket 服务器: {uri}")
self.websocket = await websockets.connect(uri)
self.running = True
print(f"✅ WebSocket 连接成功建立")
return True
2025-09-20 16:50:45 +08:00
except Exception as e:
2025-09-25 10:52:52 +08:00
print(f"❌ WebSocket 连接失败: {e}")
return False
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
async def disconnect(self):
"""断开连接"""
self.running = False
if self.websocket:
await self.websocket.close()
print("🔌 WebSocket 连接已断开")
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
async def subscribe_script(self, script_id):
"""订阅脚本日志"""
if not self.websocket:
print("WebSocket 未连接")
return False
2025-07-14 10:29:37 +08:00
try:
2025-09-25 10:52:52 +08:00
message = {
"type": "subscribe",
"script_id": script_id
}
await self.websocket.send(json.dumps(message))
self.subscribed_scripts.add(script_id)
print(f"📡 已发送订阅请求: {script_id}")
2025-09-20 16:50:45 +08:00
return True
except Exception as e:
2025-09-25 10:52:52 +08:00
print(f"订阅脚本失败: {e}")
2025-09-20 16:50:45 +08:00
return False
2025-07-14 10:29:37 +08:00
2025-09-25 10:52:52 +08:00
async def unsubscribe_script(self, script_id):
"""取消订阅脚本日志"""
if not self.websocket:
print("WebSocket 未连接")
return False
try:
message = {
"type": "unsubscribe",
"script_id": script_id
}
await self.websocket.send(json.dumps(message))
self.subscribed_scripts.discard(script_id)
print(f" 已发送取消订阅请求: {script_id}")
return True
except Exception as e:
print(f"取消订阅脚本失败: {e}")
return False
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
async def get_status(self):
"""获取连接状态"""
if not self.websocket:
print("WebSocket 未连接")
return False
2025-09-20 16:50:45 +08:00
try:
2025-09-25 10:52:52 +08:00
message = {"type": "get_status"}
await self.websocket.send(json.dumps(message))
print("已发送状态查询请求")
return True
2025-09-20 16:50:45 +08:00
except Exception as e:
2025-09-25 10:52:52 +08:00
print(f"获取状态失败: {e}")
2025-09-20 16:50:45 +08:00
return False
2025-07-14 10:29:37 +08:00
2025-09-25 10:52:52 +08:00
async def send_ping(self):
"""发送心跳"""
if not self.websocket:
return False
2025-09-20 16:50:45 +08:00
try:
2025-09-25 10:52:52 +08:00
message = {
"type": "ping",
"timestamp": datetime.now().isoformat()
}
await self.websocket.send(json.dumps(message))
return True
2025-09-20 16:50:45 +08:00
except Exception as e:
2025-09-25 10:52:52 +08:00
print(f"❌ 发送心跳失败: {e}")
2025-09-20 16:50:45 +08:00
return False
2025-07-14 10:29:37 +08:00
2025-09-25 10:52:52 +08:00
def format_message(self, message):
"""格式化消息显示"""
msg_type = message.get("type", "unknown")
timestamp = datetime.now().strftime("%H:%M:%S")
if msg_type == "welcome":
return f"🎉 [{timestamp}] 欢迎消息: {message.get('message')} (连接ID: {message.get('connection_id')})"
elif msg_type == "script_log":
script_id = message.get("script_id", "unknown")
level = message.get("level", "INFO")
log_msg = message.get("message", "")
# 根据日志级别选择emoji
level_emoji = {
"INFO": "",
"WARNING": "⚠️",
"ERROR": "",
"DEBUG": "🐛"
}
emoji = level_emoji.get(level, "📝")
return f"{emoji} [{timestamp}] [{script_id}] {level}: {log_msg}"
elif msg_type == "script_status":
script_id = message.get("script_id", "unknown")
status = message.get("status", "unknown")
status_msg = message.get("message", "")
return f"🔄 [{timestamp}] [{script_id}] 状态变更: {status} - {status_msg}"
elif msg_type == "function_execution":
script_id = message.get("script_id", "unknown")
func_name = message.get("function_name", "unknown")
result = message.get("result", {})
return f"⚡ [{timestamp}] [{script_id}] 函数执行: {func_name} -> {json.dumps(result, ensure_ascii=False)}"
elif msg_type == "subscription_success":
return f"✅ [{timestamp}] 订阅成功: {message.get('message')}"
elif msg_type == "unsubscription_success":
return f"✅ [{timestamp}] 取消订阅成功: {message.get('message')}"
elif msg_type == "status":
data = message.get("data", {})
total_connections = data.get("total_connections", 0)
total_scripts = data.get("total_script_subscriptions", 0)
return f"📊 [{timestamp}] 连接状态: {total_connections} 个连接, {total_scripts} 个脚本订阅"
elif msg_type == "error":
return f"❌ [{timestamp}] 错误: {message.get('message')}"
elif msg_type == "pong":
return f"💓 [{timestamp}] 心跳响应"
else:
return f"❓ [{timestamp}] 未知消息类型 {msg_type}: {json.dumps(message, ensure_ascii=False)}"
async def listen_messages(self):
"""监听消息"""
if not self.websocket:
print("❌ WebSocket 未连接")
return
try:
while self.running:
try:
# 等待消息,设置超时避免无限阻塞
message = await asyncio.wait_for(
self.websocket.recv(),
timeout=1.0
)
try:
data = json.loads(message)
formatted_msg = self.format_message(data)
print(formatted_msg)
except json.JSONDecodeError:
print(f"❌ JSON 解析失败: {message}")
except asyncio.TimeoutError:
# 超时是正常的,继续循环
continue
except websockets.exceptions.ConnectionClosed:
print("🔌 WebSocket 连接已关闭")
break
except Exception as e:
print(f"❌ 接收消息异常: {e}")
break
except Exception as e:
print(f"❌ 监听消息异常: {e}")
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
async def interactive_monitor(self):
"""交互式监控"""
print("\n" + "="*50)
print("VWED WebSocket 脚本日志监控器")
print("="*50)
print("可用命令:")
print(" sub <script_id> - 订阅脚本日志")
print(" unsub <script_id> - 取消订阅脚本日志")
print(" status - 获取连接状态")
print(" ping - 发送心跳")
print(" list - 显示已订阅的脚本")
print(" quit - 退出监控")
print("="*50)
# 启动消息监听任务
listen_task = asyncio.create_task(self.listen_messages())
try:
while self.running:
try:
# 等待用户输入
user_input = await asyncio.get_event_loop().run_in_executor(
None, input, "请输入命令 (sub/unsub/status/ping/list/quit): "
)
command_parts = user_input.strip().split()
if not command_parts:
continue
command = command_parts[0].lower()
if command == "quit":
print("👋 退出监控...")
break
elif command == "sub" and len(command_parts) > 1:
script_id = command_parts[1]
await self.subscribe_script(script_id)
elif command == "unsub" and len(command_parts) > 1:
script_id = command_parts[1]
await self.unsubscribe_script(script_id)
elif command == "status":
await self.get_status()
elif command == "ping":
await self.send_ping()
elif command == "list":
if self.subscribed_scripts:
print(f"📋 已订阅的脚本: {', '.join(self.subscribed_scripts)}")
else:
print("📋 当前没有订阅任何脚本")
else:
print("❌ 未知命令或参数不足")
except KeyboardInterrupt:
print("\n👋 收到退出信号...")
break
except Exception as e:
print(f"❌ 处理命令异常: {e}")
finally:
self.running = False
listen_task.cancel()
try:
await listen_task
except asyncio.CancelledError:
pass
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
async def main():
"""主函数"""
monitor = VWEDWebSocketLogMonitor()
# 设置信号处理
def signal_handler(signum, _):
print(f"\n👋 收到信号 {signum},正在退出...")
monitor.running = False
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
# 连接 WebSocket
if await monitor.connect():
# 开始交互式监控
await monitor.interactive_monitor()
else:
print("❌ 无法连接到 WebSocket 服务器")
return 1
except Exception as e:
print(f"❌ 监控异常: {e}")
return 1
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
finally:
# 清理连接
await monitor.disconnect()
2025-09-20 16:50:45 +08:00
2025-09-25 10:52:52 +08:00
return 0
2025-07-14 10:29:37 +08:00
2025-04-30 16:57:46 +08:00
2025-07-14 10:29:37 +08:00
if __name__ == "__main__":
2025-09-25 10:52:52 +08:00
try:
exit_code = asyncio.run(main())
sys.exit(exit_code)
except KeyboardInterrupt:
print("\n👋 程序已退出")
sys.exit(0)