Daily build
This commit is contained in:
13
core/api/__init__.py
Normal file
13
core/api/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from .base import BaseAPI
|
||||
from .message import MessageAPI
|
||||
from .group import GroupAPI
|
||||
from .friend import FriendAPI
|
||||
from .account import AccountAPI
|
||||
|
||||
__all__ = [
|
||||
"BaseAPI",
|
||||
"MessageAPI",
|
||||
"GroupAPI",
|
||||
"FriendAPI",
|
||||
"AccountAPI",
|
||||
]
|
||||
124
core/api/account.py
Normal file
124
core/api/account.py
Normal file
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
账号相关 API 模块
|
||||
"""
|
||||
from typing import Dict, Any
|
||||
from .base import BaseAPI
|
||||
from models.objects import LoginInfo, VersionInfo, Status
|
||||
|
||||
|
||||
class AccountAPI(BaseAPI):
|
||||
"""
|
||||
账号相关 API Mixin
|
||||
"""
|
||||
|
||||
async def get_login_info(self) -> LoginInfo:
|
||||
"""
|
||||
获取登录号信息
|
||||
|
||||
:return: 登录信息对象
|
||||
"""
|
||||
res = await self.call_api("get_login_info")
|
||||
return LoginInfo(**res)
|
||||
|
||||
async def get_version_info(self) -> VersionInfo:
|
||||
"""
|
||||
获取版本信息
|
||||
|
||||
:return: 版本信息对象
|
||||
"""
|
||||
res = await self.call_api("get_version_info")
|
||||
return VersionInfo(**res)
|
||||
|
||||
async def get_status(self) -> Status:
|
||||
"""
|
||||
获取状态
|
||||
|
||||
:return: 状态对象
|
||||
"""
|
||||
res = await self.call_api("get_status")
|
||||
return Status(**res)
|
||||
|
||||
async def bot_exit(self) -> Dict[str, Any]:
|
||||
"""
|
||||
退出机器人
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("bot_exit")
|
||||
|
||||
async def set_self_longnick(self, long_nick: str) -> Dict[str, Any]:
|
||||
"""
|
||||
设置个性签名
|
||||
|
||||
:param long_nick: 个性签名内容
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_self_longnick", {"longNick": long_nick})
|
||||
|
||||
async def set_input_status(self, user_id: int, event_type: int) -> Dict[str, Any]:
|
||||
"""
|
||||
设置输入状态
|
||||
|
||||
:param user_id: 用户 ID
|
||||
:param event_type: 事件类型
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_input_status", {"user_id": user_id, "event_type": event_type})
|
||||
|
||||
async def set_diy_online_status(self, face_id: int, face_type: int, wording: str) -> Dict[str, Any]:
|
||||
"""
|
||||
设置自定义在线状态
|
||||
|
||||
:param face_id: 状态 ID
|
||||
:param face_type: 状态类型
|
||||
:param wording: 状态描述
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_diy_online_status", {
|
||||
"face_id": face_id,
|
||||
"face_type": face_type,
|
||||
"wording": wording
|
||||
})
|
||||
|
||||
async def set_online_status(self, status_code: int) -> Dict[str, Any]:
|
||||
"""
|
||||
设置在线状态
|
||||
|
||||
:param status_code: 状态码
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_online_status", {"status_code": status_code})
|
||||
|
||||
async def set_qq_profile(self, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
设置 QQ 资料
|
||||
|
||||
:param kwargs: 个人资料相关参数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_qq_profile", kwargs)
|
||||
|
||||
async def set_qq_avatar(self, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
设置 QQ 头像
|
||||
|
||||
:param kwargs: 头像相关参数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_qq_avatar", kwargs)
|
||||
|
||||
async def get_clientkey(self) -> Dict[str, Any]:
|
||||
"""
|
||||
获取客户端密钥
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_clientkey")
|
||||
|
||||
async def clean_cache(self) -> Dict[str, Any]:
|
||||
"""
|
||||
清理缓存
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("clean_cache")
|
||||
24
core/api/base.py
Normal file
24
core/api/base.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
API 基础模块
|
||||
|
||||
定义了 API 调用的基础接口。
|
||||
"""
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
class BaseAPI(ABC):
|
||||
"""
|
||||
API 基础抽象类
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def call_api(self, action: str, params: Optional[Dict[str, Any]] = None) -> Any:
|
||||
"""
|
||||
调用 API
|
||||
|
||||
:param action: API 动作名称
|
||||
:param params: API 参数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
raise NotImplementedError
|
||||
53
core/api/friend.py
Normal file
53
core/api/friend.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
好友相关 API 模块
|
||||
"""
|
||||
from typing import List, Dict, Any
|
||||
from .base import BaseAPI
|
||||
from models.objects import FriendInfo, StrangerInfo
|
||||
|
||||
|
||||
class FriendAPI(BaseAPI):
|
||||
"""
|
||||
好友相关 API Mixin
|
||||
"""
|
||||
|
||||
async def send_like(self, user_id: int, times: int = 1) -> Dict[str, Any]:
|
||||
"""
|
||||
发送点赞
|
||||
|
||||
:param user_id: 对方 QQ 号
|
||||
:param times: 点赞次数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("send_like", {"user_id": user_id, "times": times})
|
||||
|
||||
async def get_stranger_info(self, user_id: int, no_cache: bool = False) -> StrangerInfo:
|
||||
"""
|
||||
获取陌生人信息
|
||||
|
||||
:param user_id: QQ 号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: 陌生人信息对象
|
||||
"""
|
||||
res = await self.call_api("get_stranger_info", {"user_id": user_id, "no_cache": no_cache})
|
||||
return StrangerInfo(**res)
|
||||
|
||||
async def get_friend_list(self) -> List[FriendInfo]:
|
||||
"""
|
||||
获取好友列表
|
||||
|
||||
:return: 好友信息对象列表
|
||||
"""
|
||||
res = await self.call_api("get_friend_list")
|
||||
return [FriendInfo(**item) for item in res]
|
||||
|
||||
async def set_friend_add_request(self, flag: str, approve: bool = True, remark: str = "") -> Dict[str, Any]:
|
||||
"""
|
||||
处理加好友请求
|
||||
|
||||
:param flag: 加好友请求的 flag(需从上报的数据中获取)
|
||||
:param approve: 是否同意请求
|
||||
:param remark: 添加后的好友备注(仅在同意时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_friend_add_request", {"flag": flag, "approve": approve, "remark": remark})
|
||||
190
core/api/group.py
Normal file
190
core/api/group.py
Normal file
@@ -0,0 +1,190 @@
|
||||
"""
|
||||
群组相关 API 模块
|
||||
"""
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .base import BaseAPI
|
||||
from models.objects import GroupInfo, GroupMemberInfo, GroupHonorInfo
|
||||
|
||||
|
||||
class GroupAPI(BaseAPI):
|
||||
"""
|
||||
群组相关 API Mixin
|
||||
"""
|
||||
|
||||
async def set_group_kick(self, group_id: int, user_id: int, reject_add_request: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
群组踢人
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要踢的 QQ 号
|
||||
:param reject_add_request: 拒绝此人的加群请求
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_kick", {"group_id": group_id, "user_id": user_id, "reject_add_request": reject_add_request})
|
||||
|
||||
async def set_group_ban(self, group_id: int, user_id: int, duration: int = 30 * 60) -> Dict[str, Any]:
|
||||
"""
|
||||
群组单人禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要禁言的 QQ 号
|
||||
:param duration: 禁言时长(秒),0 表示解除禁言
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_ban", {"group_id": group_id, "user_id": user_id, "duration": duration})
|
||||
|
||||
async def set_group_anonymous_ban(self, group_id: int, anonymous: Dict[str, Any] = None, duration: int = 30 * 60, flag: str = None) -> Dict[str, Any]:
|
||||
"""
|
||||
群组匿名禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param anonymous: 可选,要禁言的匿名用户对象(群消息事件的 anonymous 字段)
|
||||
:param duration: 禁言时长(秒)
|
||||
:param flag: 可选,要禁言的匿名用户的 flag(需从群消息事件的 anonymous 字段中获取)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
params = {"group_id": group_id, "duration": duration}
|
||||
if anonymous:
|
||||
params["anonymous"] = anonymous
|
||||
if flag:
|
||||
params["flag"] = flag
|
||||
return await self.call_api("set_group_anonymous_ban", params)
|
||||
|
||||
async def set_group_whole_ban(self, group_id: int, enable: bool = True) -> Dict[str, Any]:
|
||||
"""
|
||||
群组全员禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param enable: 是否开启
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_whole_ban", {"group_id": group_id, "enable": enable})
|
||||
|
||||
async def set_group_admin(self, group_id: int, user_id: int, enable: bool = True) -> Dict[str, Any]:
|
||||
"""
|
||||
群组设置管理员
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param enable: True 为设置,False 为取消
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_admin", {"group_id": group_id, "user_id": user_id, "enable": enable})
|
||||
|
||||
async def set_group_anonymous(self, group_id: int, enable: bool = True) -> Dict[str, Any]:
|
||||
"""
|
||||
群组匿名
|
||||
|
||||
:param group_id: 群号
|
||||
:param enable: 是否开启
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_anonymous", {"group_id": group_id, "enable": enable})
|
||||
|
||||
async def set_group_card(self, group_id: int, user_id: int, card: str = "") -> Dict[str, Any]:
|
||||
"""
|
||||
设置群名片(群备注)
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param card: 群名片内容,不填或空字符串表示删除群名片
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_card", {"group_id": group_id, "user_id": user_id, "card": card})
|
||||
|
||||
async def set_group_name(self, group_id: int, group_name: str) -> Dict[str, Any]:
|
||||
"""
|
||||
设置群名
|
||||
|
||||
:param group_id: 群号
|
||||
:param group_name: 新群名
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_name", {"group_id": group_id, "group_name": group_name})
|
||||
|
||||
async def set_group_leave(self, group_id: int, is_dismiss: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
退出群组
|
||||
|
||||
:param group_id: 群号
|
||||
:param is_dismiss: 是否解散,如果登录号是群主,则仅在此项为 True 时能够解散
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_leave", {"group_id": group_id, "is_dismiss": is_dismiss})
|
||||
|
||||
async def set_group_special_title(self, group_id: int, user_id: int, special_title: str = "", duration: int = -1) -> Dict[str, Any]:
|
||||
"""
|
||||
设置群组专属头衔
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param special_title: 专属头衔,不填或空字符串表示删除
|
||||
:param duration: 有效期(秒),-1 表示永久
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_special_title", {"group_id": group_id, "user_id": user_id, "special_title": special_title, "duration": duration})
|
||||
|
||||
async def get_group_info(self, group_id: int, no_cache: bool = False) -> GroupInfo:
|
||||
"""
|
||||
获取群信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: 群信息对象
|
||||
"""
|
||||
res = await self.call_api("get_group_info", {"group_id": group_id, "no_cache": no_cache})
|
||||
return GroupInfo(**res)
|
||||
|
||||
async def get_group_list(self) -> List[GroupInfo]:
|
||||
"""
|
||||
获取群列表
|
||||
|
||||
:return: 群信息对象列表
|
||||
"""
|
||||
res = await self.call_api("get_group_list")
|
||||
return [GroupInfo(**item) for item in res]
|
||||
|
||||
async def get_group_member_info(self, group_id: int, user_id: int, no_cache: bool = False) -> GroupMemberInfo:
|
||||
"""
|
||||
获取群成员信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: QQ 号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: 群成员信息对象
|
||||
"""
|
||||
res = await self.call_api("get_group_member_info", {"group_id": group_id, "user_id": user_id, "no_cache": no_cache})
|
||||
return GroupMemberInfo(**res)
|
||||
|
||||
async def get_group_member_list(self, group_id: int) -> List[GroupMemberInfo]:
|
||||
"""
|
||||
获取群成员列表
|
||||
|
||||
:param group_id: 群号
|
||||
:return: 群成员信息对象列表
|
||||
"""
|
||||
res = await self.call_api("get_group_member_list", {"group_id": group_id})
|
||||
return [GroupMemberInfo(**item) for item in res]
|
||||
|
||||
async def get_group_honor_info(self, group_id: int, type: str) -> GroupHonorInfo:
|
||||
"""
|
||||
获取群荣誉信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param type: 要获取的群荣誉类型,可传入 talkative, performer, legend, strong_newbie, emotion 等
|
||||
:return: 群荣誉信息对象
|
||||
"""
|
||||
res = await self.call_api("get_group_honor_info", {"group_id": group_id, "type": type})
|
||||
return GroupHonorInfo(**res)
|
||||
|
||||
async def set_group_add_request(self, flag: str, sub_type: str, approve: bool = True, reason: str = "") -> Dict[str, Any]:
|
||||
"""
|
||||
处理加群请求/邀请
|
||||
|
||||
:param flag: 加群请求的 flag(需从上报的数据中获取)
|
||||
:param sub_type: add 或 invite,请求类型(需要与上报消息中的 sub_type 字段相符)
|
||||
:param approve: 是否同意请求/邀请
|
||||
:param reason: 拒绝理由(仅在拒绝时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_add_request", {"flag": flag, "sub_type": sub_type, "approve": approve, "reason": reason})
|
||||
141
core/api/message.py
Normal file
141
core/api/message.py
Normal file
@@ -0,0 +1,141 @@
|
||||
"""
|
||||
消息相关 API 模块
|
||||
"""
|
||||
from typing import Union, List, Dict, Any, TYPE_CHECKING
|
||||
from .base import BaseAPI
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import MessageSegment, OneBotEvent
|
||||
|
||||
|
||||
class MessageAPI(BaseAPI):
|
||||
"""
|
||||
消息相关 API Mixin
|
||||
"""
|
||||
|
||||
async def send_group_msg(self, group_id: int, message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
发送群消息
|
||||
|
||||
:param group_id: 群号
|
||||
:param message: 消息内容,可以是字符串、MessageSegment 对象或 MessageSegment 列表
|
||||
:param auto_escape: 是否自动转义(仅当 message 为字符串时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api(
|
||||
"send_group_msg", {"group_id": group_id, "message": self._process_message(message), "auto_escape": auto_escape}
|
||||
)
|
||||
|
||||
async def send_private_msg(self, user_id: int, message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
发送私聊消息
|
||||
|
||||
:param user_id: 用户 QQ 号
|
||||
:param message: 消息内容,可以是字符串、MessageSegment 对象或 MessageSegment 列表
|
||||
:param auto_escape: 是否自动转义(仅当 message 为字符串时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api(
|
||||
"send_private_msg", {"user_id": user_id, "message": self._process_message(message), "auto_escape": auto_escape}
|
||||
)
|
||||
|
||||
async def send(self, event: "OneBotEvent", message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
智能发送消息,根据事件类型自动选择发送方式
|
||||
|
||||
:param event: 触发事件对象
|
||||
:param message: 消息内容
|
||||
:param auto_escape: 是否自动转义
|
||||
:return: API 响应结果
|
||||
"""
|
||||
# 如果是消息事件,直接调用 reply
|
||||
if hasattr(event, "reply"):
|
||||
await event.reply(message, auto_escape)
|
||||
return {"status": "ok", "msg": "Replied via event.reply()"}
|
||||
|
||||
# 尝试从事件中获取 user_id 或 group_id
|
||||
user_id = getattr(event, "user_id", None)
|
||||
group_id = getattr(event, "group_id", None)
|
||||
|
||||
if group_id:
|
||||
return await self.send_group_msg(group_id, message, auto_escape)
|
||||
elif user_id:
|
||||
return await self.send_private_msg(user_id, message, auto_escape)
|
||||
|
||||
return {"status": "failed", "msg": "Unknown message target"}
|
||||
|
||||
async def delete_msg(self, message_id: int) -> Dict[str, Any]:
|
||||
"""
|
||||
撤回消息
|
||||
|
||||
:param message_id: 消息 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("delete_msg", {"message_id": message_id})
|
||||
|
||||
async def get_msg(self, message_id: int) -> Dict[str, Any]:
|
||||
"""
|
||||
获取消息
|
||||
|
||||
:param message_id: 消息 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_msg", {"message_id": message_id})
|
||||
|
||||
async def get_forward_msg(self, id: str) -> Dict[str, Any]:
|
||||
"""
|
||||
获取合并转发消息
|
||||
|
||||
:param id: 合并转发 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_forward_msg", {"id": id})
|
||||
|
||||
async def can_send_image(self) -> Dict[str, Any]:
|
||||
"""
|
||||
检查是否可以发送图片
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("can_send_image")
|
||||
|
||||
async def can_send_record(self) -> Dict[str, Any]:
|
||||
"""
|
||||
检查是否可以发送语音
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("can_send_record")
|
||||
|
||||
def _process_message(self, message: Union[str, "MessageSegment", List["MessageSegment"]]) -> Union[str, List[Dict[str, Any]]]:
|
||||
"""
|
||||
处理消息内容,将其转换为 API 可接受的格式
|
||||
|
||||
:param message: 原始消息内容
|
||||
:return: 处理后的消息内容
|
||||
"""
|
||||
if isinstance(message, str):
|
||||
return message
|
||||
|
||||
# 避免循环导入,在运行时导入
|
||||
from models import MessageSegment
|
||||
|
||||
if isinstance(message, MessageSegment):
|
||||
return [self._segment_to_dict(message)]
|
||||
|
||||
if isinstance(message, list):
|
||||
return [self._segment_to_dict(m) for m in message if isinstance(m, MessageSegment)]
|
||||
|
||||
return str(message)
|
||||
|
||||
def _segment_to_dict(self, segment: "MessageSegment") -> Dict[str, Any]:
|
||||
"""
|
||||
将 MessageSegment 对象转换为字典
|
||||
|
||||
:param segment: MessageSegment 对象
|
||||
:return: 字典格式的消息段
|
||||
"""
|
||||
return {
|
||||
"type": segment.type,
|
||||
"data": segment.data
|
||||
}
|
||||
383
core/bot.py
383
core/bot.py
@@ -3,16 +3,18 @@ Bot 抽象模块
|
||||
|
||||
定义了 Bot 类,封装了 OneBot API 的调用逻辑,提供了便捷的消息发送方法。
|
||||
"""
|
||||
from typing import TYPE_CHECKING, Union, List
|
||||
from typing import TYPE_CHECKING, Dict, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .ws import WS
|
||||
from models import OneBotEvent, MessageSegment
|
||||
|
||||
from .api import MessageAPI, GroupAPI, FriendAPI, AccountAPI
|
||||
|
||||
|
||||
class Bot:
|
||||
class Bot(MessageAPI, GroupAPI, FriendAPI, AccountAPI):
|
||||
"""
|
||||
Bot 抽象类,封装 API 调用和常用操作
|
||||
继承各个 API Mixin 以提高代码的可维护性
|
||||
"""
|
||||
|
||||
def __init__(self, ws_client: "WS"):
|
||||
@@ -23,7 +25,7 @@ class Bot:
|
||||
"""
|
||||
self.ws = ws_client
|
||||
|
||||
async def call_api(self, action: str, params: dict = None) -> dict:
|
||||
async def call_api(self, action: str, params: Dict[str, Any] = None) -> Any:
|
||||
"""
|
||||
调用 OneBot API
|
||||
|
||||
@@ -31,375 +33,4 @@ class Bot:
|
||||
:param params: API 参数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.ws.call_api(action, params)
|
||||
|
||||
async def send_group_msg(self, group_id: int, message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> dict:
|
||||
"""
|
||||
发送群消息
|
||||
|
||||
:param group_id: 群号
|
||||
:param message: 消息内容,可以是字符串、MessageSegment 对象或 MessageSegment 列表
|
||||
:param auto_escape: 是否自动转义(仅当 message 为字符串时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api(
|
||||
"send_group_msg", {"group_id": group_id, "message": self._process_message(message), "auto_escape": auto_escape}
|
||||
)
|
||||
|
||||
async def send_private_msg(self, user_id: int, message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> dict:
|
||||
"""
|
||||
发送私聊消息
|
||||
|
||||
:param user_id: 用户 QQ 号
|
||||
:param message: 消息内容,可以是字符串、MessageSegment 对象或 MessageSegment 列表
|
||||
:param auto_escape: 是否自动转义(仅当 message 为字符串时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api(
|
||||
"send_private_msg", {"user_id": user_id, "message": self._process_message(message), "auto_escape": auto_escape}
|
||||
)
|
||||
|
||||
async def send(self, event: "OneBotEvent", message: Union[str, "MessageSegment", List["MessageSegment"]], auto_escape: bool = False) -> dict:
|
||||
"""
|
||||
智能发送消息,根据事件类型自动选择发送方式
|
||||
|
||||
:param event: 触发事件对象
|
||||
:param message: 消息内容
|
||||
:param auto_escape: 是否自动转义
|
||||
:return: API 响应结果
|
||||
"""
|
||||
# 如果是消息事件,直接调用 reply
|
||||
if hasattr(event, "reply"):
|
||||
await event.reply(message, auto_escape)
|
||||
return {"status": "ok", "msg": "Replied via event.reply()"}
|
||||
|
||||
# 尝试从事件中获取 user_id 或 group_id
|
||||
user_id = getattr(event, "user_id", None)
|
||||
group_id = getattr(event, "group_id", None)
|
||||
|
||||
if group_id:
|
||||
return await self.send_group_msg(group_id, message, auto_escape)
|
||||
elif user_id:
|
||||
return await self.send_private_msg(user_id, message, auto_escape)
|
||||
|
||||
return {"status": "failed", "msg": "Unknown message target"}
|
||||
|
||||
async def delete_msg(self, message_id: int) -> dict:
|
||||
"""
|
||||
撤回消息
|
||||
|
||||
:param message_id: 消息 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("delete_msg", {"message_id": message_id})
|
||||
|
||||
async def get_msg(self, message_id: int) -> dict:
|
||||
"""
|
||||
获取消息
|
||||
|
||||
:param message_id: 消息 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_msg", {"message_id": message_id})
|
||||
|
||||
async def get_forward_msg(self, id: str) -> dict:
|
||||
"""
|
||||
获取合并转发消息
|
||||
|
||||
:param id: 合并转发 ID
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_forward_msg", {"id": id})
|
||||
|
||||
async def send_like(self, user_id: int, times: int = 1) -> dict:
|
||||
"""
|
||||
发送点赞
|
||||
|
||||
:param user_id: 对方 QQ 号
|
||||
:param times: 点赞次数
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("send_like", {"user_id": user_id, "times": times})
|
||||
|
||||
async def set_group_kick(self, group_id: int, user_id: int, reject_add_request: bool = False) -> dict:
|
||||
"""
|
||||
群组踢人
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要踢的 QQ 号
|
||||
:param reject_add_request: 拒绝此人的加群请求
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_kick", {"group_id": group_id, "user_id": user_id, "reject_add_request": reject_add_request})
|
||||
|
||||
async def set_group_ban(self, group_id: int, user_id: int, duration: int = 30 * 60) -> dict:
|
||||
"""
|
||||
群组单人禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要禁言的 QQ 号
|
||||
:param duration: 禁言时长(秒),0 表示解除禁言
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_ban", {"group_id": group_id, "user_id": user_id, "duration": duration})
|
||||
|
||||
async def set_group_anonymous_ban(self, group_id: int, anonymous: dict = None, duration: int = 30 * 60, flag: str = None) -> dict:
|
||||
"""
|
||||
群组匿名禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param anonymous: 可选,要禁言的匿名用户对象(群消息事件的 anonymous 字段)
|
||||
:param duration: 禁言时长(秒)
|
||||
:param flag: 可选,要禁言的匿名用户的 flag(需从群消息事件的 anonymous 字段中获取)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
params = {"group_id": group_id, "duration": duration}
|
||||
if anonymous:
|
||||
params["anonymous"] = anonymous
|
||||
if flag:
|
||||
params["flag"] = flag
|
||||
return await self.call_api("set_group_anonymous_ban", params)
|
||||
|
||||
async def set_group_whole_ban(self, group_id: int, enable: bool = True) -> dict:
|
||||
"""
|
||||
群组全员禁言
|
||||
|
||||
:param group_id: 群号
|
||||
:param enable: 是否开启
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_whole_ban", {"group_id": group_id, "enable": enable})
|
||||
|
||||
async def set_group_admin(self, group_id: int, user_id: int, enable: bool = True) -> dict:
|
||||
"""
|
||||
群组设置管理员
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param enable: True 为设置,False 为取消
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_admin", {"group_id": group_id, "user_id": user_id, "enable": enable})
|
||||
|
||||
async def set_group_anonymous(self, group_id: int, enable: bool = True) -> dict:
|
||||
"""
|
||||
群组匿名
|
||||
|
||||
:param group_id: 群号
|
||||
:param enable: 是否开启
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_anonymous", {"group_id": group_id, "enable": enable})
|
||||
|
||||
async def set_group_card(self, group_id: int, user_id: int, card: str = "") -> dict:
|
||||
"""
|
||||
设置群名片(群备注)
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param card: 群名片内容,不填或空字符串表示删除群名片
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_card", {"group_id": group_id, "user_id": user_id, "card": card})
|
||||
|
||||
async def set_group_name(self, group_id: int, group_name: str) -> dict:
|
||||
"""
|
||||
设置群名
|
||||
|
||||
:param group_id: 群号
|
||||
:param group_name: 新群名
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_name", {"group_id": group_id, "group_name": group_name})
|
||||
|
||||
async def set_group_leave(self, group_id: int, is_dismiss: bool = False) -> dict:
|
||||
"""
|
||||
退出群组
|
||||
|
||||
:param group_id: 群号
|
||||
:param is_dismiss: 是否解散,如果登录号是群主,则仅在此项为 True 时能够解散
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_leave", {"group_id": group_id, "is_dismiss": is_dismiss})
|
||||
|
||||
async def set_group_special_title(self, group_id: int, user_id: int, special_title: str = "", duration: int = -1) -> dict:
|
||||
"""
|
||||
设置群组专属头衔
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: 要设置的 QQ 号
|
||||
:param special_title: 专属头衔,不填或空字符串表示删除
|
||||
:param duration: 有效期(秒),-1 表示永久
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_special_title", {"group_id": group_id, "user_id": user_id, "special_title": special_title, "duration": duration})
|
||||
|
||||
async def get_group_info(self, group_id: int, no_cache: bool = False) -> dict:
|
||||
"""
|
||||
获取群信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_group_info", {"group_id": group_id, "no_cache": no_cache})
|
||||
|
||||
async def get_group_list(self) -> dict:
|
||||
"""
|
||||
获取群列表
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_group_list")
|
||||
|
||||
async def get_group_member_info(self, group_id: int, user_id: int, no_cache: bool = False) -> dict:
|
||||
"""
|
||||
获取群成员信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param user_id: QQ 号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_group_member_info", {"group_id": group_id, "user_id": user_id, "no_cache": no_cache})
|
||||
|
||||
async def get_group_member_list(self, group_id: int) -> dict:
|
||||
"""
|
||||
获取群成员列表
|
||||
|
||||
:param group_id: 群号
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_group_member_list", {"group_id": group_id})
|
||||
|
||||
async def get_group_honor_info(self, group_id: int, type: str) -> dict:
|
||||
"""
|
||||
获取群荣誉信息
|
||||
|
||||
:param group_id: 群号
|
||||
:param type: 要获取的群荣誉类型,可传入 talkative, performer, legend, strong_newbie, emotion 等
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_group_honor_info", {"group_id": group_id, "type": type})
|
||||
|
||||
async def get_login_info(self) -> dict:
|
||||
"""
|
||||
获取登录号信息
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_login_info")
|
||||
|
||||
async def get_stranger_info(self, user_id: int, no_cache: bool = False) -> dict:
|
||||
"""
|
||||
获取陌生人信息
|
||||
|
||||
:param user_id: QQ 号
|
||||
:param no_cache: 是否不使用缓存
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_stranger_info", {"user_id": user_id, "no_cache": no_cache})
|
||||
|
||||
async def get_friend_list(self) -> dict:
|
||||
"""
|
||||
获取好友列表
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_friend_list")
|
||||
|
||||
async def set_friend_add_request(self, flag: str, approve: bool = True, remark: str = "") -> dict:
|
||||
"""
|
||||
处理加好友请求
|
||||
|
||||
:param flag: 加好友请求的 flag(需从上报的数据中获取)
|
||||
:param approve: 是否同意请求
|
||||
:param remark: 添加后的好友备注(仅在同意时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_friend_add_request", {"flag": flag, "approve": approve, "remark": remark})
|
||||
|
||||
async def set_group_add_request(self, flag: str, sub_type: str, approve: bool = True, reason: str = "") -> dict:
|
||||
"""
|
||||
处理加群请求/邀请
|
||||
|
||||
:param flag: 加群请求的 flag(需从上报的数据中获取)
|
||||
:param sub_type: add 或 invite,请求类型(需要与上报消息中的 sub_type 字段相符)
|
||||
:param approve: 是否同意请求/邀请
|
||||
:param reason: 拒绝理由(仅在拒绝时有效)
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("set_group_add_request", {"flag": flag, "sub_type": sub_type, "approve": approve, "reason": reason})
|
||||
|
||||
async def get_version_info(self) -> dict:
|
||||
"""
|
||||
获取版本信息
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_version_info")
|
||||
|
||||
async def get_status(self) -> dict:
|
||||
"""
|
||||
获取状态
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("get_status")
|
||||
|
||||
async def can_send_image(self) -> dict:
|
||||
"""
|
||||
检查是否可以发送图片
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("can_send_image")
|
||||
|
||||
async def can_send_record(self) -> dict:
|
||||
"""
|
||||
检查是否可以发送语音
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("can_send_record")
|
||||
|
||||
async def clean_cache(self) -> dict:
|
||||
"""
|
||||
清理缓存
|
||||
|
||||
:return: API 响应结果
|
||||
"""
|
||||
return await self.call_api("clean_cache")
|
||||
|
||||
def _process_message(self, message: Union[str, "MessageSegment", List["MessageSegment"]]) -> Union[str, List[dict]]:
|
||||
"""
|
||||
处理消息内容,将其转换为 API 可接受的格式
|
||||
|
||||
:param message: 原始消息内容
|
||||
:return: 处理后的消息内容
|
||||
"""
|
||||
if isinstance(message, str):
|
||||
return message
|
||||
|
||||
# 避免循环导入,在运行时导入
|
||||
from models import MessageSegment
|
||||
|
||||
if isinstance(message, MessageSegment):
|
||||
return [self._segment_to_dict(message)]
|
||||
|
||||
if isinstance(message, list):
|
||||
return [self._segment_to_dict(m) for m in message if isinstance(m, MessageSegment)]
|
||||
|
||||
return str(message)
|
||||
|
||||
def _segment_to_dict(self, segment: "MessageSegment") -> dict:
|
||||
"""
|
||||
将 MessageSegment 对象转换为字典
|
||||
|
||||
:param segment: MessageSegment 对象
|
||||
:return: 字典格式的消息段
|
||||
"""
|
||||
return {
|
||||
"type": segment.type,
|
||||
"data": segment.data
|
||||
}
|
||||
return await self.ws.call_api(action, params)
|
||||
@@ -27,6 +27,7 @@ class CommandManager:
|
||||
self.commands: Dict[str, Callable] = {} # 存储消息指令
|
||||
self.notice_handlers: List[Dict] = [] # 存储通知处理器
|
||||
self.request_handlers: List[Dict] = [] # 存储请求处理器
|
||||
self.plugins: Dict[str, Dict[str, Any]] = {} # 存储插件元数据
|
||||
|
||||
# --- 1. 消息指令装饰器 ---
|
||||
def command(self, name: str):
|
||||
|
||||
Reference in New Issue
Block a user