11import asyncio
2+ import importlib
23import itertools
34import logging
45import time
56import uuid
6- from collections .abc import Awaitable
7+ from collections .abc import Awaitable , Callable
78from typing import Any , cast
89
9- from aiocqhttp import CQHttp , Event
10+ import aiocqhttp
1011from aiocqhttp .exceptions import ActionFailed
1112
12- from astrbot .api import logger
13- from astrbot .api .event import MessageChain
14- from astrbot .api .message_components import *
15- from astrbot .api .platform import (
13+ from astrbot import logger
14+ from astrbot .core .message .components import (
15+ At ,
16+ ComponentTypes ,
17+ File ,
18+ Image ,
19+ Plain ,
20+ Poke ,
21+ Reply ,
22+ )
23+ from astrbot .core .message .message_event_result import MessageChain
24+ from astrbot .core .platform import (
1625 AstrBotMessage ,
26+ Group ,
1727 MessageMember ,
1828 MessageType ,
1929 Platform ,
2030 PlatformMetadata ,
2131)
2232from astrbot .core .platform .astr_message_event import MessageSesion
33+ from astrbot .core .platform .register import register_platform_adapter
2334
24- from ...register import register_platform_adapter
25- from .aiocqhttp_message_event import *
2635from .aiocqhttp_message_event import AiocqhttpMessageEvent
2736
2837
@@ -37,6 +46,7 @@ def __init__(
3746 platform_config : dict ,
3847 platform_settings : dict ,
3948 event_queue : asyncio .Queue ,
49+ bot_factory : Callable [..., Any ] | None = None ,
4050 ) -> None :
4151 super ().__init__ (platform_config , event_queue )
4252
@@ -51,17 +61,10 @@ def __init__(
5161 support_streaming_message = False ,
5262 )
5363
54- self .bot = CQHttp (
55- use_ws_reverse = True ,
56- import_name = "aiocqhttp" ,
57- api_timeout_sec = 180 ,
58- access_token = platform_config .get (
59- "ws_reverse_token" ,
60- ), # 以防旧版本配置不存在
61- )
64+ self .bot = self ._create_bot (platform_config , bot_factory = bot_factory )
6265
6366 @self .bot .on_request ()
64- async def request (event : Event ) -> None :
67+ async def request (event : aiocqhttp . Event ) -> None :
6568 try :
6669 abm = await self .convert_message (event )
6770 if not abm :
@@ -72,7 +75,7 @@ async def request(event: Event) -> None:
7275 return
7376
7477 @self .bot .on_notice ()
75- async def notice (event : Event ) -> None :
78+ async def notice (event : aiocqhttp . Event ) -> None :
7679 try :
7780 abm = await self .convert_message (event )
7881 if abm :
@@ -82,7 +85,7 @@ async def notice(event: Event) -> None:
8285 return
8386
8487 @self .bot .on_message ("group" )
85- async def group (event : Event ) -> None :
88+ async def group (event : aiocqhttp . Event ) -> None :
8689 try :
8790 abm = await self .convert_message (event )
8891 if abm :
@@ -92,7 +95,7 @@ async def group(event: Event) -> None:
9295 return
9396
9497 @self .bot .on_message ("private" )
95- async def private (event : Event ) -> None :
98+ async def private (event : aiocqhttp . Event ) -> None :
9699 try :
97100 abm = await self .convert_message (event )
98101 if abm :
@@ -105,6 +108,29 @@ async def private(event: Event) -> None:
105108 def on_websocket_connection (_ ) -> None :
106109 logger .info ("aiocqhttp(OneBot v11) 适配器已连接。" )
107110
111+ @staticmethod
112+ def _create_bot (
113+ platform_config : dict ,
114+ bot_factory : Callable [..., Any ] | None = None ,
115+ ) -> aiocqhttp .CQHttp :
116+ if bot_factory is None :
117+ # Resolve aiocqhttp at runtime so tests that swap sys.modules later
118+ # still affect bot creation even if this module was imported earlier.
119+ aiocqhttp_module = importlib .import_module ("aiocqhttp" )
120+ bot_factory = aiocqhttp_module .CQHttp
121+
122+ return cast (
123+ aiocqhttp .CQHttp ,
124+ bot_factory (
125+ use_ws_reverse = True ,
126+ import_name = "aiocqhttp" ,
127+ api_timeout_sec = 180 ,
128+ access_token = platform_config .get (
129+ "ws_reverse_token" ,
130+ ), # 以防旧版本配置不存在
131+ ),
132+ )
133+
108134 async def send_by_session (
109135 self ,
110136 session : MessageSesion ,
@@ -124,7 +150,7 @@ async def send_by_session(
124150 )
125151 await super ().send_by_session (session , message_chain )
126152
127- async def convert_message (self , event : Event ) -> AstrBotMessage | None :
153+ async def convert_message (self , event : aiocqhttp . Event ) -> AstrBotMessage | None :
128154 logger .debug (f"[aiocqhttp] RawMessage { event } " )
129155
130156 if event ["post_type" ] == "message" :
@@ -139,7 +165,9 @@ async def convert_message(self, event: Event) -> AstrBotMessage | None:
139165
140166 return abm
141167
142- async def _convert_handle_request_event (self , event : Event ) -> AstrBotMessage :
168+ async def _convert_handle_request_event (
169+ self , event : aiocqhttp .Event
170+ ) -> AstrBotMessage :
143171 """OneBot V11 请求类事件"""
144172 abm = AstrBotMessage ()
145173 abm .self_id = str (event .self_id )
@@ -164,7 +192,9 @@ async def _convert_handle_request_event(self, event: Event) -> AstrBotMessage:
164192 abm .raw_message = event
165193 return abm
166194
167- async def _convert_handle_notice_event (self , event : Event ) -> AstrBotMessage :
195+ async def _convert_handle_notice_event (
196+ self , event : aiocqhttp .Event
197+ ) -> AstrBotMessage :
168198 """OneBot V11 通知类事件"""
169199 abm = AstrBotMessage ()
170200 abm .self_id = str (event .self_id )
@@ -196,7 +226,7 @@ async def _convert_handle_notice_event(self, event: Event) -> AstrBotMessage:
196226
197227 async def _convert_handle_message_event (
198228 self ,
199- event : Event ,
229+ event : aiocqhttp . Event ,
200230 get_reply = True ,
201231 ) -> AstrBotMessage :
202232 """OneBot V11 消息类事件
@@ -309,7 +339,7 @@ async def _convert_handle_message_event(
309339 )
310340 # 添加必要的 post_type 字段,防止 Event.from_payload 报错
311341 reply_event_data ["post_type" ] = "message"
312- new_event = Event .from_payload (reply_event_data )
342+ new_event = aiocqhttp . Event .from_payload (reply_event_data )
313343 if not new_event :
314344 logger .error (
315345 f"无法从回复消息数据构造 Event 对象: { reply_event_data } " ,
@@ -401,6 +431,14 @@ async def _convert_handle_message_event(
401431 f"不支持的消息段类型,已忽略: { t } , data={ m ['data' ]} "
402432 )
403433 continue
434+ if (
435+ t == "image"
436+ and not m ["data" ].get ("file" )
437+ and m ["data" ].get ("url" )
438+ ):
439+ a = Image (file = m ["data" ]["url" ], url = m ["data" ]["url" ])
440+ abm .message .append (a )
441+ continue
404442 a = ComponentTypes [t ](** m ["data" ])
405443 abm .message .append (a )
406444 except Exception as e :
@@ -456,5 +494,5 @@ async def handle_msg(self, message: AstrBotMessage) -> None:
456494
457495 self .commit_event (message_event )
458496
459- def get_client (self ) -> CQHttp :
497+ def get_client (self ) -> aiocqhttp . CQHttp :
460498 return self .bot
0 commit comments