feat: 添加状态监控插件和Redis原子操作支持
- 新增 `/status` 指令,展示机器人运行状态和系统指标 - 实现Redis Lua脚本支持原子化计数器操作 - 添加消息收发统计功能 - 完善文档,包括插件开发和性能优化指南 - 重构WebSocket连接池,增加健康检查机制 - 移除旧版编译脚本,优化项目结构
This commit is contained in:
@@ -5,11 +5,35 @@
|
||||
状态设置等相关的 OneBot v11 API 封装。
|
||||
"""
|
||||
import orjson
|
||||
from typing import Dict, Any
|
||||
from typing import Dict, Any, Type, TypeVar
|
||||
from dataclasses import is_dataclass, fields
|
||||
from .base import BaseAPI
|
||||
from models.objects import LoginInfo, VersionInfo, Status
|
||||
from ..managers.redis_manager import redis_manager
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
def _safe_dataclass_from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
|
||||
"""
|
||||
安全地从字典创建 dataclass 实例,忽略多余的键。
|
||||
"""
|
||||
if not data:
|
||||
try:
|
||||
return cls()
|
||||
except TypeError:
|
||||
raise ValueError(f"无法在没有数据的情况下创建 {cls.__name__} 的实例")
|
||||
|
||||
# 使用官方的 is_dataclass 进行检查,对 MyPyC 更友好
|
||||
if not is_dataclass(cls):
|
||||
raise TypeError(f"{cls.__name__} 不是一个 dataclass")
|
||||
|
||||
# 获取 dataclass 的所有字段名
|
||||
known_fields = {f.name for f in fields(cls)}
|
||||
|
||||
# 过滤出 dataclass 认识的键值对
|
||||
filtered_data = {k: v for k, v in data.items() if k in known_fields}
|
||||
|
||||
return cls(**filtered_data)
|
||||
|
||||
class AccountAPI(BaseAPI):
|
||||
"""
|
||||
@@ -30,11 +54,11 @@ class AccountAPI(BaseAPI):
|
||||
if not no_cache:
|
||||
cached_data = await redis_manager.get(cache_key)
|
||||
if cached_data:
|
||||
return LoginInfo(**orjson.loads(cached_data))
|
||||
return _safe_dataclass_from_dict(LoginInfo, orjson.loads(cached_data))
|
||||
|
||||
res = await self.call_api("get_login_info")
|
||||
await redis_manager.set(cache_key, orjson.dumps(res), ex=3600) # 缓存 1 小时
|
||||
return LoginInfo(**res)
|
||||
return _safe_dataclass_from_dict(LoginInfo, res)
|
||||
|
||||
async def get_version_info(self) -> VersionInfo:
|
||||
"""
|
||||
@@ -43,8 +67,8 @@ class AccountAPI(BaseAPI):
|
||||
Returns:
|
||||
VersionInfo: 包含 OneBot 实现版本信息的 `VersionInfo` 数据对象。
|
||||
"""
|
||||
res = await self.call_api("get_friend_list")
|
||||
return VersionInfo(**res)
|
||||
res = await self.call_api("get_version_info")
|
||||
return _safe_dataclass_from_dict(VersionInfo, res)
|
||||
|
||||
async def get_status(self) -> Status:
|
||||
"""
|
||||
@@ -54,7 +78,7 @@ class AccountAPI(BaseAPI):
|
||||
Status: 包含 OneBot 状态信息的 `Status` 数据对象。
|
||||
"""
|
||||
res = await self.call_api("get_status")
|
||||
return Status(**res)
|
||||
return _safe_dataclass_from_dict(Status, res)
|
||||
|
||||
async def bot_exit(self) -> Dict[str, Any]:
|
||||
"""
|
||||
@@ -162,56 +186,25 @@ class AccountAPI(BaseAPI):
|
||||
"""
|
||||
return await self.call_api("clean_cache")
|
||||
|
||||
async def get_stranger_info(self, user_id: int, no_cache: bool = False) -> Any:
|
||||
async def get_profile_like(self) -> Dict[str, Any]:
|
||||
"""
|
||||
获取陌生人信息。
|
||||
获取个人资料的点赞信息。
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: OneBot API 的响应数据。
|
||||
"""
|
||||
return await self.call_api("get_profile_like")
|
||||
|
||||
async def nc_get_user_status(self, user_id: int) -> Dict[str, Any]:
|
||||
"""
|
||||
获取用户的在线状态 (NapCat 特有 API)。
|
||||
|
||||
Args:
|
||||
user_id (int): 目标用户的 QQ 号。
|
||||
no_cache (bool, optional): 是否不使用缓存。Defaults to False.
|
||||
|
||||
Returns:
|
||||
Any: 包含陌生人信息的字典或对象。
|
||||
Dict[str, Any]: OneBot API 的响应数据。
|
||||
"""
|
||||
return await self.call_api("get_stranger_info", {"user_id": user_id, "no_cache": no_cache})
|
||||
return await self.call_api("nc_get_user_status", {"user_id": user_id})
|
||||
|
||||
async def get_friend_list(self, no_cache: bool = False) -> list:
|
||||
"""
|
||||
获取好友列表。
|
||||
|
||||
Args:
|
||||
no_cache (bool, optional): 是否不使用缓存。Defaults to False.
|
||||
|
||||
Returns:
|
||||
list: 好友列表。
|
||||
"""
|
||||
cache_key = f"neobot:cache:get_friend_list:{self.self_id}"
|
||||
if not no_cache:
|
||||
cached_data = await redis_manager.get(cache_key)
|
||||
if cached_data:
|
||||
return orjson.loads(cached_data)
|
||||
|
||||
res = await self.call_api("get_friend_list")
|
||||
await redis_manager.set(cache_key, orjson.dumps(res), ex=3600) # 缓存 1 小时
|
||||
return res
|
||||
|
||||
async def get_group_list(self, no_cache: bool = False) -> list:
|
||||
"""
|
||||
获取群列表。
|
||||
|
||||
Args:
|
||||
no_cache (bool, optional): 是否不使用缓存。Defaults to False.
|
||||
|
||||
Returns:
|
||||
list: 群列表。
|
||||
"""
|
||||
cache_key = f"neobot:cache:get_group_list:{self.self_id}"
|
||||
if not no_cache:
|
||||
cached_data = await redis_manager.get(cache_key)
|
||||
if cached_data:
|
||||
return orjson.loads(cached_data)
|
||||
|
||||
res = await self.call_api("get_group_list")
|
||||
await redis_manager.set(cache_key, orjson.dumps(res), ex=3600) # 缓存 1 小时
|
||||
return res
|
||||
|
||||
|
||||
Reference in New Issue
Block a user