88from nonebot .adapters .onebot .v11 import GroupMessageEvent , GroupRecallNoticeEvent , Message , MessageSegment , permission
99from nonebot .exception import ActionFailed
1010from nonebot .plugin import PluginMetadata
11- from nonebot .rule import Rule , keyword , to_me
11+ from nonebot .rule import Rule
1212from nonebot .typing import T_State
1313from nonebot_plugin_apscheduler import scheduler
1414
2525from src .foundation .config import BotConfig
2626from src .platform .observability import SlowPathTimer , slow_path_threshold_ms
2727from src .plugins .dream .ban_ack_state import DREAM_BAN_ACK_SENT_STATE_KEY
28+ from src .shared .reply_command_rule import event_has_reply_target , event_targets_self , extract_reply_id_from_raw_message
2829from src .shared .utils .array2cqcode import try_convert_to_cqcode
2930from src .shared .utils .media_cache import get_image , insert_image
3031
@@ -260,11 +261,49 @@ async def _(bot: Bot, event: GroupMessageEvent):
260261
261262
262263async def is_reply (event : GroupMessageEvent ) -> bool :
263- return bool (event .reply )
264+ return event_has_reply_target (event )
265+
266+
267+ async def is_ban_reply_trigger (event : GroupMessageEvent ) -> bool :
268+ if "不可以" not in event .get_plaintext ():
269+ return False
270+ if not await is_reply (event ):
271+ return False
272+ return event_targets_self (event )
273+
274+
275+ def extract_ban_reply_raw_from_message (message : Message | str ) -> str :
276+ if isinstance (message , str ):
277+ return message
278+
279+ raw_message = ""
280+ for item in message :
281+ raw_reply = str (item )
282+ raw_message += re .sub (r"(\[CQ\:.+)(?:,url=*)(\])" , r"\1\2" , raw_reply )
283+ if not raw_message .strip ():
284+ raw_message = message .extract_plain_text ()
285+ return raw_message
286+
287+
288+ async def resolve_ban_reply_raw (bot : Bot , event : GroupMessageEvent ) -> str :
289+ if event .reply and getattr (event .reply , "message" , None ):
290+ return extract_ban_reply_raw_from_message (event .reply .message )
291+
292+ reply_id = extract_reply_id_from_raw_message (event .raw_message )
293+ if reply_id is None :
294+ return ""
295+
296+ try :
297+ msg = await bot .get_msg (message_id = reply_id )
298+ except ActionFailed :
299+ logger .warning (f"bot [{ event .self_id } ] failed to get replied msg [{ reply_id } ] in group [{ event .group_id } ]" )
300+ return ""
301+
302+ return extract_ban_reply_raw_from_message (Message (msg ["message" ]))
264303
265304
266305ban_msg = on_message (
267- rule = to_me () & keyword ( "不可以" ) & Rule (is_reply ),
306+ rule = Rule (is_ban_reply_trigger ),
268307 priority = 5 ,
269308 block = True ,
270309 permission = group_message_permission_for_command ("repeater.ban" ),
@@ -273,21 +312,18 @@ async def is_reply(event: GroupMessageEvent) -> bool:
273312
274313@ban_msg .handle ()
275314async def _ (bot : Bot , event : GroupMessageEvent , state : T_State ):
276- if not event .reply :
315+ raw_message = await resolve_ban_reply_raw (bot , event )
316+ if not raw_message .strip ():
317+ logger .info (f"bot [{ event .self_id } ] ban skipped (empty reply target) in group [{ event .group_id } ]" )
277318 return
278319
279- raw_message = ""
280- for item in event .reply .message : # type: ignore
281- raw_reply = str (item )
282- # 去掉图片消息中的 url, subType 等字段
283- raw_message += re .sub (r"(\[CQ\:.+)(?:,url=*)(\])" , r"\1\2" , raw_reply )
284-
285320 logger .info (f"bot [{ event .self_id } ] ready to ban [{ raw_message } ] in group [{ event .group_id } ]" )
286321
287- try :
288- await bot .delete_msg (message_id = event .reply .message_id ) # type: ignore
289- except ActionFailed :
290- logger .warning (f"bot [{ event .self_id } ] failed to delete [{ raw_message } ] in group [{ event .group_id } ]" )
322+ if event .reply :
323+ try :
324+ await bot .delete_msg (message_id = event .reply .message_id ) # type: ignore
325+ except ActionFailed :
326+ logger .warning (f"bot [{ event .self_id } ] failed to delete [{ raw_message } ] in group [{ event .group_id } ]" )
291327
292328 banned = await Chat .ban (event .group_id , event .self_id , raw_message , str (event .user_id ))
293329 if banned :
@@ -355,8 +391,14 @@ async def message_is_ban(bot: Bot, event: GroupMessageEvent, state: T_State) ->
355391 return event .get_plaintext ().strip () == "不可以发这个"
356392
357393
394+ async def is_ban_latest_trigger (bot : Bot , event : GroupMessageEvent , state : T_State ) -> bool :
395+ if not await message_is_ban (bot , event , state ):
396+ return False
397+ return event_targets_self (event )
398+
399+
358400ban_msg_latest = on_message (
359- rule = to_me () & Rule (message_is_ban ),
401+ rule = Rule (is_ban_latest_trigger ),
360402 priority = 5 ,
361403 block = True ,
362404 permission = group_message_permission_for_command ("repeater.ban_latest" ),
0 commit comments