🐛 修复 leagueflow 没有有效数据爆炸 (#508)

This commit is contained in:
呵呵です
2024-10-28 21:58:38 +08:00
committed by GitHub
parent b3a77f5296
commit 381f2505d6
3 changed files with 93 additions and 85 deletions

View File

@@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from enum import IntEnum from enum import IntEnum
from typing import NamedTuple from typing import Literal, NamedTuple
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@@ -28,11 +28,16 @@ class Point(NamedTuple):
class Data(BaseModel): class Data(BaseModel):
start_time: datetime = Field(..., alias='startTime') start_time: datetime = Field(..., alias='startTime')
points: list[Point] points: list[Point] = Field(..., min_length=1)
class Empty(BaseModel):
start_time: Literal[9007199254740991] = Field(..., alias='startTime')
points: list = Field(..., max_length=0)
class LeagueFlowSuccess(BaseSuccessModel): class LeagueFlowSuccess(BaseSuccessModel):
data: Data data: Data | Empty
LeagueFlow = LeagueFlowSuccess | FailedModel LeagueFlow = LeagueFlowSuccess | FailedModel

View File

@@ -5,7 +5,7 @@ from zoneinfo import ZoneInfo
from ....utils.exception import FallbackError from ....utils.exception import FallbackError
from ....utils.render.schemas.tetrio.user.base import TetraLeagueHistoryData from ....utils.render.schemas.tetrio.user.base import TetraLeagueHistoryData
from ..api.schemas.labs.leagueflow import LeagueFlowSuccess from ..api.schemas.labs.leagueflow import Empty, LeagueFlowSuccess
from ..api.schemas.summaries.league import LeagueSuccessModel, NeverPlayedData, NeverRatedData, RatedData from ..api.schemas.summaries.league import LeagueSuccessModel, NeverPlayedData, NeverRatedData, RatedData
@@ -13,6 +13,8 @@ def flow_to_history(
leagueflow: LeagueFlowSuccess, leagueflow: LeagueFlowSuccess,
handle: Callable[[list[TetraLeagueHistoryData]], list[TetraLeagueHistoryData]] | None = None, handle: Callable[[list[TetraLeagueHistoryData]], list[TetraLeagueHistoryData]] | None = None,
) -> list[TetraLeagueHistoryData]: ) -> list[TetraLeagueHistoryData]:
if isinstance(leagueflow.data, Empty):
raise FallbackError
start_time = leagueflow.data.start_time.astimezone(ZoneInfo('Asia/Shanghai')) start_time = leagueflow.data.start_time.astimezone(ZoneInfo('Asia/Shanghai'))
ret = [ ret = [
TetraLeagueHistoryData( TetraLeagueHistoryData(

View File

@@ -4,6 +4,7 @@ from hashlib import md5
from yarl import URL from yarl import URL
from ....utils.exception import FallbackError
from ....utils.host import HostPage, get_self_netloc from ....utils.host import HostPage, get_self_netloc
from ....utils.metrics import get_metrics from ....utils.metrics import get_metrics
from ....utils.render import render from ....utils.render import render
@@ -49,9 +50,12 @@ async def make_query_image_v2(player: Player) -> bytes:
play_time = f'{game_time:.0f}s' play_time = f'{game_time:.0f}s'
else: else:
play_time = game_time play_time = game_time
try:
history = flow_to_history(leagueflow, lambda x: x[-100:])
except FallbackError:
history = None
netloc = get_self_netloc() netloc = get_self_netloc()
async with ( async with HostPage(
HostPage(
await render( await render(
'v2/tetrio/user/info', 'v2/tetrio/user/info',
Info( Info(
@@ -60,14 +64,12 @@ async def make_query_image_v2(player: Player) -> bytes:
name=user.name.upper(), name=user.name.upper(),
bio=user_info.data.bio, bio=user_info.data.bio,
banner=str( banner=str(
URL(f'http://{netloc}/host/resource/tetrio/banners/{user.ID}') URL(f'http://{netloc}/host/resource/tetrio/banners/{user.ID}') % {'revision': banner_revision}
% {'revision': banner_revision}
) )
if banner_revision is not None and banner_revision != 0 if banner_revision is not None and banner_revision != 0
else None, else None,
avatar=str( avatar=str(
URL(f'http://{netloc}/host/resource/tetrio/avatars/{user.ID}') URL(f'http://{netloc}/host/resource/tetrio/avatars/{user.ID}') % {'revision': avatar_revision}
% {'revision': avatar_revision}
) )
if avatar_revision is not None and avatar_revision != 0 if avatar_revision is not None and avatar_revision != 0
else Avatar( else Avatar(
@@ -107,7 +109,7 @@ async def make_query_image_v2(player: Player) -> bytes:
adpl=metrics.adpl, adpl=metrics.adpl,
statistic=TetraLeagueStatistic(total=league.data.gamesplayed, wins=league.data.gameswon), statistic=TetraLeagueStatistic(total=league.data.gamesplayed, wins=league.data.gameswon),
decaying=league.data.decaying, decaying=league.data.decaying,
history=flow_to_history(leagueflow, lambda x: x[-100:]), history=history,
) )
if not isinstance(league.data, NeverPlayedData) if not isinstance(league.data, NeverPlayedData)
else None, else None,
@@ -132,6 +134,5 @@ async def make_query_image_v2(player: Player) -> bytes:
zen=Zen(level=zen.data.level, score=zen.data.score), zen=Zen(level=zen.data.level, score=zen.data.score),
), ),
), ),
) as page_hash ) as page_hash:
):
return await screenshot(f'http://{netloc}/host/{page_hash}.html') return await screenshot(f'http://{netloc}/host/{page_hash}.html')