nonebot-adapter-qq 1.6.4__tar.gz → 1.6.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/PKG-INFO +1 -1
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/bot.py +59 -34
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/event.py +1 -1
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/message.py +75 -1
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/qq.py +60 -1
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/pyproject.toml +2 -2
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/LICENSE +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/README.md +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/__init__.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/adapter.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/compat.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/config.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/exception.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/__init__.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/common.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/guild.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/payload.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/permission.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/store.py +0 -0
- {nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/utils.py +0 -0
@@ -63,12 +63,15 @@ from .models import (
|
|
63
63
|
Guild,
|
64
64
|
Media,
|
65
65
|
Member,
|
66
|
+
MessageActionButton,
|
66
67
|
MessageArk,
|
67
68
|
MessageEmbed,
|
68
69
|
MessageKeyboard,
|
69
70
|
MessageMarkdown,
|
71
|
+
MessagePromptKeyboard,
|
70
72
|
MessageReference,
|
71
73
|
MessageSetting,
|
74
|
+
MessageStream,
|
72
75
|
PatchGuildRoleReturn,
|
73
76
|
PinsMessage,
|
74
77
|
PostC2CFilesReturn,
|
@@ -316,6 +319,12 @@ class Bot(BaseBot):
|
|
316
319
|
kwargs["message_reference"] = reference[-1].data["reference"]
|
317
320
|
if keyboard := (message["keyboard"] or None):
|
318
321
|
kwargs["keyboard"] = keyboard[-1].data["keyboard"]
|
322
|
+
if stream := (message["stream"] or None):
|
323
|
+
kwargs["stream"] = stream[-1].data["stream"]
|
324
|
+
if prompt_keyboard := (message["prompt_keyboard"] or None):
|
325
|
+
kwargs["prompt_keyboard"] = prompt_keyboard[-1].data["prompt_keyboard"]
|
326
|
+
if action_button := (message["action_button"] or None):
|
327
|
+
kwargs["action_button"] = action_button[-1].data["action_button"]
|
319
328
|
return kwargs
|
320
329
|
|
321
330
|
@staticmethod
|
@@ -402,7 +411,12 @@ class Bot(BaseBot):
|
|
402
411
|
msg_type = 4
|
403
412
|
elif kwargs.get("ark"):
|
404
413
|
msg_type = 3
|
405
|
-
elif
|
414
|
+
elif (
|
415
|
+
kwargs.get("markdown")
|
416
|
+
or kwargs.get("keyboard")
|
417
|
+
or kwargs.get("prompt_keyboard")
|
418
|
+
or kwargs.get("action_button")
|
419
|
+
):
|
406
420
|
msg_type = 2
|
407
421
|
elif (
|
408
422
|
message["image"]
|
@@ -1668,6 +1682,9 @@ class Bot(BaseBot):
|
|
1668
1682
|
embed: Optional[MessageEmbed] = None,
|
1669
1683
|
image: None = None,
|
1670
1684
|
message_reference: None = None,
|
1685
|
+
stream: Optional[MessageStream] = None,
|
1686
|
+
prompt_keyboard: Optional[MessagePromptKeyboard] = None,
|
1687
|
+
action_button: Optional[MessageActionButton] = None,
|
1671
1688
|
event_id: Optional[str] = None,
|
1672
1689
|
msg_id: Optional[str] = None,
|
1673
1690
|
msg_seq: Optional[int] = None,
|
@@ -1682,42 +1699,50 @@ class Bot(BaseBot):
|
|
1682
1699
|
elif timestamp is None:
|
1683
1700
|
timestamp = int(datetime.now(timezone.utc).timestamp())
|
1684
1701
|
|
1702
|
+
json_data = exclude_none(
|
1703
|
+
{
|
1704
|
+
"msg_type": msg_type,
|
1705
|
+
"content": content,
|
1706
|
+
"markdown": (
|
1707
|
+
markdown.dict(exclude_none=True) if markdown is not None else None
|
1708
|
+
),
|
1709
|
+
"keyboard": (
|
1710
|
+
keyboard.dict(exclude_none=True) if keyboard is not None else None
|
1711
|
+
),
|
1712
|
+
"media": (media.dict(exclude_none=True) if media is not None else None),
|
1713
|
+
"ark": ark.dict(exclude_none=True) if ark is not None else None,
|
1714
|
+
"embed": (embed.dict(exclude_none=True) if embed is not None else None),
|
1715
|
+
"image": image,
|
1716
|
+
"message_reference": (
|
1717
|
+
message_reference.dict(exclude_none=True)
|
1718
|
+
if message_reference is not None
|
1719
|
+
else None
|
1720
|
+
),
|
1721
|
+
"stream": (
|
1722
|
+
stream.dict(exclude_none=True, exclude_unset=True)
|
1723
|
+
if stream is not None
|
1724
|
+
else None
|
1725
|
+
),
|
1726
|
+
"prompt_keyboard": (
|
1727
|
+
prompt_keyboard.dict(exclude_none=True, exclude_unset=True)
|
1728
|
+
if prompt_keyboard is not None
|
1729
|
+
else None
|
1730
|
+
),
|
1731
|
+
"action_button": (
|
1732
|
+
action_button.dict(exclude_none=True)
|
1733
|
+
if action_button is not None
|
1734
|
+
else None
|
1735
|
+
),
|
1736
|
+
"event_id": event_id,
|
1737
|
+
"msg_id": msg_id,
|
1738
|
+
"msg_seq": msg_seq,
|
1739
|
+
"timestamp": timestamp,
|
1740
|
+
}
|
1741
|
+
)
|
1685
1742
|
request = Request(
|
1686
1743
|
"POST",
|
1687
1744
|
self.adapter.get_api_base().joinpath("v2", "users", openid, "messages"),
|
1688
|
-
json=
|
1689
|
-
{
|
1690
|
-
"msg_type": msg_type,
|
1691
|
-
"content": content,
|
1692
|
-
"markdown": (
|
1693
|
-
markdown.dict(exclude_none=True)
|
1694
|
-
if markdown is not None
|
1695
|
-
else None
|
1696
|
-
),
|
1697
|
-
"keyboard": (
|
1698
|
-
keyboard.dict(exclude_none=True)
|
1699
|
-
if keyboard is not None
|
1700
|
-
else None
|
1701
|
-
),
|
1702
|
-
"media": (
|
1703
|
-
media.dict(exclude_none=True) if media is not None else None
|
1704
|
-
),
|
1705
|
-
"ark": ark.dict(exclude_none=True) if ark is not None else None,
|
1706
|
-
"embed": (
|
1707
|
-
embed.dict(exclude_none=True) if embed is not None else None
|
1708
|
-
),
|
1709
|
-
"image": image,
|
1710
|
-
"message_reference": (
|
1711
|
-
message_reference.dict(exclude_none=True)
|
1712
|
-
if message_reference is not None
|
1713
|
-
else None
|
1714
|
-
),
|
1715
|
-
"event_id": event_id,
|
1716
|
-
"msg_id": msg_id,
|
1717
|
-
"msg_seq": msg_seq,
|
1718
|
-
"timestamp": timestamp,
|
1719
|
-
}
|
1720
|
-
),
|
1745
|
+
json=json_data,
|
1721
1746
|
)
|
1722
1747
|
return type_validate_python(PostC2CMessagesReturn, await self._request(request))
|
1723
1748
|
|
@@ -3,7 +3,7 @@ from dataclasses import dataclass
|
|
3
3
|
from io import BytesIO
|
4
4
|
from pathlib import Path
|
5
5
|
import re
|
6
|
-
from typing import TYPE_CHECKING, Optional, TypedDict, Union, overload
|
6
|
+
from typing import TYPE_CHECKING, Literal, Optional, TypedDict, Union, overload
|
7
7
|
from typing_extensions import Self, override
|
8
8
|
|
9
9
|
from nonebot.adapters import Message as BaseMessage
|
@@ -13,11 +13,14 @@ from nonebot.compat import type_validate_python
|
|
13
13
|
from .models import Attachment as QQAttachment
|
14
14
|
from .models import Message as GuildMessage
|
15
15
|
from .models import (
|
16
|
+
MessageActionButton,
|
16
17
|
MessageArk,
|
17
18
|
MessageEmbed,
|
18
19
|
MessageKeyboard,
|
19
20
|
MessageMarkdown,
|
21
|
+
MessagePromptKeyboard,
|
20
22
|
MessageReference,
|
23
|
+
MessageStream,
|
21
24
|
QQMessage,
|
22
25
|
)
|
23
26
|
from .utils import escape, unescape
|
@@ -148,6 +151,35 @@ class MessageSegment(BaseMessageSegment["Message"]):
|
|
148
151
|
},
|
149
152
|
)
|
150
153
|
|
154
|
+
@staticmethod
|
155
|
+
def stream(
|
156
|
+
state: Literal[1, 10, 11, 20],
|
157
|
+
_id: Optional[str],
|
158
|
+
index: int,
|
159
|
+
reset: Optional[bool] = None,
|
160
|
+
) -> "Stream":
|
161
|
+
_data = {
|
162
|
+
"state": state,
|
163
|
+
"index": index,
|
164
|
+
}
|
165
|
+
if _id is not None:
|
166
|
+
_data["id"] = _id
|
167
|
+
|
168
|
+
if reset is not None:
|
169
|
+
_data["reset"] = reset
|
170
|
+
|
171
|
+
return Stream("stream", data={"stream": MessageStream(**_data)})
|
172
|
+
|
173
|
+
@staticmethod
|
174
|
+
def prompt_keyboard(prompt_keyboard: MessagePromptKeyboard) -> "PromptKeyboard":
|
175
|
+
return PromptKeyboard(
|
176
|
+
"prompt_keyboard", data={"prompt_keyboard": prompt_keyboard}
|
177
|
+
)
|
178
|
+
|
179
|
+
@staticmethod
|
180
|
+
def action_button(action_button: MessageActionButton) -> "ActionButton":
|
181
|
+
return ActionButton("action_button", data={"action_button": action_button})
|
182
|
+
|
151
183
|
@override
|
152
184
|
def __add__(
|
153
185
|
self, other: Union[str, "MessageSegment", Iterable["MessageSegment"]]
|
@@ -445,6 +477,48 @@ SEGMENT_TYPE_MAP: dict[str, type[MessageSegment]] = {
|
|
445
477
|
}
|
446
478
|
|
447
479
|
|
480
|
+
class _ActionButtonData(TypedDict):
|
481
|
+
action_button: MessageActionButton
|
482
|
+
|
483
|
+
|
484
|
+
@dataclass
|
485
|
+
class ActionButton(MessageSegment):
|
486
|
+
if TYPE_CHECKING:
|
487
|
+
data: _ActionButtonData
|
488
|
+
|
489
|
+
@override
|
490
|
+
def __str__(self) -> str:
|
491
|
+
return f"<action_button:{self.data['action_button']!r}>"
|
492
|
+
|
493
|
+
|
494
|
+
class _PromptKeyboardData(TypedDict):
|
495
|
+
prompt_keyboard: MessagePromptKeyboard
|
496
|
+
|
497
|
+
|
498
|
+
@dataclass
|
499
|
+
class PromptKeyboard(MessageSegment):
|
500
|
+
if TYPE_CHECKING:
|
501
|
+
data: _PromptKeyboardData
|
502
|
+
|
503
|
+
@override
|
504
|
+
def __str__(self) -> str:
|
505
|
+
return f"<prompt_keyboard:{self.data['prompt_keyboard']!r}>"
|
506
|
+
|
507
|
+
|
508
|
+
class _StreamData(TypedDict):
|
509
|
+
stream: MessageStream
|
510
|
+
|
511
|
+
|
512
|
+
@dataclass
|
513
|
+
class Stream(MessageSegment):
|
514
|
+
if TYPE_CHECKING:
|
515
|
+
data: _StreamData
|
516
|
+
|
517
|
+
@override
|
518
|
+
def __str__(self) -> str:
|
519
|
+
return f"<stream:{self.data['stream']!r}>"
|
520
|
+
|
521
|
+
|
448
522
|
class Message(BaseMessage[MessageSegment]):
|
449
523
|
@classmethod
|
450
524
|
@override
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Optional
|
2
|
+
from typing import Literal, Optional
|
3
3
|
from urllib.parse import urlparse
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
@@ -77,16 +77,75 @@ class PostGroupMembersReturn(BaseModel):
|
|
77
77
|
next_index: Optional[int] = None
|
78
78
|
|
79
79
|
|
80
|
+
class MessageActionButton(BaseModel):
|
81
|
+
template_id: Literal["1", "10"] = "1" # 待废弃字段!!!
|
82
|
+
callback_data: Optional[str] = None
|
83
|
+
feedback: Optional[bool] = None # 反馈按钮(赞踩按钮)
|
84
|
+
tts: Optional[bool] = None # TTS 语音播放按钮
|
85
|
+
re_generate: Optional[bool] = None # 重新生成按钮
|
86
|
+
stop_generate: Optional[bool] = None # 停止生成按钮
|
87
|
+
|
88
|
+
|
89
|
+
class PromptAction(BaseModel):
|
90
|
+
type: Literal[2] = 2
|
91
|
+
|
92
|
+
|
93
|
+
class PromptRenderData(BaseModel):
|
94
|
+
label: str
|
95
|
+
style: Literal[2] = 2
|
96
|
+
|
97
|
+
|
98
|
+
class PromptButton(BaseModel):
|
99
|
+
render_data: PromptRenderData
|
100
|
+
action: PromptAction
|
101
|
+
|
102
|
+
|
103
|
+
class PromptRow(BaseModel):
|
104
|
+
buttons: list[PromptButton]
|
105
|
+
|
106
|
+
|
107
|
+
class PromptContent(BaseModel):
|
108
|
+
rows: list[PromptRow]
|
109
|
+
|
110
|
+
|
111
|
+
class PromptKeyboardModel(BaseModel):
|
112
|
+
content: PromptContent
|
113
|
+
|
114
|
+
|
115
|
+
class MessagePromptKeyboard(BaseModel):
|
116
|
+
keyboard: PromptKeyboardModel
|
117
|
+
|
118
|
+
|
119
|
+
class MessageStream(BaseModel):
|
120
|
+
state: Literal[1, 10, 11, 20]
|
121
|
+
"""1: 正文生成中, 10: 正文生成结束, 11: 引志消息生成中, 20: 引导消息生成结束。"""
|
122
|
+
id: Optional[str] = None
|
123
|
+
"""第一条不用填写,第二条需要填写第一个分片返回的 msgID"""
|
124
|
+
index: int
|
125
|
+
"""从 1 开始"""
|
126
|
+
reset: Optional[bool] = None
|
127
|
+
"""只能用于流式消息没有发送完成时,reset 时 index 需要从 0 开始,需要填写流式 id"""
|
128
|
+
|
129
|
+
|
80
130
|
__all__ = [
|
81
131
|
"Attachment",
|
82
132
|
"FriendAuthor",
|
83
133
|
"GroupMember",
|
84
134
|
"GroupMemberAuthor",
|
85
135
|
"Media",
|
136
|
+
"MessageActionButton",
|
137
|
+
"MessagePromptKeyboard",
|
138
|
+
"MessageStream",
|
86
139
|
"PostC2CFilesReturn",
|
87
140
|
"PostC2CMessagesReturn",
|
88
141
|
"PostGroupFilesReturn",
|
89
142
|
"PostGroupMembersReturn",
|
90
143
|
"PostGroupMessagesReturn",
|
144
|
+
"PromptAction",
|
145
|
+
"PromptButton",
|
146
|
+
"PromptContent",
|
147
|
+
"PromptKeyboardModel",
|
148
|
+
"PromptRenderData",
|
149
|
+
"PromptRow",
|
91
150
|
"QQMessage",
|
92
151
|
]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "nonebot-adapter-qq"
|
3
|
-
version = "1.6.
|
3
|
+
version = "1.6.5"
|
4
4
|
description = "QQ adapter for nonebot2"
|
5
5
|
authors = ["yanyongyu <yyy@nonebot.dev>"]
|
6
6
|
license = "MIT"
|
@@ -27,7 +27,7 @@ typing-extensions = ">=4.4.0, <5.0.0"
|
|
27
27
|
pydantic = ">=1.10.0,<3.0.0,!=2.5.0,!=2.5.1"
|
28
28
|
|
29
29
|
[tool.poetry.group.dev.dependencies]
|
30
|
-
ruff = "^0.
|
30
|
+
ruff = "^0.12.0"
|
31
31
|
nonemoji = "^0.1.3"
|
32
32
|
pre-commit = "^4.0.0"
|
33
33
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{nonebot_adapter_qq-1.6.4 → nonebot_adapter_qq-1.6.5}/nonebot/adapters/qq/models/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|