satori-python-server 0.16.2__tar.gz → 0.16.4__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,5 +1,5 @@
1
1
  includes = ["src/satori/server"]
2
- raw-dependencies = ["satori-python-core >= 0.16.1"]
2
+ raw-dependencies = ["satori-python-core >= 0.16.3"]
3
3
 
4
4
  [project]
5
5
  name = "satori-python-server"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: satori-python-server
3
- Version: 0.16.2
3
+ Version: 0.16.4
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>
@@ -23,7 +23,7 @@ Requires-Dist: graia-amnesia>=0.9.0
23
23
  Requires-Dist: starlette[python-multipart]>=0.37.2
24
24
  Requires-Dist: uvicorn[standard]>=0.28.0
25
25
  Requires-Dist: python-multipart>=0.0.9
26
- Requires-Dist: satori-python-core>=0.16.1
26
+ Requires-Dist: satori-python-core>=0.16.3
27
27
  Description-Content-Type: text/markdown
28
28
 
29
29
  # satori-python
@@ -73,6 +73,13 @@ pip install satori-python-client
73
73
  pip install satori-python-server
74
74
  ```
75
75
 
76
+ ### 官方适配器
77
+
78
+ | 适配器 | 安装 |
79
+ |------------|----------------------------------------------|
80
+ | Satori | `pip install satori-python-adapter-satori` |
81
+ | OneBot V11 | `pip install satori-python-adapter-onebot11` |
82
+
76
83
  ## 使用
77
84
 
78
85
  客户端:
@@ -45,6 +45,13 @@ pip install satori-python-client
45
45
  pip install satori-python-server
46
46
  ```
47
47
 
48
+ ### 官方适配器
49
+
50
+ | 适配器 | 安装 |
51
+ |------------|----------------------------------------------|
52
+ | Satori | `pip install satori-python-adapter-satori` |
53
+ | OneBot V11 | `pip install satori-python-adapter-onebot11` |
54
+
48
55
  ## 使用
49
56
 
50
57
  客户端:
@@ -11,7 +11,7 @@ dependencies = [
11
11
  "starlette[python-multipart]>=0.37.2",
12
12
  "uvicorn[standard]>=0.28.0",
13
13
  "python-multipart>=0.0.9",
14
- "satori-python-core >= 0.16.1",
14
+ "satori-python-core >= 0.16.3",
15
15
  ]
16
16
  description = "Satori Protocol SDK for python, specify server part"
17
17
  readme = "README.md"
@@ -27,7 +27,7 @@ classifiers = [
27
27
  "Programming Language :: Python :: 3.12",
28
28
  "Operating System :: OS Independent",
29
29
  ]
30
- version = "0.16.2"
30
+ version = "0.16.4"
31
31
 
32
32
  [project.license]
33
33
  text = "MIT"
@@ -18,6 +18,7 @@ from typing import Any
18
18
 
19
19
  import aiohttp
20
20
  from creart import it
21
+ from graia.amnesia.builtins.aiohttp import AiohttpClientService
21
22
  from graia.amnesia.builtins.asgi import UvicornASGIService
22
23
  from launart import Launart, Service, any_completed
23
24
  from loguru import logger
@@ -115,13 +116,12 @@ class Server(Service, RouterMixin):
115
116
  stream_chunk_size: int = 64 * 1024,
116
117
  ):
117
118
  self.connections = []
118
- manager = it(Launart)
119
- manager.add_component(UvicornASGIService(host, port))
119
+ self.host = host
120
+ self.port = port
120
121
  self.version = version
121
122
  self.path = path
122
123
  if self.path and not self.path.startswith("/"):
123
124
  self.path = f"/{self.path}"
124
- self.url_base = f"http://{host}:{port}{self.path}/{version}"
125
125
  self.token = token
126
126
  self._adapters = []
127
127
  self.providers = []
@@ -136,6 +136,10 @@ class Server(Service, RouterMixin):
136
136
  self.resources: dict[str, Path] = {}
137
137
  super().__init__()
138
138
 
139
+ @property
140
+ def url_base(self):
141
+ return f"http://{self.host}:{self.port}{self.path}/{self.version}"
142
+
139
143
  def apply(self, item: Provider | Router | Adapter):
140
144
  if isinstance(item, Adapter):
141
145
  item.ensure_server(self)
@@ -157,9 +161,11 @@ class Server(Service, RouterMixin):
157
161
  self._event_cache.append(event)
158
162
  self._sequence += 1
159
163
  for connection in self.connections:
164
+ if not connection.alive:
165
+ continue
160
166
  try:
161
167
  await connection.send({"op": Opcode.EVENT, "body": event.dump()})
162
- except WebSocketDisconnect:
168
+ except (WebSocketDisconnect, RuntimeError):
163
169
  break
164
170
  except Exception as e:
165
171
  print_exc()
@@ -287,13 +293,14 @@ class Server(Service, RouterMixin):
287
293
  file = Path(self._tempdir.name) / path[5:]
288
294
  if file.exists():
289
295
  return FileResponse(file)
290
- raise FileNotFoundError(f"{path[5:]} not found")
291
296
  assert request is not None
292
297
  for provider in self.providers:
293
298
  if provider.ensure(platform, self_id):
294
299
  return await provider.handle_internal(
295
300
  Request(request, "internal", {}, platform=platform, self_id=self_id), path
296
301
  )
302
+ if path.startswith("_tmp"):
303
+ raise FileNotFoundError(f"File not found: {path[5:]}")
297
304
  raise NotImplementedError(f"Login with {platform}:{self_id} not found")
298
305
  raise TypeError(f"Invalid internal url: {url}")
299
306
 
@@ -457,7 +464,10 @@ class Server(Service, RouterMixin):
457
464
  ):
458
465
  if manager is None:
459
466
  manager = it(Launart)
467
+ manager.add_component(UvicornASGIService(self.host, self.port))
460
468
  manager.add_component(self)
469
+ with suppress(ValueError):
470
+ manager.add_component(AiohttpClientService())
461
471
  manager.launch_blocking(loop=loop, stop_signal=stop_signal)
462
472
 
463
473
  async def run_async(
@@ -1,12 +1,13 @@
1
1
  from abc import abstractmethod
2
2
  from collections.abc import AsyncIterator
3
- from typing import TYPE_CHECKING, Optional
3
+ from typing import TYPE_CHECKING, Optional, Union
4
4
 
5
5
  from launart import Service
6
6
  from starlette.responses import Response
7
7
  from starlette.routing import BaseRoute
8
8
 
9
- from ..model import Event, Login
9
+ from satori.model import Event, Login, LoginPartial
10
+
10
11
  from .model import Request
11
12
  from .route import RouterMixin
12
13
  from .utils import ctx
@@ -15,6 +16,9 @@ if TYPE_CHECKING:
15
16
  from . import Server
16
17
 
17
18
 
19
+ LoginType = Union[Login, LoginPartial]
20
+
21
+
18
22
  class Adapter(Service, RouterMixin):
19
23
  server: "Server"
20
24
 
@@ -39,7 +43,7 @@ class Adapter(Service, RouterMixin):
39
43
  return Response(await resp.read())
40
44
 
41
45
  @abstractmethod
42
- async def get_logins(self) -> list[Login]: ...
46
+ async def get_logins(self) -> list[LoginType]: ...
43
47
 
44
48
  def __init__(self):
45
49
  super().__init__()
@@ -88,20 +88,20 @@ class ChannelListParam(TypedDict):
88
88
  CHANNEL_LIST: TypeAlias = RouteCall[ChannelListParam, Union[PageResult[Channel], dict[str, Any]]]
89
89
 
90
90
 
91
- class ChanneCreateParam(TypedDict):
91
+ class ChannelCreateParam(TypedDict):
92
92
  guild_id: str
93
93
  data: dict
94
94
 
95
95
 
96
- CHANNEL_CREATE: TypeAlias = RouteCall[ChanneCreateParam, Union[Channel, dict[str, Any]]]
96
+ CHANNEL_CREATE: TypeAlias = RouteCall[ChannelCreateParam, Union[Channel, dict[str, Any]]]
97
97
 
98
98
 
99
- class ChanneUpdateParam(TypedDict):
99
+ class ChannelUpdateParam(TypedDict):
100
100
  channel_id: str
101
101
  data: dict
102
102
 
103
103
 
104
- CHANNEL_UPDATE: TypeAlias = RouteCall[ChanneUpdateParam, None]
104
+ CHANNEL_UPDATE: TypeAlias = RouteCall[ChannelUpdateParam, None]
105
105
 
106
106
 
107
107
  class ChannelMuteParam(TypedDict):
@@ -261,7 +261,7 @@ FRIEND_LIST: TypeAlias = RouteCall[FriendListParam, Union[PageResult[User], dict
261
261
  class ApproveParam(TypedDict):
262
262
  message_id: str
263
263
  approve: bool
264
- comment: str
264
+ comment: NotRequired[str]
265
265
 
266
266
 
267
267
  APPROVE: TypeAlias = RouteCall[ApproveParam, None]