使用新版模板 (#313)

* 🔥 删除现有模板

*  自动克隆模板仓库

* 🔥 删除 identicon 相关代码

* 🚚 修改静态文件路径

*  使用新模板进行渲染

*  每次渲染都获取一次模板, 以应对实时更新

*  TETR.IO 绑定图使用新模板

* 🚚 修改网络路径

*  TOP 绑定图使用新模板

*  TOS 绑定图使用新模板

* 🐛 防止截图超时

* 🐛 Pydantic V1 会把 float 转换成 int

* ✏️ 模板字段名写错了

*  兼容 Pydantic V1

*  TETR.IO 查询图使用新模板

* 🐛 在查询的用户没有历史记录时不去查询更多记录
This commit is contained in:
呵呵です
2024-05-10 09:41:05 +08:00
committed by GitHub
parent e47f1bb6f9
commit 716e392a3a
54 changed files with 280 additions and 1826 deletions

View File

@@ -28,7 +28,7 @@ from ...db.models import HistoricalData
from ...utils.avatar import get_avatar
from ...utils.exception import MessageFormatError, RequestError, WhatTheFuckError
from ...utils.host import HostPage, get_self_netloc
from ...utils.render import render
from ...utils.render import Bind, TETRIOInfo, render
from ...utils.request import splice_url
from ...utils.retry import retry
from ...utils.screenshot import screenshot
@@ -96,22 +96,26 @@ class Processor(ProcessorMeta):
if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE):
async with HostPage(
await render(
'bind.j2.html',
user_avatar=f'https://tetr.io/user-content/avatars/{user_info.data.user.id}.jpg?rv={user_info.data.user.avatar_revision}'
if user_info.data.user.avatar_revision is not None
else f'../../identicon?md5={md5(user_info.data.user.id.encode()).hexdigest()}', # noqa: S324
state='unknown',
bot_avatar=bot_avatar,
game_type=self.game_platform,
user_name=user_info.data.user.username.upper(),
bot_name=bot_info.user_name,
command='io查我',
'binding',
Bind(
platform='TETR.IO',
status='unknown',
user=Bind.People(
avatar=f'https://tetr.io/user-content/avatars/{user_info.data.user.id}.jpg?rv={user_info.data.user.avatar_revision}'
if user_info.data.user.avatar_revision is not None
else f'{{"type":"identicon","hash":"{md5(user_info.data.user.id.encode()).hexdigest()}"}}', # noqa: S324
name=user_info.data.user.username.upper(),
),
bot=Bind.People(
avatar=bot_avatar,
name=bot_info.user_name,
),
command='io查我',
),
)
) as page_hash:
message = UniMessage.image(
raw=await screenshot(
urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', ''))
)
raw=await screenshot(urlunparse(('http', get_self_netloc(), f'/host/{page_hash}.html', '', '', '')))
)
return message
@@ -138,19 +142,20 @@ class Processor(ProcessorMeta):
.where(HistoricalData.user_unique_identifier == self.user.unique_identifier)
)
).all()
extra = (
await session.scalars(
select(HistoricalData)
.where(HistoricalData.game_platform == GAME_TYPE)
.where(HistoricalData.user_unique_identifier == self.user.unique_identifier)
.order_by(HistoricalData.id.desc())
.where(HistoricalData.id < min([i.id for i in historical_data]))
.limit(1)
)
).one_or_none()
if extra is not None:
historical_data = list(historical_data)
historical_data.append(extra)
if historical_data:
extra = (
await session.scalars(
select(HistoricalData)
.where(HistoricalData.game_platform == GAME_TYPE)
.where(HistoricalData.user_unique_identifier == self.user.unique_identifier)
.order_by(HistoricalData.id.desc())
.where(HistoricalData.id < min([i.id for i in historical_data]))
.limit(1)
)
).one_or_none()
if extra is not None:
historical_data = list(historical_data)
historical_data.append(extra)
class HistoricalTr(NamedTuple):
time: datetime
@@ -213,7 +218,6 @@ class Processor(ProcessorMeta):
histories[1],
today - forward,
)
else:
histories.insert(0, HistoricalTr((today - forward), histories[0].tr))
@@ -257,43 +261,52 @@ class Processor(ProcessorMeta):
blitz_value = f'{blitz.record.endcontext.score:,}'
async with HostPage(
await render(
'data.j2.html',
user_avatar=f'https://tetr.io/user-content/avatars/{user_info.data.user.id}.jpg?rv={user_info.data.user.avatar_revision}'
if user_info.data.user.avatar_revision is not None
else f'../../identicon?md5={md5(user_info.data.user.id.encode()).hexdigest()}', # noqa: S324
user_name=user_name,
user_sign=user_info.data.user.bio,
game_type='TETR.IO',
ranking=round(league.glicko, 2),
rd=round(league.rd, 2),
rank=league.rank,
TR=round(league.rating, 2),
global_rank=league.standing,
lpm=round(lpm := (league.pps * 24), 2),
pps=league.pps,
apm=league.apm,
apl=round(league.apm / lpm, 2),
adpm=round(adpm := (league.vs * 0.6), 2),
adpl=round(adpm / lpm, 2),
vs=league.vs,
sprint=sprint_value,
blitz=blitz_value,
data=[[int(datetime.timestamp(time) * 1000), tr] for time, tr in histories],
split_value=split_value,
offset=offset,
value_max=value_max,
value_min=value_min,
app=(app := (league.apm / (60 * league.pps))),
dsps=(dsps := ((league.vs / 100) - (league.apm / 60))),
dspp=(dspp := (dsps / league.pps)),
ci=150 * dspp - 125 * app + 50 * (league.vs / league.apm) - 25,
ge=2 * ((app * dsps) / league.pps),
'tetrio/info',
TETRIOInfo(
user=TETRIOInfo.User(
avatar=f'https://tetr.io/user-content/avatars/{user_info.data.user.id}.jpg?rv={user_info.data.user.avatar_revision}'
if user_info.data.user.avatar_revision is not None
else f'{{"type":"identicon","hash":"{md5(user_info.data.user.id.encode()).hexdigest()}"}}', # noqa: S324
name=user_name,
bio=user_info.data.user.bio,
),
ranking=TETRIOInfo.Ranking(
rating=round(league.glicko, 2),
rd=round(league.rd, 2),
),
tetra_league=TETRIOInfo.TetraLeague(
rank=league.rank,
tr=round(league.rating, 2),
global_rank=league.standing,
pps=league.pps,
lpm=round(lpm := (league.pps * 24), 2),
apm=league.apm,
apl=round(league.apm / lpm, 2),
vs=league.vs,
adpm=round(adpm := (league.vs * 0.6), 2),
adpl=round(adpm / lpm, 2),
),
tetra_league_history=TETRIOInfo.TetraLeagueHistory(
data=[TETRIOInfo.TetraLeagueHistory.Data(record_at=time, tr=tr) for time, tr in histories],
split_interval=split_value,
min_tr=value_min,
max_tr=value_max,
offset=offset,
),
radar=TETRIOInfo.Radar(
app=(app := (league.apm / (60 * league.pps))),
dsps=(dsps := ((league.vs / 100) - (league.apm / 60))),
dspp=(dspp := (dsps / league.pps)),
ci=150 * dspp - 125 * app + 50 * (league.vs / league.apm) - 25,
ge=2 * ((app * dsps) / league.pps),
),
sprint=sprint_value,
blitz=blitz_value,
),
)
) as page_hash:
return UniMessage.image(
raw=await screenshot(
urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', ''))
)
raw=await screenshot(urlunparse(('http', get_self_netloc(), f'/host/{page_hash}.html', '', '', '')))
)
# fallback
ret_message = ''

View File

@@ -16,7 +16,7 @@ from ...db import BindStatus, create_or_update_bind
from ...utils.avatar import get_avatar
from ...utils.exception import MessageFormatError, RequestError
from ...utils.host import HostPage, get_self_netloc
from ...utils.render import render
from ...utils.render import Bind, render
from ...utils.request import Request, splice_url
from ...utils.screenshot import screenshot
from .. import Processor as ProcessorMeta
@@ -83,24 +83,27 @@ class Processor(ProcessorMeta):
game_platform=GAME_TYPE,
game_account=self.user.name,
)
bot_avatar = await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg')
if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE):
async with HostPage(
await render(
'bind.j2.html',
user_avatar='../../static/static/logo/top.ico',
state='unknown',
bot_avatar=bot_avatar,
game_type=self.game_platform,
user_name=(await self.get_user_name()).upper(),
bot_name=bot_info.user_name,
command='top查我',
'binding',
Bind(
platform=self.game_platform,
status='unknown',
user=Bind.People(
avatar=await get_avatar(user_info, 'Data URI', None),
name=(await self.get_user_name()).upper(),
),
bot=Bind.People(
avatar=await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg'),
name=bot_info.user_name,
),
command='top查我',
),
)
) as page_hash:
message = UniMessage.image(
raw=await screenshot(
urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', ''))
)
raw=await screenshot(urlunparse(('http', get_self_netloc(), f'/host/{page_hash}.html', '', '', '')))
)
return message

View File

@@ -6,7 +6,7 @@ from nonebot.matcher import Matcher
from nonebot_plugin_alconna import At, on_alconna
from nonebot_plugin_alconna.uniseg import UniMessage
from nonebot_plugin_orm import get_session
from nonebot_plugin_userinfo import BotUserInfo, UserInfo # type: ignore[import-untyped]
from nonebot_plugin_userinfo import BotUserInfo, EventUserInfo, UserInfo # type: ignore[import-untyped]
from ...db import query_bind_info
from ...utils.exception import HandleNotFinishedError, NeedCatchError, RequestError
@@ -132,7 +132,14 @@ except ImportError:
@alc.assign('bind')
async def _(bot: Bot, event: Event, matcher: Matcher, account: User, bot_info: UserInfo = BotUserInfo()): # noqa: B008
async def _( # noqa: PLR0913
bot: Bot,
event: Event,
matcher: Matcher,
account: User,
bot_info: UserInfo = BotUserInfo(), # noqa: B008
user_info: UserInfo = EventUserInfo(), # noqa: B008
):
proc = Processor(
event_id=id(event),
user=account,
@@ -140,7 +147,9 @@ async def _(bot: Bot, event: Event, matcher: Matcher, account: User, bot_info: U
)
try:
await (
await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id(), bot_info=bot_info)
await proc.handle_bind(
platform=get_platform(bot), account=event.get_user_id(), bot_info=bot_info, nb_user_info=user_info
)
).finish()
except NeedCatchError as e:
await matcher.send(str(e))

View File

@@ -14,7 +14,7 @@ from ...db import BindStatus, create_or_update_bind
from ...utils.avatar import get_avatar
from ...utils.exception import MessageFormatError, RequestError
from ...utils.host import HostPage, get_self_netloc
from ...utils.render import render
from ...utils.render import Bind, render
from ...utils.request import Request, splice_url
from ...utils.screenshot import screenshot
from .. import Processor as ProcessorMeta
@@ -84,7 +84,9 @@ class Processor(ProcessorMeta):
return GAME_TYPE
@override
async def handle_bind(self, platform: str, account: str, bot_info: NBUserInfo) -> UniMessage:
async def handle_bind(
self, platform: str, account: str, bot_info: NBUserInfo, nb_user_info: NBUserInfo
) -> UniMessage:
"""处理绑定消息"""
self.command_type = 'bind'
await self.get_user()
@@ -96,25 +98,27 @@ class Processor(ProcessorMeta):
game_platform=GAME_TYPE,
game_account=self.user.unique_identifier,
)
bot_avatar = await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg')
user_info = await self.get_user_info()
if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE):
async with HostPage(
await render(
'bind.j2.html',
user_avatar='../../static/static/logo/tos.ico',
state='unknown',
bot_avatar=bot_avatar,
game_type=self.game_platform,
user_name=user_info.data.name.upper(),
bot_name=bot_info.user_name,
command='茶服查我',
'binding',
Bind(
platform=self.game_platform,
status='unknown',
user=Bind.People(
avatar=await get_avatar(nb_user_info, 'Data URI', None), name=user_info.data.name
),
bot=Bind.People(
avatar=await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg'),
name=bot_info.user_name,
),
command='茶服查我',
),
)
) as page_hash:
message = UniMessage.image(
raw=await screenshot(
urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', ''))
)
raw=await screenshot(urlunparse(('http', get_self_netloc(), f'/host/{page_hash}.html', '', '', '')))
)
return message