satori-python-server 0.14.1__tar.gz → 0.14.3__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_server-0.14.1 → satori_python_server-0.14.3}/PKG-INFO +1 -1
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/pyproject.toml +1 -1
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/__init__.py +22 -12
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/adapter.py +9 -1
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/conection.py +1 -1
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/model.py +3 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/.mina/server.toml +0 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/LICENSE +0 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/README.md +0 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/deque.py +0 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/formdata.py +0 -0
- {satori_python_server-0.14.1 → satori_python_server-0.14.3}/src/satori/server/route.py +0 -0
|
@@ -20,7 +20,7 @@ from graia.amnesia.builtins.asgi import UvicornASGIService
|
|
|
20
20
|
from launart import Launart, Service, any_completed
|
|
21
21
|
from loguru import logger
|
|
22
22
|
from starlette.applications import Starlette
|
|
23
|
-
from starlette.datastructures import FormData
|
|
23
|
+
from starlette.datastructures import FormData as FormData
|
|
24
24
|
from starlette.requests import Request as StarletteRequest
|
|
25
25
|
from starlette.responses import JSONResponse, Response
|
|
26
26
|
from starlette.routing import Route, WebSocketRoute
|
|
@@ -34,7 +34,7 @@ from satori.model import Event, ModelBase, Opcode
|
|
|
34
34
|
from .adapter import Adapter as Adapter
|
|
35
35
|
from .conection import WebsocketConnection
|
|
36
36
|
from .deque import Deque
|
|
37
|
-
from .formdata import parse_content_disposition
|
|
37
|
+
from .formdata import parse_content_disposition as parse_content_disposition
|
|
38
38
|
from .model import Provider as Provider
|
|
39
39
|
from .model import Request as Request
|
|
40
40
|
from .model import Router as Router
|
|
@@ -94,6 +94,7 @@ class Server(Service, RouterMixin):
|
|
|
94
94
|
self.path = path
|
|
95
95
|
if self.path and not self.path.startswith("/"):
|
|
96
96
|
self.path = f"/{self.path}"
|
|
97
|
+
self.url_base = f"http://{host}:{port}{self.path}/{version}"
|
|
97
98
|
self._adapters = []
|
|
98
99
|
self.providers = []
|
|
99
100
|
self.routers = []
|
|
@@ -107,14 +108,13 @@ class Server(Service, RouterMixin):
|
|
|
107
108
|
|
|
108
109
|
def apply(self, item: Provider | Router | Adapter):
|
|
109
110
|
if isinstance(item, Adapter):
|
|
111
|
+
item.ensure_server(self)
|
|
110
112
|
self._adapters.append(item)
|
|
111
113
|
self.providers.append(item)
|
|
112
|
-
|
|
113
|
-
self.proxy_url_mapping[proxy_url_pf] = item
|
|
114
|
+
self.proxy_url_mapping[item.id] = item.proxy_urls()
|
|
114
115
|
elif isinstance(item, Provider):
|
|
115
116
|
self.providers.append(item)
|
|
116
|
-
|
|
117
|
-
self.proxy_url_mapping[proxy_url_pf] = item
|
|
117
|
+
self.proxy_url_mapping[item.id] = item.proxy_urls()
|
|
118
118
|
elif isinstance(item, Router):
|
|
119
119
|
self.routers.append(item)
|
|
120
120
|
else:
|
|
@@ -159,20 +159,29 @@ class Server(Service, RouterMixin):
|
|
|
159
159
|
for provider in self.providers:
|
|
160
160
|
if not provider.authenticate(token):
|
|
161
161
|
return await ws.close(code=3000, reason="Unauthorized")
|
|
162
|
-
|
|
162
|
+
_logins = await provider.get_logins()
|
|
163
|
+
for _login in _logins:
|
|
164
|
+
_login.proxy_urls.extend(provider.proxy_urls())
|
|
165
|
+
logins.extend(_logins)
|
|
163
166
|
sequence = body.get("sequence")
|
|
164
167
|
if sequence is None:
|
|
165
168
|
sequence = -1
|
|
166
169
|
await connection.send({"op": Opcode.READY, "body": {"logins": [lo.dump() for lo in logins]}})
|
|
167
170
|
self.connections.append(connection)
|
|
168
171
|
logger.debug(f"New connection: {id(connection)}")
|
|
172
|
+
heartbeat_task = asyncio.create_task(connection.heartbeat())
|
|
173
|
+
close_task = asyncio.create_task(connection.close_signal.wait())
|
|
169
174
|
try:
|
|
170
175
|
if sequence > -1:
|
|
171
176
|
for event in self._event_cache.after(sequence):
|
|
172
177
|
await connection.send({"op": Opcode.EVENT, "body": event.dump()})
|
|
173
178
|
await asyncio.sleep(0.1)
|
|
174
|
-
await any_completed(
|
|
179
|
+
await any_completed(heartbeat_task, close_task)
|
|
175
180
|
finally:
|
|
181
|
+
await connection.connection_closed()
|
|
182
|
+
logger.debug(f"Connection closed: {id(connection)}")
|
|
183
|
+
heartbeat_task.cancel()
|
|
184
|
+
close_task.cancel()
|
|
176
185
|
self.connections.remove(connection)
|
|
177
186
|
|
|
178
187
|
async def admin_login_list_handler(self, request: StarletteRequest):
|
|
@@ -232,10 +241,11 @@ class Server(Service, RouterMixin):
|
|
|
232
241
|
for provider in self.providers:
|
|
233
242
|
if provider.ensure(platform, self_id):
|
|
234
243
|
return await provider.download_uploaded(platform, self_id, path)
|
|
235
|
-
for
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
244
|
+
for provider in self.providers:
|
|
245
|
+
for proxy_url_pf in self.proxy_url_mapping[provider.id]:
|
|
246
|
+
if url.startswith(proxy_url_pf):
|
|
247
|
+
async with self.session.get(url) as resp:
|
|
248
|
+
return await resp.read()
|
|
239
249
|
raise ValueError(f"Unknown proxy url: {url}")
|
|
240
250
|
|
|
241
251
|
def get_local_file(self, url: str):
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
from collections.abc import AsyncIterator
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
4
|
|
|
5
5
|
from launart import Service
|
|
6
6
|
|
|
7
7
|
from ..model import Event, Login
|
|
8
8
|
from .route import RouterMixin
|
|
9
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from . import Server
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
class Adapter(Service, RouterMixin):
|
|
15
|
+
server: "Server"
|
|
16
|
+
|
|
12
17
|
@abstractmethod
|
|
13
18
|
def get_platform(self) -> str: ...
|
|
14
19
|
|
|
@@ -38,3 +43,6 @@ class Adapter(Service, RouterMixin):
|
|
|
38
43
|
@property
|
|
39
44
|
def id(self):
|
|
40
45
|
return f"satori-python.adapter.{self.get_platform()}#{id(self)}"
|
|
46
|
+
|
|
47
|
+
def ensure_server(self, server: "Server"):
|
|
48
|
+
self.server = server
|
|
@@ -22,7 +22,7 @@ class WebsocketConnection:
|
|
|
22
22
|
async def heartbeat(self):
|
|
23
23
|
while True:
|
|
24
24
|
try:
|
|
25
|
-
msg = await asyncio.wait_for(self.connection.receive_json(), timeout=
|
|
25
|
+
msg = await asyncio.wait_for(self.connection.receive_json(), timeout=12)
|
|
26
26
|
if not isinstance(msg, dict) or msg.get("op") != Opcode.PING:
|
|
27
27
|
continue
|
|
28
28
|
await self.connection.send_json({"op": Opcode.PONG})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|