satori-python-core 0.11.4__tar.gz → 0.12.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.
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/PKG-INFO +2 -2
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/pyproject.toml +5 -5
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/__init__.py +1 -1
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/element.py +10 -5
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/model.py +79 -101
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/parser.py +2 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/.mina/core.toml +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/LICENSE +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/README.md +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/config.py +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/const.py +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/event.py +0 -0
- {satori_python_core-0.11.4 → satori_python_core-0.12.0}/src/satori/exception.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: satori-python-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: Satori Protocol SDK for python, specify common part
|
|
5
5
|
Home-page: https://github.com/RF-Tar-Railt/satori-python
|
|
6
6
|
Author-Email: RF-Tar-Railt <rf_tar_railt@qq.com>
|
|
@@ -19,7 +19,7 @@ Project-URL: Repository, https://github.com/RF-Tar-Railt/satori-python
|
|
|
19
19
|
Requires-Python: >=3.8
|
|
20
20
|
Requires-Dist: loguru>=0.7.2
|
|
21
21
|
Requires-Dist: yarl>=1.9.4
|
|
22
|
-
Requires-Dist: typing-extensions>=4.
|
|
22
|
+
Requires-Dist: typing-extensions>=4.7.0
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
|
|
25
25
|
# satori-python
|
|
@@ -7,7 +7,7 @@ authors = [
|
|
|
7
7
|
dependencies = [
|
|
8
8
|
"loguru>=0.7.2",
|
|
9
9
|
"yarl>=1.9.4",
|
|
10
|
-
"typing-extensions>=4.
|
|
10
|
+
"typing-extensions>=4.7.0",
|
|
11
11
|
]
|
|
12
12
|
description = "Satori Protocol SDK for python, specify common part"
|
|
13
13
|
readme = "README.md"
|
|
@@ -23,7 +23,7 @@ classifiers = [
|
|
|
23
23
|
"Programming Language :: Python :: 3.12",
|
|
24
24
|
"Operating System :: OS Independent",
|
|
25
25
|
]
|
|
26
|
-
version = "0.
|
|
26
|
+
version = "0.12.0"
|
|
27
27
|
|
|
28
28
|
[project.license]
|
|
29
29
|
text = "MIT"
|
|
@@ -41,9 +41,9 @@ build-backend = "mina.backend"
|
|
|
41
41
|
[tool.pdm.dev-dependencies]
|
|
42
42
|
dev = [
|
|
43
43
|
"isort>=5.13.2",
|
|
44
|
-
"black>=24.
|
|
45
|
-
"ruff>=0.
|
|
46
|
-
"pre-commit>=3.
|
|
44
|
+
"black>=24.4.0",
|
|
45
|
+
"ruff>=0.4.1",
|
|
46
|
+
"pre-commit>=3.7.0",
|
|
47
47
|
"fix-future-annotations>=0.5.0",
|
|
48
48
|
"mina-build<0.6,>=0.5.1",
|
|
49
49
|
"pdm-mina>=0.3.2",
|
|
@@ -18,13 +18,17 @@ class Element:
|
|
|
18
18
|
|
|
19
19
|
__names__: ClassVar[Tuple[str, ...]]
|
|
20
20
|
|
|
21
|
+
@property
|
|
22
|
+
def children(self) -> List["Element"]:
|
|
23
|
+
return self._children
|
|
24
|
+
|
|
21
25
|
@property
|
|
22
26
|
def tag(self) -> str:
|
|
23
27
|
return self.__class__.__name__.lower()
|
|
24
28
|
|
|
25
29
|
@classmethod
|
|
26
30
|
def unpack(cls, attrs: Dict[str, Any]):
|
|
27
|
-
obj = cls(**{k: v for k, v in attrs.items() if k in cls.__names__})
|
|
31
|
+
obj = cls(**{k: v for k, v in attrs.items() if k in cls.__names__}) # type: ignore
|
|
28
32
|
obj._attrs.update({k: v for k, v in attrs.items() if k not in cls.__names__})
|
|
29
33
|
return obj
|
|
30
34
|
|
|
@@ -132,7 +136,7 @@ class Sharp(Element):
|
|
|
132
136
|
name: Optional[str] = None
|
|
133
137
|
|
|
134
138
|
|
|
135
|
-
@dataclass
|
|
139
|
+
@dataclass(repr=False)
|
|
136
140
|
class Link(Element):
|
|
137
141
|
"""<a> 元素用于显示一个链接。"""
|
|
138
142
|
|
|
@@ -163,7 +167,7 @@ class Resource(Element):
|
|
|
163
167
|
title: Optional[str] = None
|
|
164
168
|
extra: InitVar[Optional[Dict[str, Any]]] = None
|
|
165
169
|
cache: Optional[bool] = None
|
|
166
|
-
timeout: Optional[
|
|
170
|
+
timeout: Optional[int] = None
|
|
167
171
|
|
|
168
172
|
__names__ = ("src", "title")
|
|
169
173
|
|
|
@@ -178,7 +182,7 @@ class Resource(Element):
|
|
|
178
182
|
poster: Optional[str] = None,
|
|
179
183
|
extra: Optional[Dict[str, Any]] = None,
|
|
180
184
|
cache: Optional[bool] = None,
|
|
181
|
-
timeout: Optional[
|
|
185
|
+
timeout: Optional[int] = None,
|
|
182
186
|
**kwargs,
|
|
183
187
|
):
|
|
184
188
|
data: Dict[str, Any] = {"extra": extra}
|
|
@@ -537,7 +541,7 @@ def transform(elements: List[RawElement]) -> List[Element]:
|
|
|
537
541
|
tag = elem.tag()
|
|
538
542
|
if tag in ELEMENT_TYPE_MAP:
|
|
539
543
|
seg_cls = ELEMENT_TYPE_MAP[tag]
|
|
540
|
-
msg.append(seg_cls.unpack(elem.attrs))
|
|
544
|
+
msg.append(seg_cls.unpack(elem.attrs)(*transform(elem.children)))
|
|
541
545
|
elif tag in ("a", "link"):
|
|
542
546
|
link = Link.unpack(elem.attrs)
|
|
543
547
|
if elem.children:
|
|
@@ -547,6 +551,7 @@ def transform(elements: List[RawElement]) -> List[Element]:
|
|
|
547
551
|
button = Button.unpack(elem.attrs)
|
|
548
552
|
if elem.children:
|
|
549
553
|
button(*transform(elem.children))
|
|
554
|
+
msg.append(button)
|
|
550
555
|
elif tag in STYLE_TYPE_MAP:
|
|
551
556
|
seg_cls = STYLE_TYPE_MAP[tag]
|
|
552
557
|
msg.append(seg_cls.unpack(elem.attrs)(*transform(elem.children)))
|
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
from dataclasses import asdict, dataclass
|
|
1
|
+
from dataclasses import asdict, dataclass, field, fields
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from enum import IntEnum
|
|
4
|
-
from typing import Any, Callable, Dict, Generic, List, Optional, TypeVar
|
|
4
|
+
from typing import Any, Callable, ClassVar, Dict, Generic, List, Literal, Optional, TypeVar
|
|
5
|
+
from typing_extensions import TypeAlias
|
|
5
6
|
|
|
6
7
|
from .element import Element, transform
|
|
8
|
+
from .parser import Element as RawElement
|
|
7
9
|
from .parser import parse
|
|
8
10
|
|
|
9
11
|
|
|
12
|
+
@dataclass
|
|
10
13
|
class ModelBase:
|
|
14
|
+
__converter__: ClassVar[Dict[str, Callable[[Any], Any]]] = {}
|
|
15
|
+
|
|
11
16
|
@classmethod
|
|
12
17
|
def parse(cls, raw: dict):
|
|
13
|
-
|
|
18
|
+
fs = fields(cls)
|
|
19
|
+
data = {}
|
|
20
|
+
for fd in fs:
|
|
21
|
+
if fd.name in raw:
|
|
22
|
+
if fd.name in cls.__converter__:
|
|
23
|
+
data[fd.name] = cls.__converter__[fd.name](raw[fd.name])
|
|
24
|
+
else:
|
|
25
|
+
data[fd.name] = raw[fd.name]
|
|
26
|
+
return cls(**data) # type: ignore
|
|
14
27
|
|
|
15
28
|
def dump(self) -> dict:
|
|
16
29
|
raise NotImplementedError
|
|
@@ -30,11 +43,7 @@ class Channel(ModelBase):
|
|
|
30
43
|
name: Optional[str] = None
|
|
31
44
|
parent_id: Optional[str] = None
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
def parse(cls, raw: dict):
|
|
35
|
-
data = raw.copy()
|
|
36
|
-
data["type"] = ChannelType(raw["type"])
|
|
37
|
-
return cls(**data)
|
|
46
|
+
__converter__ = {"type": ChannelType}
|
|
38
47
|
|
|
39
48
|
def dump(self):
|
|
40
49
|
res = {"id": self.id, "type": self.type.value}
|
|
@@ -51,10 +60,6 @@ class Guild(ModelBase):
|
|
|
51
60
|
name: Optional[str] = None
|
|
52
61
|
avatar: Optional[str] = None
|
|
53
62
|
|
|
54
|
-
@classmethod
|
|
55
|
-
def parse(cls, raw: dict):
|
|
56
|
-
return cls(**raw)
|
|
57
|
-
|
|
58
63
|
def dump(self):
|
|
59
64
|
res = {"id": self.id}
|
|
60
65
|
if self.name:
|
|
@@ -72,10 +77,6 @@ class User(ModelBase):
|
|
|
72
77
|
avatar: Optional[str] = None
|
|
73
78
|
is_bot: Optional[bool] = None
|
|
74
79
|
|
|
75
|
-
@classmethod
|
|
76
|
-
def parse(cls, raw: dict):
|
|
77
|
-
return cls(**raw)
|
|
78
|
-
|
|
79
80
|
def dump(self):
|
|
80
81
|
res: Dict[str, Any] = {"id": self.id}
|
|
81
82
|
if self.name:
|
|
@@ -93,25 +94,17 @@ class User(ModelBase):
|
|
|
93
94
|
class Member(ModelBase):
|
|
94
95
|
user: Optional[User] = None
|
|
95
96
|
nick: Optional[str] = None
|
|
96
|
-
name: Optional[str] = None
|
|
97
97
|
avatar: Optional[str] = None
|
|
98
98
|
joined_at: Optional[datetime] = None
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
def parse(cls, raw: dict):
|
|
102
|
-
data = raw.copy()
|
|
103
|
-
if "user" in raw:
|
|
104
|
-
data["user"] = User.parse(raw["user"])
|
|
105
|
-
if "joined_at" in raw:
|
|
106
|
-
data["joined_at"] = datetime.fromtimestamp(int(raw["joined_at"]) / 1000)
|
|
107
|
-
return cls(**data)
|
|
100
|
+
__converter__ = {"user": User.parse, "joined_at": lambda ts: datetime.fromtimestamp(int(ts) / 1000)}
|
|
108
101
|
|
|
109
102
|
def dump(self):
|
|
110
103
|
res = {}
|
|
111
104
|
if self.user:
|
|
112
105
|
res["user"] = self.user.dump()
|
|
113
|
-
if self.nick
|
|
114
|
-
res["nick"] = self.nick
|
|
106
|
+
if self.nick:
|
|
107
|
+
res["nick"] = self.nick
|
|
115
108
|
if self.avatar:
|
|
116
109
|
res["avatar"] = self.avatar
|
|
117
110
|
if self.joined_at:
|
|
@@ -124,10 +117,6 @@ class Role(ModelBase):
|
|
|
124
117
|
id: str
|
|
125
118
|
name: Optional[str] = None
|
|
126
119
|
|
|
127
|
-
@classmethod
|
|
128
|
-
def parse(cls, raw: dict):
|
|
129
|
-
return cls(**raw)
|
|
130
|
-
|
|
131
120
|
def dump(self):
|
|
132
121
|
res = {"id": self.id}
|
|
133
122
|
if self.name:
|
|
@@ -149,17 +138,17 @@ class Login(ModelBase):
|
|
|
149
138
|
user: Optional[User] = None
|
|
150
139
|
self_id: Optional[str] = None
|
|
151
140
|
platform: Optional[str] = None
|
|
141
|
+
features: List[str] = field(default_factory=list)
|
|
142
|
+
proxy_urls: List[str] = field(default_factory=list)
|
|
152
143
|
|
|
153
|
-
|
|
154
|
-
def parse(cls, raw: dict):
|
|
155
|
-
data = raw.copy()
|
|
156
|
-
if "user" in raw:
|
|
157
|
-
data["user"] = User(**raw["user"])
|
|
158
|
-
data["status"] = LoginStatus(data["status"])
|
|
159
|
-
return cls(**data)
|
|
144
|
+
__converter__ = {"user": User.parse, "status": LoginStatus}
|
|
160
145
|
|
|
161
146
|
def dump(self):
|
|
162
|
-
res: Dict[str, Any] = {
|
|
147
|
+
res: Dict[str, Any] = {
|
|
148
|
+
"status": self.status.value,
|
|
149
|
+
"features": self.features,
|
|
150
|
+
"proxy_urls": self.proxy_urls,
|
|
151
|
+
}
|
|
163
152
|
if self.user:
|
|
164
153
|
res["user"] = self.user.dump()
|
|
165
154
|
if self.self_id:
|
|
@@ -175,10 +164,6 @@ class ArgvInteraction(ModelBase):
|
|
|
175
164
|
arguments: list
|
|
176
165
|
options: Any
|
|
177
166
|
|
|
178
|
-
@classmethod
|
|
179
|
-
def parse(cls, raw: dict):
|
|
180
|
-
return cls(**raw)
|
|
181
|
-
|
|
182
167
|
def dump(self):
|
|
183
168
|
return asdict(self)
|
|
184
169
|
|
|
@@ -187,10 +172,6 @@ class ArgvInteraction(ModelBase):
|
|
|
187
172
|
class ButtonInteraction(ModelBase):
|
|
188
173
|
id: str
|
|
189
174
|
|
|
190
|
-
@classmethod
|
|
191
|
-
def parse(cls, raw: dict):
|
|
192
|
-
return cls(**raw)
|
|
193
|
-
|
|
194
175
|
def dump(self):
|
|
195
176
|
return asdict(self)
|
|
196
177
|
|
|
@@ -245,23 +226,19 @@ class MessageObject(ModelBase):
|
|
|
245
226
|
|
|
246
227
|
@classmethod
|
|
247
228
|
def parse(cls, raw: dict):
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
"content"
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
data["created_at"] = datetime.fromtimestamp(int(raw["created_at"]) / 1000)
|
|
262
|
-
if "updated_at" in raw:
|
|
263
|
-
data["updated_at"] = datetime.fromtimestamp(int(raw["updated_at"]) / 1000)
|
|
264
|
-
return cls(**data)
|
|
229
|
+
if "elements" in raw and "content" not in raw:
|
|
230
|
+
content = [RawElement(*item.values()) for item in raw["elements"]]
|
|
231
|
+
raw["content"] = "".join(str(i) for i in content)
|
|
232
|
+
return super().parse(raw)
|
|
233
|
+
|
|
234
|
+
__converter__ = {
|
|
235
|
+
"channel": Channel.parse,
|
|
236
|
+
"guild": Guild.parse,
|
|
237
|
+
"member": Member.parse,
|
|
238
|
+
"user": User.parse,
|
|
239
|
+
"created_at": lambda ts: datetime.fromtimestamp(int(ts) / 1000),
|
|
240
|
+
"updated_at": lambda ts: datetime.fromtimestamp(int(ts) / 1000),
|
|
241
|
+
}
|
|
265
242
|
|
|
266
243
|
def dump(self):
|
|
267
244
|
res: Dict[str, Any] = {"id": self.id, "content": self.content}
|
|
@@ -281,7 +258,7 @@ class MessageObject(ModelBase):
|
|
|
281
258
|
|
|
282
259
|
|
|
283
260
|
@dataclass
|
|
284
|
-
class Event:
|
|
261
|
+
class Event(ModelBase):
|
|
285
262
|
id: int
|
|
286
263
|
type: str
|
|
287
264
|
platform: str
|
|
@@ -301,40 +278,19 @@ class Event:
|
|
|
301
278
|
_type: Optional[str] = None
|
|
302
279
|
_data: Optional[dict] = None
|
|
303
280
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if "channel" in raw:
|
|
318
|
-
data["channel"] = Channel.parse(raw["channel"])
|
|
319
|
-
if "guild" in raw:
|
|
320
|
-
data["guild"] = Guild.parse(raw["guild"])
|
|
321
|
-
if "login" in raw:
|
|
322
|
-
data["login"] = Login.parse(raw["login"])
|
|
323
|
-
if "member" in raw:
|
|
324
|
-
data["member"] = Member.parse(raw["member"])
|
|
325
|
-
if "message" in raw:
|
|
326
|
-
data["message"] = MessageObject.parse(raw["message"])
|
|
327
|
-
if "operator" in raw:
|
|
328
|
-
data["operator"] = User.parse(raw["operator"])
|
|
329
|
-
if "role" in raw:
|
|
330
|
-
data["role"] = Role.parse(raw["role"])
|
|
331
|
-
if "user" in raw:
|
|
332
|
-
data["user"] = User.parse(raw["user"])
|
|
333
|
-
if "_type" in raw:
|
|
334
|
-
data["_type"] = raw["_type"]
|
|
335
|
-
if "_data" in raw:
|
|
336
|
-
data["_data"] = raw["_data"]
|
|
337
|
-
return cls(**data)
|
|
281
|
+
__converter__ = {
|
|
282
|
+
"timestamp": lambda ts: datetime.fromtimestamp(int(ts) / 1000),
|
|
283
|
+
"argv": ArgvInteraction.parse,
|
|
284
|
+
"button": ButtonInteraction.parse,
|
|
285
|
+
"channel": Channel.parse,
|
|
286
|
+
"guild": Guild.parse,
|
|
287
|
+
"login": Login.parse,
|
|
288
|
+
"member": Member.parse,
|
|
289
|
+
"message": MessageObject.parse,
|
|
290
|
+
"operator": User.parse,
|
|
291
|
+
"role": Role.parse,
|
|
292
|
+
"user": User.parse,
|
|
293
|
+
}
|
|
338
294
|
|
|
339
295
|
def dump(self):
|
|
340
296
|
res = {
|
|
@@ -380,8 +336,8 @@ class PageResult(ModelBase, Generic[T]):
|
|
|
380
336
|
next: Optional[str] = None
|
|
381
337
|
|
|
382
338
|
@classmethod
|
|
383
|
-
def parse(cls, raw: dict, parser: Callable[[dict], T]) -> "PageResult[T]":
|
|
384
|
-
data = [parser(item) for item in raw["data"]]
|
|
339
|
+
def parse(cls, raw: dict, parser: Optional[Callable[[dict], T]] = None) -> "PageResult[T]":
|
|
340
|
+
data = [(parser or ModelBase.parse)(item) for item in raw["data"]]
|
|
385
341
|
return cls(data, raw.get("next"))
|
|
386
342
|
|
|
387
343
|
def dump(self):
|
|
@@ -389,3 +345,25 @@ class PageResult(ModelBase, Generic[T]):
|
|
|
389
345
|
if self.next:
|
|
390
346
|
res["next"] = self.next
|
|
391
347
|
return res
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@dataclass
|
|
351
|
+
class PageDequeResult(PageResult[T]):
|
|
352
|
+
prev: Optional[str] = None
|
|
353
|
+
|
|
354
|
+
@classmethod
|
|
355
|
+
def parse(cls, raw: dict, parser: Optional[Callable[[dict], T]] = None) -> "PageDequeResult[T]":
|
|
356
|
+
data = [(parser or ModelBase.parse)(item) for item in raw["data"]]
|
|
357
|
+
return cls(data, raw.get("next"), raw.get("prev"))
|
|
358
|
+
|
|
359
|
+
def dump(self):
|
|
360
|
+
res: dict = {"data": [item.dump() for item in self.data]}
|
|
361
|
+
if self.next:
|
|
362
|
+
res["next"] = self.next
|
|
363
|
+
if self.prev:
|
|
364
|
+
res["prev"] = self.prev
|
|
365
|
+
return res
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
Direction: TypeAlias = Literal["before", "after", "around"]
|
|
369
|
+
Order: TypeAlias = Literal["asc", "desc"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|