🐛 Fix player info system

This commit is contained in:
xtaodada 2024-07-12 21:54:54 +08:00
parent e25bd55e48
commit 3dbc17b2a2
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
8 changed files with 144 additions and 66 deletions

@ -1 +1 @@
Subproject commit 549a40e8afe579d2448809ef566e91f84e1440f9
Subproject commit 0ae6a4043375a50a011efd212d54bb6c9feb7b23

View File

@ -1,62 +1,113 @@
from datetime import datetime, timedelta
from typing import Optional
from enkanetwork import Assets
from pydantic import BaseModel
from simnet import ZZZClient
from core.plugin import Plugin
from core.services.players.models import PlayersDataBase as Player
from core.services.players.services import PlayerInfoService, PlayersService
from metadata.genshin import AVATAR_DATA
from gram_core.dependence.redisdb import RedisDB
from gram_core.services.players.models import ExtraPlayerInfo
from plugins.tools.genshin import GenshinHelper
from utils.const import RESOURCE_DIR
from utils.log import logger
class PlayerAvatarInfo(BaseModel, frozen=False):
player_id: int
name_card: str
avatar: str
nickname: str
level: int
class PlayerInfoSystem(Plugin):
def __init__(
self,
player_service: PlayersService = None,
player_info_service: PlayerInfoService = None,
helper: GenshinHelper = None,
redis: RedisDB = None,
) -> None:
self.player_info_service = player_info_service
self.player_service = player_service
self.player_info_service = player_info_service
self.helper = helper
self.cache = redis.client
self.qname = "players_info_avatar"
self.ttl = 1 * 60 * 60 # 1小时
async def get_player_info(self, player_id: int, user_id: int, user_name: str):
player = await self.player_service.get(user_id, player_id)
async def get_form_cache(self, player_id: int) -> Optional[PlayerAvatarInfo]:
qname = f"{self.qname}:{player_id}"
data = await self.cache.get(qname)
if data is None:
return None
json_data = str(data, encoding="utf-8")
return PlayerAvatarInfo.parse_raw(json_data)
async def set_form_cache(self, player: PlayerAvatarInfo):
qname = f"{self.qname}:{player.player_id}"
await self.cache.set(qname, player.json(), ex=self.ttl)
@staticmethod
def get_base_avatar_info(player_id: int, user_name: str) -> PlayerAvatarInfo:
res = RESOURCE_DIR / "img"
return PlayerAvatarInfo(
player_id=player_id,
name_card=(res / "home.png").as_uri(),
avatar=(res / "avatar.png").as_uri(),
nickname=user_name,
level=0,
)
async def update_player_info(self, player: "Player", nickname: str, level: int):
player_info = await self.player_info_service.get_form_sql(player)
if player_info is not None and player_info.create_time is not None:
player_info.nickname = nickname
if player_info.extra_data is None:
player_info.extra_data = ExtraPlayerInfo()
player_info.extra_data.level = level
await self.player_info_service.update(player_info)
async def get_player_info_by_cookie(self, player: "Player", user_name: str) -> PlayerAvatarInfo:
base_info = self.get_base_avatar_info(player.player_id, user_name)
try:
async with self.helper.genshin(player.user_id, player_id=player.player_id) as client:
client: "ZZZClient"
record_card = await client.get_record_card()
if record_card is not None:
base_info.nickname = record_card.nickname
base_info.level = record_card.level
await self.update_player_info(player, base_info.nickname, base_info.level)
except Exception as e:
logger.warning("卡片信息通过 cookie 请求失败 %s", str(e))
return base_info
async def get_player_info(self, player_id: int, user_name: str) -> PlayerAvatarInfo:
cache = await self.get_form_cache(player_id)
if cache is not None:
return cache
player = await self.player_service.get(None, player_id)
base_info = self.get_base_avatar_info(player_id, user_name)
if not player:
return base_info
player_info = await self.player_info_service.get(player)
nickname = user_name
name_card: Optional[str] = None
avatar: Optional[str] = None
rarity: int = 5
try:
if player_info is not None:
if player_info.nickname is not None:
nickname = player_info.nickname
if player_info.name_card is not None:
name_card = (await self.assets_service.namecard(int(player_info.name_card)).navbar()).as_uri()
if player_info.hand_image is not None:
if player_info.hand_image > 10000000:
avatar = (await self.assets_service.avatar(player_info.hand_image).icon()).as_uri()
try:
rarity = {k: v["rank"] for k, v in AVATAR_DATA.items()}[str(player_info.hand_image)]
except KeyError:
logger.warning("未找到角色 %s 的星级", player_info.hand_image)
if player_info is None or player_info.create_time is None:
return base_info
expiration_time = datetime.now() - timedelta(hours=2)
if (
player_info.last_save_time is None
or player_info.extra_data is None
or player_info.last_save_time <= expiration_time
):
base_info = await self.get_player_info_by_cookie(player, player_info.nickname)
else:
avatar = Assets.profile_picture(player_info.hand_image).url
rarity = 5
except Exception as exc: # pylint: disable=W0703
logger.error("卡片信息请求失败 %s", str(exc))
if name_card is None: # 默认
name_card = (await self.assets_service.namecard(0).navbar()).as_uri()
if avatar is None: # 默认
avatar = (await self.assets_service.avatar(0).icon()).as_uri()
return name_card, avatar, nickname, rarity
base_info.nickname = player_info.nickname
base_info.level = player_info.extra_data.level
async def get_name_card(self, player_id: int, user_id: int):
player = await self.player_service.get(user_id, player_id)
player_info = await self.player_info_service.get(player)
name_card: Optional[str] = None
try:
if player_info is not None and player_info.name_card is not None:
name_card = (await self.assets_service.namecard(int(player_info.name_card)).navbar()).as_uri()
except Exception as exc: # pylint: disable=W0703
logger.error("卡片信息请求失败 %s", str(exc))
if name_card is None: # 默认
name_card = (await self.assets_service.namecard(0).navbar()).as_uri()
return name_card
await self.set_form_cache(base_info)
return base_info
async def get_theme_info(self, player_id: int) -> PlayerAvatarInfo:
return await self.get_player_info(player_id, "")

View File

@ -13,7 +13,7 @@ from gram_core.services.template.services import TemplateService
from modules.action_log.client import ActionLogAnalyse
from plugins.tools.action_log_system import ActionLogSystem
from plugins.tools.genshin import GenshinHelper
from utils.const import RESOURCE_DIR
from plugins.tools.player_info import PlayerInfoSystem
from utils.log import logger
from utils.uid import mask_number
@ -42,11 +42,13 @@ class ActionLogPlugins(Plugin):
action_log_service: ActionLogService,
action_log_system: ActionLogSystem,
template_service: TemplateService,
player_info: PlayerInfoSystem,
):
self.helper = helper
self.action_log_service = action_log_service
self.action_log_system = action_log_system
self.template_service = template_service
self.player_info = player_info
@handler.command(command="action_log_import", filters=filters.ChatType.PRIVATE, cookie=True, block=False)
async def action_log_import(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE") -> None:
@ -95,9 +97,9 @@ class ActionLogPlugins(Plugin):
}
async def add_theme_data(self, data: Dict, player_id: int):
res = RESOURCE_DIR / "img"
data["avatar"] = (res / "avatar.png").as_uri()
data["background"] = (res / "home.png").as_uri()
theme_info = await self.player_info.get_theme_info(player_id)
data["avatar"] = theme_info.avatar
data["background"] = theme_info.name_card
return data
async def render(self, client: "ZZZClient") -> "RenderResult":

View File

@ -19,7 +19,7 @@ from gram_core.config import config
from gram_core.plugin.methods.inline_use_data import IInlineUseData
from gram_core.services.template.models import RenderGroupResult
from plugins.tools.genshin import GenshinHelper, CharacterDetails
from utils.const import RESOURCE_DIR
from plugins.tools.player_info import PlayerInfoSystem
from utils.log import logger
from utils.uid import mask_number
@ -69,6 +69,7 @@ class AvatarListPlugin(Plugin):
wiki_service: WikiService = None,
helper: GenshinHelper = None,
character_details: CharacterDetails = None,
player_info: PlayerInfoSystem = None,
) -> None:
self.cookies_service = cookies_service
self.assets_service = assets_service
@ -76,6 +77,7 @@ class AvatarListPlugin(Plugin):
self.wiki_service = wiki_service
self.helper = helper
self.character_details = character_details
self.player_info = player_info
async def get_avatar_data(self, character_id: int, client: "ZZZClient") -> Optional["ZZZCalculatorCharacter"]:
return await self.character_details.get_character_details(client, character_id)
@ -179,14 +181,14 @@ class AvatarListPlugin(Plugin):
return await asyncio.gather(*tasks)
async def add_theme_data(self, data: Dict, player_id: int):
res = RESOURCE_DIR / "img"
data["avatar"] = (res / "avatar.png").as_uri()
data["background"] = (res / "home.png").as_uri()
theme_info = await self.player_info.get_theme_info(player_id)
data["avatar"] = theme_info.avatar
data["background"] = theme_info.name_card
return data
async def render(self, client: "ZZZClient", all_avatars: bool = False) -> List["RenderResult"]:
characters: List["ZZZPartialCharacter"] = await self.get_avatars_data(client)
player_info = await self.player_info.get_player_info(client.player_id, "")
has_more = (not all_avatars) and len(characters) > MAX_AVATAR_COUNT
if has_more:
characters = characters[:MAX_AVATAR_COUNT]
@ -194,6 +196,8 @@ class AvatarListPlugin(Plugin):
base_render_data = {
"uid": mask_number(client.player_id), # 玩家uid
"nickname": player_info.nickname, # 玩家昵称
"level": player_info.level,
"has_more": has_more, # 是否显示了全部角色
}
await self.add_theme_data(base_render_data, client.player_id)

View File

@ -32,7 +32,7 @@ from modules.gacha_log.log import GachaLog
from modules.gacha_log.migrate import GachaLogMigrate
from modules.gacha_log.models import GachaLogInfo
from plugins.tools.genshin import PlayerNotFoundError
from utils.const import RESOURCE_DIR
from plugins.tools.player_info import PlayerInfoSystem
from utils.log import logger
try:
@ -70,6 +70,7 @@ class WishLogPlugin(Plugin.Conversation):
players_service: PlayersService,
assets: AssetsService,
cookie_service: CookiesService,
player_info: PlayerInfoSystem,
):
self.template_service = template_service
self.players_service = players_service
@ -77,6 +78,7 @@ class WishLogPlugin(Plugin.Conversation):
self.cookie_service = cookie_service
self.gacha_log = GachaLog()
self.wish_photo = None
self.player_info = player_info
async def get_player_id(self, user_id: int, player_id: int, offset: int) -> int:
"""获取绑定的游戏ID"""
@ -543,9 +545,9 @@ class WishLogPlugin(Plugin.Conversation):
await png.edit_media(message)
async def add_theme_data(self, data: Dict, player_id: int):
res = RESOURCE_DIR / "img"
data["avatar"] = (res / "avatar.png").as_uri()
data["background"] = (res / "home.png").as_uri()
theme_info = await self.player_info.get_theme_info(player_id)
data["avatar"] = theme_info.avatar
data["background"] = theme_info.name_card
return data
@staticmethod

View File

@ -1,4 +1,3 @@
import random
from typing import Optional, TYPE_CHECKING, List
from telegram.constants import ChatAction
from telegram.ext import filters
@ -10,7 +9,7 @@ from core.services.template.models import RenderResult
from core.services.template.services import TemplateService
from gram_core.plugin.methods.inline_use_data import IInlineUseData
from plugins.tools.genshin import GenshinHelper
from utils.const import RESOURCE_DIR
from plugins.tools.player_info import PlayerInfoSystem
from utils.log import logger
from utils.uid import mask_number
@ -25,9 +24,15 @@ __all__ = ("PlayerStatsPlugins",)
class PlayerStatsPlugins(Plugin):
"""玩家统计查询"""
def __init__(self, template: TemplateService, helper: GenshinHelper):
def __init__(
self,
template: TemplateService,
helper: GenshinHelper,
player_info: PlayerInfoSystem,
):
self.template_service = template
self.helper = helper
self.player_info = player_info
@handler.command("stats", player=True, block=False)
@handler.message(filters.Regex("^玩家统计查询(.*)"), player=True, block=False)
@ -60,11 +65,13 @@ class PlayerStatsPlugins(Plugin):
async def render(self, client: "ZZZClient", nickname: str) -> RenderResult:
uid = client.player_id
user_info = await client.get_zzz_user(uid)
player_info = await self.player_info.get_player_info(uid, nickname)
data = {
"uid": mask_number(uid),
"stats": user_info.stats,
"nickname": nickname,
"nickname": player_info.nickname,
"level": player_info.level,
"stats_labels": [
("活跃天数", "active_days"),
("获取角色数", "avatar_num"),
@ -112,9 +119,9 @@ class PlayerStatsPlugins(Plugin):
await render_result.edit_inline_media(callback_query)
async def add_theme_data(self, data, player_id: int):
res = RESOURCE_DIR / "img"
data["avatar"] = (res / "avatar.png").as_uri()
data["background"] = (res / "home.png").as_uri()
theme_info = await self.player_info.get_theme_info(player_id)
data["avatar"] = theme_info.avatar
data["background"] = theme_info.name_card
return data
async def get_inline_use_data(self) -> List[Optional[IInlineUseData]]:

View File

@ -33,6 +33,13 @@
alt="Avatar"
/>
<div class="flex-1">
<div class="nickname text-4xl italic mb-2 px-2 text-light">
{{ nickname }}
{% if level > 0 %}
<span class="text-lg">lv.{{ level }}</span>
{% endif %}
</div>
<div class="uid text-light text-2xl">UID: {{ uid }}</div>
</div>
<div class="z-10">

View File

@ -46,7 +46,12 @@
<div
class="z-10 flex-1 flex flex-col justify-center gap-y-2 text-dark"
>
<h1 class="bg-background text-4xl line-clamp-1">{{ nickname }}</h1>
<h1 class="bg-background text-4xl line-clamp-1">
{{ nickname }}
{% if level > 0 %}
<span class="text-lg">lv.{{ level }}</span>
{% endif %}
</h1>
<h1 class="text-lg">UID: {{ uid }}</h1>
</div>
<div class="z-10">