nonebot-adapter-qq 1.3.5__tar.gz → 1.4.0__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.3.5 → nonebot_adapter_qq-1.4.0}/PKG-INFO +3 -3
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/adapter.py +12 -10
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/bot.py +21 -19
- nonebot_adapter_qq-1.4.0/nonebot/adapters/qq/compat.py +23 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/config.py +10 -2
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/event.py +5 -10
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/message.py +9 -7
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/common.py +6 -3
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/guild.py +23 -8
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/payload.py +43 -15
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/qq.py +4 -2
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/utils.py +4 -4
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/pyproject.toml +10 -8
- nonebot_adapter_qq-1.3.5/nonebot/adapters/qq/models/_transformer.py +0 -106
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/LICENSE +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/README.md +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/__init__.py +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/exception.py +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/__init__.py +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/permission.py +0 -0
- {nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/store.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nonebot-adapter-qq
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.0
|
4
4
|
Summary: QQ adapter for nonebot2
|
5
5
|
Home-page: https://github.com/nonebot/adapter-qq
|
6
6
|
License: MIT
|
@@ -19,8 +19,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.10
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
22
|
-
Requires-Dist: nonebot2 (>=2.
|
23
|
-
Requires-Dist: pydantic (>=1.
|
22
|
+
Requires-Dist: nonebot2 (>=2.2.0,<3.0.0)
|
23
|
+
Requires-Dist: pydantic (>=1.10.0,<3.0.0,!=2.5.0,!=2.5.1)
|
24
24
|
Requires-Dist: typing-extensions (>=4.4.0,<5.0.0)
|
25
25
|
Requires-Dist: yarl (>=1.9.0,<2.0.0)
|
26
26
|
Project-URL: Documentation, https://github.com/nonebot/adapter-qq#readme
|
@@ -1,11 +1,12 @@
|
|
1
1
|
import sys
|
2
|
+
import json
|
2
3
|
import asyncio
|
3
4
|
from typing_extensions import override
|
4
5
|
from typing import Any, List, Tuple, Literal, Optional
|
5
6
|
|
6
|
-
from pydantic import parse_raw_as
|
7
7
|
from nonebot.utils import escape_tag
|
8
8
|
from nonebot.exception import WebSocketClosed
|
9
|
+
from nonebot.compat import PYDANTIC_V2, type_validate_python
|
9
10
|
from nonebot.drivers import (
|
10
11
|
URL,
|
11
12
|
Driver,
|
@@ -376,36 +377,37 @@ class Adapter(BaseAdapter):
|
|
376
377
|
)
|
377
378
|
|
378
379
|
def get_auth_base(self) -> URL:
|
379
|
-
return URL(self.qq_config.qq_auth_base)
|
380
|
+
return URL(str(self.qq_config.qq_auth_base))
|
380
381
|
|
381
382
|
def get_api_base(self) -> URL:
|
382
383
|
if self.qq_config.qq_is_sandbox:
|
383
|
-
return URL(self.qq_config.qq_sandbox_api_base)
|
384
|
+
return URL(str(self.qq_config.qq_sandbox_api_base))
|
384
385
|
else:
|
385
|
-
return URL(self.qq_config.qq_api_base)
|
386
|
+
return URL(str(self.qq_config.qq_api_base))
|
386
387
|
|
387
388
|
@staticmethod
|
388
389
|
async def receive_payload(bot: Bot, ws: WebSocket) -> Payload:
|
389
|
-
payload =
|
390
|
+
payload = type_validate_python(PayloadType, json.loads(await ws.receive()))
|
390
391
|
if isinstance(payload, Dispatch):
|
391
392
|
bot.on_dispatch(payload)
|
392
393
|
return payload
|
393
394
|
|
394
395
|
@staticmethod
|
395
396
|
def payload_to_json(payload: Payload) -> str:
|
396
|
-
|
397
|
-
payload.
|
398
|
-
|
397
|
+
if PYDANTIC_V2:
|
398
|
+
return payload.model_dump_json(by_alias=True)
|
399
|
+
|
400
|
+
return payload.json(by_alias=True)
|
399
401
|
|
400
402
|
@staticmethod
|
401
403
|
def payload_to_event(payload: Dispatch) -> Event:
|
402
404
|
EventClass = EVENT_CLASSES.get(payload.type, None)
|
403
405
|
if EventClass is None:
|
404
406
|
log("WARNING", f"Unknown payload type: {payload.type}")
|
405
|
-
event = Event
|
407
|
+
event = type_validate_python(Event, payload.data)
|
406
408
|
event.__type__ = payload.type # type: ignore
|
407
409
|
return event
|
408
|
-
return EventClass
|
410
|
+
return type_validate_python(EventClass, payload.data)
|
409
411
|
|
410
412
|
@override
|
411
413
|
async def _call_api(self, bot: Bot, api: str, **data: Any) -> Any:
|
@@ -1296,12 +1296,14 @@ class Bot(BaseBot):
|
|
1296
1296
|
{
|
1297
1297
|
"name": name,
|
1298
1298
|
"description": description,
|
1299
|
-
"start_timestamp":
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1299
|
+
"start_timestamp": (
|
1300
|
+
str(start_timestamp)
|
1301
|
+
if start_timestamp is not None
|
1302
|
+
else None
|
1303
|
+
),
|
1304
|
+
"end_timestamp": (
|
1305
|
+
str(end_timestamp) if end_timestamp is not None else None
|
1306
|
+
),
|
1305
1307
|
"jump_channel_id": jump_channel_id,
|
1306
1308
|
"remind_type": str(remind_type),
|
1307
1309
|
}
|
@@ -1339,16 +1341,18 @@ class Bot(BaseBot):
|
|
1339
1341
|
{
|
1340
1342
|
"name": name,
|
1341
1343
|
"description": description,
|
1342
|
-
"start_timestamp":
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1344
|
+
"start_timestamp": (
|
1345
|
+
str(start_timestamp)
|
1346
|
+
if start_timestamp is not None
|
1347
|
+
else None
|
1348
|
+
),
|
1349
|
+
"end_timestamp": (
|
1350
|
+
str(end_timestamp) if end_timestamp is not None else None
|
1351
|
+
),
|
1348
1352
|
"jump_channel_id": jump_channel_id,
|
1349
|
-
"remind_type":
|
1350
|
-
|
1351
|
-
|
1353
|
+
"remind_type": (
|
1354
|
+
str(remind_type) if remind_type is not None else None
|
1355
|
+
),
|
1352
1356
|
}
|
1353
1357
|
)
|
1354
1358
|
},
|
@@ -1489,8 +1493,7 @@ class Bot(BaseBot):
|
|
1489
1493
|
title: str,
|
1490
1494
|
content: str,
|
1491
1495
|
format: Literal[1, 2, 3],
|
1492
|
-
) -> PutThreadReturn:
|
1493
|
-
...
|
1496
|
+
) -> PutThreadReturn: ...
|
1494
1497
|
|
1495
1498
|
@overload
|
1496
1499
|
async def put_thread(
|
@@ -1500,8 +1503,7 @@ class Bot(BaseBot):
|
|
1500
1503
|
title: str,
|
1501
1504
|
content: RichText,
|
1502
1505
|
format: Literal[4],
|
1503
|
-
) -> PutThreadReturn:
|
1504
|
-
...
|
1506
|
+
) -> PutThreadReturn: ...
|
1505
1507
|
|
1506
1508
|
@API
|
1507
1509
|
async def put_thread(
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from typing import Literal, overload
|
2
|
+
|
3
|
+
from nonebot.compat import PYDANTIC_V2
|
4
|
+
|
5
|
+
__all__ = ("model_validator", "field_validator")
|
6
|
+
|
7
|
+
if PYDANTIC_V2:
|
8
|
+
from pydantic import field_validator as field_validator
|
9
|
+
from pydantic import model_validator as model_validator
|
10
|
+
else:
|
11
|
+
from pydantic import validator, root_validator
|
12
|
+
|
13
|
+
@overload
|
14
|
+
def model_validator(*, mode: Literal["before"]): ...
|
15
|
+
|
16
|
+
@overload
|
17
|
+
def model_validator(*, mode: Literal["after"]): ...
|
18
|
+
|
19
|
+
def model_validator(*, mode: Literal["before", "after"]):
|
20
|
+
return root_validator(pre=mode == "before", allow_reuse=True)
|
21
|
+
|
22
|
+
def field_validator(__field, *fields, mode: Literal["before", "after"] = "after"):
|
23
|
+
return validator(__field, *fields, pre=mode == "before", allow_reuse=True)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import List, Tuple, Optional
|
2
2
|
|
3
|
-
from pydantic import
|
3
|
+
from pydantic import Field, HttpUrl, BaseModel
|
4
|
+
from nonebot.compat import PYDANTIC_V2, ConfigDict
|
4
5
|
|
5
6
|
|
6
7
|
class Intents(BaseModel):
|
@@ -18,6 +19,13 @@ class Intents(BaseModel):
|
|
18
19
|
audio_action: bool = False
|
19
20
|
at_messages: bool = True
|
20
21
|
|
22
|
+
if PYDANTIC_V2:
|
23
|
+
model_config: ConfigDict = ConfigDict(extra="forbid")
|
24
|
+
else:
|
25
|
+
|
26
|
+
class Config:
|
27
|
+
extra = "forbid"
|
28
|
+
|
21
29
|
def to_int(self):
|
22
30
|
return (
|
23
31
|
self.guilds << 0
|
@@ -54,7 +62,7 @@ class BotInfo(BaseModel):
|
|
54
62
|
return self.intent.is_group_enabled
|
55
63
|
|
56
64
|
|
57
|
-
class Config(BaseModel
|
65
|
+
class Config(BaseModel):
|
58
66
|
qq_is_sandbox: bool = False
|
59
67
|
qq_api_base: HttpUrl = Field("https://api.sgroup.qq.com/")
|
60
68
|
qq_sandbox_api_base: HttpUrl = Field("https://sandbox.api.sgroup.qq.com")
|
@@ -443,8 +443,7 @@ class InteractionCreateEvent(NoticeEvent, ButtonInteraction):
|
|
443
443
|
|
444
444
|
|
445
445
|
# Message Audit Event
|
446
|
-
class MessageAuditEvent(NoticeEvent, MessageAudited):
|
447
|
-
...
|
446
|
+
class MessageAuditEvent(NoticeEvent, MessageAudited): ...
|
448
447
|
|
449
448
|
|
450
449
|
@register_event_class
|
@@ -479,8 +478,7 @@ class MessageReactionRemoveEvent(MessageReactionEvent):
|
|
479
478
|
|
480
479
|
|
481
480
|
# Audio Event
|
482
|
-
class AudioEvent(NoticeEvent, AudioAction):
|
483
|
-
...
|
481
|
+
class AudioEvent(NoticeEvent, AudioAction): ...
|
484
482
|
|
485
483
|
|
486
484
|
@register_event_class
|
@@ -514,8 +512,7 @@ class ForumEvent(NoticeEvent, ForumSourceInfo):
|
|
514
512
|
return f"guild_{self.guild_id}_channel_{self.channel_id}_{self.author_id}"
|
515
513
|
|
516
514
|
|
517
|
-
class ForumThreadEvent(ForumEvent, Thread[RichText]):
|
518
|
-
...
|
515
|
+
class ForumThreadEvent(ForumEvent, Thread[RichText]): ...
|
519
516
|
|
520
517
|
|
521
518
|
@register_event_class
|
@@ -533,8 +530,7 @@ class ForumThreadDeleteEvent(ForumThreadEvent):
|
|
533
530
|
__type__ = EventType.FORUM_THREAD_DELETE
|
534
531
|
|
535
532
|
|
536
|
-
class ForumPostEvent(ForumEvent, Post):
|
537
|
-
...
|
533
|
+
class ForumPostEvent(ForumEvent, Post): ...
|
538
534
|
|
539
535
|
|
540
536
|
@register_event_class
|
@@ -547,8 +543,7 @@ class ForumPostDeleteEvent(ForumPostEvent):
|
|
547
543
|
__type__ = EventType.FORUM_POST_DELETE
|
548
544
|
|
549
545
|
|
550
|
-
class ForumReplyEvent(ForumEvent, Reply):
|
551
|
-
...
|
546
|
+
class ForumReplyEvent(ForumEvent, Reply): ...
|
552
547
|
|
553
548
|
|
554
549
|
@register_event_class
|
@@ -108,9 +108,11 @@ class MessageSegment(BaseMessageSegment["Message"]):
|
|
108
108
|
return Markdown(
|
109
109
|
"markdown",
|
110
110
|
data={
|
111
|
-
"markdown":
|
112
|
-
|
113
|
-
|
111
|
+
"markdown": (
|
112
|
+
MessageMarkdown(content=markdown)
|
113
|
+
if isinstance(markdown, str)
|
114
|
+
else markdown
|
115
|
+
)
|
114
116
|
},
|
115
117
|
)
|
116
118
|
|
@@ -120,13 +122,13 @@ class MessageSegment(BaseMessageSegment["Message"]):
|
|
120
122
|
|
121
123
|
@overload
|
122
124
|
@staticmethod
|
123
|
-
def reference(reference: MessageReference) -> "Reference":
|
124
|
-
...
|
125
|
+
def reference(reference: MessageReference) -> "Reference": ...
|
125
126
|
|
126
127
|
@overload
|
127
128
|
@staticmethod
|
128
|
-
def reference(
|
129
|
-
|
129
|
+
def reference(
|
130
|
+
reference: str, ignore_error: Optional[bool] = None
|
131
|
+
) -> "Reference": ...
|
130
132
|
|
131
133
|
@staticmethod
|
132
134
|
def reference(
|
@@ -1,14 +1,17 @@
|
|
1
1
|
from urllib.parse import urlparse
|
2
2
|
from typing import List, Literal, Optional
|
3
3
|
|
4
|
-
from pydantic import BaseModel
|
4
|
+
from pydantic import BaseModel
|
5
|
+
|
6
|
+
from nonebot.adapters.qq.compat import field_validator
|
5
7
|
|
6
8
|
|
7
9
|
# Message Attachment
|
8
10
|
class MessageAttachment(BaseModel):
|
9
11
|
url: str
|
10
12
|
|
11
|
-
@
|
13
|
+
@field_validator("url", mode="after")
|
14
|
+
@classmethod
|
12
15
|
def check_url(cls, v: str):
|
13
16
|
if v and not urlparse(v).hostname:
|
14
17
|
return f"https://{v}"
|
@@ -85,7 +88,7 @@ class Action(BaseModel):
|
|
85
88
|
data: Optional[str] = None
|
86
89
|
reply: Optional[bool] = None
|
87
90
|
enter: Optional[bool] = None
|
88
|
-
anchor: Optional[
|
91
|
+
anchor: Optional[int] = None
|
89
92
|
unsupport_tips: Optional[str] = None
|
90
93
|
click_limit: Optional[int] = None # deprecated
|
91
94
|
at_bot_show_channel_list: Optional[bool] = None # deprecated
|
@@ -1,12 +1,20 @@
|
|
1
|
+
import json
|
1
2
|
from enum import IntEnum
|
2
3
|
from datetime import datetime
|
3
4
|
from typing import List, Union, Generic, TypeVar, Optional
|
4
5
|
|
5
|
-
from pydantic
|
6
|
-
from
|
6
|
+
from pydantic import BaseModel
|
7
|
+
from nonebot.compat import PYDANTIC_V2, model_fields, type_validate_python
|
8
|
+
|
9
|
+
from nonebot.adapters.qq.compat import field_validator, model_validator
|
7
10
|
|
8
11
|
from .common import MessageArk, MessageEmbed, MessageReference, MessageAttachment
|
9
12
|
|
13
|
+
if PYDANTIC_V2:
|
14
|
+
GenericModel = BaseModel
|
15
|
+
else:
|
16
|
+
from pydantic.generics import GenericModel
|
17
|
+
|
10
18
|
T = TypeVar("T")
|
11
19
|
|
12
20
|
|
@@ -329,7 +337,8 @@ class Elem(BaseModel):
|
|
329
337
|
video: Optional[VideoElem] = None
|
330
338
|
url: Optional[URLElem] = None
|
331
339
|
|
332
|
-
@
|
340
|
+
@model_validator(mode="before")
|
341
|
+
@classmethod
|
333
342
|
def infer_type(cls, values: dict):
|
334
343
|
if values.get("type") is not None:
|
335
344
|
return values
|
@@ -373,10 +382,11 @@ class ThreadObjectInfo(BaseModel):
|
|
373
382
|
content: RichText
|
374
383
|
date_time: datetime
|
375
384
|
|
376
|
-
@
|
385
|
+
@field_validator("content", model="before")
|
386
|
+
@classmethod
|
377
387
|
def parse_content(cls, v):
|
378
388
|
if isinstance(v, str):
|
379
|
-
return RichText.
|
389
|
+
return type_validate_python(RichText, json.loads(v))
|
380
390
|
return v
|
381
391
|
|
382
392
|
|
@@ -387,10 +397,15 @@ class ThreadInfo(ThreadObjectInfo, GenericModel, Generic[_T_Title]):
|
|
387
397
|
# 事件推送拿到的title实际上是RichText的JSON字符串,而API调用返回的title是普通文本
|
388
398
|
title: _T_Title
|
389
399
|
|
390
|
-
@
|
400
|
+
@field_validator("title", mode="before")
|
401
|
+
@classmethod
|
391
402
|
def parse_title(cls, v):
|
392
|
-
if
|
393
|
-
|
403
|
+
if (
|
404
|
+
isinstance(v, str)
|
405
|
+
and next(f for f in model_fields(cls) if f.name == "title").annotation
|
406
|
+
is RichText
|
407
|
+
):
|
408
|
+
return type_validate_python(RichText, json.loads(v))
|
394
409
|
return v
|
395
410
|
|
396
411
|
|
@@ -2,9 +2,8 @@ from enum import IntEnum
|
|
2
2
|
from typing import Tuple, Union
|
3
3
|
from typing_extensions import Literal, Annotated
|
4
4
|
|
5
|
-
from pydantic import
|
6
|
-
|
7
|
-
from ._transformer import BoolToIntTransformer, AliasExportTransformer
|
5
|
+
from pydantic import Field, BaseModel
|
6
|
+
from nonebot.compat import PYDANTIC_V2, ConfigDict
|
8
7
|
|
9
8
|
PAYLOAD_FIELD_ALIASES = {"opcode": "op", "data": "d", "sequence": "s", "type": "t"}
|
10
9
|
|
@@ -21,14 +20,22 @@ class Opcode(IntEnum):
|
|
21
20
|
HTTP_CALLBACK_ACK = 12
|
22
21
|
|
23
22
|
|
24
|
-
class Payload(
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
class Payload(BaseModel):
|
24
|
+
if PYDANTIC_V2:
|
25
|
+
model_config: ConfigDict = ConfigDict(
|
26
|
+
extra="allow",
|
27
|
+
populate_by_name=True,
|
28
|
+
alias_generator=lambda x: PAYLOAD_FIELD_ALIASES.get(x, x),
|
29
|
+
)
|
30
|
+
else:
|
31
|
+
|
32
|
+
class Config:
|
33
|
+
extra = "allow"
|
34
|
+
allow_population_by_field_name = True
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
@classmethod
|
37
|
+
def alias_generator(cls, string: str) -> str:
|
38
|
+
return PAYLOAD_FIELD_ALIASES.get(string, string)
|
32
39
|
|
33
40
|
|
34
41
|
class Dispatch(Payload):
|
@@ -43,23 +50,37 @@ class Heartbeat(Payload):
|
|
43
50
|
data: int
|
44
51
|
|
45
52
|
|
46
|
-
class IdentifyData(BaseModel
|
53
|
+
class IdentifyData(BaseModel):
|
47
54
|
token: str
|
48
55
|
intents: int
|
49
56
|
shard: Tuple[int, int]
|
50
57
|
properties: dict
|
51
58
|
|
59
|
+
if PYDANTIC_V2:
|
60
|
+
model_config: ConfigDict = ConfigDict(extra="allow")
|
61
|
+
else:
|
62
|
+
|
63
|
+
class Config:
|
64
|
+
extra = "allow"
|
65
|
+
|
52
66
|
|
53
67
|
class Identify(Payload):
|
54
68
|
opcode: Literal[Opcode.IDENTIFY] = Field(Opcode.IDENTIFY)
|
55
69
|
data: IdentifyData
|
56
70
|
|
57
71
|
|
58
|
-
class ResumeData(BaseModel
|
72
|
+
class ResumeData(BaseModel):
|
59
73
|
token: str
|
60
74
|
session_id: str
|
61
75
|
seq: int
|
62
76
|
|
77
|
+
if PYDANTIC_V2:
|
78
|
+
model_config: ConfigDict = ConfigDict(extra="allow")
|
79
|
+
else:
|
80
|
+
|
81
|
+
class Config:
|
82
|
+
extra = "allow"
|
83
|
+
|
63
84
|
|
64
85
|
class Resume(Payload):
|
65
86
|
opcode: Literal[Opcode.RESUME] = Field(Opcode.RESUME)
|
@@ -74,9 +95,16 @@ class InvalidSession(Payload):
|
|
74
95
|
opcode: Literal[Opcode.INVALID_SESSION] = Field(Opcode.INVALID_SESSION)
|
75
96
|
|
76
97
|
|
77
|
-
class HelloData(BaseModel
|
98
|
+
class HelloData(BaseModel):
|
78
99
|
heartbeat_interval: int
|
79
100
|
|
101
|
+
if PYDANTIC_V2:
|
102
|
+
model_config: ConfigDict = ConfigDict(extra="allow")
|
103
|
+
else:
|
104
|
+
|
105
|
+
class Config:
|
106
|
+
extra = "allow"
|
107
|
+
|
80
108
|
|
81
109
|
class Hello(Payload):
|
82
110
|
opcode: Literal[Opcode.HELLO] = Field(Opcode.HELLO)
|
@@ -87,9 +115,9 @@ class HeartbeatAck(Payload):
|
|
87
115
|
opcode: Literal[Opcode.HEARTBEAT_ACK] = Field(Opcode.HEARTBEAT_ACK)
|
88
116
|
|
89
117
|
|
90
|
-
class HTTPCallbackAck(
|
118
|
+
class HTTPCallbackAck(Payload):
|
91
119
|
opcode: Literal[Opcode.HTTP_CALLBACK_ACK] = Field(Opcode.HTTP_CALLBACK_ACK)
|
92
|
-
data:
|
120
|
+
data: int
|
93
121
|
|
94
122
|
|
95
123
|
PayloadType = Union[
|
@@ -2,7 +2,9 @@ from datetime import datetime
|
|
2
2
|
from typing import List, Optional
|
3
3
|
from urllib.parse import urlparse
|
4
4
|
|
5
|
-
from pydantic import BaseModel
|
5
|
+
from pydantic import BaseModel
|
6
|
+
|
7
|
+
from nonebot.adapters.qq.compat import field_validator
|
6
8
|
|
7
9
|
|
8
10
|
class FriendAuthor(BaseModel):
|
@@ -23,7 +25,7 @@ class Attachment(BaseModel):
|
|
23
25
|
size: Optional[str] = None
|
24
26
|
url: Optional[str] = None
|
25
27
|
|
26
|
-
@
|
28
|
+
@field_validator("url", mode="after")
|
27
29
|
def check_url(cls, v: str):
|
28
30
|
if v and not urlparse(v).hostname:
|
29
31
|
return f"https://{v}"
|
@@ -45,12 +45,12 @@ class API(Generic[B, P, R]):
|
|
45
45
|
self.name = name
|
46
46
|
|
47
47
|
@overload
|
48
|
-
def __get__(self, obj: None, objtype: Type[B]) -> "API[B, P, R]":
|
49
|
-
...
|
48
|
+
def __get__(self, obj: None, objtype: Type[B]) -> "API[B, P, R]": ...
|
50
49
|
|
51
50
|
@overload
|
52
|
-
def __get__(
|
53
|
-
|
51
|
+
def __get__(
|
52
|
+
self, obj: B, objtype: Optional[Type[B]]
|
53
|
+
) -> Callable[P, Awaitable[R]]: ...
|
54
54
|
|
55
55
|
def __get__(
|
56
56
|
self, obj: Optional[B], objtype: Optional[Type[B]] = None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "nonebot-adapter-qq"
|
3
|
-
version = "1.
|
3
|
+
version = "1.4.0"
|
4
4
|
description = "QQ adapter for nonebot2"
|
5
5
|
authors = ["yanyongyu <yyy@nonebot.dev>"]
|
6
6
|
license = "MIT"
|
@@ -21,14 +21,14 @@ packages = [{ include = "nonebot" }]
|
|
21
21
|
[tool.poetry.dependencies]
|
22
22
|
python = "^3.8"
|
23
23
|
yarl = "^1.9.0"
|
24
|
-
|
25
|
-
nonebot2 = "^2.1.0"
|
24
|
+
nonebot2 = "^2.2.0"
|
26
25
|
typing-extensions = ">=4.4.0, <5.0.0"
|
26
|
+
pydantic = ">=1.10.0,<3.0.0,!=2.5.0,!=2.5.1"
|
27
27
|
|
28
28
|
[tool.poetry.group.dev.dependencies]
|
29
|
-
ruff = "^0.
|
29
|
+
ruff = "^0.2.0"
|
30
30
|
isort = "^5.10.1"
|
31
|
-
black = "^
|
31
|
+
black = "^24.0.0"
|
32
32
|
nonemoji = "^0.1.3"
|
33
33
|
pre-commit = "^3.3.0"
|
34
34
|
|
@@ -47,15 +47,17 @@ force_sort_within_sections = true
|
|
47
47
|
extra_standard_library = ["typing_extensions"]
|
48
48
|
|
49
49
|
[tool.ruff]
|
50
|
-
select = ["E", "W", "F", "UP", "C", "T", "Q"]
|
51
|
-
ignore = ["E402", "F403", "F405", "C901", "UP037"]
|
52
|
-
|
53
50
|
line-length = 88
|
54
51
|
target-version = "py38"
|
55
52
|
|
53
|
+
[tool.ruff.lint]
|
54
|
+
select = ["E", "W", "F", "UP", "C", "T", "Q"]
|
55
|
+
ignore = ["E402", "F403", "F405", "C901", "UP037"]
|
56
|
+
|
56
57
|
[tool.pyright]
|
57
58
|
pythonPlatform = "All"
|
58
59
|
pythonVersion = "3.8"
|
60
|
+
defineConstant = { PYDANTIC_V2 = true }
|
59
61
|
|
60
62
|
[build-system]
|
61
63
|
requires = ["poetry-core>=1.0.0"]
|
@@ -1,106 +0,0 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Union, Optional
|
2
|
-
|
3
|
-
from pydantic import BaseModel
|
4
|
-
|
5
|
-
if TYPE_CHECKING:
|
6
|
-
from pydantic.typing import DictStrAny, MappingIntStrAny, AbstractSetIntStr
|
7
|
-
|
8
|
-
|
9
|
-
class ExcludeNoneTransformer(BaseModel):
|
10
|
-
def dict(
|
11
|
-
self,
|
12
|
-
*,
|
13
|
-
include: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
14
|
-
exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
15
|
-
by_alias: bool = False,
|
16
|
-
skip_defaults: Optional[bool] = None,
|
17
|
-
exclude_unset: bool = False,
|
18
|
-
exclude_defaults: bool = False,
|
19
|
-
**kwargs: Any,
|
20
|
-
) -> "DictStrAny":
|
21
|
-
return super().dict(
|
22
|
-
include=include,
|
23
|
-
exclude=exclude,
|
24
|
-
by_alias=by_alias,
|
25
|
-
skip_defaults=skip_defaults,
|
26
|
-
exclude_unset=exclude_unset,
|
27
|
-
exclude_defaults=exclude_defaults,
|
28
|
-
exclude_none=True,
|
29
|
-
)
|
30
|
-
|
31
|
-
|
32
|
-
class BoolToIntTransformer(BaseModel):
|
33
|
-
def dict(
|
34
|
-
self,
|
35
|
-
*,
|
36
|
-
include: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
37
|
-
exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
38
|
-
by_alias: bool = False,
|
39
|
-
skip_defaults: Optional[bool] = None,
|
40
|
-
exclude_unset: bool = False,
|
41
|
-
exclude_defaults: bool = False,
|
42
|
-
exclude_none: bool = False,
|
43
|
-
) -> "DictStrAny":
|
44
|
-
data = super().dict(
|
45
|
-
include=include,
|
46
|
-
exclude=exclude,
|
47
|
-
by_alias=by_alias,
|
48
|
-
skip_defaults=skip_defaults,
|
49
|
-
exclude_unset=exclude_unset,
|
50
|
-
exclude_defaults=exclude_defaults,
|
51
|
-
exclude_none=exclude_none,
|
52
|
-
)
|
53
|
-
for key, value in data.items():
|
54
|
-
if isinstance(value, bool):
|
55
|
-
data[key] = int(value)
|
56
|
-
return data
|
57
|
-
|
58
|
-
|
59
|
-
class IntToStrTransformer(BaseModel):
|
60
|
-
def dict(
|
61
|
-
self,
|
62
|
-
*,
|
63
|
-
include: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
64
|
-
exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
65
|
-
by_alias: bool = False,
|
66
|
-
skip_defaults: Optional[bool] = None,
|
67
|
-
exclude_unset: bool = False,
|
68
|
-
exclude_defaults: bool = False,
|
69
|
-
exclude_none: bool = False,
|
70
|
-
) -> "DictStrAny":
|
71
|
-
data = super().dict(
|
72
|
-
include=include,
|
73
|
-
exclude=exclude,
|
74
|
-
by_alias=by_alias,
|
75
|
-
skip_defaults=skip_defaults,
|
76
|
-
exclude_unset=exclude_unset,
|
77
|
-
exclude_defaults=exclude_defaults,
|
78
|
-
exclude_none=exclude_none,
|
79
|
-
)
|
80
|
-
for key, value in data.items():
|
81
|
-
if isinstance(value, int):
|
82
|
-
data[key] = str(value)
|
83
|
-
return data
|
84
|
-
|
85
|
-
|
86
|
-
class AliasExportTransformer(BaseModel):
|
87
|
-
def dict(
|
88
|
-
self,
|
89
|
-
*,
|
90
|
-
include: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
91
|
-
exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None] = None,
|
92
|
-
skip_defaults: Optional[bool] = None,
|
93
|
-
exclude_unset: bool = False,
|
94
|
-
exclude_defaults: bool = False,
|
95
|
-
exclude_none: bool = False,
|
96
|
-
**kwargs: Any,
|
97
|
-
) -> "DictStrAny":
|
98
|
-
return super().dict(
|
99
|
-
include=include,
|
100
|
-
exclude=exclude,
|
101
|
-
by_alias=True,
|
102
|
-
skip_defaults=skip_defaults,
|
103
|
-
exclude_unset=exclude_unset,
|
104
|
-
exclude_defaults=exclude_defaults,
|
105
|
-
exclude_none=exclude_none,
|
106
|
-
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{nonebot_adapter_qq-1.3.5 → nonebot_adapter_qq-1.4.0}/nonebot/adapters/qq/models/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|