Skip to content

Commit 59d4aaf

Browse files
committed
refactor: 类型批注
1 parent 025a95d commit 59d4aaf

10 files changed

Lines changed: 79 additions & 83 deletions

File tree

core/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
cluster = Cluster()
1010

1111

12-
async def main():
12+
async def main() -> None:
1313
try:
1414
await cluster.token.fetchToken()
1515
await cluster.getConfiguration()
@@ -23,7 +23,7 @@ async def main():
2323
except Exception as e:
2424
logger.terror("orm.error.failed", e=e)
2525

26-
async def syncFiles():
26+
async def syncFiles() -> None:
2727
if cluster.scheduler:
2828
cluster.scheduler.pause()
2929
if cluster.enabled and cluster.socket:

core/api.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,3 @@ async def getStatus(cluster) -> web.Response:
3737
"version": VERSION,
3838
}
3939
return web.json_response(data=response)
40-
41-
async def postConfig() -> web.Response:
42-
pass

core/classes.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from dataclasses import dataclass
2-
from typing import List, Dict, Any
2+
from typing import List
33
from abc import ABC, abstractmethod
4-
import io
54
from aiohttp import web
6-
import tqdm
5+
from tqdm import tqdm
6+
from typing import Union
7+
import io
78

89

910
@dataclass
@@ -31,25 +32,25 @@ async def init(self) -> None:
3132
pass
3233

3334
@abstractmethod
34-
async def check(self) -> bool:
35+
async def check(self) -> None:
3536
pass
3637

3738
@abstractmethod
3839
async def writeFile(
39-
self, path: str, content: io.BytesIO, delay: int, retry: int
40-
) -> int:
40+
self, file: FileInfo, content: io.BytesIO, delay: int, retry: int
41+
) -> bool:
4142
pass
4243

4344
@abstractmethod
44-
async def getMissingFiles(files: FileList, pbar: tqdm) -> FileList:
45+
async def getMissingFiles(self, files: FileList, pbar: tqdm) -> FileList:
4546
pass
4647

4748
@abstractmethod
48-
async def express(
49-
hash: str, counters: dict
50-
) -> web.Response:
49+
async def express(self,
50+
hash: str, counter: dict
51+
) -> Union[web.Response, web.FileResponse]:
5152
pass
5253

5354
@abstractmethod
54-
async def recycleFiles(files: FileList) -> None:
55+
async def recycleFiles(self, files: FileList) -> None:
5556
pass

core/cluster.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from core.router import Router
1414
from core.orm import writeHits
1515
from core.i18n import locale
16-
from typing import List, Any
16+
from typing import List, Any, Union
1717
from aiohttp import web, ClientResponseError
1818
from urllib.parse import urljoin
1919
from tqdm import tqdm
@@ -53,7 +53,7 @@ def __init__(self) -> None:
5353
if not self.id or not self.secret:
5454
raise ClusterIdNotSetError if not self.id else ClusterSecretNotSetError
5555

56-
async def fetchToken(self):
56+
async def fetchToken(self) -> None:
5757
logger.tinfo("token.info.fetching")
5858
async with aiohttp.ClientSession(
5959
self.base_url, headers={"User-Agent": self.user_agent}
@@ -100,15 +100,15 @@ def __init__(self) -> None:
100100
self.filelist = FileList(files=[])
101101
self.storages = getStorages()
102102
self.configuration = None
103-
self.semaphore = None
104-
self.socket = None
105-
self.router = None
103+
self.semaphore = asyncio.Semaphore()
104+
self.socket = socketio.AsyncClient(handle_sigint=False)
105+
self.router: Router | None = None
106106
self.runner = None
107107
self.failed_filelist = FileList(files=[])
108108
self.enabled = False
109109
self.site = None
110110
self.want_enable = False
111-
self.scheduler = None
111+
self.scheduler = scheduler
112112
self.start_time = int(time.time() * 1000)
113113

114114
async def fetchFileList(self) -> None:
@@ -227,7 +227,6 @@ async def recycleFiles(self) -> None:
227227
async def downloadFile(
228228
self, file: FileInfo, session: aiohttp.ClientSession, pbar: tqdm
229229
) -> None:
230-
# logger.debug(file)
231230
async with self.semaphore:
232231
delay, retry = Config.get("advanced.delay"), Config.get("advanced.retry")
233232

@@ -255,7 +254,7 @@ async def downloadFile(
255254
e=e.message,
256255
retry=delay,
257256
)
258-
self.report(e, session)
257+
await self.report(e, session)
259258

260259
except Exception as e:
261260
logger.terror(
@@ -273,7 +272,7 @@ async def downloadFile(
273272
async def report(
274273
self, error: ClientResponseError, session: aiohttp.ClientSession
275274
) -> None:
276-
history_urls = [urljoin(self.base_url), *error.history]
275+
history_urls = [*error.history]
277276
try:
278277
async with session.post(
279278
"/openbmclapi/report",
@@ -402,6 +401,10 @@ async def keepAlive(self) -> bool:
402401
logger.terror("cluster.error.keep_alive.socket_not_setup")
403402
return False
404403

404+
if self.router is None:
405+
logger.terror("cluster.error.keep_alive.router_not_setup")
406+
return False
407+
405408
future = asyncio.Future()
406409

407410
async def callback(data: List[Any]):
@@ -482,28 +485,22 @@ async def callback(data: List[Any]):
482485
async def connect(self) -> None:
483486
if self.socket and self.socket.connected:
484487
return
485-
486-
self.socket = socketio.AsyncClient(handle_sigint=False)
487-
488-
@self.socket.on("connect")
489-
async def _() -> None:
488+
async def onConnect() -> None:
490489
logger.tsuccess("client.success.connected")
491490
await self.disable()
492491
if self.want_enable:
493492
await self.enable()
494493
if self.scheduler:
495494
self.scheduler.resume()
496-
497-
@self.socket.on("disconnect")
498-
async def _() -> None:
495+
async def onDisconnect() -> None:
499496
logger.twarning("client.warn.disconnected")
500497
if self.scheduler:
501498
self.scheduler.pause()
502-
503-
@self.socket.on("message")
504-
async def _(message: str) -> None:
499+
async def onMessage(message: str) -> None:
505500
logger.tinfo("client.info.message", message=message)
506-
501+
self.socket.on("connect", onConnect)
502+
self.socket.on("disconnect", onDisconnect)
503+
self.socket.on("message", onMessage)
507504
await self.socket.connect(
508505
self.base_url,
509506
transports=["websocket"],

core/logger.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from loguru import logger as Logger
1+
from loguru import logger as Logger, Record
22
from pathlib import Path
33
import sys
44
from core.config import Config
@@ -8,14 +8,14 @@
88
debug_mode = Config.get("advanced.debug")
99

1010

11-
def filter(record):
12-
if "apscheduler" in record["name"]:
13-
record["depth"] = 2
14-
return 1
11+
def filter(record: Record) -> bool:
12+
if record["name"] and "apscheduler" in record["name"]:
13+
record["extra"] = {"depth": 2}
14+
return True
1515

1616

1717
class LoggingLogger:
18-
def __init__(self):
18+
def __init__(self) -> None:
1919
self.log = Logger.opt(depth=1)
2020
self.log.remove()
2121
self.log.add(

core/router.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
from core.orm import writeAgent
2-
from core.utils import checkSign
32
from core.api import getStatus
43
from core.storages import AListStorage
54
from core.logger import logger
65
from aiohttp import web
6+
from typing import Union
7+
from multidict import MultiMapping
78
import aiohttp
9+
import base64
10+
import hashlib
11+
import time
812
import random
913

1014

@@ -19,6 +23,18 @@ def __init__(self, app: web.Application, cluster) -> None:
1923
self.ws_clients = []
2024
self.connection = 0
2125

26+
def checkSign(self, hash: str, secret: str, query: MultiMapping) -> bool:
27+
if not (s := query.get("s")) or not (e := query.get("e")):
28+
return False
29+
sign = (
30+
base64.urlsafe_b64encode(
31+
hashlib.sha1(f"{secret}{hash}{e}".encode()).digest()
32+
)
33+
.decode()
34+
.rstrip("=")
35+
)
36+
return sign == s and time.time() < int(e, 36)
37+
2238
def init(self) -> None:
2339
@self.route.get("/download/{hash}")
2440
async def _(
@@ -27,7 +43,7 @@ async def _(
2743
self.connection += 1
2844
writeAgent(request.headers["User-Agent"], 1)
2945
file_hash = request.match_info.get("hash", "").lower()
30-
if not checkSign(file_hash, self.secret, request.query):
46+
if not self.checkSign(file_hash, self.secret, request.query):
3147
return web.Response(text="Invalid signature.", status=403)
3248

3349
response = await random.choice(self.storages).express(
@@ -39,15 +55,15 @@ async def _(
3955
return response
4056

4157
@self.route.get("/measure/{size}")
42-
async def _(request: web.Request) -> web.Response:
58+
async def _(request: web.Request) -> Union[web.Response, web.StreamResponse]:
4359
try:
4460
size = int(request.match_info.get("size", "0"))
4561

4662
if (
47-
not checkSign(f"/measure/{size}", self.secret, request.query)
63+
not self.checkSign(f"/measure/{size}", self.secret, request.query)
4864
or size > 200
4965
):
50-
return web.Response(status=403 if size > 200 else 400)
66+
return web.HTTPForbidden() if size > 200 else web.HTTPBadRequest()
5167

5268
response = None
5369
for storage in self.storages:

core/storages/alist.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ async def express(self, hash: str, counter: dict) -> web.Response:
189189
counter["hits"] += 1
190190
return response
191191
except Exception as e:
192-
response = web.HTTPError(text=e)
192+
response = web.HTTPError(text=str(e))
193193
logger.debug(e)
194194
return response
195195

@@ -254,5 +254,5 @@ async def getSize() -> int:
254254
logger.terror("storage.error.alist.write_file.failed", file=file.hash)
255255
return False
256256

257-
async def recycleFiles(files):
257+
async def recycleFiles(self, files) -> None:
258258
pass

core/storages/local.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from core.logger import logger
33
from core.i18n import locale
44
from aiohttp import web
5-
from typing import Any, Dict
5+
from typing import Union
66
from tqdm import tqdm
77
from pathlib import Path
88
import os
@@ -83,7 +83,7 @@ async def checkFile(file: FileInfo, pbar: tqdm) -> bool:
8383
]
8484
return FileList(files=missing_files)
8585

86-
async def express(self, hash: str, counter: dict) -> web.Response:
86+
async def express(self, hash: str, counter: dict) -> Union[web.Response, web.FileResponse]:
8787
path = os.path.join(self.path, hash[:2], hash)
8888
if not os.path.exists(path):
8989
response = web.HTTPNotFound()
@@ -96,7 +96,7 @@ async def express(self, hash: str, counter: dict) -> web.Response:
9696
counter["hits"] += 1
9797
return response
9898
except Exception as e:
99-
response = web.HTTPError(text=e)
99+
response = web.HTTPError(text=str(e))
100100
logger.debug(e)
101101
return response
102102

core/storages/s3.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from core.logger import logger
33
from botocore.config import Config
44
from botocore.exceptions import ClientError
5-
from typing import Literal, Union
5+
from typing import Literal, Union, Self
66
from tqdm import tqdm
77
import boto3
88
import humanize
@@ -86,18 +86,18 @@ async def check(self) -> None:
8686
logger.terror("storage.error.s3.check", e=e)
8787

8888
async def getMissingFiles(self, files: FileList, pbar: tqdm) -> FileList:
89-
async def checkFile(file: FileInfo, pbar: tqdm) -> bool:
90-
pbar.update(1)
91-
file_path = f"{file.hash[:2]}/{file.hash}"
92-
try:
93-
response = self.client.head_object(Bucket=self.bucket, Key=file_path)
94-
s3_file_size = response["ContentLength"]
95-
return s3_file_size != file.size
96-
except Exception:
97-
pass
89+
s3_files = {}
90+
try:
91+
paginator = self.client.get_paginator("list_objects_v2")
92+
async for page in paginator.paginate(Bucket=self.bucket):
93+
for obj in page.get("Contents", []):
94+
s3_files[obj["Key"]] = obj["Size"]
95+
except ClientError as e:
96+
logger.terror("storage.error.s3.get_s3_files", e=e)
9897

99-
results = await asyncio.gather(*[checkFile(file, pbar) for file in files.files])
100-
missing_files = [
101-
file for file, is_missing in zip(files.files, results) if is_missing
102-
]
103-
return FileList(files=missing_files)
98+
missing_files = []
99+
for file in files.files:
100+
file_key = f"{file.hash[:2]}/{file.hash}"
101+
if file_key not in s3_files or s3_files[file_key] != file.size:
102+
missing_files.append(file)
103+
pbar.update(1)

core/utils.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)