Files
nonebot-plugin-tetris-stats/nonebot_plugin_tetris_stats/utils/render.py

109 lines
2.7 KiB
Python

from datetime import datetime
from typing import Annotated, ClassVar, Literal, overload
from jinja2 import Environment, FileSystemLoader
from nonebot.compat import PYDANTIC_V2
from pydantic import BaseModel
from ..game_data_processor.io_data_processor.typing import Rank
from .templates import templates_dir
from .typing import Number
if PYDANTIC_V2:
from pydantic import PlainSerializer
env = Environment(
loader=FileSystemLoader(templates_dir), autoescape=True, trim_blocks=True, lstrip_blocks=True, enable_async=True
)
def format_datetime_to_timestamp(dt: datetime) -> int:
return int(dt.timestamp() * 1000)
class Bind(BaseModel):
class People(BaseModel):
avatar: str
name: str
platform: Literal['TETR.IO', 'TOP', 'TOS']
status: Literal['error', 'success', 'unknown', 'unlink', 'unverified']
user: People
bot: People
command: str
class TETRIOInfo(BaseModel):
class User(BaseModel):
class Avatar(BaseModel):
type: Literal['identicon']
hash: str
avatar: str | Avatar
name: str
bio: str | None
class Ranking(BaseModel):
rating: Number
rd: Number
class TetraLeague(BaseModel):
rank: Rank
tr: Number
global_rank: Number
pps: Number
lpm: Number
apm: Number
apl: Number
vs: Number
adpm: Number
adpl: Number
class TetraLeagueHistory(BaseModel):
class Data(BaseModel):
if PYDANTIC_V2:
record_at: Annotated[datetime, PlainSerializer(format_datetime_to_timestamp, return_type=int)]
else:
record_at: datetime # type: ignore[no-redef]
tr: Number
data: list[Data]
split_interval: Number
min_tr: Number
max_tr: Number
offset: Number
class Radar(BaseModel):
app: Number
dsps: Number
dspp: Number
ci: Number
ge: Number
user: User
ranking: Ranking
tetra_league: TetraLeague
tetra_league_history: TetraLeagueHistory
radar: Radar
sprint: str
blitz: str
if not PYDANTIC_V2:
class Config:
json_encoders: ClassVar[dict] = {datetime: format_datetime_to_timestamp}
@overload
async def render(render_type: Literal['binding'], data: Bind) -> str: ...
@overload
async def render(render_type: Literal['tetrio/info'], data: TETRIOInfo) -> str: ...
async def render(render_type: Literal['binding', 'tetrio/info'], data: Bind | TETRIOInfo) -> str:
if PYDANTIC_V2:
return await env.get_template('index.html').render_async(path=render_type, data=data.model_dump_json())
return await env.get_template('index.html').render_async(path=render_type, data=data.json())