实现 深渊螺旋 基础数据查询

This commit is contained in:
洛水.山岭居室 2022-07-01 02:07:48 +08:00 committed by GitHub
parent 9b5f16d0c4
commit ff57c122c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 298 additions and 1 deletions

View File

@ -1,14 +1,17 @@
import hashlib import hashlib
import os import os
from typing import List from typing import List, Optional, Tuple
import aiofiles import aiofiles
import genshin
import httpx import httpx
from genshin import GenshinClient
from httpx import UnsupportedProtocol from httpx import UnsupportedProtocol
from telegram import Bot from telegram import Bot
from logger import Log from logger import Log
from model.base import ServiceEnum from model.base import ServiceEnum
from service.base import UserInfoData
from service.cache import RedisCache from service.cache import RedisCache
USER_AGENT: str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " \ USER_AGENT: str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " \
@ -68,6 +71,19 @@ async def url_to_file(url: str, prefix: str = "file://") -> str:
return prefix + file_dir return prefix + file_dir
async def get_genshin_client(user_info_data: UserInfoData, game_service: Optional[ServiceEnum] = None) \
-> Tuple[GenshinClient, int]:
if game_service is None:
game_service = user_info_data.service
if game_service == ServiceEnum.HYPERION:
client = genshin.ChineseClient(cookies=user_info_data.mihoyo_cookie)
uid = user_info_data.mihoyo_game_uid
else:
client = genshin.GenshinClient(cookies=user_info_data.hoyoverse_cookie, lang="zh-cn")
uid = user_info_data.hoyoverse_game_uid
return client, uid
def get_server(uid: int) -> ServiceEnum: def get_server(uid: int) -> ServiceEnum:
server = SERVICE_MAP.get(str(uid)[0]) server = SERVICE_MAP.get(str(uid)[0])
if server: if server:

99
plugins/abyss.py Normal file
View File

@ -0,0 +1,99 @@
from telegram import Update
from telegram.constants import ChatAction
from telegram.ext import CommandHandler, MessageHandler, filters
from logger import Log
from manager import listener_plugins_class
from model.helpers import get_genshin_client, url_to_file
from service.base import UserInfoData
from utils.base import PaimonContext
@listener_plugins_class()
class Abyss:
def __init__(self, *args):
"""Abyss插件入口"""
pass
@staticmethod
def create_handlers(*args) -> list:
_ = args
abyss = Abyss()
return [
CommandHandler("abyss", abyss.command_start, block=False),
MessageHandler(filters.Regex(r"^深渊数据查询(.*)"), abyss.command_start, block=True)
]
@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, user_info_data: UserInfoData) -> dict:
client, uid = await get_genshin_client(user_info_data)
spiral_abyss_info = await client.get_spiral_abyss(uid)
if not spiral_abyss_info.unlocked:
raise ValueError("unlocked is false")
ranks = spiral_abyss_info.ranks
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 url_to_file(ranks.most_kills[0].icon),
"value": ranks.most_kills[0].value,
},
"strongest_strike": {
"icon": await url_to_file(ranks.strongest_strike[0].icon),
"value": ranks.strongest_strike[0].value
},
"most_damage_taken": {
"icon": await url_to_file(ranks.most_damage_taken[0].icon),
"value": ranks.most_damage_taken[0].value
},
"most_bursts_used": {
"icon": await url_to_file(ranks.most_bursts_used[0].icon),
"value": ranks.most_bursts_used[0].value
},
"most_skills_used": {
"icon": await url_to_file(ranks.most_skills_used[0].icon),
"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 url_to_file(most_played.icon),
"value": most_played.value,
"background": self._get_role_star_bg(most_played.rarity)
}
abyss_data["most_played_list"].append(temp)
return abyss_data
async def command_start(self, update: Update, context: PaimonContext) -> None:
user = update.effective_user
message = update.message
service = context.service
Log.info(f"用户 {user.full_name}[{user.id}] 查深渊挑战命令请求")
await message.reply_chat_action(ChatAction.TYPING)
user_info = await service.user_service_db.get_user_info(user.id)
try:
abyss_data = await self._get_abyss_data(user_info)
except ValueError as exc:
if "unlocked is false" in str(exc):
await message.reply_text("本次深渊旅行者还没挑战呢,咕咕咕~~~")
return
raise exc
png_data = await service.template.render('genshin/abyss', "abyss.html", abyss_data,
{"width": 690, "height": 504}, full_page=False)
await message.reply_photo(png_data, filename=f"abyss_{user.id}.png",
allow_sending_without_reply=True)
return

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="zh-ch">
<head>
<meta charset="UTF-8">
<title>abyss</title>
<link type="text/css" href="../../styles/tailwind.min.css" rel="stylesheet">
<link type="text/css" href="../../styles/public.css" rel="stylesheet">
<style>
#container {
background: url("./background/lookback-bg.png");
}
.character-icon {
width: 128px;
height: 128px;
}
.character-side-icon {
width: 32px;
height: 32px;
}
</style>
</head>
<body>
<div class="mx-auto flex flex-col h-full bg-no-repeat bg-cover" id="container">
<div class="title text-2xl my-4 text-yellow-500 mx-auto">深境螺旋</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-white bg-opacity-10">
<div class="uid text-center mx-auto">UID {{uid}}</div>
<div class="text-center mx-auto">最深抵达 {{max_floor}}</div>
<div class="text-center mx-auto">战斗次数 {{total_battles}}</div>
<div class="text-center mx-auto">获得星级 {{total_stars}}</div>
</div>
<div class="base-info flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
<div class="mx-auto flex my-2">
{% for most_played in most_played_list %}
<div class="bg-white rounded-lg mx-2">
<div class="character-icon rounded-lg bg-cover"
style="background: url({{most_played.background}});background-size: cover;">
<img src="{{most_played.icon}}" alt=""></div>
<div class="text-center">{{most_played.value}}次</div>
</div>
{% endfor %}
</div>
</div>
<div class="flex flex-col my-1">
<div class="flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
</div>
<div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最多击破数:{{most_kills.value}}</div>
<img class="character-side-icon ml-auto" src="{{most_kills.icon}}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最强一击:{{strongest_strike.value}}</div>
<img class="character-side-icon ml-auto" src="{{strongest_strike.icon}}" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">承受最多伤害:{{most_damage_taken.value}}</div>
<img class="character-side-icon ml-auto" src="{{most_damage_taken.icon}}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素爆发数:{{most_bursts_used.value}}</div>
<img class="character-side-icon ml-auto" src="{{most_bursts_used.icon}}" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素战技释放次数:{{most_skills_used.value}}</div>
<img class="character-side-icon ml-auto" src="{{most_skills_used.icon}}" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6"></div>
</div>
</div>
</div>
<div class="my-2"></div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="zh-ch">
<head>
<meta charset="UTF-8">
<title>abyss</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
#container {
background: url("./background/lookback-bg.png");
}
.character-icon {
width: 128px;
height: 128px;
}
.character-side-icon {
width: 32px;
height: 32px;
}
</style>
</head>
<body>
<div class="mx-auto flex flex-col h-full bg-no-repeat bg-cover" id="container">
<div class="title text-2xl my-4 text-yellow-500 mx-auto">深境螺旋</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-white bg-opacity-10">
<div class="uid text-center mx-auto">UID 1414514</div>
<div class="text-center mx-auto">最深抵达 12-3</div>
<div class="text-center mx-auto">战斗次数 12</div>
<div class="text-center mx-auto">获得星级 36</div>
</div>
<div class="base-info flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
<div class="mx-auto flex my-2">
<div class="bg-white rounded-lg mx-2">
<div class="character-icon rounded-lg bg-cover"
style="background: url('./background/roleStarBg4.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2">
<div class="character-icon rounded-lg bg-cover"
style="background: url('./background/roleStarBg4.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2">
<div class="character-icon rounded-lg bg-cover"
style="background: url('./background/roleStarBg5.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
<div class="bg-white rounded-lg mx-2">
<div class="character-icon rounded-lg bg-cover"
style="background: url('./background/roleStarBg5.png');background-size: cover;">
<img src="./../../img/example/256x256.png" alt=""></div>
<div class="text-center">12次</div>
</div>
</div>
</div>
<div class="flex flex-col my-1">
<div class="flex flex-col px-20 py-1 text-black my-1">
<div class="text-center mr-auto text-yellow-500">出战次数</div>
</div>
<div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最多击破数21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">最强一击21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">承受最多伤害21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素爆发数21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div>
</div>
<div class="base-info flex flex-row px-20 py-1 my-1 text-white bg-black bg-opacity-10 ">
<div class="text-center flex flex-row flex-1 mr-6">
<div class="my-auto">元素战技释放次数21</div>
<img class="character-side-icon ml-auto" src="./../../img/example/256x256.png" alt="">
</div>
<div class="text-center flex flex-row flex-1 mr-6"></div>
</div>
</div>
</div>
<div class="my-2"></div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B