11"""基于 `ichika.core.PlumbingClient` 封装的高层 API"""
22from __future__ import annotations
33
4- from typing import Any , Awaitable , Callable , Literal , Protocol
4+ from typing import Any , Awaitable , Callable , Iterable , Literal , Protocol
55from weakref import WeakValueDictionary
66
77from graia .amnesia .message import Element , MessageChain
88
9- from .core import PlumbingClient , RawMessageReceipt
9+ from .core import Friend , Group , PlumbingClient , RawMessageReceipt
1010from .message import _serialize_message as _serialize_msg
1111from .message .elements import (
1212 At ,
@@ -41,54 +41,67 @@ def __call__(
4141 ...
4242
4343
44+ def _uin (obj : Friend | Group | int ) -> int :
45+ return obj if isinstance (obj , int ) else obj .uin
46+
47+
48+ def _chain_coerce (msg : str | Element | MessageChain | Iterable [str | Element ]) -> MessageChain :
49+ if isinstance (msg , MessageChain ):
50+ return msg
51+ if isinstance (msg , (str , Element )):
52+ msg = [msg ]
53+ if isinstance (msg , Iterable ):
54+ return MessageChain ([Text (e ) if isinstance (e , str ) else e for e in msg ])
55+
56+
4457class Client (PlumbingClient ):
4558 """基于 [`PlumbingClient`][ichika.core.PlumbingClient] 封装的高层 API"""
4659
47- async def upload_friend_image (self , uin : int , data : bytes ) -> Image :
60+ async def upload_friend_image (self , friend : int | Friend , data : bytes ) -> Image :
4861 """上传好友图片
4962
50- :param uin : 好友 QQ 号
63+ :param friend : 好友 QQ 号或好友对象
5164 :param data: 图片数据
5265
5366 :return: 图片元素
5467 """
55- image_dict = await super ().upload_friend_image (uin , data )
68+ image_dict = await super ().upload_friend_image (_uin ( friend ) , data )
5669 image_dict .pop ("type" )
5770 return Image (** image_dict )
5871
59- async def upload_friend_audio (self , uin : int , data : bytes ) -> Audio :
72+ async def upload_friend_audio (self , friend : int | Friend , data : bytes ) -> Audio :
6073 """上传好友语音
6174
62- :param uin : 好友 QQ 号
75+ :param friend : 好友 QQ 号或好友对象
6376 :param data: 语音数据,应为 SILK/AMR 编码的音频数据
6477
6578 :return: 语音元素
6679 """
67- audio_dict = await super ().upload_friend_audio (uin , data )
80+ audio_dict = await super ().upload_friend_audio (_uin ( friend ) , data )
6881 audio_dict .pop ("type" )
6982 return Audio (** audio_dict )
7083
71- async def upload_group_image (self , uin : int , data : bytes ) -> Image :
84+ async def upload_group_image (self , group : int | Group , data : bytes ) -> Image :
7285 """上传群图片
7386
74- :param uin: 群号
87+ :param group: 群号或群对象
7588 :param data: 图片数据
7689
7790 :return: 图片元素
7891 """
79- image_dict = await super ().upload_group_image (uin , data )
92+ image_dict = await super ().upload_group_image (_uin ( group ) , data )
8093 image_dict .pop ("type" )
8194 return Image (** image_dict )
8295
83- async def upload_group_audio (self , uin : int , data : bytes ) -> Audio :
96+ async def upload_group_audio (self , group : int | Group , data : bytes ) -> Audio :
8497 """上传群语音
8598
86- :param uin: 群号
99+ :param group: 群号或群对象
87100 :param data: 语音数据,应为 SILK/AMR 编码的音频数据
88101
89102 :return: 语音元素
90103 """
91- audio_dict = await super ().upload_group_audio (uin , data )
104+ audio_dict = await super ().upload_group_audio (_uin ( group ) , data )
92105 audio_dict .pop ("type" )
93106 return Audio (** audio_dict )
94107
@@ -149,16 +162,16 @@ async def _prepare_forward(self, uin: int, fwd: ForwardMessage) -> dict[str, Any
149162 data ["content" ] = [await self ._prepare_forward (uin , f ) for f in fwd .content ]
150163 return data
151164
152- async def upload_forward_msg (self , group_uin : int , msgs : list [ForwardMessage ]) -> ForwardCard :
165+ async def upload_forward_msg (self , group : int | Group , msgs : list [ForwardMessage ]) -> ForwardCard :
153166 """上传合并转发消息
154167
155- :param group_uin: 用于标记的原始群号
168+ :param group: 用于标记的原始群号或群对象
156169 :param msgs: 转发消息列表
157170
158171 :return: 转发卡片元素
159172 """
160173 res_id , file_name , content = await super ().upload_forward_msg (
161- group_uin , [await self ._prepare_forward (group_uin , msg ) for msg in msgs ]
174+ _uin ( group ) , [await self ._prepare_forward (_uin ( group ) , msg ) for msg in msgs ]
162175 )
163176 return ForwardCard (res_id , file_name , content )
164177
@@ -178,28 +191,36 @@ async def _send_special_element(self, uin: int, kind: str, element: Element) ->
178191
179192 raise TypeError (f"无法发送元素: { element !r} " )
180193
181- async def send_group_message (self , uin : int , chain : MessageChain ) -> RawMessageReceipt :
194+ async def send_group_message (
195+ self , group : int | Group , chain : str | Element | MessageChain | Iterable [str | Element ]
196+ ) -> RawMessageReceipt :
182197 """发送群消息
183198
184- :param uin: 群号
199+ :param group: 群号或群对象
185200 :param chain: 消息链
186201
187202 :return: 消息发送凭据,可用于撤回
188203 """
204+ uin : int = _uin (group )
205+ chain = _chain_coerce (chain )
189206 if isinstance (validated := self ._validate_chain (chain ), Element ):
190207 return await self ._send_special_element (uin , "group" , validated )
191208 for idx , elem in enumerate (chain ):
192209 chain .content [idx ] = await self ._validate_mm (uin , elem , self .upload_group_image )
193210 return await super ().send_group_message (uin , _serialize_msg (chain ))
194211
195- async def send_friend_message (self , uin : int , chain : MessageChain ) -> RawMessageReceipt :
212+ async def send_friend_message (
213+ self , friend : int | Friend , chain : str | Element | MessageChain | Iterable [str | Element ]
214+ ) -> RawMessageReceipt :
196215 """发送好友消息
197216
198- :param uin : 好友 QQ 号
217+ :param friend : 好友 QQ 号或好友对象
199218 :param chain: 消息链
200219
201220 :return: 消息发送凭据,可用于撤回
202221 """
222+ uin : int = _uin (friend )
223+ chain = _chain_coerce (chain )
203224 if isinstance (validated := self ._validate_chain (chain ), Element ):
204225 return await self ._send_special_element (uin , "friend" , validated )
205226 for idx , elem in enumerate (chain ):
0 commit comments