Support starrail activity - FantasticStory

This commit is contained in:
xtaodada 2023-07-21 16:40:23 +08:00
parent 79e2662fba
commit 98147c4aeb
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
15 changed files with 2296 additions and 26 deletions

View File

@ -1,7 +1,6 @@
from typing import Optional, List, Dict, TYPE_CHECKING
from simnet.errors import BadRequest as SimnetBadRequest
from simnet.models.starrail.chronicle.activity import StarRailStarFight
from simnet.models.starrail.chronicle.activity import StarRailStarFight, StarRailFantasticStory
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, Message
from telegram.constants import ChatAction
from telegram.ext import CallbackContext, filters
@ -9,7 +8,6 @@ from telegram.helpers import create_deep_linked_url
from core.dependence.assets import AssetsService
from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.template.models import RenderResult
from core.services.template.services import TemplateService
from plugins.tools.genshin import GenshinHelper, PlayerNotFoundError, CookiesNotFoundError
@ -74,15 +72,9 @@ class PlayerActivityPlugins(Plugin):
logger.info("用户 %s[%s] 查询星芒战幕信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
try:
async with self.helper.genshin(user.id) as client:
if client.player_id != uid:
raise CookiesNotFoundError(uid)
render_result = await self.star_fight_render(client, uid)
except CookiesNotFoundError:
async with self.helper.public_genshin(user.id) as client:
render_result = await self.star_fight_render(client, uid)
except PlayerNotFoundError:
except (PlayerNotFoundError, CookiesNotFoundError):
buttons = [[InlineKeyboardButton("点我绑定账号", url=create_deep_linked_url(context.bot.username, "set_cookie"))]]
if filters.ChatType.GROUPS.filter(message):
reply_message = await message.reply_text(
@ -93,25 +85,11 @@ class PlayerActivityPlugins(Plugin):
else:
await message.reply_text("未查询到您所绑定的账号信息,请先绑定账号", reply_markup=InlineKeyboardMarkup(buttons))
return
except SimnetBadRequest as exc:
if exc.retcode == 1034:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return
raise exc
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多 请稍后重试")
return
except AttributeError as exc:
logger.error("活动数据有误")
logger.exception(exc)
await message.reply_text("活动数据有误 估计是彦卿晕了")
return
except NotSupport:
reply_message = await message.reply_text("暂不支持该服务器查询活动数据")
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
except NotHaveData:
reply_message = await message.reply_text("没有查找到此活动数据")
if filters.ChatType.GROUPS.filter(reply_message):
@ -152,3 +130,70 @@ class PlayerActivityPlugins(Plugin):
full_page=True,
query_selector="#container",
)
@handler.command("fantastic_story", block=False)
@handler.message(filters.Regex("^评书奇谭信息查询(.*)"), block=False)
async def fantastic_story_command_start(self, update: Update, context: CallbackContext) -> Optional[int]:
user = update.effective_user
message = update.effective_message
logger.info("用户 %s[%s] 查询评书奇谭信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
async with self.helper.genshin(user.id) as client:
render_result = await self.fantastic_story_render(client, uid)
except PlayerNotFoundError:
buttons = [[InlineKeyboardButton("点我绑定账号", url=create_deep_linked_url(context.bot.username, "set_cookie"))]]
if filters.ChatType.GROUPS.filter(message):
reply_message = await message.reply_text(
"未查询到您所绑定的账号信息,请先私聊彦卿绑定账号", reply_markup=InlineKeyboardMarkup(buttons)
)
self.add_delete_message_job(reply_message, delay=30)
self.add_delete_message_job(message, delay=30)
else:
await message.reply_text("未查询到您所绑定的账号信息,请先绑定账号", reply_markup=InlineKeyboardMarkup(buttons))
return
except AttributeError as exc:
logger.error("活动数据有误")
logger.exception(exc)
await message.reply_text("活动数据有误 估计是彦卿晕了")
return
except NotHaveData:
reply_message = await message.reply_text("没有查找到此活动数据")
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
await render_result.reply_photo(message, filename=f"{user.id}.png", allow_sending_without_reply=True)
async def get_fantastic_story_rander_data(self, uid: int, data: StarRailFantasticStory) -> Dict:
if not data.exists_data:
raise NotHaveData
avatar_icons = {}
for record in data.records:
for avatar in record.avatars:
avatar_icons[avatar.id] = self.assets.avatar.square(avatar.id).as_uri()
return {
"uid": uid,
"records": data.records,
"avatar_icons": avatar_icons,
}
async def fantastic_story_render(self, client: "StarRailClient", uid: Optional[int] = None) -> RenderResult:
if uid is None:
uid = client.player_id
act_data = await client.get_starrail_activity(uid)
try:
fantastic_story_data = act_data.fantastic_story
except ValueError:
raise NotHaveData
data = await self.get_fantastic_story_rander_data(uid, fantastic_story_data)
return await self.template_service.render(
"starrail/activity/fantastic_story.html",
data,
{"width": 500, "height": 1200},
full_page=True,
query_selector="#container",
)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,189 @@
/*! Copyright © 2011 - 2023 miHoYo. All Rights Reserved */
.no-data[data-v-5b777587] {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}
.no-data .text[data-v-5b777587] {
margin-top: 2.66667vw;
font-size: 3.73333vw;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #7f858a;
height: 3.73333vw;
line-height: 3.73333vw
}
.item.is-editable.unable-be-select[data-v-03247942] {
opacity: .3
}
.item .name[data-v-03247942] {
height: 3.73333vw;
font-size: 3.73333vw;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #1e1f20;
line-height: 3.73333vw;
margin-top: 2.13333vw;
text-align: center
}
.item .name .text[data-v-03247942] {
text-align: center;
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
height: 3.73333vw;
line-height: 3.73333vw;
width: 22.4vw;
display: inline-block;
position: relative;
left: -.8vw
}
.item .inner[data-v-03247942] {
width: 100%;
position: relative
}
.item .inner .select-label[data-v-03247942], .item .inner[data-v-03247942] {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}
.item .inner .select-label[data-v-03247942] {
width: 5.33333vw;
height: 5.33333vw;
border: .53333vw solid #fff;
position: absolute;
top: 1.06667vw;
right: 1.06667vw;
font-size: 3.73333vw;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #fff;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border-radius: 100%
}
.item .inner .select-label.selected[data-v-03247942] {
background: #f69502
}
.item .inner .avatar-box[data-v-03247942] {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
position: relative;
overflow: hidden;
text-align: center;
border-radius: 0 4vw 0 0
}
.item .inner .avatar-box .avatar-bg[data-v-03247942] {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 0
}
.item .inner .avatar[data-v-03247942] {
height: 100%;
width: 100%;
position: relative;
top: -.53333vw;
display: inline-block
}
.item .inner .icon[data-v-03247942] {
position: absolute;
left: 1.6vw;
top: 1.6vw
}
.item .inner .index[data-v-03247942] {
top: 0;
right: 0;
width: 4.8vw;
height: 5.86667vw;
background: rgba(0, 0, 0, .5);
border-radius: 0 4vw 0 1.6vw;
font-size: 3.73333vw;
line-height: 3.73333vw
}
.item .inner .index[data-v-03247942], .item .inner .level[data-v-03247942] {
position: absolute;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #fff;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}
.item .inner .level[data-v-03247942] {
bottom: .53333vw;
left: 0;
height: 3.73333vw;
background: #030b0e;
width: 100%;
font-size: 3.2vw;
line-height: 3.2vw
}
.item .inner .trial[data-v-03247942] {
position: absolute;
top: 0;
right: 0;
padding: 1px 1.06667vw;
background: #ffc870;
border-radius: 2.66667vw;
font-weight: 500;
font-size: 2.66667vw;
line-height: 2.66667vw;
font-family: PingFangSC-Medium, PingFang SC;
color: #000;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}

View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fantastic Story</title>
<link href="css/7_1860676e902f99970620.css" rel="stylesheet">
<link href="css/32_a6abfefd22b3d1a40162.css" rel="stylesheet">
</head>
<body>
<div id="container">
<div data-v-6cd4e78c="" data-v-056bcd56="" class="layout"
style="background: url('images/story-bg.436f1d88.png') 0% 0% / 100% no-repeat rgb(71, 89, 131);">
<div data-v-6cd4e78c="" class="header">
<div data-v-6cd4e78c="" class="border">
<div data-v-6cd4e78c="" class="left"><span data-v-6cd4e78c="">评书奇谭</span></div> <!---->
</div>
</div>
<div data-v-6cd4e78c="" class="container">
<div data-v-6cd4e78c="" class="border">
{% set bg = ['1.96e45c02', '2.3f186847', '3.f7c6b1e9', '4.32486a3e', '5.426291c0', '6.b4b0eadf'] %}
{% set level_icon = ['', '1212', '1213', '1214', '1215'] %}
{% for record in records %}
{% set not_challenge = record.score == 0 %}
<div data-v-44091bd3="" class="card" data-v-6cd4e78c="">
<div data-v-44091bd3="" class="bg {% if not_challenge %}not-challenged{% endif %}">
<img data-v-44091bd3="" src="images/{{ bg[loop.index0] }}.png" class="icon">
</div>
<div data-v-44091bd3="" class="inner {% if not_challenge %}not-challenged{% endif %}">
<div data-v-44091bd3="" class="header">
<div data-v-44091bd3="" class="name">
{{ record.name }}
{% if not not_challenge %}
<span data-v-44091bd3="">{{ record.time_str }}</span>
{% endif %}
</div>
{% if not not_challenge %}
<div data-v-44091bd3="" class="info">
<div data-v-44091bd3="" class="round">文段分数 {{ record.score }}</div>
</div>
<div data-v-44091bd3="" class="right">
<img data-v-44091bd3="" src="images/{{ level_icon[record.score_rank] }}.png"
class="icon">
</div>
{% endif %}
</div>
{% if not_challenge %}
<div data-v-44091bd3="" class="not-challenged-text">尚未挑战</div>
{% else %}
<div data-v-44091bd3="" class="line"></div>
<div data-v-44091bd3="" class="roles">
{% for role in record.avatars %}
<div data-v-03247942="" data-v-44091bd3=""
class="role-item item unable-be-select">
<div data-v-03247942="" class="inner">
<div data-v-03247942="" class="avatar-box"
style="width: 16.5333vw; height: 19.2vw;">
<div data-v-03247942="" class="avatar-bg"
style="background: url('{{ avatar_icons[role.id] }}') center center / 100% no-repeat;"></div>
<div data-v-03247942="" class="level">等级 {{ role.level }}</div>
</div>
{% if role.is_trial %}
<div data-v-03247942="" class="trial">试用</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<div data-v-44091bd3="" class="buffs">
{% for buff in record.buffs %}
<div data-v-44091bd3="" class="buff-item">
<div data-v-44091bd3="" class="icon"
style="background-image: url('{{ buff.icon }}');"></div>
<div data-v-44091bd3="" class="text">
{{ buff.name }}{{ buff.desc }}
</div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB