diff --git a/core/template/services.py b/core/template/services.py
index 37584b09..9dc3bbde 100644
--- a/core/template/services.py
+++ b/core/template/services.py
@@ -1,6 +1,6 @@
import os
import time
-from typing import Optional, Dict
+from typing import Dict, Optional
from jinja2 import Environment, PackageLoader, Template
from playwright.async_api import ViewportSize
@@ -65,7 +65,7 @@ class TemplateService:
viewport: ViewportSize = None,
full_page: bool = True,
evaluate: Optional[str] = None,
- query_selector: str = None,
+ query_selector: str = None
) -> bytes:
"""模板渲染成图片
:param template_path: 模板目录
diff --git a/metadata/genshin.py b/metadata/genshin.py
index 01552b0b..ef1cac81 100644
--- a/metadata/genshin.py
+++ b/metadata/genshin.py
@@ -19,6 +19,7 @@ __all__ = [
"ARTIFACT_DATA",
"NAMECARD_DATA",
"honey_id_to_game_id",
+ "game_id_to_role_id",
"Data",
]
@@ -91,3 +92,10 @@ NAMECARD_DATA: dict[str, dict[str, int | str]] = Data("namecard")
@functools.lru_cache()
def honey_id_to_game_id(honey_id: str, item_type: str) -> str | None:
return next((key for key, value in HONEY_DATA[item_type].items() if value[0] == honey_id), None)
+
+
+@functools.lru_cache
+def game_id_to_role_id(gid: str) -> int | None:
+ return next(
+ (int(key.split("-")[0]) for key, value in AVATAR_DATA.items() if value["icon"].split("_")[-1] == gid), None
+ )
diff --git a/metadata/shortname.py b/metadata/shortname.py
index 14094657..432cd2d2 100644
--- a/metadata/shortname.py
+++ b/metadata/shortname.py
@@ -217,6 +217,7 @@ roles = {
10000051: ["优菈", "Eula", "eula", "优拉", "尤拉", "尤菈", "浪花骑士", "记仇", "劳伦斯"],
10000052: [
"雷电将军",
+ "Shougun",
"Raiden Shogun",
"Raiden",
"raiden",
diff --git a/plugins/genshin/abyss.py b/plugins/genshin/abyss.py
index 3963ab55..24514595 100644
--- a/plugins/genshin/abyss.py
+++ b/plugins/genshin/abyss.py
@@ -1,9 +1,17 @@
-from typing import Dict, Optional
+"""深渊数据查询"""
+import asyncio
+import re
+from datetime import datetime
+from functools import lru_cache, partial
+from typing import List, Match, Optional, Tuple
+import ujson as json
+from arkowrapper import ArkoWrapper
from genshin import Client
-from telegram import Update
-from telegram.constants import ChatAction
-from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters
+from pytz import timezone
+from telegram import InlineKeyboardButton, InlineKeyboardMarkup, InputMediaPhoto, Update
+from telegram.constants import ChatAction, ParseMode
+from telegram.ext import CallbackContext, filters
from core.base.assets import AssetsService
from core.baseplugin import BasePlugin
@@ -13,23 +21,51 @@ from core.plugin import Plugin, handler
from core.template import TemplateService
from core.user import UserService
from core.user.error import UserNotFoundError
+from metadata.genshin import game_id_to_role_id
from utils.decorators.error import error_callable
from utils.decorators.restricts import restricts
-from utils.helpers import get_genshin_client, get_public_genshin_client
+from utils.helpers import async_re_sub, get_genshin_client, get_public_genshin_client
from utils.log import logger
+TZ = timezone("Asia/Shanghai")
+cmd_pattern = r"^/abyss\s*((?:\d+)|(?:all))?\s*(pre)?"
+msg_pattern = r"^深渊数据((?:查询)|(?:总览))(上期)?\D?(\d*)?.*?$"
+
+regex_01 = r"['\"]icon['\"]:\s*['\"](.*?)['\"]"
+regex_02 = r"['\"]side_icon['\"]:\s*['\"](.*?)['\"]"
+
+
+async def replace_01(match: Match, assets_service: AssetsService) -> str:
+ aid = game_id_to_role_id(re.findall(r"UI_AvatarIcon_(.*?).png", match.group(1))[0])
+ return (await assets_service.avatar(aid).icon()).as_uri()
+
+
+async def replace_02(match: Match, assets_service: AssetsService) -> str:
+ aid = game_id_to_role_id(re.findall(r"UI_AvatarIcon_Side_(.*?).png", match.group(1))[0])
+ return (await assets_service.avatar(aid).side()).as_uri()
+
+
+@lru_cache
+def get_args(text: str) -> Tuple[int, bool, bool]:
+ if text.startswith("/"):
+ result = re.match(cmd_pattern, text).groups()
+ try:
+ floor = int(result[0] or 0)
+ except ValueError:
+ floor = 0
+ return floor, result[0] == "all", bool(result[1])
+ else:
+ result = re.match(msg_pattern, text).groups()
+ return int(result[2] or 0), result[0] == "总览", result[1] == "上期"
+
class AbyssUnlocked(Exception):
"""根本没动"""
- pass
-
class NoMostKills(Exception):
"""挑战了但是数据没刷新"""
- pass
-
class Abyss(Plugin, BasePlugin):
"""深渊数据查询"""
@@ -46,95 +82,245 @@ class Abyss(Plugin, BasePlugin):
self.user_service = user_service
self.assets_service = assets_service
- @staticmethod
- def _get_role_star_bg(value: int):
- if value == 4:
- return "./background/roleStarBg4.png"
- elif value == 5:
- return "./background/roleStarBg5.png"
- else:
- raise ValueError("错误的数据")
-
- async def _get_abyss_data(self, client: Client, uid: Optional[int] = None) -> Dict:
- if uid is None:
- _uid = client.uid
- await client.get_record_cards()
- else:
- _uid = uid
- spiral_abyss_info = await client.get_spiral_abyss(_uid)
- if not spiral_abyss_info.unlocked:
- raise AbyssUnlocked
- ranks = spiral_abyss_info.ranks
- if len(spiral_abyss_info.ranks.most_kills) == 0:
- raise NoMostKills
- abyss_data = {
- "uid": _uid,
- "max_floor": spiral_abyss_info.max_floor,
- "total_battles": spiral_abyss_info.total_battles,
- "total_stars": spiral_abyss_info.total_stars,
- "most_played_list": [],
- "most_kills": {
- "icon": await self.assets_service.avatar(ranks.most_kills[0].id).side(),
- "value": ranks.most_kills[0].value,
- },
- "strongest_strike": {
- "icon": await self.assets_service.avatar(ranks.strongest_strike[0].id).side(),
- "value": ranks.strongest_strike[0].value,
- },
- "most_damage_taken": {
- "icon": await self.assets_service.avatar(ranks.most_damage_taken[0].id).side(),
- "value": ranks.most_damage_taken[0].value,
- },
- "most_bursts_used": {
- "icon": await self.assets_service.avatar(ranks.most_bursts_used[0].id).side(),
- "value": ranks.most_bursts_used[0].value,
- },
- "most_skills_used": {
- "icon": await self.assets_service.avatar(ranks.most_skills_used[0].id).side(),
- "value": ranks.most_skills_used[0].value,
- },
- }
- # most_kills
- most_played_list = ranks.most_played
- for most_played in most_played_list:
- temp = {
- "icon": await self.assets_service.avatar(most_played.id).icon(),
- "value": most_played.value,
- "background": self._get_role_star_bg(most_played.rarity),
- }
- abyss_data["most_played_list"].append(temp)
- return abyss_data
-
- @handler(CommandHandler, command="abyss", block=False)
- @handler(MessageHandler, filters=filters.Regex("^深渊数据查询(.*)"), block=False)
+ @handler.command("abyss", block=False)
+ @handler.message(filters.Regex(msg_pattern), block=False)
@restricts()
@error_callable
async def command_start(self, update: Update, context: CallbackContext) -> None:
user = update.effective_user
message = update.effective_message
- logger.info(f"用户 {user.full_name}[{user.id}] 查深渊挑战命令请求")
- await message.reply_chat_action(ChatAction.TYPING)
- try:
- try:
- client = await get_genshin_client(user.id)
- abyss_data = await self._get_abyss_data(client)
- except CookiesNotFoundError:
- client, uid = await get_public_genshin_client(user.id)
- abyss_data = await self._get_abyss_data(client, uid)
- except UserNotFoundError:
- reply_message = await message.reply_text("未查询到账号信息,请先私聊派蒙绑定账号")
+
+ # 若查询帮助
+ if (message.text.startswith("/") and "help" in message.text) or "帮助" in message.text:
+ await message.reply_text(
+ "深渊挑战数据功能使用帮助(中括号表示可选参数)\n\n"
+ "指令格式:\n/abyss + [层数/all] + [pre]
\n(pre
表示上期)\n\n"
+ "文本格式:\n深渊数据 + 查询/总览 + [上期] + [层数]
\n\n"
+ "例如以下指令都正确:\n"
+ "/abyss
\n/abyss 12 pre
\n/abyss all pre
\n"
+ "深渊数据查询
\n深渊数据查询上期第12层
\n深渊数据总览上期
",
+ parse_mode=ParseMode.HTML,
+ )
+ logger.info(f"用户 {user.full_name}[{user.id}] 查询[bold]深渊挑战数据[/bold]帮助", extra={"markup": True})
+ return
+
+ # 解析参数
+ floor, total, previous = get_args(message.text)
+
+ if floor > 12 or floor < 0:
+ reply_msg = await message.reply_text("深渊层数输入错误,请重新输入")
if filters.ChatType.GROUPS.filter(message):
- self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 10)
+ self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
return
- except TooManyRequestPublicCookies:
- await message.reply_text("用户查询次数过多 请稍后重试")
- return
- except (AbyssUnlocked, NoMostKills):
- await message.reply_text("本次深渊旅行者还没挑战呢,咕咕咕~~~")
- return
- await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
- png_data = await self.template_service.render(
- "genshin/abyss", "abyss.html", abyss_data, {"width": 865, "height": 504}, full_page=False
+ elif 0 < floor < 9:
+ previous = False
+
+ logger.info(
+ f"用户 {user.full_name}[{user.id}] [bold]深渊挑战数据[/bold]请求: "
+ f"floor={floor} total={total} previous={previous}",
+ extra={"markup": True},
)
- await message.reply_photo(png_data, filename=f"abyss_{user.id}.png", allow_sending_without_reply=True)
+
+ try:
+ client = await get_genshin_client(user.id)
+ await client.get_record_cards()
+ uid = client.uid
+ except UserNotFoundError: # 若未找到账号
+ if filters.ChatType.GROUPS.filter(message):
+ buttons = [[InlineKeyboardButton("点我私聊", url=f"https://t.me/{context.bot.username}?start=set_cookies")]]
+ reply_msg = await message.reply_text(
+ "未查询到您所绑定的账号信息,请先私聊派蒙绑定账号", reply_markup=InlineKeyboardMarkup(buttons)
+ )
+ self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 30)
+
+ self._add_delete_message_job(context, message.chat_id, message.message_id, 30)
+ else:
+ await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
+ return
+ except CookiesNotFoundError: # 若未找到cookie
+ client, uid = await get_public_genshin_client(user.id)
+ except TooManyRequestPublicCookies:
+ reply_msg = await message.reply_text(
+ "查询次数太多,请您稍后重试",
+ )
+ if filters.ChatType.GROUPS.filter(message):
+ self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
+ self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
+ return
+
+ async def reply_message(content: str) -> None:
+ _user = await client.get_genshin_user(uid)
+ _reply_msg = await message.reply_text(
+ f"旅行者 {_user.info.nickname}({uid}
) {content}", parse_mode=ParseMode.HTML
+ )
+ if filters.ChatType.GROUPS.filter(message):
+ self._add_delete_message_job(context, _reply_msg.chat_id, _reply_msg.message_id, 10)
+ self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
+
+ if total:
+ reply_msg = await message.reply_text("派蒙需要时间整理深渊数据,还请耐心等待哦~")
+ if filters.ChatType.GROUPS.filter(message):
+ self._add_delete_message_job(context, reply_msg.chat_id, reply_msg.message_id, 10)
+ self._add_delete_message_job(context, message.chat_id, message.message_id, 10)
+
+ await message.reply_chat_action(ChatAction.TYPING)
+
+ try:
+ images = await self.get_rendered_pic(client, uid, floor, total, previous)
+ except AbyssUnlocked: # 若深渊未解锁
+ return await reply_message("还未解锁深渊哦~")
+ except NoMostKills: # 若深渊还未挑战
+ return await reply_message("还没有挑战本次深渊呢,咕咕咕~")
+ except IndexError: # 若深渊为挑战此层
+ return await reply_message("还没有挑战本层呢,咕咕咕~")
+ if images is None:
+ return await reply_message(f"还没有第 {floor} 层的挑战数据")
+
+ await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
+
+ for group in ArkoWrapper(images).map(InputMediaPhoto).group(10): # 每 10 张图片分一个组
+ await message.reply_media_group(list(group), allow_sending_without_reply=True)
+
+ logger.info(f"用户 {user.full_name}[{user.id}] [bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True})
+
+ async def get_rendered_pic(
+ self, client: Client, uid: int, floor: int, total: bool, previous: bool
+ ) -> Optional[List[bytes]]:
+ """
+ 获取渲染后的图片
+
+ Args:
+ client (Client): 获取 genshin 数据的 client
+ uid (int): 需要查询的 uid
+ floor (int): 层数
+ total (bool): 是否为总览
+ previous (bool): 是否为上期
+
+ Returns:
+ bytes格式的图片
+ """
+
+ def json_encoder(value):
+ if isinstance(value, datetime):
+ return value.astimezone(TZ).strftime("%Y-%m-%d %H:%M:%S")
+ return value
+
+ abyss_data = await client.get_spiral_abyss(uid, previous=previous, lang="zh-cn")
+ if not abyss_data.unlocked:
+ raise AbyssUnlocked()
+ if not abyss_data.ranks.most_kills:
+ raise NoMostKills()
+ end_time = abyss_data.end_time.astimezone(TZ)
+ time = end_time.strftime("%Y年%m月") + "上" if end_time.day <= 16 else "下" + "期"
+ stars = [i.stars for i in filter(lambda x: x.floor > 8, abyss_data.floors)]
+ total_stars = f"{sum(stars)} ({'-'.join(map(str, stars))})"
+
+ render_data = {}
+ result = await async_re_sub(
+ regex_01,
+ partial(replace_01, assets_service=self.assets_service),
+ abyss_data.json(encoder=json_encoder),
+ )
+ result = await async_re_sub(regex_02, partial(replace_02, assets_service=self.assets_service), result)
+
+ render_data["time"] = time
+ render_data["stars"] = total_stars
+ render_data["uid"] = uid
+ render_data["floor_colors"] = {
+ 1: "#374952",
+ 2: "#374952",
+ 3: "#55464B",
+ 4: "#55464B",
+ 5: "#55464B",
+ 6: "#1D2A5D",
+ 7: "#1D2A5D",
+ 8: "#1D2A5D",
+ 9: "#292B58",
+ 10: "#382024",
+ 11: "#252550",
+ 12: "#1D2A4A",
+ }
+ if total:
+ avatars = await client.get_genshin_characters(uid, lang="zh-cn")
+ render_data["avatar_data"] = {i.id: i.constellation for i in avatars}
+ data = json.loads(result)
+ render_data["data"] = data
+
+ render_result = []
+
+ async def overview_task():
+ render_result.append(
+ [
+ -1,
+ await self.template_service.render(
+ "genshin/abyss", "overview.html", render_data, viewport={"width": 750, "height": 580}
+ ),
+ ]
+ )
+
+ async def floor_task(floor_index: int):
+ floor_d = data["floors"][floor_index]
+ render_result.append(
+ [
+ floor_d["floor"],
+ await self.template_service.render(
+ "genshin/abyss",
+ "floor.html",
+ {
+ **render_data,
+ "floor": floor_d,
+ "total_stars": f"{floor_d['stars']}/{floor_d['max_stars']}",
+ },
+ viewport={"width": 690, "height": 500},
+ full_page=True,
+ ),
+ ]
+ )
+
+ task_list = [asyncio.create_task(overview_task())]
+ for i, f in enumerate(data["floors"]):
+ if f["floor"] >= 9:
+ task_list.append(asyncio.create_task(floor_task(i)))
+ await asyncio.gather(*task_list)
+
+ return list(map(lambda x: x[1], sorted(render_result, key=lambda x: x[0])))
+ elif floor < 1:
+ render_data["data"] = json.loads(result)
+ return [
+ await self.template_service.render(
+ "genshin/abyss",
+ "overview.html",
+ render_data,
+ viewport={"width": 750, "height": 580},
+ )
+ ]
+ else:
+ num_dic = {
+ "0": "",
+ "1": "一",
+ "2": "二",
+ "3": "三",
+ "4": "四",
+ "5": "五",
+ "6": "六",
+ "7": "七",
+ "8": "八",
+ "9": "九",
+ }
+ if num := num_dic.get(str(floor)):
+ render_data["floor-num"] = num
+ else:
+ render_data["floor-num"] = f"十{num_dic.get(str(floor % 10))}"
+ floors = json.loads(result)["floors"]
+ if (floor_data := list(filter(lambda x: x["floor"] == floor, floors))) is None:
+ return None
+ avatars = await client.get_genshin_characters(uid, lang="zh-cn")
+ render_data["avatar_data"] = {i.id: i.constellation for i in avatars}
+ render_data["floor"] = floor_data[0]
+ render_data["total_stars"] = f"{floor_data[0]['stars']}/{floor_data[0]['max_stars']}"
+ return [
+ await self.template_service.render(
+ "genshin/abyss", "floor.html", render_data, viewport={"width": 690, "height": 500}, full_page=True
+ )
+ ]
diff --git a/resources/genshin/daily_material/bg/rarity/full/1.png b/resources/background/rarity/full/1.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/full/1.png
rename to resources/background/rarity/full/1.png
diff --git a/resources/genshin/daily_material/bg/rarity/full/2.png b/resources/background/rarity/full/2.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/full/2.png
rename to resources/background/rarity/full/2.png
diff --git a/resources/genshin/daily_material/bg/rarity/full/3.png b/resources/background/rarity/full/3.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/full/3.png
rename to resources/background/rarity/full/3.png
diff --git a/resources/genshin/daily_material/bg/rarity/full/4.png b/resources/background/rarity/full/4.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/full/4.png
rename to resources/background/rarity/full/4.png
diff --git a/resources/genshin/daily_material/bg/rarity/full/5.png b/resources/background/rarity/full/5.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/full/5.png
rename to resources/background/rarity/full/5.png
diff --git a/resources/genshin/daily_material/bg/rarity/half/1.png b/resources/background/rarity/half/1.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/half/1.png
rename to resources/background/rarity/half/1.png
diff --git a/resources/genshin/daily_material/bg/rarity/half/2.png b/resources/background/rarity/half/2.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/half/2.png
rename to resources/background/rarity/half/2.png
diff --git a/resources/genshin/daily_material/bg/rarity/half/3.png b/resources/background/rarity/half/3.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/half/3.png
rename to resources/background/rarity/half/3.png
diff --git a/resources/genshin/daily_material/bg/rarity/half/4.png b/resources/background/rarity/half/4.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/half/4.png
rename to resources/background/rarity/half/4.png
diff --git a/resources/genshin/daily_material/bg/rarity/half/5.png b/resources/background/rarity/half/5.png
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/half/5.png
rename to resources/background/rarity/half/5.png
diff --git a/resources/genshin/daily_material/bg/rarity/star.webp b/resources/background/rarity/star.webp
similarity index 100%
rename from resources/genshin/daily_material/bg/rarity/star.webp
rename to resources/background/rarity/star.webp
diff --git a/resources/fonts/HYWenHei-35W.ttf b/resources/fonts/HYWenHei-35W.ttf
new file mode 100644
index 00000000..64d5ac66
Binary files /dev/null and b/resources/fonts/HYWenHei-35W.ttf differ
diff --git a/resources/fonts/HYWenHei-45W.ttf b/resources/fonts/HYWenHei-45W.ttf
new file mode 100644
index 00000000..75ee78a6
Binary files /dev/null and b/resources/fonts/HYWenHei-45W.ttf differ
diff --git a/resources/fonts/HYWenHei-55W.ttf b/resources/fonts/HYWenHei-55W.ttf
new file mode 100644
index 00000000..92040355
Binary files /dev/null and b/resources/fonts/HYWenHei-55W.ttf differ
diff --git a/resources/fonts/HYWenHei-65W.ttf b/resources/fonts/HYWenHei-65W.ttf
new file mode 100644
index 00000000..e3cfe72c
Binary files /dev/null and b/resources/fonts/HYWenHei-65W.ttf differ
diff --git a/resources/fonts/HYWenHei-75W.ttf b/resources/fonts/HYWenHei-75W.ttf
new file mode 100644
index 00000000..4bef1cad
Binary files /dev/null and b/resources/fonts/HYWenHei-75W.ttf differ
diff --git a/resources/fonts/汉仪文黑-85W.ttf b/resources/fonts/HYWenHei-85W.ttf
similarity index 100%
rename from resources/fonts/汉仪文黑-85W.ttf
rename to resources/fonts/HYWenHei-85W.ttf
diff --git a/resources/genshin/abyss/abyss.html b/resources/genshin/abyss/abyss.html
deleted file mode 100644
index f1ad4b02..00000000
--- a/resources/genshin/abyss/abyss.html
+++ /dev/null
@@ -1,101 +0,0 @@
-
-
-
-
- abyss
-
-
-
-
-
-
-
深境螺旋
-
-
UID {{ uid }}
-
最深抵达 {{ max_floor }}
-
战斗次数 {{ total_battles }}
-
获得星级 {{ total_stars }}
-
-
-
出战次数
-
- {% for most_played in most_played_list %}
-
-
-
-
{{ most_played.value }}次
-
- {% endfor %}
-
-
-
-
-
-
-
-
最多击破数:{{ most_kills.value }}
-
-
-
-
最强一击:{{ strongest_strike.value }}
-
-
-
-
-
-
承受最多伤害:{{ most_damage_taken.value }}
-
-
-
-
元素爆发数:{{ most_bursts_used.value }}
-
-
-
-
-
-
元素战技释放次数:{{ most_skills_used.value }}
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/resources/genshin/abyss/background/abyss.png b/resources/genshin/abyss/background/abyss.png
new file mode 100644
index 00000000..9cbc0215
Binary files /dev/null and b/resources/genshin/abyss/background/abyss.png differ
diff --git a/resources/genshin/abyss/background/banner 01.png b/resources/genshin/abyss/background/banner 01.png
new file mode 100644
index 00000000..d6d1ae92
Binary files /dev/null and b/resources/genshin/abyss/background/banner 01.png differ
diff --git a/resources/genshin/abyss/background/banner 02.png b/resources/genshin/abyss/background/banner 02.png
new file mode 100644
index 00000000..f948a1fa
Binary files /dev/null and b/resources/genshin/abyss/background/banner 02.png differ
diff --git a/resources/genshin/abyss/background/floor1.png b/resources/genshin/abyss/background/floor1.png
new file mode 100644
index 00000000..5ec57368
Binary files /dev/null and b/resources/genshin/abyss/background/floor1.png differ
diff --git a/resources/genshin/abyss/background/floor10.png b/resources/genshin/abyss/background/floor10.png
new file mode 100644
index 00000000..18a364ff
Binary files /dev/null and b/resources/genshin/abyss/background/floor10.png differ
diff --git a/resources/genshin/abyss/background/floor11.png b/resources/genshin/abyss/background/floor11.png
new file mode 100644
index 00000000..df319f61
Binary files /dev/null and b/resources/genshin/abyss/background/floor11.png differ
diff --git a/resources/genshin/abyss/background/floor12.png b/resources/genshin/abyss/background/floor12.png
new file mode 100644
index 00000000..775233d4
Binary files /dev/null and b/resources/genshin/abyss/background/floor12.png differ
diff --git a/resources/genshin/abyss/background/floor2.png b/resources/genshin/abyss/background/floor2.png
new file mode 100644
index 00000000..5ec57368
Binary files /dev/null and b/resources/genshin/abyss/background/floor2.png differ
diff --git a/resources/genshin/abyss/background/floor3.png b/resources/genshin/abyss/background/floor3.png
new file mode 100644
index 00000000..0c8c546d
Binary files /dev/null and b/resources/genshin/abyss/background/floor3.png differ
diff --git a/resources/genshin/abyss/background/floor4.png b/resources/genshin/abyss/background/floor4.png
new file mode 100644
index 00000000..0c8c546d
Binary files /dev/null and b/resources/genshin/abyss/background/floor4.png differ
diff --git a/resources/genshin/abyss/background/floor5.png b/resources/genshin/abyss/background/floor5.png
new file mode 100644
index 00000000..0c8c546d
Binary files /dev/null and b/resources/genshin/abyss/background/floor5.png differ
diff --git a/resources/genshin/abyss/background/floor6.png b/resources/genshin/abyss/background/floor6.png
new file mode 100644
index 00000000..290aab49
Binary files /dev/null and b/resources/genshin/abyss/background/floor6.png differ
diff --git a/resources/genshin/abyss/background/floor7.png b/resources/genshin/abyss/background/floor7.png
new file mode 100644
index 00000000..290aab49
Binary files /dev/null and b/resources/genshin/abyss/background/floor7.png differ
diff --git a/resources/genshin/abyss/background/floor8.png b/resources/genshin/abyss/background/floor8.png
new file mode 100644
index 00000000..290aab49
Binary files /dev/null and b/resources/genshin/abyss/background/floor8.png differ
diff --git a/resources/genshin/abyss/background/floor9.png b/resources/genshin/abyss/background/floor9.png
new file mode 100644
index 00000000..d22f314c
Binary files /dev/null and b/resources/genshin/abyss/background/floor9.png differ
diff --git a/resources/genshin/abyss/background/four-star.png b/resources/genshin/abyss/background/four-star.png
new file mode 100644
index 00000000..d2297b5d
Binary files /dev/null and b/resources/genshin/abyss/background/four-star.png differ
diff --git a/resources/genshin/abyss/background/star.png b/resources/genshin/abyss/background/star.png
new file mode 100644
index 00000000..fb5901cf
Binary files /dev/null and b/resources/genshin/abyss/background/star.png differ
diff --git a/resources/genshin/abyss/example.html b/resources/genshin/abyss/example.html
index d8742e39..6b8a3e6e 100644
--- a/resources/genshin/abyss/example.html
+++ b/resources/genshin/abyss/example.html
@@ -2,115 +2,518 @@
- abyss
-
-
+ abyss-example
+
+
-
-
深境螺旋
-
-
UID 1414514
-
最深抵达 12-3
-
战斗次数 12
-
获得星级 36
-
-
-
出战次数
-
-
-
-
-
12次
+
+
+
挑战回顾
+
+
+
UID: 100206192
+
+ 36 (9-9-9-9)
+
-
-
-
-
12次
-
-
-
-
-
12次
-
-
-
-
-
12次
+
+
时间: 2022年10月上
+
最深抵达: 12-3
-
-
-
-
战斗数据榜
+
+
出战次数
+
+
+
+
+
+
15次
+
+
+
+
+
+
+
15次
+
+
+
+
+
+
+
15次
+
+
+
+
+
+
+
15次
+
+
-
-
-
最多击破数:21
-
+
战斗数据
+
+
+
战斗次数: 12
+
+
最多击破:999
+
+
-
-
最强一击:21
-
+
+
+
最强一击: 999,999
+
+
+
+
最多承伤: 114,514
+
+
-
-
-
-
承受最多伤害:21
-
+
+
+
元素爆发: 26
+
+
+
+
元素战技: 48
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 第 1 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
+
Lv.90
+
+
+
5命
+
+
+
+
+
Lv.90
+
+
+
4命
+
+
+
+
+
Lv.90
+
+
+
3命
+
+
+
+
+
Lv.90
+
+
上半
+
+
+
+
2命
+
+
+
+
+
Lv.90
+
+
+
1命
+
+
+
+
+
Lv.90
+
+
+
+
+
+
+
Lv.90
+
+
+
+
+
+
Lv.90
+
+
下半
+
+
+
+
+
+
+
+ 第 2 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
上半
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
下半
+
+
+
+
+
+
+
+ 第 3 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
4命
+
+
+
+
Lv.90
+
+
+
2命
+
+
+
+
Lv.90
+
+
+
+
+
+
Lv.90
+
+
+
+
+
+
+
+
+
+
+
+ 第 1 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
+
Lv.90
+
+
+
5命
+
+
+
+
+
Lv.90
+
+
+
4命
+
+
+
+
Lv.90
+
+
+
3命
+
+
+
+
Lv.90
+
+
上半
+
+
+
+
2命
+
+
+
+
Lv.90
+
+
+
1命
+
+
+
+
Lv.90
+
+
+
+
+
+
Lv.90
+
+
+
+
+
+
Lv.90
+
+
下半
+
+
+
+
+
+
+
+ 第 2 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
上半
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
6命
+
+
+
+
Lv.90
+
+
下半
+
+
+
+
+
+
+
+ 第 3 间 2022-10-01 10:02:05
+
+
+
+
+
+
+
6命
+
+
+
+
Lv.90
+
+
+
4命
+
+
+
+
Lv.90
+
+
+
2命
+
+
+
+
Lv.90
+
+
+
+
+
+
Lv.90
+
+
-
-
元素爆发数:21
-
-
-
-
-
-
元素战技释放次数:21
-
-
-
-
\ No newline at end of file
diff --git a/resources/genshin/abyss/floor.html b/resources/genshin/abyss/floor.html
new file mode 100644
index 00000000..4e824b56
--- /dev/null
+++ b/resources/genshin/abyss/floor.html
@@ -0,0 +1,97 @@
+
+
+
+
+
floor
+
+
+
+
+
+
+
+
+
+
+
+
+
UID: {{ uid }}
+
深境螺旋第 {{ floor.floor }} 层
+
+
+
+ {{ total_stars }}
+
+
+ {% for chamber in floor.chambers %}
+
+
+
+
+ 第 {{ loop.index }} 间 {{ chamber.battles[0].timestamp }}
+
+
+ {% for n in range(chamber.stars) %}
+
+ {% endfor %}
+ {% for n in range(chamber.max_stars - chamber.stars) %}
+
+ {% endfor %}
+
+
+
+ {% for battle in chamber.battles %}
+
+ {% for character in battle.characters %}
+
+ {% if avatar_data[character.id] > 0 %}
+ {% set constellation = avatar_data[character.id] %}
+ {% set bg = ['blue','blue', 'green','green', 'red', 'red'][constellation - 1] %}
+
+ {{ constellation }} 命
+
+ {% endif %}
+
+
+
+
Lv.{{ character.level }}
+
+ {% endfor %}
+ {% if loop.length > 1 %}
+
{{ ['上', '下'][loop.index0] }}半
+ {% endif %}
+
+ {% endfor %}
+
+
+ {% endfor %}
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/genshin/abyss/overview.html b/resources/genshin/abyss/overview.html
new file mode 100644
index 00000000..6b64bb14
--- /dev/null
+++ b/resources/genshin/abyss/overview.html
@@ -0,0 +1,89 @@
+
+
+
+
+
overview
+
+
+
+
+
+
+
+
挑战回顾
+
+
+
UID: {{ uid }}
+
+ {{ stars }}
+
+
+
+
时间: {{ time }}
+
最深抵达: {{ data.max_floor }}
+
+
+
+
出战次数
+
+ {% for avatar in data.ranks.most_played %}
+
+
+
+
+
{{ avatar.value }} 次
+
+ {% if loop.index != 4 %}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+
战斗数据
+
+
+
战斗次数: {{ data.total_battles }}
+
+
最多击破:{{ data.ranks.most_kills[0].value }}
+
+
+
+
+
+
最强一击: {{ data.ranks.strongest_strike[0].value }}
+
+
+
+
最多承伤: {{ data.ranks.most_damage_taken[0].value }}
+
+
+
+
+
+
元素爆发: {{ data.ranks.most_bursts_used[0].value }}
+
+
+
+
元素战技: {{ data.ranks.most_skills_used[0].value }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/genshin/abyss/style.css b/resources/genshin/abyss/style.css
new file mode 100644
index 00000000..6e5fa6b5
--- /dev/null
+++ b/resources/genshin/abyss/style.css
@@ -0,0 +1,346 @@
+:root {
+ --white: rgb(246 248 249);
+ --bg-color: rgb(233 229 220);
+ --h-color: rgb(203 189 162);
+ --red: rgb(255 86 33/ 80%);
+ --blue: rgb(98 168 233/ 80%);
+ --green: rgb(67 185 124/ 80%);
+}
+
+body {
+ margin: 0;
+ padding: 10px;
+}
+
+.hr {
+ width: 100%;
+ height: 3px;
+ background-color: rgb(246 248 249 / 50%);
+}
+
+.container {
+ width: 750px;
+ position: relative;
+ filter: drop-shadow(2px 2px 5px rgb(0 0 0 /70%));
+}
+
+.title {
+ text-align: center;
+ font-size: 27px;
+ font-weight: bold;
+ color: var(--h-color);
+}
+
+.caption {
+ margin: 10px 0;
+ color: var(--h-color);
+ font-size: 20px;
+}
+
+/* 概览 */
+
+.overview {
+ height: 540px;
+ padding: 20px 40px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-image: linear-gradient(to top, rgb(0 0 0 / 10%), rgb(0 0 0 / 10%)), url("./background/lookback-bg.png");
+ background-attachment: local;
+ border-radius: 15px;
+ overflow: hidden;
+}
+
+.summarize {
+ font-size: 20px;
+ width: calc(100% - 90px);
+ height: calc(100px - 20px);
+ margin: 20px 0;
+ padding: 10px 0 10px 80px;
+ border-radius: 5px;
+ border: 2px solid rgb(118 121 120 / 80%);
+ outline: 4px solid rgb(74, 82, 101);
+ background-color: rgb(74 82 101 / 60%);
+ background-image: url("./background/banner 01.png"), url("./background/banner 02.png");
+ background-repeat: no-repeat, no-repeat;
+ background-position: right, left;
+ background-size: auto 100%, auto 100%;
+ backdrop-filter: blur(5px);
+}
+
+.summarize > div {
+ width: 100%;
+ height: 50%;
+ color: var(--white);
+ display: flex;
+ align-items: center;
+}
+
+.summarize > div > div {
+ flex: 1;
+}
+
+.star {
+ display: inline-flex;
+ align-items: center;
+ position: relative;
+}
+
+.star::before {
+ content: "";
+ width: 40px;
+ height: 40px;
+ background-size: cover;
+ background-image: url("./background/star.png");
+}
+
+.star > span {
+ margin-left: 10px;
+}
+
+.most-played {
+ width: 100%;
+ margin: 30px 0;
+}
+
+.characters {
+ width: calc(100% - 60px);
+ padding: 0 30px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.character {
+ width: 100px;
+ height: 125px;
+ margin: 0 20px;
+ background-color: rgb(233 229 220);
+ overflow: hidden;
+ border-radius: 10px;
+ position: relative;
+}
+
+.icon {
+ width: 100%;
+ height: 100px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ overflow: hidden;
+ border-radius: 0 0 20px 0;
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.icon > img {
+ width: inherit;
+ height: inherit;
+}
+
+.character > .caption {
+ font-size: 18px;
+ margin: 4px 0 0;
+ padding: 0;
+ height: min-content;
+ text-align: center;
+ color: black;
+}
+
+.four-star {
+ width: 15px;
+ height: 15px;
+ position: relative;
+}
+
+.four-star::after {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ width: inherit;
+ height: inherit;
+ background-position: center;
+ background-image: url("./background/four-star.png");
+ background-blend-mode: lighten;
+ background-size: contain;
+}
+
+.ranks {
+ width: calc(100% + 80px);
+ transform: translateX(-40px);
+ color: var(--white);
+ position: relative;
+ display: flex;
+ flex-flow: column;
+ flex-wrap: wrap;
+}
+
+.ranks > div {
+ font-size: 18px;
+ width: 100%;
+ height: 43px;
+ display: flex;
+ align-items: center;
+}
+
+.rank {
+ flex: 1;
+ position: relative;
+ display: flex;
+ margin-left: 80px;
+ margin-right: 60px;
+}
+
+.ranks > div > .rank:first-child {
+ margin-right: 10px;
+}
+
+.rank > img {
+ width: 50px;
+ position: absolute;
+ right: 0;
+ bottom: -5px;
+}
+
+/* 层数 */
+
+.floors {
+ margin-top: 20px;
+}
+
+.floor {
+ margin: 20px 0;
+ padding: 0 30px;
+ width: calc(100% - 60px);
+ border-radius: 20px;
+ overflow: hidden;
+ outline: rgb(233 229 220 / 30%) solid 3px;
+ outline-offset: -7px;
+ background-position: top center;
+ background-repeat: no-repeat;
+ background-size: contain;
+}
+
+.head {
+ width: 100%;
+ height: 160px;
+ display: flex;
+}
+
+.floor-name {
+ font-size: 28px;
+ display: flex;
+ align-items: center;
+ font-weight: bold;
+ color: var(--white);
+}
+
+.floor-name > div:not(.floor-num) {
+ margin-left: 20px;
+ text-shadow: 1px 1px 5px rgb(0 0 0/50%);
+}
+
+.floor-num {
+ color: black;
+ width: 100px;
+ height: 100px;
+ background-image: url("./background/abyss.png");
+ background-size: contain;
+ filter: drop-shadow(0 0 5px rgb(0 0 0/80%)) grayscale(10%);
+ position: relative;
+}
+
+.head > .star {
+ margin-left: auto;
+ float: right;
+ color: var(--white);
+ font-size: 25px;
+ text-shadow: 1px 1px 5px rgb(0 0 0/50%);
+}
+
+.head > .star::before {
+ width: 50px;
+ height: 50px;
+}
+
+.chamber {
+ margin: 10px 0;
+ display: flex;
+ flex-flow: column;
+}
+
+.chamber-info {
+ height: 70px;
+ display: flex;
+ align-items: center;
+ color: var(--white);
+ font-size: 22px;
+}
+
+.stars {
+ margin-left: auto;
+}
+
+.dim-star::before {
+ filter: brightness(50%);
+}
+
+.battle {
+ margin: 10px 0 20px 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.battle > .character {
+ flex: 2;
+ max-width: 120px;
+ height: 145px;
+}
+
+.battle > .battle-info {
+ flex: 1;
+ color: var(--white);
+ font-size: 22px;
+ font-weight: bold;
+}
+
+.battle > .character > div:first-child:not(.icon, .element) {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 5px;
+ min-width: 27px;
+ text-align: center;
+ border-radius: 0 0 0 10px;
+ filter: drop-shadow(1px 1px 5px rgb(0 0 0/50%));
+ font-weight: 500;
+ color: var(--white);
+}
+
+.battle > .character > .element {
+ position: absolute;
+ top: 3px;
+ left: 3px;
+ width: 30px;
+ height: 30px;
+ background-size: contain;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.battle > .character > .icon {
+ width: 100%;
+ height: fit-content;
+ border-radius: 0 0 28px 0;
+}
+
+.battle > .character > .caption {
+ font-size: 20px;
+ margin-top: 2px;
+}
diff --git a/resources/genshin/daily_material/character.html b/resources/genshin/daily_material/character.html
index 98d25618..2df4295c 100644
--- a/resources/genshin/daily_material/character.html
+++ b/resources/genshin/daily_material/character.html
@@ -31,12 +31,12 @@
{% for material in area.materials %}
+ style="background-image: url(../../background/rarity/half/{{ material.rarity }}.png)">
{% for _ in range(material.rarity) %}
-
+
{% endfor %}
@@ -53,7 +53,7 @@
{% endif %}
>
+ style="background-image: url(../../background/rarity/full/{{ item.rarity }}.png)">
{% if item.level != none %}
Lv.{{ item.level }}
{% endif %}
diff --git a/resources/genshin/daily_material/example.html b/resources/genshin/daily_material/example.html
index e03b1156..9a36269e 100644
--- a/resources/genshin/daily_material/example.html
+++ b/resources/genshin/daily_material/example.html
@@ -27,52 +27,52 @@
-
-
-
-
+
Lv.90
6命
@@ -82,7 +82,7 @@
-
+
Lv.90
6命
@@ -92,7 +92,7 @@
-
+
Lv.90
6命
@@ -102,7 +102,7 @@
-
+
Lv.90
@@ -111,7 +111,7 @@
-
-
+
@@ -139,52 +139,52 @@
-
-
-
-
+
Lv.90
6命
@@ -194,7 +194,7 @@
-
+
Lv.90
6命
@@ -204,7 +204,7 @@
-
+
Lv.90
6命
@@ -214,7 +214,7 @@
-
+
Lv.90
@@ -223,7 +223,7 @@
-
-
+
@@ -255,45 +255,45 @@
-
-
-
-
@@ -303,7 +303,7 @@
-
+
Lv.90
精炼5
@@ -316,7 +316,7 @@
-
+
Lv.90
精炼5
@@ -329,7 +329,7 @@
-
+
Lv.90
精炼5
@@ -342,7 +342,7 @@
-
+
Lv.90
精炼5
@@ -352,7 +352,7 @@
-
-
+
diff --git a/resources/genshin/daily_material/style.css b/resources/genshin/daily_material/style.css
index 63c9c693..91a64047 100644
--- a/resources/genshin/daily_material/style.css
+++ b/resources/genshin/daily_material/style.css
@@ -1,13 +1,13 @@
@font-face {
font-family: 'HYWH';
- src: url('../../fonts/汉仪文黑-85W.ttf') format('truetype');
+ src: url('../../fonts/HYWenHei-85W.ttf') format('truetype');
}
:root {
- --bg-color: #ebe5d9;
- --font-color: #514e49;
- --color-1: #d6ba92;
- --shadow: #726c65;
+ --bg-color: #EBE5D9;
+ --font-color: #514E49;
+ --color-1: #D6BA92;
+ --shadow: #726C65;
}
@@ -190,7 +190,7 @@ body {
display: flex;
justify-content: center;
align-items: center;
- filter: drop-shadow(1px 1px 2px #6c6c6c);
+ filter: drop-shadow(1px 1px 2px #6C6C6C);
}
.material-star > img {
diff --git a/resources/genshin/daily_material/weapon.html b/resources/genshin/daily_material/weapon.html
index 0d81c82e..0c19d2a1 100644
--- a/resources/genshin/daily_material/weapon.html
+++ b/resources/genshin/daily_material/weapon.html
@@ -31,12 +31,12 @@
{% for material in area.materials %}
+ style="background-image: url(../../background/rarity/half/{{ material.rarity }}.png)">
{% for _ in range(material.rarity) %}
-
+
{% endfor %}
@@ -58,7 +58,7 @@
{% endif %}
+ style="background-image: url(../../background/rarity/full/{{ item.rarity }}.png)">
{% if item.level != none %}
Lv.{{ item.level }}
{% endif %}
diff --git a/resources/genshin/gacha_count/example.html b/resources/genshin/gacha_count/example.html
index 983e6798..9fddf2cb 100644
--- a/resources/genshin/gacha_count/example.html
+++ b/resources/genshin/gacha_count/example.html
@@ -4,7 +4,7 @@
-
+
diff --git a/resources/genshin/gacha_count/gacha_count.css b/resources/genshin/gacha_count/gacha_count.css
index 191d032d..4d1e2a5e 100644
--- a/resources/genshin/gacha_count/gacha_count.css
+++ b/resources/genshin/gacha_count/gacha_count.css
@@ -7,7 +7,7 @@
@font-face {
font-family: "HYWenHei-55W";
- src: url("./../../fonts/汉仪文黑-85W.ttf");
+ src: url("../../fonts/HYWenHei-85W.ttf");
font-weight: normal;
font-style: normal;
}
@@ -22,7 +22,7 @@
body {
font-size: 16px;
width: 530px;
- color: #1e1f20;
+ color: #1E1F20;
transform: scale(1.5);
transform-origin: 0 0;
}
@@ -30,7 +30,7 @@ body {
.container {
width: 530px;
padding: 20px 15px 10px 15px;
- background-color: #f5f6fb;
+ background-color: #F5F6FB;
}
.head_box {
@@ -72,7 +72,7 @@ body {
margin-top: 20px;
margin-bottom: 20px;
padding: 10px 5px 5px 5px;
- background: #fff;
+ background: #FFF;
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
position: relative;
}
@@ -111,7 +111,7 @@ body {
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
height: 70px;
width: 70px;
- background: #e9e5dc;
+ background: #E9E5DC;
position: relative;
}
@@ -132,7 +132,7 @@ body {
z-index: 9;
font-size: 18px;
text-align: center;
- color: #fff;
+ color: #FFF;
border-radius: 3px;
padding: 1px 5px;
background: rgb(0 0 0 / 50%);
@@ -144,15 +144,15 @@ body {
}
.label_302 {
- background-color: #e69449;
+ background-color: #E69449;
}
.label_200 {
- background-color: #757cc8;
+ background-color: #757CC8;
}
.label {
- color: #fff;
+ color: #FFF;
border-radius: 10px;
font-size: 16px;
padding: 2px 7px;
@@ -177,38 +177,38 @@ body {
}
.list_box .item .life1 {
- background-color: #62a8ea;
+ background-color: #62A8EA;
}
.list_box .item .life2 {
- background-color: #62a8ea;
+ background-color: #62A8EA;
}
.list_box .item .life3 {
- background-color: #45b97c;
+ background-color: #45B97C;
}
.list_box .item .life4 {
- background-color: #45b97c;
+ background-color: #45B97C;
}
.list_box .item .life5 {
- background-color: #ff5722;
+ background-color: #FF5722;
}
.list_box .item .life6 {
- background-color: #ff5722;
+ background-color: #FF5722;
}
.logo {
font-size: 14px;
font-family: "tttgbnumber", serif;
text-align: center;
- color: #7994a7;
+ color: #7994A7;
}
.hasMore {
font-size: 12px;
margin: -6px 0 10px 6px;
- color: #7f858a;
+ color: #7F858A;
}
diff --git a/resources/genshin/gacha_count/gacha_count.html b/resources/genshin/gacha_count/gacha_count.html
index 0a834ebb..02e28da0 100644
--- a/resources/genshin/gacha_count/gacha_count.html
+++ b/resources/genshin/gacha_count/gacha_count.html
@@ -4,7 +4,7 @@
-
+
@@ -20,34 +20,34 @@
-
ID: {{uid}}
-
抽卡统计-{{typeName}}
+
ID: {{ uid }}
+
抽卡统计-{{ typeName }}
{% for val in pool %}
-
-
-
-
「{{val.name}}」
-
{{val.count}}抽
+
+
+
+
「{{ val.name }}」
+
{{ val.count }}抽
+
+ {% if typeName != "常驻祈愿" %}
+
{{ val.start }} - {{ val.end }}
+ {% endif %}
- {% if typeName != "常驻祈愿" %}
-
{{val.start}} - {{val.end}}
- {% endif %}
-
-
- {% for v in val.list %}
-
-
-
{{v.count}}
-
+
+ {% for v in val.list %}
+
+
+
{{ v.count }}
+
+
+ {% endfor %}
- {% endfor %}
-
{% endfor %}
{% if hasMore %}
-
*完整数据请私聊查看
+
*完整数据请私聊查看
{% endif %}
Template By Yunzai-Bot
diff --git a/resources/img/element/Anemo.png b/resources/img/element/Anemo.png
new file mode 100644
index 00000000..dc8f802d
Binary files /dev/null and b/resources/img/element/Anemo.png differ
diff --git a/resources/img/element/Cyro.png b/resources/img/element/Cyro.png
new file mode 100644
index 00000000..4f913dba
Binary files /dev/null and b/resources/img/element/Cyro.png differ
diff --git a/resources/img/element/Dendro.png b/resources/img/element/Dendro.png
new file mode 100644
index 00000000..2dcd04b9
Binary files /dev/null and b/resources/img/element/Dendro.png differ
diff --git a/resources/img/element/Electro.png b/resources/img/element/Electro.png
new file mode 100644
index 00000000..9a31a2ed
Binary files /dev/null and b/resources/img/element/Electro.png differ
diff --git a/resources/img/element/Geo.png b/resources/img/element/Geo.png
new file mode 100644
index 00000000..674e8086
Binary files /dev/null and b/resources/img/element/Geo.png differ
diff --git a/resources/img/element/Hydro.png b/resources/img/element/Hydro.png
new file mode 100644
index 00000000..2c1b3dc2
Binary files /dev/null and b/resources/img/element/Hydro.png differ
diff --git a/resources/img/element/Pyro.png b/resources/img/element/Pyro.png
new file mode 100644
index 00000000..82868f9e
Binary files /dev/null and b/resources/img/element/Pyro.png differ
diff --git a/resources/styles/public.css b/resources/styles/public.css
index 5c068e9e..97b0731a 100644
--- a/resources/styles/public.css
+++ b/resources/styles/public.css
@@ -6,12 +6,54 @@
}
@font-face {
- font-family: "hywh";
- src: url("../fonts/汉仪文黑-85W.ttf");
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-35W.ttf") format("truetype");
+ font-weight: 200;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-45W.ttf") format("truetype");
+ font-weight: 300;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-55W.ttf") format("truetype");
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-65W.ttf") format("truetype");
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-75W.ttf") format("truetype");
+ font-weight: 600;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "HYWH";
+ src: url("../fonts/HYWenHei-85W.ttf") format("truetype");
+ font-weight: 700;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Number";
+ src: url("../fonts/tttgbnumber.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
body {
- font-family: "hywh", "seguiemj", emoji, system-ui;
+ font-family: "Number", "HYWH", "seguiemj", emoji, serif, system-ui;
}
diff --git a/utils/helpers.py b/utils/helpers.py
index ae8d04c2..c0fbc4fd 100644
--- a/utils/helpers.py
+++ b/utils/helpers.py
@@ -1,9 +1,13 @@
+from __future__ import annotations
+
import hashlib
import os
+import re
from asyncio import create_subprocess_shell
from asyncio.subprocess import PIPE
+from inspect import iscoroutinefunction
from pathlib import Path
-from typing import Optional, Tuple, TypeVar, Union, cast
+from typing import Awaitable, Callable, Match, Optional, Pattern, Tuple, TypeVar, Union, cast
import aiofiles
import genshin
@@ -80,10 +84,7 @@ async def url_to_file(url: str, return_path: bool = False) -> str:
await f.write(data.content)
logger.debug(f"url_to_file 获取url[{url}] 并下载到 file_dir[{file_dir}]")
- if return_path:
- return file_dir
-
- return Path(file_dir).as_uri()
+ return file_dir if return_path else Path(file_dir).as_uri()
async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None, need_cookie: bool = True) -> Client:
@@ -133,9 +134,7 @@ async def get_public_genshin_client(user_id: int) -> Tuple[Client, Optional[int]
def region_server(uid: Union[int, str]) -> RegionEnum:
- if isinstance(uid, int):
- region = REGION_MAP.get(str(uid)[0])
- elif isinstance(uid, str):
+ if isinstance(uid, (int, str)):
region = REGION_MAP.get(str(uid)[0])
else:
raise TypeError("UID variable type error")
@@ -161,3 +160,50 @@ async def execute(command, pass_error=True):
except UnicodeDecodeError:
result = str(stdout.decode("gbk").strip())
return result
+
+
+async def async_re_sub(
+ pattern: str | Pattern,
+ repl: str | Callable[[Match], str] | Callable[[Match], Awaitable[str]],
+ string: str,
+ count: int = 0,
+ flags: int = 0,
+) -> str:
+ """
+ 一个支持 repl 参数为 async 函数的 re.sub
+ Args:
+ pattern (str | Pattern): 正则对象
+ repl (str | Callable[[Match], str] | Callable[[Match], Awaitable[str]]): 替换后的文本或函数
+ string (str): 目标文本
+ count (int): 要替换的最大次数
+ flags (int): 标志常量
+
+ Returns:
+ 返回经替换后的字符串
+ """
+ result = ""
+ temp = string
+ if count != 0:
+ for _ in range(count):
+ match = re.search(pattern, temp, flags=flags)
+ replaced = None
+ if iscoroutinefunction(repl):
+ # noinspection PyUnresolvedReferences,PyCallingNonCallable
+ replaced = await repl(match)
+ elif callable(repl):
+ # noinspection PyCallingNonCallable
+ replaced = repl(match)
+ result += temp[: match.span(1)[0]] + (replaced or repl)
+ temp = temp[match.span(1)[1] :]
+ else:
+ while match := re.search(pattern, temp, flags=flags):
+ replaced = None
+ if iscoroutinefunction(repl):
+ # noinspection PyUnresolvedReferences,PyCallingNonCallable
+ replaced = await repl(match)
+ elif callable(repl):
+ # noinspection PyCallingNonCallable
+ replaced = repl(match)
+ result += temp[: match.span(1)[0]] + (replaced or repl)
+ temp = temp[match.span(1)[1] :]
+ return result + temp
diff --git a/utils/log/_logger.py b/utils/log/_logger.py
index e2aaf958..2781b66f 100644
--- a/utils/log/_logger.py
+++ b/utils/log/_logger.py
@@ -77,7 +77,14 @@ log_console = Console(color_system=color_system, theme=Theme(DEFAULT_STYLE), wid
class Traceback(BaseTraceback):
def __init__(self, *args, **kwargs):
- kwargs.update({"show_locals": True, "max_frames": config.logger.traceback_max_frames})
+ kwargs.update(
+ {
+ "show_locals": True,
+ "max_frames": config.logger.traceback_max_frames,
+ "locals_max_length": 3,
+ "locals_max_string": 80,
+ }
+ )
super(Traceback, self).__init__(*args, **kwargs)
self.theme = PygmentsSyntaxTheme(MonokaiProStyle)