perf: simplify platform entities

This commit is contained in:
Junyan Qin
2025-03-02 17:59:13 +08:00
parent 60c0adc6f9
commit 720a218259
3 changed files with 15 additions and 124 deletions
+6 -70
View File
@@ -13,27 +13,20 @@ import pydantic.v1 as pydantic
class Entity(pydantic.BaseModel): class Entity(pydantic.BaseModel):
"""实体,表示一个用户或群。""" """实体,表示一个用户或群。"""
id: int id: int
"""QQ 号或群号""" """ID"""
@abc.abstractmethod
def get_avatar_url(self) -> str:
"""头像图片链接。"""
@abc.abstractmethod @abc.abstractmethod
def get_name(self) -> str: def get_name(self) -> str:
"""名称。""" """名称。"""
class Friend(Entity): class Friend(Entity):
"""好友""" """私聊对象"""
id: typing.Union[int, str] id: typing.Union[int, str]
"""QQ 号""" """ID"""
nickname: typing.Optional[str] nickname: typing.Optional[str]
"""昵称。""" """昵称。"""
remark: typing.Optional[str] remark: typing.Optional[str]
"""备注。""" """备注。"""
def get_avatar_url(self) -> str:
return f'http://q4.qlogo.cn/g?b=qq&nk={self.id}&s=140'
def get_name(self) -> str: def get_name(self) -> str:
return self.nickname or self.remark or '' return self.nickname or self.remark or ''
@@ -59,8 +52,6 @@ class Group(Entity):
"""群名称。""" """群名称。"""
permission: Permission permission: Permission
"""Bot 在群中的权限。""" """Bot 在群中的权限。"""
def get_avatar_url(self) -> str:
return f'https://p.qlogo.cn/gh/{self.id}/{self.id}/'
def get_name(self) -> str: def get_name(self) -> str:
return self.name return self.name
@@ -69,11 +60,11 @@ class Group(Entity):
class GroupMember(Entity): class GroupMember(Entity):
"""群成员。""" """群成员。"""
id: typing.Union[int, str] id: typing.Union[int, str]
"""QQ 号""" """群员 ID"""
member_name: str member_name: str
"""员名称。""" """群员名称。"""
permission: Permission permission: Permission
"""Bot 在群中的权限。""" """在群中的权限。"""
group: Group group: Group
"""群。""" """群。"""
special_title: str = '' special_title: str = ''
@@ -84,61 +75,6 @@ class GroupMember(Entity):
"""最后一次发言的时间。""" """最后一次发言的时间。"""
mute_time_remaining: int = 0 mute_time_remaining: int = 0
"""禁言剩余时间。""" """禁言剩余时间。"""
def get_avatar_url(self) -> str:
return f'http://q4.qlogo.cn/g?b=qq&nk={self.id}&s=140'
def get_name(self) -> str: def get_name(self) -> str:
return self.member_name return self.member_name
class Client(Entity):
"""来自其他客户端的用户。"""
id: typing.Union[int, str]
"""识别 id。"""
platform: str
"""来源平台。"""
def get_avatar_url(self) -> str:
raise NotImplementedError
def get_name(self) -> str:
return self.platform
class Subject(pydantic.BaseModel):
"""另一种实体类型表示。"""
id: typing.Union[int, str]
"""QQ 号或群号。"""
kind: typing.Literal['Friend', 'Group', 'Stranger']
"""类型。"""
class Config(pydantic.BaseModel):
"""配置项类型。"""
def modify(self, **kwargs) -> 'Config':
"""修改部分设置。"""
for k, v in kwargs.items():
if k in self.__fields__:
setattr(self, k, v)
else:
raise ValueError(f'未知配置项: {k}')
return self
class GroupConfigModel(Config):
"""群配置。"""
name: str
"""群名称。"""
confess_talk: bool
"""是否允许坦白说。"""
allow_member_invite: bool
"""是否允许成员邀请好友入群。"""
auto_approve: bool
"""是否开启自动审批入群。"""
anonymous_chat: bool
"""是否开启匿名聊天。"""
announcement: str = ''
"""群公告。"""
class MemberInfoModel(Config, GroupMember):
"""群成员信息。"""
+1 -32
View File
@@ -43,21 +43,6 @@ class Event(pydantic.BaseModel):
return Event return Event
###############################
# Bot Event
class BotEvent(Event):
"""Bot 自身事件。
Args:
type: 事件名。
qq: Bot 的 QQ 号。
"""
type: str
"""事件名。"""
qq: int
"""Bot 的 QQ 号。"""
############################### ###############################
# Message Event # Message Event
class MessageEvent(Event): class MessageEvent(Event):
@@ -79,7 +64,7 @@ class MessageEvent(Event):
class FriendMessage(MessageEvent): class FriendMessage(MessageEvent):
"""好友消息。 """私聊消息。
Args: Args:
type: 事件名。 type: 事件名。
@@ -111,19 +96,3 @@ class GroupMessage(MessageEvent):
@property @property
def group(self) -> platform_entities.Group: def group(self) -> platform_entities.Group:
return self.sender.group return self.sender.group
class StrangerMessage(MessageEvent):
"""陌生人消息。
Args:
type: 事件名。
sender: 发送消息的人。
message_chain: 消息内容。
"""
type: str = 'StrangerMessage'
"""事件名。"""
sender: platform_entities.Friend
"""发送消息的人。"""
message_chain: platform_message.MessageChain
"""消息内容。"""
+8 -22
View File
@@ -116,18 +116,6 @@ class MessageChain(PlatformBaseModel):
print('At Me') print('At Me')
``` ```
消息链对索引操作进行了增强。以消息组件类型为索引,获取消息链中的全部该类型的消息组件。
```py
plain_list = message_chain[Plain]
'[Plain("Hello World!")]'
```
可以用加号连接两个消息链。
```py
MessageChain(['Hello World!']) + MessageChain(['Goodbye World!'])
# 返回 MessageChain([Plain("Hello World!"), Plain("Goodbye World!")])
```
""" """
__root__: typing.List[MessageComponent] __root__: typing.List[MessageComponent]
@@ -488,9 +476,9 @@ class Quote(MessageComponent):
group_id: typing.Optional[typing.Union[int, str]] = None group_id: typing.Optional[typing.Union[int, str]] = None
"""被引用回复的原消息所接收的群号,当为好友消息时为0。""" """被引用回复的原消息所接收的群号,当为好友消息时为0。"""
sender_id: typing.Optional[typing.Union[int, str]] = None sender_id: typing.Optional[typing.Union[int, str]] = None
"""被引用回复的原消息的发送者的QQ号""" """被引用回复的原消息的发送者的ID"""
target_id: typing.Optional[typing.Union[int, str]] = None target_id: typing.Optional[typing.Union[int, str]] = None
"""被引用回复的原消息的接收者者的QQ号(或群号)""" """被引用回复的原消息的接收者者的ID或群ID"""
origin: MessageChain origin: MessageChain
"""被引用回复的原消息的消息链对象。""" """被引用回复的原消息的消息链对象。"""
@@ -504,7 +492,7 @@ class At(MessageComponent):
type: str = "At" type: str = "At"
"""消息组件类型。""" """消息组件类型。"""
target: typing.Union[int, str] target: typing.Union[int, str]
"""群员 QQ 号""" """群员 ID"""
display: typing.Optional[str] = None display: typing.Optional[str] = None
"""At时显示的文字,发送消息时无效,自动使用群名片。""" """At时显示的文字,发送消息时无效,自动使用群名片。"""
def __eq__(self, other): def __eq__(self, other):
@@ -527,9 +515,9 @@ class Image(MessageComponent):
type: str = "Image" type: str = "Image"
"""消息组件类型。""" """消息组件类型。"""
image_id: typing.Optional[str] = None image_id: typing.Optional[str] = None
"""图片的 image_id群图片与好友图片格式不同。不为空时将忽略 url 属性。""" """图片的 image_id,不为空时将忽略 url 属性。"""
url: typing.Optional[pydantic.HttpUrl] = None url: typing.Optional[pydantic.HttpUrl] = None
"""图片的 URL,发送时可作网络图片的链接;接收时为腾讯图片服务器的链接,可用于图片下载。""" """图片的 URL,发送时可作网络图片的链接;接收时为图片的链接,可用于图片下载。"""
path: typing.Union[str, Path, None] = None path: typing.Union[str, Path, None] = None
"""图片的路径,发送本地图片。""" """图片的路径,发送本地图片。"""
base64: typing.Optional[str] = None base64: typing.Optional[str] = None
@@ -663,7 +651,7 @@ class Voice(MessageComponent):
voice_id: typing.Optional[str] = None voice_id: typing.Optional[str] = None
"""语音的 voice_id,不为空时将忽略 url 属性。""" """语音的 voice_id,不为空时将忽略 url 属性。"""
url: typing.Optional[str] = None url: typing.Optional[str] = None
"""语音的 URL,发送时可作网络语音的链接;接收时为腾讯语音服务器的链接,可用于语音下载。""" """语音的 URL,发送时可作网络语音的链接;接收时为语音文件的链接,可用于语音下载。"""
path: typing.Optional[str] = None path: typing.Optional[str] = None
"""语音的路径,发送本地语音。""" """语音的路径,发送本地语音。"""
base64: typing.Optional[str] = None base64: typing.Optional[str] = None
@@ -691,8 +679,6 @@ class Voice(MessageComponent):
): ):
"""下载语音到本地。 """下载语音到本地。
语音采用 silk v3 格式,silk 格式的编码解码请使用 [graiax-silkcoder](https://pypi.org/project/graiax-silkcoder/)。
Args: Args:
filename: 下载到本地的文件路径。与 `directory` 二选一。 filename: 下载到本地的文件路径。与 `directory` 二选一。
directory: 下载到本地的文件夹路径。与 `filename` 二选一。 directory: 下载到本地的文件夹路径。与 `filename` 二选一。
@@ -750,13 +736,13 @@ class Voice(MessageComponent):
class ForwardMessageNode(pydantic.BaseModel): class ForwardMessageNode(pydantic.BaseModel):
"""合并转发中的一条消息。""" """合并转发中的一条消息。"""
sender_id: typing.Optional[typing.Union[int, str]] = None sender_id: typing.Optional[typing.Union[int, str]] = None
"""发送人QQ号""" """发送人ID"""
sender_name: typing.Optional[str] = None sender_name: typing.Optional[str] = None
"""显示名称。""" """显示名称。"""
message_chain: typing.Optional[MessageChain] = None message_chain: typing.Optional[MessageChain] = None
"""消息内容。""" """消息内容。"""
message_id: typing.Optional[int] = None message_id: typing.Optional[int] = None
"""消息的 message_id,可以只使用此属性,从缓存中读取消息内容""" """消息的 message_id。"""
time: typing.Optional[datetime] = None time: typing.Optional[datetime] = None
"""发送时间。""" """发送时间。"""
@pydantic.validator('message_chain', check_fields=False) @pydantic.validator('message_chain', check_fields=False)