diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa52712..9de21b7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ ci: autoupdate_commit_msg: "⬆️ `pre-commit-ci`自动升级" repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.15 + rev: v0.16.1 hooks: - id: ruff args: [--fix] @@ -20,7 +20,7 @@ repos: - repo: https://github.com/astral-sh/uv-pre-commit # uv version. - rev: 0.11.17 + rev: 0.12.1 hooks: - id: uv-lock - id: uv-export diff --git a/VAUID/utils/api/model/asset.py b/VAUID/utils/api/model/asset.py index ecf94a0..b3d3c2f 100644 --- a/VAUID/utils/api/model/asset.py +++ b/VAUID/utils/api/model/asset.py @@ -1,4 +1,4 @@ -from typing import Any, List, Optional, TypedDict +from typing import Any, TypedDict # --- 资金相关 (Money) --- @@ -15,7 +15,7 @@ class MoneyData(TypedDict): more: str intent: str show_new_icon: bool - list: List[MoneyItem] + list: list[MoneyItem] # --- 英雄相关 (Agent) --- @@ -32,7 +32,7 @@ class AgentItem(TypedDict): unlock_time: str lock_status: int intent: str - record_stones: Optional[Any] + record_stones: Any | None is_record_stones_agent: bool icon_grey: str @@ -44,7 +44,7 @@ class AgentData(TypedDict): more: str intent: str show_new_icon: bool - list: List[AgentItem] + list: list[AgentItem] # --- 皮肤图鉴相关 (Skin) --- @@ -75,7 +75,7 @@ class SkinData(TypedDict): more: str intent: str show_new_icon: bool - list: List[SkinItem] + list: list[SkinItem] # --- 收藏品相关 (Spray, Card, Charm) --- @@ -94,7 +94,7 @@ class CollectionData(TypedDict): more: str intent: str show_new_icon: bool - list: List[CollectionItem] + list: list[CollectionItem] # --- 枪卡相关 (Skin Card) --- @@ -111,15 +111,15 @@ class EvolutionConf(TypedDict): desc: str required_task_num: str resource_imgname: str - resource_conf: Optional[ResourceConf] - index: Optional[int] + resource_conf: ResourceConf | None + index: int | None class UpgradeConf(TypedDict): icon: str unlock_icon: str task_id: str - index: Optional[int] + index: int | None class SkinCardItem(TypedDict): @@ -128,7 +128,7 @@ class SkinCardItem(TypedDict): bg_img: str list_img: str skin_limit: int - skin_list_str: List[str] + skin_list_str: list[str] name: str desc: str sub_desc: str @@ -139,7 +139,7 @@ class SkinCardItem(TypedDict): limit_num: int resource_link: str resource_type: str - resource_img_name_list: List[Any] + resource_img_name_list: list[Any] resource_imgname_list: str status: int acquire_time: int @@ -148,8 +148,8 @@ class SkinCardItem(TypedDict): upgrade_conf: str evolution_conf: str base_resource: str - upgrade_conf_list: List[UpgradeConf] - evolution_conf_list: List[EvolutionConf] + upgrade_conf_list: list[UpgradeConf] + evolution_conf_list: list[EvolutionConf] base_resource_conf: ResourceConf is_lock: bool is_wear: bool @@ -163,7 +163,7 @@ class SkinCardData(TypedDict): more: str intent: str show_new_icon: bool - list: List[SkinCardItem] + list: list[SkinCardItem] # --- 简单模块 (Skin Assemble, Stone Overview) --- diff --git a/VAUID/utils/api/models.py b/VAUID/utils/api/models.py index ff1c244..9a40ef5 100644 --- a/VAUID/utils/api/models.py +++ b/VAUID/utils/api/models.py @@ -1,31 +1,31 @@ -from typing import List, Literal, Optional, TypedDict +from typing import Literal, TypedDict class LoginData(TypedDict): - openid: List[str] + openid: list[str] """用户的 id""" - appid: List[str] + appid: list[str] """用户的 appid""" - access_token: List[str] + access_token: list[str] """用户的 access_token""" - pay_token: List[str] - key: List[str] - browser: List[str] + pay_token: list[str] + key: list[str] + browser: list[str] """0""" - browser_error: List[str] + browser_error: list[str] """0""" - status_os: List[str] - sdkv: List[str] - status_machine: List[str] + status_os: list[str] + sdkv: list[str] + status_machine: list[str] """用户的 status_machine""" - update_auth: List[str] + update_auth: list[str] """1""" - has_auth: List[str] + has_auth: list[str] """1""" - auth_time: List[str] - page_type: List[str] + auth_time: list[str] + page_type: list[str] """1""" - redirect_uri_key: List[str] + redirect_uri_key: list[str] class ResultInfo(TypedDict): @@ -48,13 +48,13 @@ class GameInfo(TypedDict): """VA""" level: int """游戏等级""" - tier: Optional[str] + tier: str | None """段位""" gameColor: str """游戏颜色?""" - content: Optional[str] + content: str | None """游戏段位内容""" - gameId: Optional[str] + gameId: str | None """不知道""" league_point: str @@ -74,7 +74,7 @@ class SummonerInfo(TypedDict): """背景图 url""" appNum: str """qq 号""" - gameInfoList: List[GameInfo] + gameInfoList: list[GameInfo] class FeedBase(TypedDict): @@ -106,13 +106,13 @@ class InfoBody(TypedDict): """默认不是不知道是啥""" isVip: bool """默认 false""" - tag: List[Tag_point] + tag: list[Tag_point] isOnline: bool """是否在线""" class InfoBodyList(TypedDict): - userList: List[InfoBody] + userList: list[InfoBody] class FeedNews(TypedDict): @@ -165,7 +165,7 @@ class tc(TypedDict): class LeftData(TypedDict): - list: List[tc] + list: list[tc] image_url: str """段位图片""" title: str @@ -173,7 +173,7 @@ class LeftData(TypedDict): class RightData(TypedDict): - list: List[tc] + list: list[tc] image_url: str """武器图片""" title: str @@ -213,11 +213,11 @@ class CardUrl(TypedDict): """分享或复制按钮 url""" qr_code_url: str """二维码""" - left_data: Optional[LeftData] - middle_data: Optional[tc] + left_data: LeftData | None + middle_data: tc | None """KAST""" - right_data: Optional[RightData] - round_win_rate: Optional[tc] + right_data: RightData | None + round_win_rate: tc | None """回合胜率""" card_switch_tips: str """无""" @@ -231,7 +231,7 @@ class CardInfo(TypedDict): has_role: int """是否有角色?""" role_info: RoleInfo - tools: List[Tool] + tools: list[Tool] scene: str """场景""" card_visible: int @@ -246,7 +246,7 @@ class CardInfo(TypedDict): class ListInfo(TypedDict): - list: List[tc] + list: list[tc] image_url: str """图片""" title: str @@ -463,7 +463,7 @@ class Battle(TypedDict): """是否好友""" competitive_tier: Competitve """排位信息""" - achievement: List[Achievement] + achievement: list[Achievement] """成就信息""" @@ -472,7 +472,7 @@ class ValBattle(TypedDict): next_baton: str """下一把武器 uid""" - battle_list: List[Battle] + battle_list: list[Battle] msg: str """两个月内的记录""" @@ -486,7 +486,7 @@ class Header(TypedDict): - 1006 能力图 """ title: str - tips: List[str] + tips: list[str] """提示信息""" isShowIcon: bool """是否显示图标""" @@ -497,17 +497,17 @@ class tv(TypedDict): title: str """标题 | 变化趋势""" - values: List[int] + values: list[int] """段位趋势""" - heights: List[int] + heights: list[int] """段位高度""" - x: List[int] + x: list[int] """段位坐标 (0123456789)""" - y: List[int] + y: list[int] """段位坐标 (段位)""" - rate: List[List[int]] + rate: list[list[int]] """段位坐标 (xy)""" - max_point: List[int] + max_point: list[int] """段位最高坐标 (xy)""" max_value_text: str """段位最高名称""" @@ -525,11 +525,11 @@ class Radar(TypedDict): sub_tab_name: str """位置名称 | 决斗 | 先锋 | 控场 | 哨卫""" desc: str - data_array: List[str] + data_array: list[str] """六边形数据值""" - proportion_array: List[int] + proportion_array: list[int] """六边形数据长度""" - desc_array: List[str] + desc_array: list[str] """六边形数据名称""" tips_bg_color: str @@ -547,7 +547,7 @@ class ts(TypedDict): class RadarChart(TypedDict): - tabs: List[Radar] + tabs: list[Radar] """同段位水平""" player_dict: Radar """个人水平""" @@ -564,15 +564,15 @@ class RadarChart(TypedDict): class Body(TypedDict): """头部信息""" - first_list: List[tc] + first_list: list[tc] """ - 当前段位 白银 - 赛季最高 白银 - 近期表现 A """ - line_chart_list: List[tv] + line_chart_list: list[tv] """段位趋势 2 个""" - second_list: List[tc] + second_list: list[tc] """ - 胜率 - 平均战斗 @@ -583,7 +583,7 @@ class Body(TypedDict): radar_chart: RadarChart """能力图""" - shooting: List[ts] + shooting: list[ts] """ - 精准击败 - 身体 @@ -705,4 +705,4 @@ class Shop(TypedDict): """商店结束时间戳""" cur_ts: float """商店当前时间戳""" - list: List[ShopDay] + list: list[ShopDay] diff --git a/VAUID/utils/api/request.py b/VAUID/utils/api/request.py index 8db0185..c59e390 100644 --- a/VAUID/utils/api/request.py +++ b/VAUID/utils/api/request.py @@ -1,40 +1,40 @@ import json as js import time -from typing import Any, Dict, List, Union, Literal, Callable, Optional, cast -from dataclasses import field, dataclass - -from httpx import AsyncClient +from collections.abc import Callable +from dataclasses import dataclass, field +from typing import Any, Literal, cast from gsuid_core.logger import logger from gsuid_core.models import Event +from httpx import AsyncClient +from ..database.models import ValUser from .api import ( PFAPI, + AssetAPI, + CardAPI, GunAPI, MapAPI, - CardAPI, - ShopAPI, - ViveAPI, - AssetAPI, OnlineAPI, SearchAPI, - ValCardAPI, + ShopAPI, SummonerAPI, + ValCardAPI, + ViveAPI, ) +from .model.asset import AssetData from .models import ( - Shop, - Vive, Battle, - PFInfo, - GunInfo, - MapInfo, CardInfo, - InfoBody, CardOnline, + GunInfo, + InfoBody, + MapInfo, + PFInfo, + Shop, SummonerInfo, + Vive, ) -from .model.asset import AssetData -from ..database.models import ValUser SEASON_ID = "dcde7346-4085-de4f-c463-2489ed47983b" DEFAULT_TIMEOUT = 300 @@ -44,8 +44,8 @@ class ApiRequest: url: str method: Literal["GET", "POST"] = "GET" - params: Optional[Dict[str, Any]] = None - json: Optional[Dict[str, Any]] = None + params: dict[str, Any] | None = None + json: dict[str, Any] | None = None need_cookie: bool = True @@ -53,9 +53,9 @@ class ApiRequest: class QueryContext: user_id: str bot_id: str - cookie: Optional[str] = None - opuid: Optional[str] = None - _random_cookie: Optional[str] = field(default=None, repr=False) + cookie: str | None = None + opuid: str | None = None + _random_cookie: str | None = field(default=None, repr=False) async def init(self): opuid, ck = await WeGameApi._get_cookie_by_id(self.user_id, self.bot_id) @@ -63,7 +63,7 @@ async def init(self): self.cookie = ck return self - async def get_random_cookie(self) -> Optional[str]: + async def get_random_cookie(self) -> str | None: if self._random_cookie is None: _, self._random_cookie = await WeGameApi.get_sence() return self._random_cookie @@ -71,7 +71,7 @@ async def get_random_cookie(self) -> Optional[str]: class WeGameApi: ssl_verify: bool = False - _HEADER: Dict[str, str] = { + _HEADER: dict[str, str] = { "User-Agent": ( "mval/1.4.1.10011 Channel/3" "Mozilla/5.0 (Linux; Android 9; V2171A Build/PQ3A.190605.10171107; wv)" @@ -89,21 +89,21 @@ async def create_context(cls, ev: Event) -> QueryContext: return ctx @staticmethod - async def _get_cookie(uid: str) -> List[str]: + async def _get_cookie(uid: str) -> list[str]: cookie = await ValUser.get_user_cookie_by_uid(uid) if cookie is None: raise Exception("No valid cookie") return [uid, cookie] if cookie else ["", ""] @staticmethod - async def _get_cookie_by_id(user_id: str, bot_id: str) -> List[str]: + async def _get_cookie_by_id(user_id: str, bot_id: str) -> list[str]: data = await ValUser.select_data(user_id, bot_id) if data is None: raise Exception("No valid uid") return [data.uid or "", data.cookie] if data.cookie else ["", ""] @staticmethod - async def get_sence() -> List[str]: + async def get_sence() -> list[str]: user_list = await ValUser.get_all_user() if not user_list: return ["", ""] @@ -121,10 +121,10 @@ async def _va_request( self, url: str, method: Literal["GET", "POST"] = "GET", - headers: Optional[Dict[str, str]] = None, - params: Optional[Dict[str, Any]] = None, - json: Optional[Dict[str, Any]] = None, - ) -> Union[Dict, int]: + headers: dict[str, str] | None = None, + params: dict[str, Any] | None = None, + json: dict[str, Any] | None = None, + ) -> dict | int: req_headers = dict(self._HEADER) if headers: headers = { @@ -166,10 +166,10 @@ async def _va_request( def _parse_response( self, - data: Union[Dict, int], - parser: Optional[Callable[[Dict], Any]] = None, + data: dict | int, + parser: Callable[[dict], Any] | None = None, default_on_error: Any = "", - ) -> Union[Any, int]: + ) -> Any | int: if isinstance(data, int): return data if data.get("result", 0) != 0: @@ -179,10 +179,10 @@ def _parse_response( async def _request_with_fallback( self, request: ApiRequest, - parser: Callable[[Dict], Any], - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[Any, int]: + parser: Callable[[dict], Any], + cookie: str | None = None, + random_cookie: str | None = None, + ) -> Any | int: if cookie: data = await self._va_request( request.url, @@ -209,7 +209,7 @@ async def _request_with_fallback( ) return self._parse_response(data, parser, default_on_error="") - async def search_player(self, key_word: str) -> Union[List[InfoBody], int]: + async def search_player(self, key_word: str) -> list[InfoBody] | int: data = await self._va_request( SearchAPI, params={ @@ -222,11 +222,11 @@ async def search_player(self, key_word: str) -> Union[List[InfoBody], int]: ) if isinstance(data, int): return data - return cast(List[InfoBody], data["data"]["userList"]) + return cast(list[InfoBody], data["data"]["userList"]) async def get_player_info( - self, ctx: QueryContext, uid_list: List[str] - ) -> Union[SummonerInfo, int, str, None]: + self, ctx: QueryContext, uid_list: list[str] + ) -> SummonerInfo | int | str | None: if len(uid_list) < 1 or not ctx.cookie: return None @@ -252,7 +252,7 @@ async def get_player_info( return cast(str, data.get("data", "")) return cast(SummonerInfo, data["data"][0]) - async def get_player_card(self, uid: str) -> Union[CardInfo, int, str]: + async def get_player_card(self, uid: str) -> CardInfo | int | str: uid, ck = await self._get_cookie(uid) data = await self._va_request( CardAPI, headers={"Cookie": ck}, json={"uuid": uid, "jump_key": "mine"} @@ -264,13 +264,13 @@ async def get_player_card(self, uid: str) -> Union[CardInfo, int, str]: async def get_detail_card( self, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[Battle], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[Battle] | int: request = ApiRequest(url=ValCardAPI, json={"scene": scene}) return await self._request_with_fallback( request, - lambda d: cast(List[Battle], d["data"]["battle_list"]), + lambda d: cast(list[Battle], d["data"]["battle_list"]), cookie, random_cookie, ) @@ -279,9 +279,9 @@ async def get_online( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[CardOnline, int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> CardOnline | int: request = ApiRequest(url=OnlineAPI, json={"uuid": uid, "scene": scene}) return await self._request_with_fallback( request, @@ -294,16 +294,16 @@ async def get_gun( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[GunInfo], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[GunInfo] | int: request = ApiRequest( url=GunAPI, json={"scene": scene, "season_id": SEASON_ID, "queue_id": "255"}, ) return await self._request_with_fallback( request, - lambda d: cast(List[GunInfo], d["data"]["list"]), + lambda d: cast(list[GunInfo], d["data"]["list"]), cookie, random_cookie, ) @@ -312,16 +312,16 @@ async def get_map( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[MapInfo], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[MapInfo] | int: request = ApiRequest( url=MapAPI, json={"scene": scene, "season_id": SEASON_ID, "queue_id": "255"}, ) return await self._request_with_fallback( request, - lambda d: cast(List[MapInfo], d["data"]["list"]), + lambda d: cast(list[MapInfo], d["data"]["list"]), cookie, random_cookie, ) @@ -330,13 +330,13 @@ async def get_vive( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[Vive], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[Vive] | int: request = ApiRequest(url=ViveAPI, json={"scene": scene}) return await self._request_with_fallback( request, - lambda d: cast(List[Vive], d["data"]["list"]), + lambda d: cast(list[Vive], d["data"]["list"]), cookie, random_cookie, ) @@ -345,16 +345,16 @@ async def get_pf( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[PFInfo], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[PFInfo] | int: request = ApiRequest( url=PFAPI, json={"scene": scene, "season_id": SEASON_ID, "queue_id": "255"}, ) return await self._request_with_fallback( request, - lambda d: cast(List[PFInfo], d["data"]["list"]), + lambda d: cast(list[PFInfo], d["data"]["list"]), cookie, random_cookie, ) @@ -363,9 +363,9 @@ async def get_shop( self, uid: str, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[List[Shop], int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> list[Shop] | int: request = ApiRequest( url=ShopAPI, json={ @@ -377,7 +377,7 @@ async def get_shop( ) return await self._request_with_fallback( request, - lambda d: cast(List[Shop], d["data"]), + lambda d: cast(list[Shop], d["data"]), cookie, random_cookie, ) @@ -385,9 +385,9 @@ async def get_shop( async def get_asset( self, scene: str, - cookie: Optional[str] = None, - random_cookie: Optional[str] = None, - ) -> Union[AssetData, int]: + cookie: str | None = None, + random_cookie: str | None = None, + ) -> AssetData | int: request = ApiRequest( url=AssetAPI, json={ diff --git a/VAUID/utils/database/models.py b/VAUID/utils/database/models.py index 9b5abb7..c784958 100644 --- a/VAUID/utils/database/models.py +++ b/VAUID/utils/database/models.py @@ -1,11 +1,11 @@ -from typing import TypeVar, Optional +from typing import TypeVar -from sqlmodel import Field -from sqlalchemy.ext.asyncio import AsyncSession - -from gsuid_core.webconsole.mount_app import PageSchema, GsAdminModel, site -from gsuid_core.utils.database.startup import exec_list from gsuid_core.utils.database.base_models import Bind, User, with_session +from gsuid_core.utils.database.startup import exec_list +from gsuid_core.webconsole.mount_app import GsAdminModel, PageSchema, site +from sqlalchemy.ext.asyncio import AsyncSession +from sqlmodel import Field +from typing_extensions import Self exec_list.extend( [ @@ -19,21 +19,21 @@ class ValBind(Bind): - uid: Optional[str] = Field(default=None, title="VAUID") + uid: str | None = Field(default=None, title="VAUID") model_config = {"table": True} # type: ignore class ValUser(User): - uid: Optional[str] = Field(default=None, title="VAUID") - latest_battle_id: Optional[str] = Field(default=None, title="最新战绩ID") - latest_battle_time: Optional[int] = Field(default=0, title="最新战绩时间") + uid: str | None = Field(default=None, title="VAUID") + latest_battle_id: str | None = Field(default=None, title="最新战绩ID") + latest_battle_time: int | None = Field(default=0, title="最新战绩时间") model_config = {"table": True} # type: ignore @classmethod @with_session - async def get_latest_battle_id(cls, user_id: str, bot_id: str) -> Optional[str]: + async def get_latest_battle_id(cls, user_id: str, bot_id: str) -> str | None: """获取用户最新战绩ID""" data = await cls.select_data(user_id, bot_id) return data.latest_battle_id if data else None @@ -59,13 +59,13 @@ async def update_latest_battle( @classmethod @with_session async def insert_or_update_user( - cls: type[T_ValUser], + cls, session: AsyncSession, bot_id: str, user_id: str, uid: str, cookie: str, - ) -> T_ValUser: + ) -> Self: obj = await cls.base_select_data( bot_id=bot_id, user_id=user_id, diff --git a/VAUID/utils/error_reply.py b/VAUID/utils/error_reply.py index 869c065..8aba1c2 100644 --- a/VAUID/utils/error_reply.py +++ b/VAUID/utils/error_reply.py @@ -1,5 +1,3 @@ -from typing import Union - TEXT_HINT = "[va] 请输入正确的参数" UID_HINT = "[va] 你还没有绑定UID,请先使用[va绑定]命令进行绑定" CK_HINT = "[va] 你还没有添加可用CK,请先使用[va添加ck]命令进行绑定" @@ -16,7 +14,7 @@ } -def get_error(retcode: Union[int, str]) -> str: +def get_error(retcode: int | str) -> str: return error_dict.get( int(retcode), f"未知错误, 错误码为{retcode}, 可能由于未开启Wegame召唤师搜索!", diff --git a/VAUID/utils/helper.py b/VAUID/utils/helper.py index 72e8df7..2f81188 100644 --- a/VAUID/utils/helper.py +++ b/VAUID/utils/helper.py @@ -1,11 +1,9 @@ -from typing import Optional - from gsuid_core.models import Event from ..utils.database.models import ValBind -async def get_bind_uid(ev: Event) -> Optional[str]: +async def get_bind_uid(ev: Event) -> str | None: user_id = ev.at if ev.at else ev.user_id bot_id = ev.bot_id[0] if isinstance(ev.bot_id, list) else ev.bot_id return await ValBind.get_uid_by_game(user_id, bot_id) diff --git a/VAUID/utils/va_config.py b/VAUID/utils/va_config.py index ee17a20..21b7a5a 100644 --- a/VAUID/utils/va_config.py +++ b/VAUID/utils/va_config.py @@ -1,16 +1,15 @@ # 先导入基础配置模型 -from typing import Dict # 设定一个配置文件(json)保存文件路径 from gsuid_core.data_store import get_res_path -from gsuid_core.utils.plugins_config.models import GSC # 然后添加到GsCore网页控制台中 from gsuid_core.utils.plugins_config.gs_config import StringConfig +from gsuid_core.utils.plugins_config.models import GSC # 建立自己插件的CONFIG_DEFAULT # 名字无所谓, 类型一定是Dict[str, GSC],以下为示例,可以添加无数个配置 -CONIFG_DEFAULT: Dict[str, GSC] = {} +CONIFG_DEFAULT: dict[str, GSC] = {} CONFIG_PATH = get_res_path("VAUID") / "config.json" diff --git a/VAUID/utils/va_font.py b/VAUID/utils/va_font.py index 44432d6..a7f0829 100644 --- a/VAUID/utils/va_font.py +++ b/VAUID/utils/va_font.py @@ -1,8 +1,7 @@ from pathlib import Path -from PIL import ImageFont - from gsuid_core.utils.fonts.fonts import core_font as va_font +from PIL import ImageFont FONT_MAIN_PATH = Path(__file__).parent / "fonts/loli.ttf" FONT_TIELE_PATH = Path(__file__).parent / "fonts/title.ttf" diff --git a/VAUID/va_help/__init__.py b/VAUID/va_help/__init__.py index 4ef2fa3..bb4ec2f 100644 --- a/VAUID/va_help/__init__.py +++ b/VAUID/va_help/__init__.py @@ -1,17 +1,16 @@ -from PIL import Image - -from gsuid_core.sv import SV from gsuid_core.bot import Bot +from gsuid_core.help.utils import register_help from gsuid_core.logger import logger from gsuid_core.models import Event -from gsuid_core.help.utils import register_help +from gsuid_core.sv import SV +from PIL import Image from .get_help import ICON, get_help sv_csgo_help = SV("va帮助") -@sv_csgo_help.on_fullmatch(("帮助")) +@sv_csgo_help.on_fullmatch("帮助") async def send_help_img(bot: Bot, ev: Event): logger.info("开始执行[va帮助]") im = await get_help() diff --git a/VAUID/va_help/get_help.py b/VAUID/va_help/get_help.py index 83d12ca..503315b 100644 --- a/VAUID/va_help/get_help.py +++ b/VAUID/va_help/get_help.py @@ -1,13 +1,11 @@ import json -from typing import Dict from pathlib import Path import aiofiles -from PIL import Image - -from gsuid_core.sv import get_plugin_prefix -from gsuid_core.help.model import PluginHelp from gsuid_core.help.draw_new_plugin_help import get_new_help +from gsuid_core.help.model import PluginHelp +from gsuid_core.sv import get_plugin_prefix +from PIL import Image from ..version import VAUID_version @@ -23,7 +21,7 @@ def get_footer(): return Image.open(TEXT_PATH / "footer.png") -async def get_help_data() -> Dict[str, PluginHelp]: +async def get_help_data() -> dict[str, PluginHelp]: async with aiofiles.open(HELP_DATA, "rb") as file: return json.loads(await file.read()) diff --git a/VAUID/va_info/__init__.py b/VAUID/va_info/__init__.py index c60902e..3bad772 100644 --- a/VAUID/va_info/__init__.py +++ b/VAUID/va_info/__init__.py @@ -1,17 +1,19 @@ """VA 用户信息查询模块""" -from gsuid_core.sv import SV from gsuid_core.bot import Bot from gsuid_core.logger import logger from gsuid_core.models import Event +from gsuid_core.sv import SV from .. import ( va_notify as va_notify_module, # noqa: F401 +) +from .. import ( va_subscribe as va_subscribe_module, # noqa: F401 ) -from .va_info import get_va_info_img, get_va_asset_img -from ..utils.helper import get_bind_uid from ..utils.error_reply import UID_HINT +from ..utils.helper import get_bind_uid +from .va_info import get_va_asset_img, get_va_info_img va_user_info = SV("VA 用户信息查询") diff --git a/VAUID/va_info/draw.py b/VAUID/va_info/draw.py index 4e1825d..d644dd9 100644 --- a/VAUID/va_info/draw.py +++ b/VAUID/va_info/draw.py @@ -1,38 +1,36 @@ """VA 信息绘图模块 - 负责绘制用户信息图片""" -import math import asyncio -from typing import List, Tuple, Union, Optional - -from PIL import Image, ImageDraw +import math from gsuid_core.logger import logger from gsuid_core.utils.image.convert import convert_img -from gsuid_core.utils.image.image_tools import easy_paste, draw_pic_with_ring +from gsuid_core.utils.image.image_tools import draw_pic_with_ring, easy_paste +from PIL import Image, ImageDraw -from .utils import DrawUtils, save_img, get_cached_texture -from ..utils.va_font import va_font_20, va_font_30, va_font_42 +from ..utils.api.model.asset import AgentData, CollectionData, SkinData from ..utils.api.models import ( - Vive, Battle, - PFInfo, - GunInfo, CardInfo, CardOnline, + GunInfo, + PFInfo, SummonerInfo, + Vive, ) -from ..utils.api.model.asset import SkinData, AgentData, CollectionData +from ..utils.va_font import va_font_20, va_font_30, va_font_42 +from .utils import DrawUtils, get_cached_texture, save_img async def draw_va_info_img( detail: SummonerInfo, card: CardInfo, - valcard: Optional[List[Battle]], - online: Optional[CardOnline], - gun: List[GunInfo], - hero: List[PFInfo], - vive: List[Vive], -) -> Union[bytes, str]: + valcard: list[Battle] | None, + online: CardOnline | None, + gun: list[GunInfo], + hero: list[PFInfo], + vive: list[Vive], +) -> bytes | str: """绘制 VA 用户信息图片 Args: @@ -215,10 +213,10 @@ def draw_stat(x: int, y: int, value: str, label: str): async def draw_asset_section( img: Image.Image, img_draw: ImageDraw.ImageDraw, - section_data: Union[SkinData, AgentData, CollectionData], + section_data: SkinData | AgentData | CollectionData, section_name: str, y_offset: int, - size: Tuple[int, int] = (80, 80), + size: tuple[int, int] = (80, 80), icon_key: str = "icon", name_key: str = "name", title_offset: int = 50, diff --git a/VAUID/va_info/utils.py b/VAUID/va_info/utils.py index 196d183..dda1795 100644 --- a/VAUID/va_info/utils.py +++ b/VAUID/va_info/utils.py @@ -1,37 +1,36 @@ -import math import asyncio -from typing import Dict, List, Tuple, Literal, Optional -from pathlib import Path +import math from functools import lru_cache +from pathlib import Path +from typing import Literal -from PIL import Image, ImageDraw -from PIL.ImageDraw import ImageDraw as ImageDrawType - -from gsuid_core.logger import logger from gsuid_core.data_store import get_res_path -from gsuid_core.utils.image.utils import download_pic_to_image +from gsuid_core.logger import logger from gsuid_core.utils.image.image_tools import easy_paste +from gsuid_core.utils.image.utils import download_pic_to_image +from PIL import Image, ImageDraw +from PIL.ImageDraw import ImageDraw as ImageDrawType -from ..utils.va_font import va_font_20, va_font_30, va_font_42 from ..utils.api.models import ( - Vive, Battle, - PFInfo, GunInfo, + PFInfo, + Vive, ) +from ..utils.va_font import va_font_20, va_font_30, va_font_42 TEXTURE = Path(__file__).parent / "texture2d" # 图片缓存字典 -_image_cache: Dict[str, Image.Image] = {} +_image_cache: dict[str, Image.Image] = {} async def save_img( img_url: str, img_type: str, - size: Optional[Tuple[int, int]] = None, - rename: Optional[str] = None, + size: tuple[int, int] | None = None, + rename: str | None = None, ): """下载图片并缓存以读取""" img_path = get_res_path("VAUID") / img_type / img_url.split("/")[-1] @@ -74,7 +73,7 @@ def get_cached_texture(filename: str) -> Image.Image: class DrawUtils: @staticmethod - async def draw_hero_section(left_bg: Image.Image, hero: List[PFInfo]): + async def draw_hero_section(left_bg: Image.Image, hero: list[PFInfo]): """绘制英雄信息部分""" hero_bg = get_cached_texture("bg_val_mine_header.png") hero_draw = ImageDraw.Draw(hero_bg) @@ -124,7 +123,7 @@ async def draw_hero_section(left_bg: Image.Image, hero: List[PFInfo]): easy_paste(left_bg, hero_bg, (20, 40), "lt") @staticmethod - async def draw_weapon_section(left_bg: Image.Image, gun: List[GunInfo]): + async def draw_weapon_section(left_bg: Image.Image, gun: list[GunInfo]): """绘制武器信息部分""" if gun is None: return @@ -183,7 +182,7 @@ async def draw_weapon_section(left_bg: Image.Image, gun: List[GunInfo]): @staticmethod def draw_vive_section( - right_bg: Image.Image, right_draw: ImageDrawType, vive: List[Vive] + right_bg: Image.Image, right_draw: ImageDrawType, vive: list[Vive] ): """绘制射击数据部分""" if vive is None: @@ -208,7 +207,7 @@ def draw_vive_section( async def draw_battle_section( right_bg: Image.Image, right_draw: ImageDrawType, - valcard: Optional[List[Battle]], + valcard: list[Battle] | None, ): """绘制战绩部分""" if valcard is None or isinstance(valcard, int): @@ -223,7 +222,7 @@ async def draw_battle_section( for battle in battles_to_show: image_tasks.append(save_img(battle["image_url"], "head2")) if battle["score_level"].get("level", "").strip(): - icon_key_map: Dict[ + icon_key_map: dict[ str, Literal["head_icon_win", "head_icon_fail", "head_icon_draw"], ] = { @@ -342,10 +341,10 @@ async def draw_battle_section( @staticmethod def draw_hexagonal_panel( - proportion_array: List[float], + proportion_array: list[float], image: Image.Image, - fill_color: Optional[Tuple[int, int, int, int]] = (255, 255, 255, 100), - outline_color: Optional[Tuple[int, int, int, int]] = (0, 0, 0, 255), + fill_color: tuple[int, int, int, int] | None = (255, 255, 255, 100), + outline_color: tuple[int, int, int, int] | None = (0, 0, 0, 255), ): """绘制六边形面板 @@ -378,7 +377,7 @@ def draw_hexagonal_panel( @lru_cache(maxsize=256) -def hex_to_rgba(hex_color: str, alpha: int = 255) -> Tuple[int, int, int, int]: +def hex_to_rgba(hex_color: str, alpha: int = 255) -> tuple[int, int, int, int]: """将十六进制颜色转换为 RGBA,使用LRU缓存优化性能""" hex_color = hex_color.lstrip("#") r = int(hex_color[0:2], 16) diff --git a/VAUID/va_info/va_info.py b/VAUID/va_info/va_info.py index b9147c7..6a950b3 100644 --- a/VAUID/va_info/va_info.py +++ b/VAUID/va_info/va_info.py @@ -1,22 +1,20 @@ import asyncio -from typing import List, Union, Optional - -from PIL import Image, ImageDraw from gsuid_core.logger import logger from gsuid_core.models import Event from gsuid_core.utils.image.convert import convert_img -from gsuid_core.utils.image.image_tools import easy_paste, draw_pic_with_ring +from gsuid_core.utils.image.image_tools import draw_pic_with_ring, easy_paste +from PIL import Image, ImageDraw -from .draw import draw_va_info_img, draw_asset_section -from .utils import save_img, get_cached_texture +from ..utils.api.models import Battle, CardOnline, GunInfo, PFInfo, Vive +from ..utils.error_reply import get_error from ..utils.va_api import va_api from ..utils.va_font import va_font_20, va_font_42 -from ..utils.api.models import Vive, Battle, PFInfo, GunInfo, CardOnline -from ..utils.error_reply import get_error +from .draw import draw_asset_section, draw_va_info_img +from .utils import get_cached_texture, save_img -async def get_va_info_img(ev: Event, uid: str) -> Union[str, bytes]: +async def get_va_info_img(ev: Event, uid: str) -> str | bytes: ctx = await va_api.create_context(ev) detail = await va_api.get_player_info(ctx, [uid]) @@ -47,13 +45,13 @@ async def get_va_info_img(ev: Event, uid: str) -> Union[str, bytes]: cardetail_raw, online_raw, gun_raw, hero_raw, vive_raw = results - cardetail: Optional[List[Battle]] = None + cardetail: list[Battle] | None = None if isinstance(cardetail_raw, (int, str, BaseException)): logger.info(f"cardetail error: {cardetail_raw}") else: cardetail = cardetail_raw - online: Optional[CardOnline] = None + online: CardOnline | None = None if isinstance(online_raw, (int, BaseException)): logger.error( f"online error: {get_error(online_raw) if isinstance(online_raw, int) else online_raw}" @@ -66,21 +64,21 @@ async def get_va_info_img(ev: Event, uid: str) -> Union[str, bytes]: return "获取武器数据失败" if isinstance(gun_raw, int): return get_error(gun_raw) - gun: List[GunInfo] = gun_raw + gun: list[GunInfo] = gun_raw if isinstance(hero_raw, BaseException): logger.error(f"hero error: {hero_raw}") return "获取英雄数据失败" if isinstance(hero_raw, int): return get_error(hero_raw) - hero: List[PFInfo] = hero_raw + hero: list[PFInfo] = hero_raw if isinstance(vive_raw, BaseException): logger.error(f"vive error: {vive_raw}") return "获取 vive 数据失败" if isinstance(vive_raw, int): return get_error(vive_raw) - vive: List[Vive] = vive_raw + vive: list[Vive] = vive_raw if not detail.get("gameInfoList"): return "报错了,检查控制台" @@ -88,7 +86,7 @@ async def get_va_info_img(ev: Event, uid: str) -> Union[str, bytes]: return await draw_va_info_img(detail, card, cardetail, online, gun, hero, vive) -async def get_va_asset_img(ev: Event, uid: str) -> Union[str, bytes]: +async def get_va_asset_img(ev: Event, uid: str) -> str | bytes: ctx = await va_api.create_context(ev) detail = await va_api.get_player_info(ctx, [uid]) diff --git a/VAUID/va_notify/__init__.py b/VAUID/va_notify/__init__.py index f8993e2..cbeb60d 100644 --- a/VAUID/va_notify/__init__.py +++ b/VAUID/va_notify/__init__.py @@ -1,7 +1,7 @@ """VA 战绩定时推送模块""" -import random import asyncio +import random from gsuid_core.aps import scheduler from gsuid_core.logger import logger diff --git a/VAUID/va_shop/__init__.py b/VAUID/va_shop/__init__.py index aa4a0cd..0bb77cc 100644 --- a/VAUID/va_shop/__init__.py +++ b/VAUID/va_shop/__init__.py @@ -1,11 +1,11 @@ -from gsuid_core.sv import SV from gsuid_core.bot import Bot from gsuid_core.logger import logger from gsuid_core.models import Event +from gsuid_core.sv import SV -from .shop_info import get_va_shop_img -from ..utils.helper import get_bind_uid from ..utils.error_reply import UID_HINT +from ..utils.helper import get_bind_uid +from .shop_info import get_va_shop_img va_shop_query = SV("VA 商店查询") diff --git a/VAUID/va_shop/shop_info.py b/VAUID/va_shop/shop_info.py index d9f114f..4f87cb8 100644 --- a/VAUID/va_shop/shop_info.py +++ b/VAUID/va_shop/shop_info.py @@ -1,11 +1,9 @@ -from typing import List, Union - from gsuid_core.logger import logger from gsuid_core.models import Event -from ..utils.va_api import va_api from ..utils.api.models import Shop, SummonerInfo from ..utils.error_reply import get_error +from ..utils.va_api import va_api async def time_delta(m_time: float) -> str: @@ -14,7 +12,7 @@ async def time_delta(m_time: float) -> str: return f"{hours}小时{minutes}分钟{seconds}秒" -async def get_va_shop_img(ev: Event, uid: str) -> Union[str, bytes]: +async def get_va_shop_img(ev: Event, uid: str) -> str | bytes: ctx = await va_api.create_context(ev) detail = await va_api.get_player_info(ctx, [uid]) @@ -42,7 +40,7 @@ async def get_va_shop_img(ev: Event, uid: str) -> Union[str, bytes]: return await draw_va_shop_img(detail, shop_list) -async def draw_va_shop_img(detail: SummonerInfo, shop_list: List[Shop]) -> str: +async def draw_va_shop_img(detail: SummonerInfo, shop_list: list[Shop]) -> str: msg: str = "" day_list = next((i for i in shop_list if i["key"] == "dailystore"), None) king_list = next((i for i in shop_list if i["key"] == "kingdomstore"), None) diff --git a/VAUID/va_subscribe/__init__.py b/VAUID/va_subscribe/__init__.py index 57fd7ee..e8df490 100644 --- a/VAUID/va_subscribe/__init__.py +++ b/VAUID/va_subscribe/__init__.py @@ -2,26 +2,26 @@ from typing import Any, Dict, Optional -from gsuid_core.sv import SV from gsuid_core.bot import Bot from gsuid_core.logger import logger from gsuid_core.models import Event from gsuid_core.subscribe import gs_subscribe +from gsuid_core.sv import SV -from ..utils.va_api import va_api from ..utils.database.models import ValBind, ValUser +from ..utils.va_api import va_api va_watch_record = SV("VA战绩订阅") -def _parse_detail(detail: Any) -> Optional[Dict[str, Any]]: +def _parse_detail(detail: Any) -> dict[str, Any] | None: """安全解析detail响应""" if isinstance(detail, dict) and "gameInfoList" in detail: return detail return None -def _parse_card(card: Any) -> Optional[Dict[str, Any]]: +def _parse_card(card: Any) -> dict[str, Any] | None: """安全解析card响应""" if isinstance(card, dict) and "role_info" in card: return card @@ -114,7 +114,7 @@ async def cancel_subscribe_va_record(bot: Bot, ev: Event): async def check_new_battle( uid: str, user_id: str, bot_id: str -) -> tuple[bool, Optional[Dict[str, Any]]]: +) -> tuple[bool, dict[str, Any] | None]: """ 检查用户是否有新战绩 diff --git a/VAUID/va_user/__init__.py b/VAUID/va_user/__init__.py index e516041..0f6a56b 100644 --- a/VAUID/va_user/__init__.py +++ b/VAUID/va_user/__init__.py @@ -1,6 +1,6 @@ +import asyncio import re import sys -import asyncio import urllib.parse from typing import cast @@ -9,29 +9,30 @@ else: from async_timeout import timeout # 导入 Playwright -from playwright.async_api import async_playwright - -from gsuid_core.sv import SV from gsuid_core.bot import Bot from gsuid_core.logger import logger +from gsuid_core.message_models import Button from gsuid_core.models import Event # 导入 gsuid_core 组件 from gsuid_core.segment import MessageSegment -from gsuid_core.utils.message import send_diff_msg -from gsuid_core.message_models import Button +from gsuid_core.sv import SV from gsuid_core.utils.image.convert import convert_img +from gsuid_core.utils.message import send_diff_msg +from playwright.async_api import async_playwright -from .login import exchange_val_token +from ..utils.api.models import LoginData +from ..utils.database.models import ValBind, ValUser +from ..utils.error_reply import get_error from .add_ck import add_cookie -from .search_player import search_player_with_name from .browser_install import ( ensure_browser_available, +) +from .browser_install import ( is_browser_not_installed_error as is_browser_not_installed_error, ) -from ..utils.api.models import LoginData -from ..utils.error_reply import get_error -from ..utils.database.models import ValBind, ValUser +from .login import exchange_val_token +from .search_player import search_player_with_name va_user_bind = SV("VA用户绑定") va_add_ck = SV("VA添加CK", area="DIRECT") @@ -50,7 +51,7 @@ async def send_va_add_ck_msg(bot: Bot, ev: Event): await bot.send(await add_cookie(ev, uid, ck)) -@va_user_bind.on_command(("扫码登录")) +@va_user_bind.on_command("扫码登录") async def on_valo_login(bot: Bot, ev: Event): await bot.send("正在获取登录二维码,请稍候...") LOGIN_URL = "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?pt_enable_pwd=1&appid=716027609&pt_3rd_aid=102061775&daid=381&pt_skey_valid=0&style=35&force_qr=1&autorefresh=1&s_url=http%3A%2F%2Fconnect.qq.com&refer_cgi=m_authorize&ucheck=1&fall_to_wv=1&status_os=12&redirect_uri=auth%3A%2F%2Ftauth.qq.com%2F&client_id=102061775&pf=openmobile_android&response_type=token&scope=all&sdkp=a&sdkv=3.5.17.lite&sign=a6479455d3e49b597350f13f776a6288&status_machine=MjMxMTdSSzY2Qw%3D%3D&switch=1&time=1763280194&show_download_ui=true&h5sig=trobryxo8IPM0GaSQH12mowKG-CY65brFzkK7_-9EW4&loginty=6" @@ -225,7 +226,7 @@ async def send_va_bind_uid_msg(bot: Bot, ev: Event): await bot.logger.info("[Val] 开始执行[绑定/解绑用户信息]") qid = ev.user_id - await bot.logger.info("[Val] [绑定/解绑]UserID: {}".format(qid)) + await bot.logger.info(f"[Val] [绑定/解绑]UserID: {qid}") if uid and len(uid.split("-")) != 3: return await bot.send("你输入了错误的格式!\n请使用va搜索命令获取正确的UID") diff --git a/VAUID/va_user/browser_install.py b/VAUID/va_user/browser_install.py index 164ba47..602fbdd 100644 --- a/VAUID/va_user/browser_install.py +++ b/VAUID/va_user/browser_install.py @@ -1,9 +1,9 @@ """Playwright浏览器自动安装辅助模块""" -import os import asyncio +import os import subprocess -from typing import Optional, AsyncIterator +from collections.abc import AsyncIterator from pathlib import Path from gsuid_core.logger import logger @@ -15,7 +15,7 @@ PLAYWRIGHT_BROWSERS_PATH = Path(_PLAYWRIGHT_BROWSERS_PATH_STR) -def get_chrome_headless_shell_executable() -> Optional[Path]: +def get_chrome_headless_shell_executable() -> Path | None: """获取chrome-headless-shell可执行文件路径""" chrome_shell_path = ( PLAYWRIGHT_BROWSERS_PATH diff --git a/VAUID/va_user/login.py b/VAUID/va_user/login.py index d2a9e0d..6e7fd29 100644 --- a/VAUID/va_user/login.py +++ b/VAUID/va_user/login.py @@ -1,7 +1,4 @@ -from typing import Dict, Optional - import aiohttp - from gsuid_core.logger import logger MVAL_API = ( @@ -9,7 +6,7 @@ ) -async def exchange_val_token(openid: str, access_token: str) -> Optional[Dict]: +async def exchange_val_token(openid: str, access_token: str) -> dict | None: payload = { "clienttype": 9, "config_params": {"client_dev_name": "23117RK66C", "lang_type": 0},