From 01a8026a5499078b8c8ba4adab9030be586ee6ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:10:25 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20`pre-commit-ci`?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.14 → v0.15.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.14...v0.15.4) - [github.com/astral-sh/uv-pre-commit: 0.9.28 → 0.10.7](https://github.com/astral-sh/uv-pre-commit/compare/0.9.28...0.10.7) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3e9aa48..a042691 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.14.14 + rev: v0.15.4 hooks: - id: ruff args: [--fix] @@ -20,7 +20,7 @@ repos: - repo: https://github.com/astral-sh/uv-pre-commit # uv version. - rev: 0.9.28 + rev: 0.10.7 hooks: - id: uv-lock - id: uv-export From fd34735b61d2af9c980675d7af9cbdaab4c73667 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:18:29 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9A=A8=20`pre-commit-ci`=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=A0=BC=E5=BC=8F=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VAUID/utils/api/request.py | 77 +++++++++++++++++++++++++++++++------- VAUID/va_info/utils.py | 42 +++++++++++++++------ VAUID/va_info/va_info.py | 74 ++++++++++++++++++++++++++++++------ VAUID/va_user/__init__.py | 33 ++++++++++++---- VAUID/va_user/login.py | 4 +- 5 files changed, 183 insertions(+), 47 deletions(-) diff --git a/VAUID/utils/api/request.py b/VAUID/utils/api/request.py index a1793b4..c15b3e4 100644 --- a/VAUID/utils/api/request.py +++ b/VAUID/utils/api/request.py @@ -146,7 +146,10 @@ async def _va_request( """统一的 API 请求方法""" req_headers = dict(self._HEADER) if headers: - headers = {k.capitalize() if k.lower() == "cookie" else k: v for k, v in headers.items()} + headers = { + k.capitalize() if k.lower() == "cookie" else k: v + for k, v in headers.items() + } req_headers.update(headers) if json: @@ -210,7 +213,13 @@ async def _request_with_fallback( """ # 使用优先 cookie 请求 if cookie: - data = await self._va_request(request.url, request.method, {"Cookie": cookie}, request.params, request.json) + data = await self._va_request( + request.url, + request.method, + {"Cookie": cookie}, + request.params, + request.json, + ) result = self._parse_response(data, parser, default_on_error="") if not isinstance(result, int) or result >= 0: return result @@ -222,7 +231,11 @@ async def _request_with_fallback( return -511 data = await self._va_request( - request.url, request.method, {"Cookie": random_cookie}, request.params, request.json + request.url, + request.method, + {"Cookie": random_cookie}, + request.params, + request.json, ) return self._parse_response(data, parser, default_on_error="") @@ -244,7 +257,9 @@ async def search_player(self, key_word: str) -> Union[List[InfoBody], int]: return data return cast(List[InfoBody], data["data"]["userList"]) - async def get_player_info(self, ctx: QueryContext, uid_list: List[str]) -> Union[SummonerInfo, int, str, None]: + async def get_player_info( + self, ctx: QueryContext, uid_list: List[str] + ) -> Union[SummonerInfo, int, str, None]: """获取玩家信息""" if len(uid_list) < 1 or not ctx.cookie: return None @@ -274,11 +289,18 @@ async def get_player_info(self, ctx: QueryContext, uid_list: List[str]) -> Union async def get_player_card(self, uid: str) -> Union[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"}) - return self._parse_response(data, lambda d: cast(CardInfo, d["data"]), default_on_error="") + data = await self._va_request( + CardAPI, headers={"Cookie": ck}, json={"uuid": uid, "jump_key": "mine"} + ) + return self._parse_response( + data, lambda d: cast(CardInfo, d["data"]), default_on_error="" + ) async def get_detail_card( - self, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[Battle], int]: """获取详细卡片""" request = ApiRequest(url=ValCardAPI, json={"scene": scene}) @@ -290,7 +312,11 @@ async def get_detail_card( ) async def get_online( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[CardOnline, int]: """获取在线信息""" request = ApiRequest(url=OnlineAPI, json={"uuid": uid, "scene": scene}) @@ -302,7 +328,11 @@ async def get_online( ) async def get_gun( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[GunInfo], int]: """获取枪械信息""" request = ApiRequest( @@ -317,7 +347,11 @@ async def get_gun( ) async def get_map( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[MapInfo], int]: """获取地图信息""" request = ApiRequest( @@ -332,7 +366,11 @@ async def get_map( ) async def get_vive( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[Vive], int]: """获取 Vive 信息""" request = ApiRequest(url=ViveAPI, json={"scene": scene}) @@ -344,7 +382,11 @@ async def get_vive( ) async def get_pf( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[PFInfo], int]: """获取 PF 信息""" request = ApiRequest( @@ -359,7 +401,11 @@ async def get_pf( ) async def get_shop( - self, uid: str, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + uid: str, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[List[Shop], int]: """获取商店信息""" request = ApiRequest( @@ -379,7 +425,10 @@ async def get_shop( ) async def get_asset( - self, scene: str, cookie: Optional[str] = None, random_cookie: Optional[str] = None + self, + scene: str, + cookie: Optional[str] = None, + random_cookie: Optional[str] = None, ) -> Union[AssetData, int]: """获取资产信息""" request = ApiRequest( diff --git a/VAUID/va_info/utils.py b/VAUID/va_info/utils.py index 0726841..196d183 100644 --- a/VAUID/va_info/utils.py +++ b/VAUID/va_info/utils.py @@ -94,7 +94,9 @@ async def draw_hero_section(left_bg: Image.Image, hero: List[PFInfo]): hero_tasks = [save_img(one_hero["image_url"], "hero2") for one_hero in hero[:3]] hero_images = await asyncio.gather(*hero_tasks) - for index, (one_hero, hero_img) in enumerate(zip(hero[:3], hero_images), start=1): + for index, (one_hero, hero_img) in enumerate( + zip(hero[:3], hero_images), start=1 + ): hero_one = Image.new("RGBA", (700, 70), (0, 0, 0, 0)) # 创建圆角头像背景 @@ -131,7 +133,9 @@ async def draw_weapon_section(left_bg: Image.Image, gun: List[GunInfo]): weapon_tasks = [save_img(one_gun["image_url"], "weapon") for one_gun in gun[:8]] weapon_images = await asyncio.gather(*weapon_tasks) - for index, (one_gun, one_weapon) in enumerate(zip(gun[:8], weapon_images), start=1): + for index, (one_gun, one_weapon) in enumerate( + zip(gun[:8], weapon_images), start=1 + ): weapon_bg = get_cached_texture("weapon.png") weapon_draw = ImageDraw.Draw(weapon_bg) @@ -178,7 +182,9 @@ async def draw_weapon_section(left_bg: Image.Image, gun: List[GunInfo]): easy_paste(left_bg, weapon_bg, (weapon_x, weapon_y), "lt") @staticmethod - def draw_vive_section(right_bg: Image.Image, right_draw: ImageDrawType, vive: List[Vive]): + def draw_vive_section( + right_bg: Image.Image, right_draw: ImageDrawType, vive: List[Vive] + ): """绘制射击数据部分""" if vive is None: return @@ -187,7 +193,9 @@ def draw_vive_section(right_bg: Image.Image, right_draw: ImageDrawType, vive: Li positions = [(370, 45), (370, 120), (370, 195)] for data, pos in zip(shooting_data[:3], positions): - right_draw.text(pos, data["content"], (255, 255, 255, 255), va_font_30, "mm") + right_draw.text( + pos, data["content"], (255, 255, 255, 255), va_font_30, "mm" + ) right_draw.text( (pos[0] + 280, pos[1]), data["sub_content"], @@ -223,11 +231,13 @@ async def draw_battle_section( "失败": "head_icon_fail", "平局": "head_icon_draw", } - icon_key: Literal["head_icon_win", "head_icon_fail", "head_icon_draw"] = icon_key_map.get( - battle["result_title"], "head_icon_draw" - ) + icon_key: Literal[ + "head_icon_win", "head_icon_fail", "head_icon_draw" + ] = icon_key_map.get(battle["result_title"], "head_icon_draw") if icon_key in battle["score_level"]: - image_tasks.append(save_img(battle["score_level"][icon_key], "rank")) + image_tasks.append( + save_img(battle["score_level"][icon_key], "rank") + ) if battle.get("achievement"): for ach in battle["achievement"]: image_tasks.append(save_img(ach["icon"], "icon")) @@ -243,7 +253,9 @@ async def draw_battle_section( "胜利": ("win", "green_head.png"), "失败": ("fail", "red_head.png"), } - result, head_file = result_map.get(one_valcard["result_title"], ("draw", "grey_head.png")) + result, head_file = result_map.get( + one_valcard["result_title"], ("draw", "grey_head.png") + ) head2_bg = get_cached_texture(head_file) result_color = one_valcard["result_color"] @@ -307,7 +319,9 @@ async def draw_battle_section( radius=15, fill=hex_to_rgba(score_color, alpha=255), ) - score_draw.text((40, 20), one_valcard["score"], "white", va_font_20, "mm") + score_draw.text( + (40, 20), one_valcard["score"], "white", va_font_20, "mm" + ) easy_paste(battle_bg, score_bg, (610, 25), "lt") if one_valcard["is_friend"] == 1: @@ -349,8 +363,12 @@ def draw_hexagonal_panel( # 角度:270°, 210°, 150°, 90°, 30°, 330° hexagon_points = [ ( - center_x + (proportion_array[i] / 100 * 200) * math.cos(-math.pi / 2 - math.pi / 3 * i), - center_y + (proportion_array[i] / 100 * 200) * math.sin(-math.pi / 2 - math.pi / 3 * i), + center_x + + (proportion_array[i] / 100 * 200) + * math.cos(-math.pi / 2 - math.pi / 3 * i), + center_y + + (proportion_array[i] / 100 * 200) + * math.sin(-math.pi / 2 - math.pi / 3 * i), ) for i in range(6) ] diff --git a/VAUID/va_info/va_info.py b/VAUID/va_info/va_info.py index 5818058..e764be3 100644 --- a/VAUID/va_info/va_info.py +++ b/VAUID/va_info/va_info.py @@ -74,7 +74,9 @@ async def get_va_info_img(ev: Event, uid: str) -> Union[str, bytes]: online: Optional[CardOnline] = None if isinstance(online_raw, (int, BaseException)): - logger.error(f"online error: {get_error(online_raw) if isinstance(online_raw, int) else online_raw}") + logger.error( + f"online error: {get_error(online_raw) if isinstance(online_raw, int) else online_raw}" + ) else: online = online_raw @@ -156,7 +158,9 @@ async def draw_va_info_img( # 在线状态 if online is not None and online.get("online_text"): - online_filename = "online.png" if "在线" in online["online_text"] else "offline.png" + online_filename = ( + "online.png" if "在线" in online["online_text"] else "offline.png" + ) online_img = get_cached_texture(f"online/{online_filename}") easy_paste(img, online_img, (180, 190), direction="cc") @@ -167,7 +171,9 @@ async def draw_va_info_img( # 文字信息 img_draw.text((240, 60), detail["nickName"], (255, 255, 255, 255), va_font_42) img_draw.text((240, 120), card_info["name"], (200, 200, 200, 255), va_font_30) - img_draw.text((240, 160), f"UID {detail['appNum']}", (200, 200, 200, 255), va_font_20) + img_draw.text( + (240, 160), f"UID {detail['appNum']}", (200, 200, 200, 255), va_font_20 + ) # === 综合信息 === rank_bg = images["bg"] @@ -261,7 +267,9 @@ def draw_stat(x: int, y: int, value: str, label: str): (590, 210), # 右上 ] - for pos, (six_val, p_six_val) in zip(data_positions, zip(six_info["data_array"], p_six_info["data_array"])): + for pos, (six_val, p_six_val) in zip( + data_positions, zip(six_info["data_array"], p_six_info["data_array"]) + ): # 计算从中心到标签位置的方向向量 dx = pos[0] - center_x dy = pos[1] - center_y @@ -269,7 +277,9 @@ def draw_stat(x: int, y: int, value: str, label: str): # 向外移动 20 像素 new_x = pos[0] + (dx / distance) * 20 new_y = pos[1] + (dy / distance) * 20 - draw_base.text((new_x, new_y), f"{p_six_val} | {six_val}", "white", va_font_20, "mm") + draw_base.text( + (new_x, new_y), f"{p_six_val} | {six_val}", "white", va_font_20, "mm" + ) draw_base.text((465, 628), six_info["sub_tab_name"], "white", va_font_30, "mm") @@ -359,7 +369,13 @@ async def draw_asset_section( # 绘制物品名称 item_name = item.get(name_key, "未知物品") - img_draw.text((x + 50, y + size[1] + 40), item_name, (255, 255, 255, 255), va_font_20, "mm") + img_draw.text( + (x + 50, y + size[1] + 40), + item_name, + (255, 255, 255, 255), + va_font_20, + "mm", + ) y_offset += section_bottom_offset return y_offset @@ -422,7 +438,9 @@ async def get_va_asset_img(ev: Event, uid: str) -> Union[str, bytes]: # 文字信息 img_draw.text((240, 60), detail["nickName"], (255, 255, 255, 255), va_font_42) # img_draw.text((240, 120), detail["gameInfoList"][0][], (200, 200, 200, 255), va_font_30) - img_draw.text((240, 160), f"UID {detail['appNum']}", (200, 200, 200, 255), va_font_20) + img_draw.text( + (240, 160), f"UID {detail['appNum']}", (200, 200, 200, 255), va_font_20 + ) # 绘制各分类 y_offset = 100 @@ -431,35 +449,67 @@ async def get_va_asset_img(ev: Event, uid: str) -> Union[str, bytes]: skin_data = asset_data.get("skin", {}) if skin_data: y_offset = await draw_asset_section( - img, img_draw, skin_data, "皮肤", y_offset, icon_key="icon", name_key="name", size=(180, 80) + img, + img_draw, + skin_data, + "皮肤", + y_offset, + icon_key="icon", + name_key="name", + size=(180, 80), ) # 2. 英雄 (Agent) agent_data = asset_data.get("agent", {}) if agent_data: y_offset = await draw_asset_section( - img, img_draw, agent_data, "英雄", y_offset, icon_key="icon", name_key="name" + img, + img_draw, + agent_data, + "英雄", + y_offset, + icon_key="icon", + name_key="name", ) # 3. 喷漆 (Spray) spray_data = asset_data.get("spray", {}) if spray_data: y_offset = await draw_asset_section( - img, img_draw, spray_data, "喷漆", y_offset, icon_key="icon", name_key="name" + img, + img_draw, + spray_data, + "喷漆", + y_offset, + icon_key="icon", + name_key="name", ) # 4. 卡面 (Card) card_data = asset_data.get("card", {}) if card_data: y_offset = await draw_asset_section( - img, img_draw, card_data, "卡面", y_offset, icon_key="icon", name_key="name", size=(80, 150) + img, + img_draw, + card_data, + "卡面", + y_offset, + icon_key="icon", + name_key="name", + size=(80, 150), ) # 5. 挂饰 (Charm) charm_data = asset_data.get("charm", {}) if charm_data: y_offset = await draw_asset_section( - img, img_draw, charm_data, "挂饰", y_offset + 50, icon_key="icon", name_key="name" + img, + img_draw, + charm_data, + "挂饰", + y_offset + 50, + icon_key="icon", + name_key="name", ) return await convert_img(img) diff --git a/VAUID/va_user/__init__.py b/VAUID/va_user/__init__.py index f8e1690..0ebc381 100644 --- a/VAUID/va_user/__init__.py +++ b/VAUID/va_user/__init__.py @@ -52,7 +52,9 @@ async def on_valo_login(bot: Bot, ev: Event): 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" async with async_playwright() as p: - browser = await p.chromium.launch(headless=True, args=["--no-sandbox", "--disable-setuid-sandbox"]) + browser = await p.chromium.launch( + headless=True, args=["--no-sandbox", "--disable-setuid-sandbox"] + ) context = await browser.new_context( user_agent=( "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) " @@ -85,7 +87,9 @@ async def handle_response(response): login_temp_data["openid"] = openid login_temp_data["access_token"] = access_token login_temp_data["appid"] = appid - logger.info(f"[Val] 成功解析凭证: OpenID={openid[:5]}..., Token={access_token[:5]}...") + logger.info( + f"[Val] 成功解析凭证: OpenID={openid[:5]}..., Token={access_token[:5]}..." + ) login_success_event.set() else: logger.error(f"[Val] 解析失败,URL内容: {fragment}") @@ -120,7 +124,9 @@ async def handle_response(response): await browser.close() # 获取信息 - final_info = await exchange_val_token(login_temp_data["openid"], login_temp_data["access_token"]) + final_info = await exchange_val_token( + login_temp_data["openid"], login_temp_data["access_token"] + ) if not final_info: return await bot.send("获取游戏凭证失败,请重试。") uid = final_info["userId"] @@ -144,7 +150,9 @@ async def handle_response(response): cookie=cookie_str, uid=uid, ) - data = await ValBind.insert_uid(ev.user_id, ev.bot_id, uid, ev.group_id, is_digit=False) + data = await ValBind.insert_uid( + ev.user_id, ev.bot_id, uid, ev.group_id, is_digit=False + ) return await send_diff_msg( bot, data, @@ -182,8 +190,12 @@ async def send_va_bind_uid_msg(bot: Bot, ev: Event): if "绑定" in ev.command: if not uid: - return await bot.send("该命令需要带上正确的uid!\n如果不知道, 可以使用va搜索命令查询\n如 va搜索爱丽数码") - data = await ValBind.insert_uid(qid, ev.bot_id, uid, ev.group_id, is_digit=False) + return await bot.send( + "该命令需要带上正确的uid!\n如果不知道, 可以使用va搜索命令查询\n如 va搜索爱丽数码" + ) + data = await ValBind.insert_uid( + qid, ev.bot_id, uid, ev.group_id, is_digit=False + ) return await send_diff_msg( bot, data, @@ -221,13 +233,18 @@ async def send_va_search_msg(bot: Bot, ev: Event): players = await search_player_with_name(name) print(players) if not players or players == 8000004: - return await bot.send("未找到用户!\n请确认名称是否完整, 以及无畏契约设置是否允许他人搜索!") + return await bot.send( + "未找到用户!\n请确认名称是否完整, 以及无畏契约设置是否允许他人搜索!" + ) if isinstance(players, int): buttons = None im = get_error(players) await bot.send_option(im, buttons) else: - buttons = [Button(f"✏️绑定{one_player['userId']}", f"va绑定{one_player['userId']}") for one_player in players] + buttons = [ + Button(f"✏️绑定{one_player['userId']}", f"va绑定{one_player['userId']}") + for one_player in players + ] out_msg = [] for one_player in players: out_msg.append( diff --git a/VAUID/va_user/login.py b/VAUID/va_user/login.py index b18a5f1..d2a9e0d 100644 --- a/VAUID/va_user/login.py +++ b/VAUID/va_user/login.py @@ -4,7 +4,9 @@ from gsuid_core.logger import logger -MVAL_API = "https://app.mval.qq.com/go/auth/login_by_qq?source_game_zone=agame&game_zone=agame" +MVAL_API = ( + "https://app.mval.qq.com/go/auth/login_by_qq?source_game_zone=agame&game_zone=agame" +) async def exchange_val_token(openid: str, access_token: str) -> Optional[Dict]: