🐛 修复下载历史重复计数
This commit is contained in:
+14
-1
@@ -3,7 +3,7 @@ import json
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from core.response import APIResponse
|
||||
from core.storage import FileStorageInterface, storages
|
||||
@@ -82,6 +82,18 @@ class FileService:
|
||||
def _file_metadata_key(self, file_id: int) -> str:
|
||||
return f"{self.FILE_METADATA_KEY_PREFIX}{file_id}"
|
||||
|
||||
def _dedupe_download_stats(self, stats: List[TransferStats]) -> List[TransferStats]:
|
||||
deduped: List[TransferStats] = []
|
||||
recent_downloads: Dict[Tuple[Optional[int], str, int], datetime] = {}
|
||||
for stat in stats:
|
||||
key = (stat.file_code_id, stat.ip or "", int(stat.size or 0))
|
||||
previous = recent_downloads.get(key)
|
||||
if previous and (stat.created_at - previous).total_seconds() <= 5:
|
||||
continue
|
||||
recent_downloads[key] = stat.created_at
|
||||
deduped.append(stat)
|
||||
return deduped
|
||||
|
||||
async def _delete_file_code(self, file_code: FileCodes):
|
||||
try:
|
||||
name = (
|
||||
@@ -1289,6 +1301,7 @@ class FileService:
|
||||
download_stats = await TransferStats.filter(
|
||||
action="download", file_code_id=file_code.id
|
||||
).order_by("created_at")
|
||||
download_stats = self._dedupe_download_stats(download_stats)
|
||||
timeline.append(
|
||||
{
|
||||
"key": "retrieved",
|
||||
|
||||
+16
-1
@@ -189,10 +189,25 @@ async def analytics(start: str = "", end: str = ""):
|
||||
end_day = parse_day(end, now.replace(hour=0, minute=0, second=0, microsecond=0))
|
||||
start_day = parse_day(start, end_day - datetime.timedelta(days=29))
|
||||
end_exclusive = end_day + datetime.timedelta(days=1)
|
||||
stats = await TransferStats.filter(
|
||||
raw_stats = await TransferStats.filter(
|
||||
created_at__gte=start_day,
|
||||
created_at__lt=end_exclusive,
|
||||
).order_by("created_at", "id")
|
||||
stats = []
|
||||
recent_downloads = {}
|
||||
for item in raw_stats:
|
||||
if item.action == "download":
|
||||
dedupe_key = (
|
||||
item.file_code_id or item.code or "",
|
||||
item.ip or "",
|
||||
int(item.size or 0),
|
||||
)
|
||||
previous = recent_downloads.get(dedupe_key)
|
||||
if previous and (item.created_at - previous).total_seconds() <= 5:
|
||||
continue
|
||||
recent_downloads[dedupe_key] = item.created_at
|
||||
stats.append(item)
|
||||
|
||||
files = await FileCodes.all()
|
||||
file_map = {item.code: item for item in files}
|
||||
|
||||
|
||||
+4
-2
@@ -292,6 +292,7 @@ async def select_file(data: SelectFileModel, ip: str = Depends(ip_limit["error"]
|
||||
return APIResponse(code=404, detail=file_code)
|
||||
|
||||
assert isinstance(file_code, FileCodes)
|
||||
if file_code.text is not None:
|
||||
await update_file_usage(file_code)
|
||||
await record_transfer_stat("download", file_code, file_code.size, ip)
|
||||
return APIResponse(detail=await build_select_detail(file_code, file_storage))
|
||||
@@ -303,10 +304,11 @@ async def download_file(key: str, code: str, ip: str = Depends(ip_limit["error"]
|
||||
if await get_select_token(code) != key:
|
||||
ip_limit["error"].add_ip(ip)
|
||||
raise HTTPException(status_code=403, detail="下载鉴权失败")
|
||||
has, file_code = await get_code_file_by_code(code, False)
|
||||
has, file_code = await get_code_file_by_code(code)
|
||||
if not has:
|
||||
return APIResponse(code=404, detail="文件不存在")
|
||||
return APIResponse(code=404, detail=file_code)
|
||||
assert isinstance(file_code, FileCodes)
|
||||
await update_file_usage(file_code)
|
||||
await record_transfer_stat("download", file_code, file_code.size, ip)
|
||||
return (
|
||||
APIResponse(detail=file_code.text)
|
||||
|
||||
Reference in New Issue
Block a user