Support query museum info

This commit is contained in:
xtaodada 2023-06-11 16:42:25 +08:00
parent 2a079aab5d
commit cb53233d5a
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
4 changed files with 297 additions and 0 deletions

154
plugins/starrail/museum.py Normal file
View File

@ -0,0 +1,154 @@
from typing import Optional, List, Dict
from genshin import Client, GenshinException
from genshin.models import StarRailMuseumBasic, StarRailMuseumDetail
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, Message
from telegram.constants import ChatAction
from telegram.ext import CallbackContext, filters
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
from utils.log import logger
__all__ = ("PlayerMuseumPlugins",)
class NotSupport(Exception):
"""不支持的服务器"""
class NotHaveData(Exception):
"""没有数据"""
class PlayerMuseumPlugins(Plugin):
"""玩家冬城博物珍奇簿查询"""
def __init__(
self,
template: TemplateService,
assets: AssetsService,
helper: GenshinHelper,
):
self.template_service = template
self.assets = assets
self.helper = helper
async def get_uid(self, user_id: int, args: List[str], reply: Optional[Message]) -> int:
"""通过消息获取 uid优先级args > reply > self"""
uid, user_id_ = None, user_id
if args:
for i in args:
if i is not None:
if i.isdigit() and len(i) == 9:
uid = int(i)
if reply:
try:
user_id_ = reply.from_user.id
except AttributeError:
pass
if not uid:
player_info = await self.helper.players_service.get_player(user_id_)
if player_info is not None:
uid = player_info.player_id
if (not uid) and (user_id_ != user_id):
player_info = await self.helper.players_service.get_player(user_id)
if player_info is not None:
uid = player_info.player_id
return uid
@handler.command("museum", block=False)
@handler.message(filters.Regex("^博物馆信息查询(.*)"), block=False)
async def 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)
if uid and str(uid)[0] not in ["1", "2", "5"]:
# todo: 支持国际服
raise NotSupport
try:
client = await self.helper.get_genshin_client(user.id)
if client.uid != uid:
raise CookiesNotFoundError(uid)
except CookiesNotFoundError:
client, _ = await self.helper.get_public_genshin_client(user.id)
render_result = await self.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 GenshinException 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):
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"{client.uid}.png", allow_sending_without_reply=True)
async def get_rander_data(self, uid: int, basic: StarRailMuseumBasic, detail: StarRailMuseumDetail) -> Dict:
exhibitions = []
for region in detail.regions:
for exhibition in region.exhibitions:
exhibitions.append(exhibition)
all_exhibitions = [exhibitions[i : i + 7] for i in range(0, len(exhibitions), 7)]
return {
"uid": uid,
"basic": basic,
"all_exhibitions": all_exhibitions,
"directors": detail.director,
}
async def render(self, client: Client, uid: Optional[int] = None) -> RenderResult:
if uid is None:
uid = client.uid
basic = await client.get_starrail_museum_info(uid)
try:
detail = await client.get_starrail_museum_detail(uid)
except GenshinException as e:
if e.retcode == 10301:
raise NotHaveData from e
raise e
data = await self.get_rander_data(uid, basic, detail)
return await self.template_service.render(
"starrail/museum/museum.html",
data,
{"width": 1000, "height": 1000},
full_page=True,
query_selector="#main-container",
)

View File

@ -45,6 +45,10 @@
<div class="command-name">/material</div>
<div class="command-description">角色培养素材查询</div>
</div>
<div class="command">
<div class="command-name">/gift</div>
<div class="command-description">查询兑换码</div>
</div>
<!-- UID 查询类 -->
<div class="command">
<div class="command-name">
@ -156,6 +160,13 @@
<!-- <div class="command-name">/calendar</div>-->
<!-- <div class="command-description">活动日历</div>-->
<!-- </div>-->
<div class="command">
<div class="command-name">
/museum
<i class="fa fa-user-circle-o ml-2"></i>
</div>
<div class="command-description">查询博物馆信息</div>
</div>
</div>
</div>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="../../styles/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="main-container">
<div style="height: 10px"></div>
<div class="text-center">
<span style="font-size: 30px">冬城博物珍奇簿</span>
<span class="badge rounded-pill bg-info">UID: {{ uid }}</span>
</div>
<div style="height: 10px"></div>
<div class="border common-width">
<div style="height: 10px"></div>
<div style="width: 88.88%; margin-left: 5%">
<div class="row">
<div class="col text-center">
<p>{{ basic.phase }}</p>
<div class="progress">
<div class="progress-bar" style="width:{{ basic.progress_exp * 100 }}%">
{{ basic.current_exp }}/{{ basic.max_exp }}
</div>
</div>
</div>
<div class="col text-center">
<p>展品收集</p>
<div class="progress">
<div class="progress-bar" style="width:{{ basic.progress_exhibition * 100 }}%">
{{ basic.exhibition_num }}/{{ basic.total_exhibition }}
</div>
</div>
</div>
<div class="col text-center">
<p>特邀助理</p>
<div class="progress">
<div class="progress-bar" style="width:{{ basic.progress_director * 100 }}%">
{{ basic.director_num }}/{{ basic.total_director }}
</div>
</div>
</div>
</div>
</div>
<div style="height: 10px"></div>
</div>
<div>
<div class="mt-3 common-width">
<div class="card">
<div class="card-body text-center">展品</div>
</div>
<div class="mt-3 card">
<div class="card-body">
{% for exhibitions in all_exhibitions %}
<div class="row">
{% for exhibition in exhibitions %}
<div class="col text-center">
<div class="justify-content-center">
{% if exhibition.is_unlock %}
<img class="exhibition" src="{{ exhibition.icon }}" alt="">
<p>{{ exhibition.name }}</p>
{% else %}
<div class="exhibition-lock">
<p style="font-size: 40px;">?</p>
</div>
<p>未获得</p>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<div>
<div class="mt-3 common-width">
<div class="card">
<div class="card-body text-center">特邀助理</div>
</div>
<div class="mt-3 card">
<div class="card-body">
<div class="row">
{% for director in directors %}
<div class="col text-center">
<div class="justify-content-center">
{% if director.is_unlock %}
<img class="director" src="{{ director.icon }}" alt="">
<p>{{ director.name }}</p>
{% else %}
<div class="director-lock">
<p style="font-size: 40px;">?</p>
</div>
<p>未获得</p>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<div style="height: 20px"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
.common-width {
width: 90%;
margin-left: 5%;
}
.exhibition {
width: 50px;
height: 50px;
}
.exhibition-lock {
height: 50px;
}
.director {
width: 50px;
height: 65px;
}
.director-lock {
height: 65px;
}