Skip to content

Commit 66276c9

Browse files
authored
✨ Feature: 全量群消息事件优化 + 私聊/群回复消息适配 (#199)
1 parent 7e0f256 commit 66276c9

4 files changed

Lines changed: 215 additions & 94 deletions

File tree

nonebot/adapters/qq/bot.py

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
Event,
3030
FriendAddEvent,
3131
GroupAddRobotEvent,
32+
GroupAtMessageCreateEvent,
3233
GroupMessageCreateEvent,
3334
GuildMessageEvent,
3435
InteractionCreateEvent,
@@ -115,36 +116,58 @@ async def _check_reply(
115116
bot: Bot 对象
116117
event: MessageEvent 对象
117118
"""
118-
if not isinstance(event, GuildMessageEvent) or event.message_reference is None:
119-
return
120-
try:
121-
event.reply = await bot.get_message_of_id(
122-
channel_id=event.channel_id,
123-
message_id=event.message_reference.message_id,
124-
)
125-
if event.reply.author.id == bot.self_info.id:
119+
if isinstance(event, GuildMessageEvent):
120+
if event.message_reference is None:
121+
return
122+
try:
123+
event.reply = await bot.get_message_of_id(
124+
channel_id=event.channel_id,
125+
message_id=event.message_reference.message_id,
126+
)
127+
if event.reply.author.id == bot.self_info.id:
128+
event.to_me = True
129+
except Exception as e:
130+
log("WARNING", f"Error when getting message reply info: {e!r}", e)
131+
else:
132+
if not event.msg_elements:
133+
return
134+
event.reply = event.msg_elements[0]
135+
if (
136+
event.reply.author
137+
and event.reply.author.bot
138+
and event.reply.author.username == bot.self_info.username
139+
):
126140
event.to_me = True
127-
except Exception as e:
128-
log("WARNING", f"Error when getting message reply info: {e!r}", e)
129141

130142

131143
def _check_at_me(
132144
bot: "Bot",
133145
event: GuildMessageEvent | QQMessageEvent,
134146
):
147+
message = event.get_message()
148+
if not message:
149+
message.append(MessageSegment.text(""))
150+
if isinstance(event, GroupAtMessageCreateEvent):
151+
event.original_message = message.copy()
152+
event.original_message.insert(0, MessageSegment.mention_user(bot.self_info.id))
153+
if message and message[0].type == "text":
154+
message[0].data["text"] = message[0].data["text"].lstrip("\xa0").lstrip()
155+
if not message[0].data["text"]:
156+
del message[0]
157+
return
135158
if (
136159
isinstance(event, GuildMessageEvent)
137160
and event.mentions is not None
138161
and bot.self_info.id in {user.id for user in event.mentions}
139162
):
140163
event.to_me = True
141164

142-
if (
143-
isinstance(event, QQMessageEvent)
144-
and event.mentions is not None
145-
and any(user.is_you for user in event.mentions)
146-
):
147-
event.to_me = True
165+
if isinstance(event, GroupMessageCreateEvent):
166+
for seg in message:
167+
if seg.type == "mention_user" and seg.data.get("is_bot", False):
168+
seg.data["user_id"] = bot.self_info.id
169+
170+
event.original_message = message.copy()
148171

149172
def _is_at_me_seg(segment: MessageSegment) -> bool:
150173
if segment.type == "mention_user":
@@ -319,7 +342,9 @@ def _prepare_message(message: str | Message | MessageSegment) -> Message:
319342

320343
@staticmethod
321344
def _extract_send_message(
322-
message: Message, escape_text: bool = True
345+
message: Message,
346+
msg_ref_id: str | None = None,
347+
escape_text: bool = True,
323348
) -> dict[str, Any]:
324349
kwargs = {}
325350
content = message.extract_content(escape_text) or None
@@ -332,6 +357,10 @@ def _extract_send_message(
332357
kwargs["markdown"] = markdown[-1].data["markdown"]
333358
if reference := (message["reference"] or None):
334359
kwargs["message_reference"] = reference[-1].data["reference"]
360+
if msg_ref_id and not reference[-1].data["reference"].message_id.startswith(
361+
"REFIDX"
362+
):
363+
kwargs["message_reference"] = MessageReference(message_id=msg_ref_id)
335364
if keyboard := (message["keyboard"] or None):
336365
kwargs["keyboard"] = keyboard[-1].data["keyboard"]
337366
if stream := (message["stream"] or None):
@@ -429,9 +458,12 @@ async def send_to_c2c(
429458
msg_id: str | None = None,
430459
msg_seq: int | None = None,
431460
event_id: str | None = None,
461+
msg_ref_id: str | None = None,
432462
) -> PostC2CMessagesReturn | PostC2CFilesReturn:
433463
message = self._prepare_message(message)
434-
kwargs = self._extract_send_message(message=message, escape_text=False)
464+
kwargs = self._extract_send_message(
465+
message=message, msg_ref_id=msg_ref_id, escape_text=False
466+
)
435467
if kwargs.get("embed"):
436468
msg_type = 4
437469
elif kwargs.get("ark"):
@@ -489,9 +521,12 @@ async def send_to_group(
489521
msg_id: str | None = None,
490522
msg_seq: int | None = None,
491523
event_id: str | None = None,
524+
msg_ref_id: str | None = None,
492525
) -> PostGroupMessagesReturn | PostGroupFilesReturn:
493526
message = self._prepare_message(message)
494-
kwargs = self._extract_send_message(message=message, escape_text=False)
527+
kwargs = self._extract_send_message(
528+
message=message, msg_ref_id=msg_ref_id, escape_text=False
529+
)
495530
if kwargs.get("embed"):
496531
msg_type = 4
497532
elif kwargs.get("ark"):
@@ -560,19 +595,41 @@ async def send(
560595
)
561596
elif isinstance(event, C2CMessageCreateEvent):
562597
event._reply_seq += 1
598+
ref_idx = None
599+
if event.message_scene:
600+
ref_idx = next(
601+
(
602+
ext.partition("=")[-1]
603+
for ext in event.message_scene.ext
604+
if ext.startswith("msg_idx=")
605+
),
606+
"",
607+
)
563608
return await self.send_to_c2c(
564609
openid=event.author.id,
565610
message=message,
566611
msg_id=event.id,
567612
msg_seq=event._reply_seq,
613+
msg_ref_id=ref_idx,
568614
)
569615
elif isinstance(event, GroupMessageCreateEvent):
570616
event._reply_seq += 1
617+
ref_idx = None
618+
if event.message_scene:
619+
ref_idx = next(
620+
(
621+
ext.partition("=")[-1]
622+
for ext in event.message_scene.ext
623+
if ext.startswith("msg_idx=")
624+
),
625+
"",
626+
)
571627
return await self.send_to_group(
572628
group_openid=event.group_openid,
573629
message=message,
574630
msg_id=event.id,
575631
msg_seq=event._reply_seq,
632+
msg_ref_id=ref_idx,
576633
)
577634
elif isinstance(event, InteractionCreateEvent):
578635
if gid := event.group_openid:
@@ -1726,7 +1783,7 @@ async def post_c2c_messages(
17261783
ark: MessageArk | None = None,
17271784
embed: MessageEmbed | None = None,
17281785
image: None = None,
1729-
message_reference: None = None,
1786+
message_reference: MessageReference | None = None,
17301787
stream: MessageStream | None = None,
17311788
prompt_keyboard: MessagePromptKeyboard | None = None,
17321789
action_button: MessageActionButton | None = None,
@@ -1964,7 +2021,7 @@ async def post_group_messages(
19642021
ark: MessageArk | None = None,
19652022
embed: MessageEmbed | None = None,
19662023
image: None = None,
1967-
message_reference: None = None,
2024+
message_reference: MessageReference | None = None,
19682025
event_id: str | None = None,
19692026
msg_id: str | None = None,
19702027
msg_seq: int | None = None,

nonebot/adapters/qq/event.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22
from enum import Enum
3-
from typing import TypeVar, cast
3+
from typing import TYPE_CHECKING, TypeVar, cast
44
from typing_extensions import override
55

66
from nonebot.utils import escape_tag
@@ -23,6 +23,7 @@
2323
MessageReaction,
2424
Post,
2525
QQMessage,
26+
QQReplyMessage,
2627
Reply,
2728
RichText,
2829
Thread,
@@ -270,6 +271,10 @@ class GuildMemberRemoveEvent(GuildMemberEvent):
270271
class MessageEvent(Event):
271272
to_me: bool = False
272273

274+
if TYPE_CHECKING:
275+
message: Message
276+
original_message: Message
277+
273278
@override
274279
def get_type(self) -> str:
275280
return "message"
@@ -306,9 +311,9 @@ def get_event_description(self) -> str:
306311

307312
@override
308313
def get_message(self) -> Message:
309-
if not hasattr(self, "_message"):
310-
setattr(self, "_message", Message.from_guild_message(self))
311-
return getattr(self, "_message")
314+
if not hasattr(self, "message"):
315+
self.message = Message.from_guild_message(self)
316+
return self.message
312317

313318

314319
@register_event_class
@@ -360,13 +365,18 @@ class DirectMessageDeleteEvent(MessageDeleteEvent):
360365

361366

362367
class QQMessageEvent(MessageEvent, QQMessage):
368+
reply: QQReplyMessage | None = None
363369
_reply_seq: int = 0
364370

365371
@override
366372
def get_message(self) -> Message:
367-
if not hasattr(self, "_message"):
368-
setattr(self, "_message", Message.from_qq_message(self))
369-
return getattr(self, "_message")
373+
if not hasattr(self, "message"):
374+
self.message = Message.from_qq_message(self)
375+
return self.message
376+
377+
def get_reply_message(self) -> Message | None:
378+
if self.reply:
379+
return Message.from_qq_message(self.reply)
370380

371381

372382
@register_event_class
@@ -396,18 +406,18 @@ class GroupMessageCreateEvent(QQMessageEvent):
396406
__type__ = EventType.GROUP_MESSAGE_CREATE
397407

398408
author: GroupMemberAuthor
399-
group_openid: str
400409
group_id: str
410+
group_openid: str
401411

402412
@override
403413
def get_message(self) -> Message:
404414
# tmp fix to remove space before text due to at not in content
405415
msg = Message.from_qq_message(self)
406416
if msg and msg[0].type == "text":
407417
msg[0].data["text"] = msg[0].data["text"].lstrip()
408-
if not hasattr(self, "_message"):
409-
setattr(self, "_message", msg)
410-
return getattr(self, "_message")
418+
if not hasattr(self, "message"):
419+
self.message = msg
420+
return self.message
411421

412422
@override
413423
def get_user_id(self) -> str:
@@ -731,6 +741,7 @@ class GroupMsgReceiveEvent(GroupRobotEvent):
731741
"GroupAddRobotEvent",
732742
"GroupAtMessageCreateEvent",
733743
"GroupDelRobotEvent",
744+
"GroupMessageCreateEvent",
734745
"GroupMsgReceiveEvent",
735746
"GroupMsgRejectEvent",
736747
"GroupRobotEvent",

0 commit comments

Comments
 (0)