Skip to content

Commit 4e1b75e

Browse files
committed
⬆️ upgrade adapter qq
resolve [Feature] 关于qq适配器GroupMessageCreateEvent消息类的适配 Fixes #143
1 parent 467e422 commit 4e1b75e

8 files changed

Lines changed: 417 additions & 383 deletions

File tree

pdm.lock

Lines changed: 313 additions & 313 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ name = "nonebot-plugin-alconna"
33
description = "Alconna Adapter for Nonebot"
44
authors = [{ name = "RF-Tar-Railt", email = "rf_tar_railt@qq.com" }]
55
dependencies = [
6-
"tarina<0.8.0,>=0.7.3",
7-
"nepattern<1.0,>=0.7.7",
8-
"arclet-alconna<2.0,>=1.8.43",
6+
"tarina>=0.7.5",
7+
"nepattern>=0.7.8",
8+
"arclet-alconna>=1.8.44",
99
"arclet-alconna-tools>=0.7.12",
10-
"importlib-metadata>=8.7.0",
11-
"nonebot2>=2.4.3",
10+
"importlib-metadata>=9.0.0",
11+
"nonebot2>=2.5.0",
1212
"nonebot-plugin-waiter>=0.8.1",
1313
]
1414
dynamic = ["version"]
@@ -182,30 +182,30 @@ asyncio_default_fixture_loop_scope = "session"
182182

183183
[dependency-groups]
184184
dev = [
185-
"black>=25.9.0",
185+
"black>=26.5.1",
186186
"loguru>=0.7.3",
187-
"ruff>=0.14.0",
187+
"ruff>=0.15.14",
188188
"nonemoji>=0.1.4",
189-
"pre-commit>=4.3.0",
190-
"nonebug>=0.4.3",
189+
"pre-commit>=4.6.0",
190+
"nonebug>=0.4.4",
191191
"pytest-xdist>=3.8.0",
192-
"fastapi>=0.119.0",
193-
"uvicorn[standard]>=0.37.0",
194-
"pydantic>=2.12.1",
195-
"nonebot2[httpx,websockets]>=2.4.3",
196-
"nonebot-adapter-console<0.10.0,>=0.9.0",
192+
"fastapi>=0.136.1",
193+
"uvicorn[standard]>=0.47.0",
194+
"pydantic>=2.13.4",
195+
"nonebot2[httpx,websockets]>=2.5.0",
196+
"nonebot-adapter-console>=0.10.0",
197197
"nonebot-adapter-ding>=2.0.0a16",
198-
"nonebot-adapter-discord>=1.1.3",
198+
"nonebot-adapter-discord>=1.1.7",
199199
"nonebot-adapter-dodo>=0.2.1",
200-
"nonebot-adapter-feishu>=2.6.2",
200+
"nonebot-adapter-feishu>=2.7.2",
201201
"nonebot-adapter-kaiheila>=0.3.4",
202202
"nonebot-adapter-mail>=1.0.0a7",
203203
"nonebot-adapter-mirai>=2.3.3",
204-
"nonebot-adapter-minecraft>=1.8.0",
204+
"nonebot-adapter-minecraft>=1.8.1",
205205
"nonebot-adapter-onebot>=2.4.6",
206-
"nonebot-adapter-qq>=1.6.6",
206+
"nonebot-adapter-qq>=1.7.1",
207207
"nonebot-adapter-red>=0.9.0",
208-
"nonebot-adapter-satori>=0.13.7",
208+
"nonebot-adapter-satori>=1.3.0",
209209
"nonebot-adapter-telegram>=0.1.0b20",
210210
"nonebot-adapter-kritor>=0.3.2",
211211
"nonebot-adapter-tailchat>=0.1.0b13",
@@ -217,24 +217,24 @@ dev = [
217217
"nonebot-plugin-localstore>=0.7.4",
218218
"pyyaml>=6.0.3",
219219
"fix-future-annotations>=0.5.0",
220-
"nonebot-adapter-milky>=1.1.0",
220+
"nonebot-adapter-milky>=1.2.0",
221221
"nonebot-adapter-efchat>=0.1.9.post2",
222-
"pytest-asyncio==0.26.0",
223-
"nonebot-adapter-bilibili-live>=0.2.4",
222+
"pytest-asyncio>=1.3.0",
223+
"nonebot-adapter-bilibili-live>=0.2.5",
224224
"nonebot-adapter-yunhu>=0.1.6",
225225
"nonebot-adapter-vocechat>=0.1.8",
226226
]
227227
test = [
228-
"nonebug>=0.4.3",
228+
"nonebug>=0.4.4",
229229
"pytest-xdist>=3.8.0",
230-
"pytest-asyncio==0.26.0",
231-
"fastapi>=0.119.0",
232-
"uvicorn[standard]>=0.37.0",
233-
"nonebot2[httpx,websockets]>=2.4.3",
234-
"nonebot-adapter-qq>=1.6.6",
230+
"pytest-asyncio>=1.3.0",
231+
"fastapi>=0.136.1",
232+
"uvicorn[standard]>=0.47.0",
233+
"nonebot2[httpx,websockets]>=2.5.0",
234+
"nonebot-adapter-qq>=1.7.1",
235235
"nonebot-adapter-satori>=1.3.0",
236-
"nonebot-adapter-discord>=1.1.3",
237-
"nonebot-adapter-minecraft>=1.8.0",
236+
"nonebot-adapter-discord>=1.1.7",
237+
"nonebot-adapter-minecraft>=1.8.1",
238238
"nonebot-adapter-onebot>=2.4.6",
239239
"nonebot-plugin-filehost>=1.1.1",
240240
"nonebot-plugin-send-anything-anywhere>=0.7.1",
@@ -244,5 +244,5 @@ test = [
244244
"pyyaml>=6.0.3",
245245
"nonebot-adapter-telegram>=0.1.0b20",
246246
"nonebot-adapter-kaiheila>=0.3.4",
247-
"nonebot-adapter-console<0.10.0,>=0.9.0",
247+
"nonebot-adapter-console>=0.10.0",
248248
]

src/nonebot_plugin_alconna/rule.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __init__(
128128
else:
129129
command.prefixes = list(global_config.command_start)
130130
if (config.alconna_use_command_sep if use_cmd_sep is None else use_cmd_sep) and global_config.command_sep:
131-
with command_manager.update(command):
131+
with command_manager.update(command) as _:
132132
command.separators = "".join(global_config.command_sep)
133133
if config.alconna_context_style:
134134
with command_manager.update(command):

src/nonebot_plugin_alconna/typings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ def __init__(
130130
origin=Text,
131131
previous=text,
132132
converter=lambda _, x: (
133-
x if x.styles and all(set(style).issuperset(_.expected) for style in x.styles.values()) else None
134-
), # type: ignore # noqa: E501
133+
x if x.styles and all(set(style).issuperset(_.expected) for style in x.styles.values()) else None # type: ignore # noqa: E501
134+
),
135135
alias=expect.capitalize(),
136136
)
137137
self.pattern = expect

src/nonebot_plugin_alconna/uniseg/adapters/github/exporter.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from nonebot.adapters import Bot, Event
2-
from nonebot.adapters.github.event import (
3-
CommitCommentCreated, # type: ignore
4-
IssueCommentCreated, # type: ignore
5-
PullRequestReviewCommentCreated, # type: ignore
2+
from nonebot.adapters.github.event import ( # type: ignore
3+
CommitCommentCreated,
4+
IssueCommentCreated,
5+
PullRequestReviewCommentCreated,
66
)
77
from nonebot.adapters.github.message import Message, MessageSegment # type: ignore
88

src/nonebot_plugin_alconna/uniseg/adapters/qq/builder.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
from nonebot.adapters.qq.message import Emoji as EmojiSegment
88
from nonebot.adapters.qq.message import Keyboard as KeyboardSegment
99
from nonebot.adapters.qq.message import Markdown as MarkdownSegment
10+
from nonebot.adapters.qq.message import Message as QQMessage
1011
from nonebot.adapters.qq.message import MentionChannel as MentionChannelSegment
1112
from nonebot.adapters.qq.message import MentionEveryone as MentionEveryoneSegment
1213
from nonebot.adapters.qq.message import MentionUser as MentionUserSegment
1314
from nonebot.adapters.qq.message import Reference as ReferenceSegment
1415
from nonebot.adapters.qq.models import Message as GuildMessage
16+
from nonebot.adapters.qq.models import QQReplyMessage
1517
from nonebot.compat import model_dump
1618

1719
from nonebot_plugin_alconna.uniseg.builder import MessageBuilder, build
@@ -32,6 +34,15 @@
3234
)
3335

3436

37+
style_dict = {
38+
0: "secondary",
39+
1: "primary",
40+
2: "info",
41+
3: "danger",
42+
4: "link",
43+
}
44+
45+
3546
class QQMessageBuilder(MessageBuilder):
3647
@classmethod
3748
def get_adapter(cls) -> SupportAdapter:
@@ -45,7 +56,7 @@ def markdown(self, seg: MarkdownSegment):
4556

4657
@build("mention_user")
4758
def mention(self, seg: MentionUserSegment):
48-
return At("user", seg.data["user_id"])
59+
return At("user", seg.data["user_id"], seg.data.get("username"))
4960

5061
@build("mention_channel")
5162
def mention_channel(self, seg: MentionChannelSegment):
@@ -157,7 +168,7 @@ def keyboard(self, seg: KeyboardSegment):
157168
clicked_label=button.render_data.visited_label,
158169
url=button.action.data if button.action.type == 0 else None,
159170
text=button.action.data if button.action.type == 2 else None,
160-
style="grey" if button.render_data.style == 0 else "blue",
171+
style=style_dict.get(button.render_data.style or 0, "grey"),
161172
permission=perm,
162173
)
163174
)
@@ -167,11 +178,8 @@ async def extract_reply(self, event: Event, bot: Bot):
167178
if TYPE_CHECKING:
168179
assert isinstance(event, (GuildMessageEvent, QQMessageEvent))
169180
if rpl := getattr(event, "reply", None):
170-
if TYPE_CHECKING:
171-
assert isinstance(rpl, GuildMessage)
172-
return Reply(
173-
str(rpl.id),
174-
rpl.content,
175-
rpl,
176-
)
181+
if isinstance(rpl, GuildMessage):
182+
return Reply(str(rpl.id), rpl.content, origin=rpl)
183+
if isinstance(rpl, QQReplyMessage):
184+
return Reply(str(rpl.msg_idx), QQMessage.from_qq_message(rpl), origin=rpl)
177185
return None

src/nonebot_plugin_alconna/uniseg/adapters/qq/exporter.py

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
DirectMessageCreateEvent,
1212
ForumEvent,
1313
FriendRobotEvent,
14-
GroupAtMessageCreateEvent,
14+
GroupMessageCreateEvent,
1515
GroupRobotEvent,
1616
GuildEvent,
1717
GuildMemberEvent,
@@ -33,7 +33,7 @@
3333
)
3434
from nonebot.adapters.qq.models.common import Button as ButtonModel
3535
from nonebot.adapters.qq.models.guild import Message as GuildMessage
36-
from tarina import lang
36+
from tarina import LRU, lang
3737

3838
from nonebot_plugin_alconna.uniseg.constraint import SupportScope
3939
from nonebot_plugin_alconna.uniseg.exporter import MessageExporter, SerializeFailed, SupportAdapter, Target, export
@@ -53,6 +53,19 @@
5353
)
5454

5555

56+
style_dict = {
57+
"grey": 0,
58+
"secondary": 0,
59+
"blue": 1,
60+
"primary": 1,
61+
"success": 1,
62+
"info": 2,
63+
"warning": 3,
64+
"danger": 3,
65+
"link": 4,
66+
}
67+
68+
5669
@dataclass
5770
class ButtonSegment(MessageSegment):
5871
@override
@@ -68,6 +81,10 @@ def __str__(self) -> str:
6881

6982

7083
class QQMessageExporter(MessageExporter[Message]):
84+
def __init__(self):
85+
super().__init__()
86+
self.id_ref_cache = LRU(16)
87+
7188
@classmethod
7289
def get_adapter(cls) -> SupportAdapter:
7390
return SupportAdapter.qq
@@ -160,7 +177,7 @@ def get_target(self, event: Event, bot: Bot | None = None) -> Target:
160177
extra={"qq.reply_seq": event._reply_seq},
161178
scope=SupportScope.qq_api,
162179
)
163-
if isinstance(event, GroupAtMessageCreateEvent):
180+
if isinstance(event, GroupMessageCreateEvent):
164181
return Target(
165182
event.group_openid,
166183
source=str(event.id),
@@ -217,7 +234,7 @@ def get_target(self, event: Event, bot: Bot | None = None) -> Target:
217234
def get_message_id(self, event: Event) -> str:
218235
assert isinstance(
219236
event,
220-
(InteractionCreateEvent, GuildMessageEvent, C2CMessageCreateEvent, GroupAtMessageCreateEvent),
237+
(InteractionCreateEvent, GuildMessageEvent, C2CMessageCreateEvent, GroupMessageCreateEvent),
221238
)
222239
return str(event.id)
223240

@@ -296,17 +313,7 @@ def _button(self, seg: Button, bot: Bot | None):
296313
else:
297314
perm = Permission(type=0, specify_user_ids=[i.target for i in seg.permission])
298315
label = str(seg.label)
299-
style_dict = {
300-
"grey": 0,
301-
"secondary": 0,
302-
"blue": 1,
303-
"primary": 1,
304-
"success": 1,
305-
"info": 2,
306-
"warning": 3,
307-
"danger": 3,
308-
"link": 4,
309-
}
316+
310317
return ButtonModel(
311318
id=seg.id or (label if seg.flag == "action" else None),
312319
render_data=RenderData(
@@ -369,8 +376,18 @@ async def send_to(self, target: Target | Event, bot: Bot, message: Message, **kw
369376

370377
if isinstance(target, Event):
371378
assert isinstance(target, QQEvent)
372-
if isinstance(target, (C2CMessageCreateEvent, GroupAtMessageCreateEvent)):
373-
message = message.exclude("mention_channel", "mention_user", "mention_everyone", "reference")
379+
if isinstance(target, (C2CMessageCreateEvent, GroupMessageCreateEvent)) and target.message_scene:
380+
ref_idx = next(
381+
(
382+
ext.partition("=")[-1]
383+
for ext in target.message_scene.ext
384+
if ext.startswith("msg_idx=")
385+
),
386+
"",
387+
)
388+
self.id_ref_cache[target.id] = ref_idx
389+
if isinstance(target, (C2CMessageCreateEvent, GroupMessageCreateEvent)):
390+
message = message.exclude("mention_channel")
374391
return await bot.send(event=target, message=message, **kwargs)
375392

376393
if target.extra.get("qq.reply_seq") is not None:
@@ -390,7 +407,7 @@ async def send_to(self, target: Target | Event, bot: Bot, message: Message, **kw
390407
**kwargs, # type: ignore
391408
)
392409
return await bot.send_to_channel(channel_id=target.id, message=message, msg_id=target.source, **kwargs)
393-
message = message.exclude("mention_channel", "mention_user", "mention_everyone", "reference")
410+
message = message.exclude("mention_channel")
394411
if target.private:
395412
res = await bot.send_to_c2c(
396413
openid=target.id,
@@ -442,7 +459,7 @@ async def recall(self, mid: Any, bot: Bot, context: Target | Event):
442459
group_openid=context.id,
443460
message_id=mid.id, # type: ignore
444461
)
445-
elif isinstance(context, GroupAtMessageCreateEvent):
462+
elif isinstance(context, GroupMessageCreateEvent):
446463
await bot.delete_group_message(
447464
group_openid=context.group_openid,
448465
message_id=mid.id, # type: ignore
@@ -470,7 +487,7 @@ async def recall(self, mid: Any, bot: Bot, context: Target | Event):
470487
openid=context.author.id,
471488
message_id=mid,
472489
)
473-
elif isinstance(context, GroupAtMessageCreateEvent):
490+
elif isinstance(context, GroupMessageCreateEvent):
474491
await bot.delete_group_message(
475492
group_openid=context.group_openid,
476493
message_id=mid,
@@ -515,4 +532,10 @@ async def reaction(self, emoji: Emoji, mid: Any, bot: Bot, context: Target | Eve
515532
def get_reply(self, mid: Any):
516533
if isinstance(mid, GuildMessage):
517534
return Reply(mid.id)
535+
if isinstance(mid, (PostGroupMessagesReturn, PostC2CMessagesReturn)):
536+
ref_idx = self.id_ref_cache.get(mid.id) if mid.id else None
537+
if ref_idx:
538+
return Reply(ref_idx)
539+
if isinstance(mid, str):
540+
return Reply(self.id_ref_cache.get(mid, mid))
518541
raise NotImplementedError

tests/fake.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,15 @@ class FakeEvent(_fake):
211211
guild_id: str = "efgh"
212212
content: str = "test"
213213
author: User = User(id=field.pop("user_id", "123456789"), username=field.pop("username", "foobar"))
214-
_message = field.pop("message", Message("test"))
215214

216215
class Config:
217-
extra = "forbid"
216+
extra = "allow"
217+
message = field.pop("message", Message("test"))
218218

219-
return FakeEvent(id=str(get_msg_id() + 5555), **field)
219+
event = FakeEvent(id=str(get_msg_id() + 5555), **field)
220+
event.message = message
221+
event.original_message = message
222+
return event
220223

221224

222225
def fake_satori_bot_params(self_id: str = "test", platform: str = "test") -> dict:

0 commit comments

Comments
 (0)