satori-python-server 0.11.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: satori-python-server
3
- Version: 0.11.5
3
+ Version: 0.12.0
4
4
  Summary: Satori Protocol SDK for python, specify server 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>
@@ -26,7 +26,7 @@ classifiers = [
26
26
  "Programming Language :: Python :: 3.12",
27
27
  "Operating System :: OS Independent",
28
28
  ]
29
- version = "0.11.5"
29
+ version = "0.12.0"
30
30
 
31
31
  [project.license]
32
32
  text = "MIT"
@@ -6,7 +6,7 @@ import signal
6
6
  import threading
7
7
  from contextlib import suppress
8
8
  from traceback import print_exc
9
- from typing import Any, Callable, Iterable, Literal, cast, overload
9
+ from typing import Any, Callable, Iterable, cast
10
10
 
11
11
  import aiohttp
12
12
  from creart import it
@@ -24,15 +24,17 @@ from satori.config import WebhookInfo
24
24
  from satori.const import Api
25
25
  from satori.model import Event, ModelBase, Opcode
26
26
 
27
- from . import route
28
27
  from .adapter import Adapter as Adapter
29
28
  from .conection import WebsocketConnection
30
- from .model import Provider
29
+ from .model import Provider as Provider
31
30
  from .model import Request as Request
32
- from .model import Router
31
+ from .model import Router as Router
32
+ from .route import INTERAL
33
+ from .route import RouteCall as RouteCall
34
+ from .route import RouterMixin as RouterMixin
33
35
 
34
36
 
35
- class Server(Service):
37
+ class Server(Service, RouterMixin):
36
38
  id = "satori-python.server"
37
39
  required: set[str] = {"asgi.service/uvicorn"}
38
40
  stages: set[str] = {"preparing", "blocking", "cleanup"}
@@ -78,172 +80,19 @@ class Server(Service):
78
80
  else:
79
81
  raise TypeError(f"Unknown config type: {item}")
80
82
 
81
- @overload
82
- def route(
83
- self, path: Literal[Api.MESSAGE_CREATE]
84
- ) -> Callable[[route.MESSAGE_CREATE], route.MESSAGE_CREATE]: ...
85
-
86
- @overload
87
- def route(
88
- self, path: Literal[Api.MESSAGE_UPDATE]
89
- ) -> Callable[[route.MESSAGE_UPDATE], route.MESSAGE_UPDATE]: ...
90
-
91
- @overload
92
- def route(self, path: Literal[Api.MESSAGE_GET]) -> Callable[[route.MESSAGE_GET], route.MESSAGE_GET]: ...
93
-
94
- @overload
95
- def route(
96
- self, path: Literal[Api.MESSAGE_DELETE]
97
- ) -> Callable[[route.MESSAGE_DELETE], route.MESSAGE_DELETE]: ...
98
-
99
- @overload
100
- def route(
101
- self, path: Literal[Api.MESSAGE_LIST]
102
- ) -> Callable[[route.MESSAGE_LIST], route.MESSAGE_LIST]: ...
103
-
104
- @overload
105
- def route(self, path: Literal[Api.CHANNEL_GET]) -> Callable[[route.CHANNEL_GET], route.CHANNEL_GET]: ...
106
-
107
- @overload
108
- def route(
109
- self, path: Literal[Api.CHANNEL_LIST]
110
- ) -> Callable[[route.CHANNEL_LIST], route.CHANNEL_LIST]: ...
111
-
112
- @overload
113
- def route(
114
- self, path: Literal[Api.CHANNEL_CREATE]
115
- ) -> Callable[[route.CHANNEL_CREATE], route.CHANNEL_CREATE]: ...
116
-
117
- @overload
118
- def route(
119
- self, path: Literal[Api.CHANNEL_UPDATE]
120
- ) -> Callable[[route.CHANNEL_UPDATE], route.CHANNEL_UPDATE]: ...
121
-
122
- @overload
123
- def route(
124
- self, path: Literal[Api.CHANNEL_DELETE]
125
- ) -> Callable[[route.CHANNEL_DELETE], route.CHANNEL_DELETE]: ...
126
-
127
- @overload
128
- def route(
129
- self, path: Literal[Api.CHANNEL_MUTE]
130
- ) -> Callable[[route.CHANNEL_MUTE], route.CHANNEL_MUTE]: ...
131
-
132
- @overload
133
- def route(
134
- self, path: Literal[Api.USER_CHANNEL_CREATE]
135
- ) -> Callable[[route.ROUTE_USER_CHANNEL_CREATE], route.ROUTE_USER_CHANNEL_CREATE]: ...
136
-
137
- @overload
138
- def route(self, path: Literal[Api.GUILD_GET]) -> Callable[[route.GUILD_GET], route.GUILD_GET]: ...
139
-
140
- @overload
141
- def route(self, path: Literal[Api.GUILD_LIST]) -> Callable[[route.GUILD_LIST], route.GUILD_LIST]: ...
142
-
143
- @overload
144
- def route(self, path: Literal[Api.GUILD_APPROVE]) -> Callable[[route.APPROVE], route.APPROVE]: ...
145
-
146
- @overload
147
- def route(
148
- self, path: Literal[Api.GUILD_MEMBER_LIST]
149
- ) -> Callable[[route.GUILD_MEMBER_LIST], route.GUILD_MEMBER_LIST]: ...
150
-
151
- @overload
152
- def route(
153
- self, path: Literal[Api.GUILD_MEMBER_GET]
154
- ) -> Callable[[route.GUILD_MEMBER_GET], route.GUILD_MEMBER_GET]: ...
155
-
156
- @overload
157
- def route(
158
- self, path: Literal[Api.GUILD_MEMBER_KICK]
159
- ) -> Callable[[route.GUILD_MEMBER_KICK], route.GUILD_MEMBER_KICK]: ...
160
-
161
- @overload
162
- def route(
163
- self, path: Literal[Api.GUILD_MEMBER_MUTE]
164
- ) -> Callable[[route.GUILD_MEMBER_MUTE], route.GUILD_MEMBER_MUTE]: ...
165
-
166
- @overload
167
- def route(self, path: Literal[Api.GUILD_MEMBER_APPROVE]) -> Callable[[route.APPROVE], route.APPROVE]: ...
168
-
169
- @overload
170
- def route(
171
- self, path: Literal[Api.GUILD_MEMBER_ROLE_SET]
172
- ) -> Callable[[route.GUILD_MEMBER_ROLE_SET], route.GUILD_MEMBER_ROLE_SET]: ...
173
-
174
- @overload
175
- def route(
176
- self, path: Literal[Api.GUILD_MEMBER_ROLE_UNSET]
177
- ) -> Callable[[route.GUILD_MEMBER_ROLE_UNSET], route.GUILD_MEMBER_ROLE_UNSET]: ...
178
-
179
- @overload
180
- def route(
181
- self, path: Literal[Api.GUILD_ROLE_LIST]
182
- ) -> Callable[[route.GUILD_ROLE_LIST], route.GUILD_ROLE_LIST]: ...
183
-
184
- @overload
185
- def route(
186
- self, path: Literal[Api.GUILD_ROLE_CREATE]
187
- ) -> Callable[[route.GUILD_ROLE_CREATE], route.GUILD_ROLE_CREATE]: ...
188
-
189
- @overload
190
- def route(
191
- self, path: Literal[Api.GUILD_ROLE_UPDATE]
192
- ) -> Callable[[route.GUILD_ROLE_UPDATE], route.GUILD_ROLE_UPDATE]: ...
193
-
194
- @overload
195
- def route(
196
- self, path: Literal[Api.GUILD_ROLE_DELETE]
197
- ) -> Callable[[route.GUILD_ROLE_DELETE], route.GUILD_ROLE_DELETE]: ...
198
-
199
- @overload
200
- def route(
201
- self, path: Literal[Api.REACTION_CREATE]
202
- ) -> Callable[[route.REACTION_CREATE], route.REACTION_CREATE]: ...
203
-
204
- @overload
205
- def route(
206
- self, path: Literal[Api.REACTION_DELETE]
207
- ) -> Callable[[route.REACTION_DELETE], route.REACTION_DELETE]: ...
208
-
209
- @overload
210
- def route(
211
- self, path: Literal[Api.REACTION_CLEAR]
212
- ) -> Callable[[route.REACTION_CLEAR], route.REACTION_CLEAR]: ...
213
-
214
- @overload
215
- def route(
216
- self, path: Literal[Api.REACTION_LIST]
217
- ) -> Callable[[route.REACTION_LIST], route.REACTION_LIST]: ...
218
-
219
- @overload
220
- def route(self, path: Literal[Api.LOGIN_GET]) -> Callable[[route.LOGIN_GET], route.LOGIN_GET]: ...
221
-
222
- @overload
223
- def route(self, path: Literal[Api.USER_GET]) -> Callable[[route.USER_GET], route.USER_GET]: ...
224
-
225
- @overload
226
- def route(self, path: Literal[Api.FRIEND_LIST]) -> Callable[[route.FRIEND_LIST], route.FRIEND_LIST]: ...
227
-
228
- @overload
229
- def route(self, path: Literal[Api.FRIEND_APPROVE]) -> Callable[[route.APPROVE], route.APPROVE]: ...
230
-
231
- @overload
232
- def route(self, path: str) -> Callable[[route.INTERAL], route.INTERAL]: ...
233
-
234
- def route(self, path: str | Api) -> Callable[[route.Router], route.Router]:
83
+ def _route(self, path: str | Api) -> Callable[[RouteCall], RouteCall]:
235
84
  """注册一个路由
236
85
 
237
86
  Args:
238
87
  path (str | Api): 路由路径;若 path 不属于 Api,则会被认为是内部接口
239
88
  """
240
89
 
241
- def wrapper(func: route.INTERAL):
90
+ def wrapper(func: INTERAL):
242
91
  async def handler(request: StarletteRequest):
243
92
  res = await func(
244
93
  Request(
245
94
  cast(dict, request.headers.mutablecopy()),
246
- path if isinstance(path, str) else path.value,
95
+ f"internal/{path}" if isinstance(path, str) else path.value,
247
96
  await request.json(),
248
97
  )
249
98
  )
@@ -309,34 +158,33 @@ class Server(Service):
309
158
  finally:
310
159
  self.connections.remove(connection)
311
160
 
161
+ async def admin_login_list_handler(self, request: StarletteRequest):
162
+ logins = []
163
+ for provider in self.providers:
164
+ logins.extend(await provider.get_logins())
165
+ return JSONResponse(content=[lo.dump() for lo in logins])
166
+
312
167
  async def http_server_handler(self, request: StarletteRequest):
313
168
  if not self.routers:
314
- return Response(status_code=404)
169
+ return Response(status_code=404, content=request.path_params["method"])
315
170
  for _router in self.routers:
316
171
  if _router.validate_headers(cast(dict, request.headers.mutablecopy())):
317
172
  method = request.path_params["method"]
318
- if method.startswith("internal/"):
319
- res = await _router.call_internal_api(
320
- Request(
321
- cast(dict, request.headers.mutablecopy()),
322
- method[len("internal/") :],
323
- await request.json(),
324
- )
325
- )
326
- else:
327
- res = await _router.call_api(
328
- Request(
329
- cast(dict, request.headers.mutablecopy()),
330
- method,
331
- await request.json(),
332
- )
173
+ if method not in _router.routes:
174
+ return Response(status_code=404, content=method)
175
+ res = await _router.routes[method](
176
+ Request(
177
+ cast(dict, request.headers.mutablecopy()),
178
+ method,
179
+ await request.json(),
333
180
  )
181
+ )
334
182
  if isinstance(res, ModelBase):
335
183
  return JSONResponse(content=res.dump())
336
184
  if res and isinstance(res, list) and isinstance(res[0], ModelBase):
337
185
  return JSONResponse(content=[_.dump() for _ in res])
338
186
  return res if isinstance(res, Response) else JSONResponse(content=res)
339
- return Response(status_code=401)
187
+ return Response(status_code=401, content=request.path_params["method"])
340
188
 
341
189
  async def launch(self, manager: Launart):
342
190
  for _adapter in self._adapters:
@@ -347,6 +195,11 @@ class Server(Service):
347
195
  app = Starlette(
348
196
  routes=[
349
197
  WebSocketRoute(f"{self.path}/{self.version}/events", self.websocket_server_handler),
198
+ Route(
199
+ f"{self.path}/{self.version}/admin/login.list",
200
+ self.admin_login_list_handler,
201
+ methods=["POST"],
202
+ ),
350
203
  *self.routes,
351
204
  Route(
352
205
  f"{self.path}/{self.version}/{{method:path}}",
@@ -0,0 +1,45 @@
1
+ from abc import abstractmethod
2
+ from typing import Any, AsyncIterator, Callable, Dict, List, Union
3
+
4
+ from launart import Service
5
+
6
+ from ..const import Api
7
+ from ..model import Event, Login
8
+ from .route import RouteCall, RouterMixin
9
+
10
+
11
+ class Adapter(Service, RouterMixin):
12
+ routes: Dict[str, RouteCall[Any, Any]]
13
+
14
+ @abstractmethod
15
+ def get_platform(self) -> str: ...
16
+
17
+ @abstractmethod
18
+ def publisher(self) -> AsyncIterator[Event]: ...
19
+
20
+ @abstractmethod
21
+ def validate_headers(self, headers: Dict[str, Any]) -> bool: ...
22
+
23
+ @abstractmethod
24
+ def authenticate(self, token: str) -> bool: ...
25
+
26
+ @abstractmethod
27
+ async def get_logins(self) -> List[Login]: ...
28
+
29
+ def _route(self, path: Union[str, Api]) -> Callable[[RouteCall], RouteCall]:
30
+ def wrapper(func: RouteCall):
31
+ if isinstance(path, Api):
32
+ self.routes[path.value] = func
33
+ else:
34
+ self.routes[f"internal/{path}"] = func
35
+ return func
36
+
37
+ return wrapper
38
+
39
+ def __init__(self):
40
+ super().__init__()
41
+ self.routes = {}
42
+
43
+ @property
44
+ def id(self):
45
+ return f"satori-python.adapter.{self.get_platform()}#{id(self)}"
@@ -1,11 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Any, AsyncIterator, Generic, Protocol, TypeVar, Union, runtime_checkable
4
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Generic, Protocol, TypeVar, Union, runtime_checkable
5
5
 
6
6
  from satori.const import Api
7
7
  from satori.model import Event, Login
8
8
 
9
+ if TYPE_CHECKING:
10
+ from .route import RouteCall
11
+
9
12
  JsonType = Union[list, dict, str, int, bool, float, None]
10
13
  TA = TypeVar("TA", str, Api)
11
14
  TP = TypeVar("TP")
@@ -29,8 +32,6 @@ class Provider(Protocol):
29
32
 
30
33
  @runtime_checkable
31
34
  class Router(Protocol):
32
- def validate_headers(self, headers: dict[str, Any]) -> bool: ...
35
+ routes: dict[str, RouteCall[Any, Any]]
33
36
 
34
- async def call_api(self, request: Request[Any]) -> Any: ...
35
-
36
- async def call_internal_api(self, request: Request[Any]) -> Any: ...
37
+ def validate_headers(self, headers: dict[str, Any]) -> bool: ...
@@ -0,0 +1,396 @@
1
+ from abc import ABCMeta, abstractmethod
2
+ from typing import Any, Awaitable, Callable, Dict, List, Literal, Protocol, TypeVar, Union, overload
3
+ from typing_extensions import NotRequired, TypeAlias, TypedDict
4
+
5
+ from satori.model import (
6
+ Channel,
7
+ Direction,
8
+ Guild,
9
+ Login,
10
+ Member,
11
+ MessageObject,
12
+ ModelBase,
13
+ Order,
14
+ PageDequeResult,
15
+ PageResult,
16
+ Role,
17
+ User,
18
+ )
19
+
20
+ from .. import Api
21
+ from .model import Request
22
+
23
+ T = TypeVar("T")
24
+ R = TypeVar("R", covariant=True)
25
+
26
+
27
+ class RouteCall(Protocol[T, R]):
28
+ def __call__(self, request: Request[T]) -> Awaitable[R]: ...
29
+
30
+
31
+ INTERAL: TypeAlias = RouteCall[
32
+ Any, Union[ModelBase, List[ModelBase], Dict[str, Any], List[Dict[str, Any]], None]
33
+ ]
34
+
35
+
36
+ class MessageParam(TypedDict):
37
+ channel_id: str
38
+ content: str
39
+
40
+
41
+ MESSAGE_CREATE: TypeAlias = RouteCall[MessageParam, Union[List[MessageObject], List[Dict[str, Any]]]]
42
+ MESSAGE_GET: TypeAlias = RouteCall[MessageParam, Union[MessageObject, Dict[str, Any]]]
43
+ MESSAGE_DELETE: TypeAlias = RouteCall[MessageParam, None]
44
+
45
+
46
+ class MessageUpdateParam(TypedDict):
47
+ channel_id: str
48
+ message_id: str
49
+ content: str
50
+
51
+
52
+ MESSAGE_UPDATE: TypeAlias = RouteCall[MessageUpdateParam, None]
53
+
54
+
55
+ class MessageListParam(TypedDict):
56
+ channel_id: str
57
+ next: NotRequired[str]
58
+ direction: NotRequired[Direction]
59
+ limit: NotRequired[int]
60
+ order: NotRequired[Order]
61
+
62
+
63
+ MESSAGE_LIST: TypeAlias = RouteCall[MessageListParam, Union[PageDequeResult[MessageObject], Dict[str, Any]]]
64
+
65
+
66
+ class ChannelParam(TypedDict):
67
+ channel_id: str
68
+
69
+
70
+ CHANNEL_GET: TypeAlias = RouteCall[ChannelParam, Union[Channel, Dict[str, Any]]]
71
+ CHANNEL_DELETE: TypeAlias = RouteCall[ChannelParam, None]
72
+
73
+
74
+ class ChannelListParam(TypedDict):
75
+ guild_id: str
76
+ next: NotRequired[str]
77
+
78
+
79
+ CHANNEL_LIST: TypeAlias = RouteCall[ChannelListParam, Union[PageResult[Channel], Dict[str, Any]]]
80
+
81
+
82
+ class ChanneCreateParam(TypedDict):
83
+ guild_id: str
84
+ data: dict
85
+
86
+
87
+ CHANNEL_CREATE: TypeAlias = RouteCall[ChanneCreateParam, Union[Channel, Dict[str, Any]]]
88
+
89
+
90
+ class ChanneUpdateParam(TypedDict):
91
+ channel_id: str
92
+ data: dict
93
+
94
+
95
+ CHANNEL_UPDATE: TypeAlias = RouteCall[ChanneUpdateParam, None]
96
+
97
+
98
+ class ChannelMuteParam(TypedDict):
99
+ channel_id: str
100
+ duration: float
101
+
102
+
103
+ CHANNEL_MUTE: TypeAlias = RouteCall[ChannelMuteParam, None]
104
+
105
+
106
+ class UserChannelCreateParam(TypedDict):
107
+ user_id: str
108
+ guild_id: NotRequired[str]
109
+
110
+
111
+ ROUTE_USER_CHANNEL_CREATE: TypeAlias = RouteCall[UserChannelCreateParam, Union[Channel, Dict[str, Any]]]
112
+
113
+
114
+ class GuildGetParam(TypedDict):
115
+ guild_id: str
116
+
117
+
118
+ GUILD_GET: TypeAlias = RouteCall[GuildGetParam, Union[Guild, Dict[str, Any]]]
119
+
120
+
121
+ class GuildListParam(TypedDict):
122
+ next: NotRequired[str]
123
+
124
+
125
+ GUILD_LIST: TypeAlias = RouteCall[GuildListParam, Union[PageResult[Guild], Dict[str, Any]]]
126
+
127
+
128
+ class GuildMemberGetParam(TypedDict):
129
+ guild_id: str
130
+ user_id: str
131
+
132
+
133
+ GUILD_MEMBER_GET: TypeAlias = RouteCall[GuildMemberGetParam, Union[Member, Dict[str, Any]]]
134
+
135
+
136
+ class GuildXXXListParam(TypedDict):
137
+ guild_id: str
138
+ next: NotRequired[str]
139
+
140
+
141
+ GUILD_MEMBER_LIST: TypeAlias = RouteCall[GuildXXXListParam, Union[PageResult[Member], Dict[str, Any]]]
142
+
143
+
144
+ class GuildMemberKickParam(TypedDict):
145
+ guild_id: str
146
+ user_id: str
147
+ permanent: NotRequired[bool]
148
+
149
+
150
+ GUILD_MEMBER_KICK: TypeAlias = RouteCall[GuildMemberKickParam, None]
151
+
152
+
153
+ class GuildMemberMuteParam(TypedDict):
154
+ guild_id: str
155
+ user_id: str
156
+ duration: float
157
+
158
+
159
+ GUILD_MEMBER_MUTE: TypeAlias = RouteCall[GuildMemberMuteParam, None]
160
+
161
+
162
+ class GuildMemberRoleParam(TypedDict):
163
+ guild_id: str
164
+ user_id: str
165
+ role_id: str
166
+
167
+
168
+ GUILD_MEMBER_ROLE_SET: TypeAlias = RouteCall[GuildMemberRoleParam, None]
169
+ GUILD_MEMBER_ROLE_UNSET: TypeAlias = RouteCall[GuildMemberRoleParam, None]
170
+
171
+ GUILD_ROLE_LIST: TypeAlias = RouteCall[GuildXXXListParam, Union[PageResult[Role], Dict[str, Any]]]
172
+
173
+
174
+ class GuildRoleCreateParam(TypedDict):
175
+ guild: str
176
+ role: dict
177
+
178
+
179
+ GUILD_ROLE_CREATE: TypeAlias = RouteCall[GuildRoleCreateParam, Union[Role, Dict[str, Any]]]
180
+
181
+
182
+ class GuildRoleUpdateParam(TypedDict):
183
+ guild: str
184
+ role_id: str
185
+ role: dict
186
+
187
+
188
+ GUILD_ROLE_UPDATE: TypeAlias = RouteCall[GuildRoleUpdateParam, None]
189
+
190
+
191
+ class GuildRoleDeleteParam(TypedDict):
192
+ guild: str
193
+ role_id: str
194
+
195
+
196
+ GUILD_ROLE_DELETE: TypeAlias = RouteCall[GuildRoleDeleteParam, None]
197
+
198
+
199
+ class ReactionCreateParam(TypedDict):
200
+ channel_id: str
201
+ message_id: str
202
+ emoji: str
203
+
204
+
205
+ REACTION_CREATE: TypeAlias = RouteCall[ReactionCreateParam, None]
206
+
207
+
208
+ class ReactionDeleteParam(TypedDict):
209
+ channel_id: str
210
+ message_id: str
211
+ emoji: str
212
+ user_id: NotRequired[str]
213
+
214
+
215
+ REACTION_DELETE: TypeAlias = RouteCall[ReactionDeleteParam, None]
216
+
217
+
218
+ class ReactionClearParam(TypedDict):
219
+ channel_id: str
220
+ message_id: str
221
+ emoji: NotRequired[str]
222
+
223
+
224
+ REACTION_CLEAR: TypeAlias = RouteCall[ReactionClearParam, None]
225
+
226
+
227
+ class ReactionListParam(TypedDict):
228
+ channel_id: str
229
+ message_id: str
230
+ emoji: str
231
+ next: NotRequired[str]
232
+
233
+
234
+ REACTION_LIST: TypeAlias = RouteCall[ReactionListParam, Union[PageResult[User], Dict[str, Any]]]
235
+ LOGIN_GET: TypeAlias = RouteCall[Any, Union[Login, Dict[str, Any]]]
236
+
237
+
238
+ class UserGetParam(TypedDict):
239
+ user_id: str
240
+
241
+
242
+ USER_GET: TypeAlias = RouteCall[UserGetParam, Union[User, Dict[str, Any]]]
243
+
244
+
245
+ class FriendListParam(TypedDict):
246
+ next: NotRequired[str]
247
+
248
+
249
+ FRIEND_LIST: TypeAlias = RouteCall[FriendListParam, Union[PageResult[User], Dict[str, Any]]]
250
+
251
+
252
+ class ApproveParam(TypedDict):
253
+ message_id: str
254
+ approve: bool
255
+ comment: str
256
+
257
+
258
+ APPROVE: TypeAlias = RouteCall[ApproveParam, None]
259
+
260
+
261
+ class RouterMixin(metaclass=ABCMeta):
262
+ @overload
263
+ def route(self, path: Literal[Api.MESSAGE_CREATE]) -> Callable[[MESSAGE_CREATE], MESSAGE_CREATE]: ...
264
+
265
+ @overload
266
+ def route(self, path: Literal[Api.MESSAGE_UPDATE]) -> Callable[[MESSAGE_UPDATE], MESSAGE_UPDATE]: ...
267
+
268
+ @overload
269
+ def route(self, path: Literal[Api.MESSAGE_GET]) -> Callable[[MESSAGE_GET], MESSAGE_GET]: ...
270
+
271
+ @overload
272
+ def route(self, path: Literal[Api.MESSAGE_DELETE]) -> Callable[[MESSAGE_DELETE], MESSAGE_DELETE]: ...
273
+
274
+ @overload
275
+ def route(self, path: Literal[Api.MESSAGE_LIST]) -> Callable[[MESSAGE_LIST], MESSAGE_LIST]: ...
276
+
277
+ @overload
278
+ def route(self, path: Literal[Api.CHANNEL_GET]) -> Callable[[CHANNEL_GET], CHANNEL_GET]: ...
279
+
280
+ @overload
281
+ def route(self, path: Literal[Api.CHANNEL_LIST]) -> Callable[[CHANNEL_LIST], CHANNEL_LIST]: ...
282
+
283
+ @overload
284
+ def route(self, path: Literal[Api.CHANNEL_CREATE]) -> Callable[[CHANNEL_CREATE], CHANNEL_CREATE]: ...
285
+
286
+ @overload
287
+ def route(self, path: Literal[Api.CHANNEL_UPDATE]) -> Callable[[CHANNEL_UPDATE], CHANNEL_UPDATE]: ...
288
+
289
+ @overload
290
+ def route(self, path: Literal[Api.CHANNEL_DELETE]) -> Callable[[CHANNEL_DELETE], CHANNEL_DELETE]: ...
291
+
292
+ @overload
293
+ def route(self, path: Literal[Api.CHANNEL_MUTE]) -> Callable[[CHANNEL_MUTE], CHANNEL_MUTE]: ...
294
+
295
+ @overload
296
+ def route(
297
+ self, path: Literal[Api.USER_CHANNEL_CREATE]
298
+ ) -> Callable[[ROUTE_USER_CHANNEL_CREATE], ROUTE_USER_CHANNEL_CREATE]: ...
299
+
300
+ @overload
301
+ def route(self, path: Literal[Api.GUILD_GET]) -> Callable[[GUILD_GET], GUILD_GET]: ...
302
+
303
+ @overload
304
+ def route(self, path: Literal[Api.GUILD_LIST]) -> Callable[[GUILD_LIST], GUILD_LIST]: ...
305
+
306
+ @overload
307
+ def route(self, path: Literal[Api.GUILD_APPROVE]) -> Callable[[APPROVE], APPROVE]: ...
308
+
309
+ @overload
310
+ def route(
311
+ self, path: Literal[Api.GUILD_MEMBER_LIST]
312
+ ) -> Callable[[GUILD_MEMBER_LIST], GUILD_MEMBER_LIST]: ...
313
+
314
+ @overload
315
+ def route(
316
+ self, path: Literal[Api.GUILD_MEMBER_GET]
317
+ ) -> Callable[[GUILD_MEMBER_GET], GUILD_MEMBER_GET]: ...
318
+
319
+ @overload
320
+ def route(
321
+ self, path: Literal[Api.GUILD_MEMBER_KICK]
322
+ ) -> Callable[[GUILD_MEMBER_KICK], GUILD_MEMBER_KICK]: ...
323
+
324
+ @overload
325
+ def route(
326
+ self, path: Literal[Api.GUILD_MEMBER_MUTE]
327
+ ) -> Callable[[GUILD_MEMBER_MUTE], GUILD_MEMBER_MUTE]: ...
328
+
329
+ @overload
330
+ def route(self, path: Literal[Api.GUILD_MEMBER_APPROVE]) -> Callable[[APPROVE], APPROVE]: ...
331
+
332
+ @overload
333
+ def route(
334
+ self, path: Literal[Api.GUILD_MEMBER_ROLE_SET]
335
+ ) -> Callable[[GUILD_MEMBER_ROLE_SET], GUILD_MEMBER_ROLE_SET]: ...
336
+
337
+ @overload
338
+ def route(
339
+ self, path: Literal[Api.GUILD_MEMBER_ROLE_UNSET]
340
+ ) -> Callable[[GUILD_MEMBER_ROLE_UNSET], GUILD_MEMBER_ROLE_UNSET]: ...
341
+
342
+ @overload
343
+ def route(self, path: Literal[Api.GUILD_ROLE_LIST]) -> Callable[[GUILD_ROLE_LIST], GUILD_ROLE_LIST]: ...
344
+
345
+ @overload
346
+ def route(
347
+ self, path: Literal[Api.GUILD_ROLE_CREATE]
348
+ ) -> Callable[[GUILD_ROLE_CREATE], GUILD_ROLE_CREATE]: ...
349
+
350
+ @overload
351
+ def route(
352
+ self, path: Literal[Api.GUILD_ROLE_UPDATE]
353
+ ) -> Callable[[GUILD_ROLE_UPDATE], GUILD_ROLE_UPDATE]: ...
354
+
355
+ @overload
356
+ def route(
357
+ self, path: Literal[Api.GUILD_ROLE_DELETE]
358
+ ) -> Callable[[GUILD_ROLE_DELETE], GUILD_ROLE_DELETE]: ...
359
+
360
+ @overload
361
+ def route(self, path: Literal[Api.REACTION_CREATE]) -> Callable[[REACTION_CREATE], REACTION_CREATE]: ...
362
+
363
+ @overload
364
+ def route(self, path: Literal[Api.REACTION_DELETE]) -> Callable[[REACTION_DELETE], REACTION_DELETE]: ...
365
+
366
+ @overload
367
+ def route(self, path: Literal[Api.REACTION_CLEAR]) -> Callable[[REACTION_CLEAR], REACTION_CLEAR]: ...
368
+
369
+ @overload
370
+ def route(self, path: Literal[Api.REACTION_LIST]) -> Callable[[REACTION_LIST], REACTION_LIST]: ...
371
+
372
+ @overload
373
+ def route(self, path: Literal[Api.LOGIN_GET]) -> Callable[[LOGIN_GET], LOGIN_GET]: ...
374
+
375
+ @overload
376
+ def route(self, path: Literal[Api.USER_GET]) -> Callable[[USER_GET], USER_GET]: ...
377
+
378
+ @overload
379
+ def route(self, path: Literal[Api.FRIEND_LIST]) -> Callable[[FRIEND_LIST], FRIEND_LIST]: ...
380
+
381
+ @overload
382
+ def route(self, path: Literal[Api.FRIEND_APPROVE]) -> Callable[[APPROVE], APPROVE]: ...
383
+
384
+ @overload
385
+ def route(self, path: str) -> Callable[[INTERAL], INTERAL]: ...
386
+
387
+ def route(self, path: Union[str, Api]) -> Callable[[RouteCall], RouteCall]:
388
+ """注册一个路由
389
+
390
+ Args:
391
+ path (str | Api): 路由路径;若 path 不属于 Api,则会被认为是内部接口
392
+ """
393
+ return self._route(path)
394
+
395
+ @abstractmethod
396
+ def _route(self, path: Union[str, Api]) -> Callable[[RouteCall], RouteCall]: ...
@@ -1,34 +0,0 @@
1
- from abc import abstractmethod
2
- from typing import Any, AsyncIterator, Dict, List
3
-
4
- from launart import Service
5
-
6
- from ..model import Event, Login
7
- from .model import Request
8
-
9
-
10
- class Adapter(Service):
11
- @abstractmethod
12
- def get_platform(self) -> str: ...
13
-
14
- @abstractmethod
15
- def publisher(self) -> AsyncIterator[Event]: ...
16
-
17
- @abstractmethod
18
- def validate_headers(self, headers: Dict[str, Any]) -> bool: ...
19
-
20
- @abstractmethod
21
- def authenticate(self, token: str) -> bool: ...
22
-
23
- @abstractmethod
24
- async def get_logins(self) -> List[Login]: ...
25
-
26
- @abstractmethod
27
- async def call_api(self, request: Request[Any]) -> Any: ...
28
-
29
- @abstractmethod
30
- async def call_internal_api(self, request: Request[Any]) -> Any: ...
31
-
32
- @property
33
- def id(self):
34
- return f"satori-python.adapter.{self.get_platform()}#{id(self)}"
@@ -1,240 +0,0 @@
1
- from typing import Any, Awaitable, Dict, List, Protocol, TypeVar, Union
2
- from typing_extensions import NotRequired, TypeAlias, TypedDict
3
-
4
- from satori.model import Channel, Guild, Login, Member, MessageObject, ModelBase, PageResult, Role, User
5
-
6
- from .model import Request
7
-
8
- T = TypeVar("T")
9
- R = TypeVar("R", covariant=True)
10
-
11
-
12
- class Router(Protocol[T, R]):
13
- def __call__(self, request: Request[T]) -> Awaitable[R]: ...
14
-
15
-
16
- INTERAL: TypeAlias = Router[
17
- Any, Union[ModelBase, List[ModelBase], Dict[str, Any], List[Dict[str, Any]], None]
18
- ]
19
-
20
-
21
- class MessageParam(TypedDict):
22
- channel_id: str
23
- content: str
24
-
25
-
26
- MESSAGE_CREATE: TypeAlias = Router[MessageParam, Union[List[MessageObject], List[Dict[str, Any]]]]
27
- MESSAGE_GET: TypeAlias = Router[MessageParam, Union[MessageObject, Dict[str, Any]]]
28
- MESSAGE_DELETE: TypeAlias = Router[MessageParam, None]
29
-
30
-
31
- class MessageUpdateParam(TypedDict):
32
- channel_id: str
33
- message_id: str
34
- content: str
35
-
36
-
37
- MESSAGE_UPDATE: TypeAlias = Router[MessageUpdateParam, None]
38
-
39
-
40
- class MessageListParam(TypedDict):
41
- channel_id: str
42
- next: NotRequired[str]
43
-
44
-
45
- MESSAGE_LIST: TypeAlias = Router[MessageListParam, Union[PageResult[MessageObject], Dict[str, Any]]]
46
-
47
-
48
- class ChannelParam(TypedDict):
49
- channel_id: str
50
-
51
-
52
- CHANNEL_GET: TypeAlias = Router[ChannelParam, Union[Channel, Dict[str, Any]]]
53
- CHANNEL_DELETE: TypeAlias = Router[ChannelParam, None]
54
-
55
-
56
- class ChannelListParam(TypedDict):
57
- guild_id: str
58
- next: NotRequired[str]
59
-
60
-
61
- CHANNEL_LIST: TypeAlias = Router[ChannelListParam, Union[PageResult[Channel], Dict[str, Any]]]
62
-
63
-
64
- class ChanneCreateParam(TypedDict):
65
- guild_id: str
66
- data: dict
67
-
68
-
69
- CHANNEL_CREATE: TypeAlias = Router[ChanneCreateParam, Union[Channel, Dict[str, Any]]]
70
-
71
-
72
- class ChanneUpdateParam(TypedDict):
73
- channel_id: str
74
- data: dict
75
-
76
-
77
- CHANNEL_UPDATE: TypeAlias = Router[ChanneUpdateParam, None]
78
-
79
-
80
- class ChannelMuteParam(TypedDict):
81
- channel_id: str
82
- duration: float
83
-
84
-
85
- CHANNEL_MUTE: TypeAlias = Router[ChannelMuteParam, None]
86
-
87
-
88
- class UserChannelCreateParam(TypedDict):
89
- user_id: str
90
- guild_id: NotRequired[str]
91
-
92
-
93
- ROUTE_USER_CHANNEL_CREATE: TypeAlias = Router[UserChannelCreateParam, Union[Channel, Dict[str, Any]]]
94
-
95
-
96
- class GuildGetParam(TypedDict):
97
- guild_id: str
98
-
99
-
100
- GUILD_GET: TypeAlias = Router[GuildGetParam, Union[Guild, Dict[str, Any]]]
101
-
102
-
103
- class GuildListParam(TypedDict):
104
- next: NotRequired[str]
105
-
106
-
107
- GUILD_LIST: TypeAlias = Router[GuildListParam, Union[PageResult[Guild], Dict[str, Any]]]
108
-
109
-
110
- class GuildMemberGetParam(TypedDict):
111
- guild_id: str
112
- user_id: str
113
-
114
-
115
- GUILD_MEMBER_GET: TypeAlias = Router[GuildMemberGetParam, Union[Member, Dict[str, Any]]]
116
-
117
-
118
- class GuildXXXListParam(TypedDict):
119
- guild_id: str
120
- next: NotRequired[str]
121
-
122
-
123
- GUILD_MEMBER_LIST: TypeAlias = Router[GuildXXXListParam, Union[PageResult[Member], Dict[str, Any]]]
124
-
125
-
126
- class GuildMemberKickParam(TypedDict):
127
- guild_id: str
128
- user_id: str
129
- permanent: NotRequired[bool]
130
-
131
-
132
- GUILD_MEMBER_KICK: TypeAlias = Router[GuildMemberKickParam, None]
133
-
134
-
135
- class GuildMemberMuteParam(TypedDict):
136
- guild_id: str
137
- user_id: str
138
- duration: float
139
-
140
-
141
- GUILD_MEMBER_MUTE: TypeAlias = Router[GuildMemberMuteParam, None]
142
-
143
-
144
- class GuildMemberRoleParam(TypedDict):
145
- guild_id: str
146
- user_id: str
147
- role_id: str
148
-
149
-
150
- GUILD_MEMBER_ROLE_SET: TypeAlias = Router[GuildMemberRoleParam, None]
151
- GUILD_MEMBER_ROLE_UNSET: TypeAlias = Router[GuildMemberRoleParam, None]
152
-
153
- GUILD_ROLE_LIST: TypeAlias = Router[GuildXXXListParam, Union[PageResult[Role], Dict[str, Any]]]
154
-
155
-
156
- class GuildRoleCreateParam(TypedDict):
157
- guild: str
158
- role: dict
159
-
160
-
161
- GUILD_ROLE_CREATE: TypeAlias = Router[GuildRoleCreateParam, Union[Role, Dict[str, Any]]]
162
-
163
-
164
- class GuildRoleUpdateParam(TypedDict):
165
- guild: str
166
- role_id: str
167
- role: dict
168
-
169
-
170
- GUILD_ROLE_UPDATE: TypeAlias = Router[GuildRoleUpdateParam, None]
171
-
172
-
173
- class GuildRoleDeleteParam(TypedDict):
174
- guild: str
175
- role_id: str
176
-
177
-
178
- GUILD_ROLE_DELETE: TypeAlias = Router[GuildRoleDeleteParam, None]
179
-
180
-
181
- class ReactionCreateParam(TypedDict):
182
- channel_id: str
183
- message_id: str
184
- emoji: str
185
-
186
-
187
- REACTION_CREATE: TypeAlias = Router[ReactionCreateParam, None]
188
-
189
-
190
- class ReactionDeleteParam(TypedDict):
191
- channel_id: str
192
- message_id: str
193
- emoji: str
194
- user_id: NotRequired[str]
195
-
196
-
197
- REACTION_DELETE: TypeAlias = Router[ReactionDeleteParam, None]
198
-
199
-
200
- class ReactionClearParam(TypedDict):
201
- channel_id: str
202
- message_id: str
203
- emoji: NotRequired[str]
204
-
205
-
206
- REACTION_CLEAR: TypeAlias = Router[ReactionClearParam, None]
207
-
208
-
209
- class ReactionListParam(TypedDict):
210
- channel_id: str
211
- message_id: str
212
- emoji: str
213
- next: NotRequired[str]
214
-
215
-
216
- REACTION_LIST: TypeAlias = Router[ReactionListParam, Union[PageResult[User], Dict[str, Any]]]
217
- LOGIN_GET: TypeAlias = Router[Any, Union[Login, Dict[str, Any]]]
218
-
219
-
220
- class UserGetParam(TypedDict):
221
- user_id: str
222
-
223
-
224
- USER_GET: TypeAlias = Router[UserGetParam, Union[User, Dict[str, Any]]]
225
-
226
-
227
- class FriendListParam(TypedDict):
228
- next: NotRequired[str]
229
-
230
-
231
- FRIEND_LIST: TypeAlias = Router[FriendListParam, Union[PageResult[User], Dict[str, Any]]]
232
-
233
-
234
- class ApproveParam(TypedDict):
235
- message_id: str
236
- approve: bool
237
- comment: str
238
-
239
-
240
- APPROVE: TypeAlias = Router[ApproveParam, None]