mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
✨ 使用新版模板 (#313)
* 🔥 删除现有模板 * ✨ 自动克隆模板仓库 * 🔥 删除 identicon 相关代码 * 🚚 修改静态文件路径 * ✨ 使用新模板进行渲染 * ✨ 每次渲染都获取一次模板, 以应对实时更新 * ✨ TETR.IO 绑定图使用新模板 * 🚚 修改网络路径 * ✨ TOP 绑定图使用新模板 * ✨ TOS 绑定图使用新模板 * 🐛 防止截图超时 * 🐛 Pydantic V1 会把 float 转换成 int * ✏️ 模板字段名写错了 * ✨ 兼容 Pydantic V1 * ✨ TETR.IO 查询图使用新模板 * 🐛 在查询的用户没有历史记录时不去查询更多记录
This commit is contained in:
@@ -1,69 +1,104 @@
|
||||
from typing import Any, Literal, overload
|
||||
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 path
|
||||
from .typing import GameType
|
||||
from .templates import templates_dir
|
||||
from .typing import Number
|
||||
|
||||
Bind = Literal['bind.j2.html']
|
||||
Data = Literal['data.j2.html']
|
||||
if PYDANTIC_V2:
|
||||
from pydantic import PlainSerializer
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(path), autoescape=True, trim_blocks=True, lstrip_blocks=True, enable_async=True
|
||||
loader=FileSystemLoader(templates_dir), autoescape=True, trim_blocks=True, lstrip_blocks=True, enable_async=True
|
||||
)
|
||||
|
||||
|
||||
@overload
|
||||
async def render(
|
||||
template: Bind,
|
||||
*,
|
||||
user_avatar: str,
|
||||
state: Literal['error', 'success', 'unknown', 'unlink', 'unverified'],
|
||||
bot_avatar: str,
|
||||
game_type: GameType,
|
||||
user_name: str,
|
||||
bot_name: str,
|
||||
command: str,
|
||||
) -> str: ...
|
||||
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):
|
||||
avatar: str
|
||||
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(
|
||||
template: Data,
|
||||
*,
|
||||
user_avatar: str,
|
||||
user_name: str,
|
||||
user_sign: str | None,
|
||||
game_type: Literal['TETR.IO'],
|
||||
ranking: str | float,
|
||||
rd: str | float,
|
||||
rank: Rank,
|
||||
TR: str | float, # noqa: N803
|
||||
global_rank: str | int,
|
||||
lpm: str | float,
|
||||
pps: str | float,
|
||||
apm: str | float,
|
||||
apl: str | float,
|
||||
adpm: str | float,
|
||||
adpl: str | float,
|
||||
vs: str | float,
|
||||
sprint: str,
|
||||
blitz: str,
|
||||
data: list[list[int | float]],
|
||||
split_value: int,
|
||||
offset: int,
|
||||
value_max: int,
|
||||
value_min: int,
|
||||
app: str | float,
|
||||
dsps: str | float,
|
||||
dspp: str | float,
|
||||
ci: str | float,
|
||||
ge: str | float,
|
||||
) -> str: ...
|
||||
async def render(render_type: Literal['binding'], data: Bind) -> str: ...
|
||||
|
||||
|
||||
async def render(template: Bind | Data, **kwargs: Any) -> str:
|
||||
if kwargs['game_type'] == 'IO':
|
||||
kwargs['game_type'] = 'TETR.IO'
|
||||
return await env.get_template(template).render_async(**kwargs)
|
||||
@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())
|
||||
|
||||
Reference in New Issue
Block a user