from typing import Optional, List, Dict, Union from .draw_image import init_image, get_genshin_image from nonebot.adapters.onebot.v11 import MessageSegment from .._utils import get_ds, element_mastery from services.log import logger from utils.http_utils import AsyncHttpx from configs.config import Config from .._models import Genshin try: import ujson as json except ModuleNotFoundError: import json async def query_role_data( user_id: int, uid: int, mys_id: Optional[str] = None, nickname: Optional[str] = None ) -> Optional[Union[MessageSegment, str]]: uid = str(uid) if uid[0] == "1" or uid[0] == "2": server_id = "cn_gf01" elif uid[0] == "5": server_id = "cn_qd01" else: return None return await get_image(user_id, uid, server_id, mys_id, nickname) async def get_image( user_id: int, uid: str, server_id: str, mys_id: Optional[str] = None, nickname: Optional[str] = None, ) -> Optional[Union[MessageSegment, str]]: """ 生成图片 :param user_id:用户qq :param uid: 用户uid :param server_id: 服务器 :param mys_id: 米游社id :param nickname: QQ昵称 :return: """ data, code = await get_info(uid, server_id) if code != 200: return data if data: char_data_list, role_data, world_data_dict, home_data_list = parsed_data(data) mys_data = await get_mys_data(uid, mys_id) if mys_data: nickname = None if char_data_list: char_detailed_data = await get_character( uid, [x["id"] for x in char_data_list], server_id ) _x = {} if char_detailed_data: for char in char_detailed_data["avatars"]: _x[char["name"]] = { "weapon": char["weapon"]["name"], "weapon_image": char["weapon"]["icon"], "level": char["weapon"]["level"], "affix_level": char["weapon"]["affix_level"], } await init_image(world_data_dict, char_data_list, _x, home_data_list) return await get_genshin_image( user_id, uid, char_data_list, role_data, world_data_dict, home_data_list, _x, mys_data, nickname, ) return "未找到用户数据..." # Github-@lulu666lulu https://github.com/Azure99/GenshinPlayerQuery/issues/20 """ {body:"",query:{"action_ticket": undefined, "game_biz": "hk4e_cn”}} 对应 https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_cn //查询米哈游账号下绑定的游戏(game_biz可留空) {body:"",query:{"uid": 12345(被查询账号米哈游uid)}} 对应 https://api-takumi.mihoyo.com/game_record/app/card/wapi/getGameRecordCard?uid= {body:"",query:{'role_id': '查询账号的uid(游戏里的)' ,'server': '游戏服务器'}} 对应 https://api-takumi.mihoyo.com/game_record/app/genshin/api/index?server= server信息 &role_id= 游戏uid {body:"",query:{'role_id': '查询账号的uid(游戏里的)' , 'schedule_type': 1(我这边只看到出现过1和2), 'server': 'cn_gf01'}} 对应 https://api-takumi.mihoyo.com/game_record/app/genshin/api/spiralAbyss?schedule_type=1&server= server信息 &role_id= 游戏uid {body:"",query:{game_id: 2(目前我知道有崩坏3是1原神是2)}} 对应 https://api-takumi.mihoyo.com/game_record/app/card/wapi/getAnnouncement?game_id= 这个是公告api b=body q=query 其中b只在post的时候有内容,q只在get的时候有内容 """ async def get_info(uid_: str, server_id: str) -> "Optional[Union[dict, str]], int": try: req = await AsyncHttpx.get( url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index?server={server_id}&role_id={uid_}", headers={ "Accept": "application/json, text/plain, */*", "DS": get_ds(f"role_id={uid_}&server={server_id}"), "Origin": "https://webstatic.mihoyo.com", "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"), "User-Agent": "Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0", "x-rpc-client_type": Config.get_config("genshin", "client_type"), "Referer": "https://webstatic.mihoyo.com/app/community-game-records/index.html?v=6", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,en-US;q=0.8", "X-Requested-With": "com.mihoyo.hyperion", "Cookie": await Genshin.get_user_cookie(int(uid_)) }, ) data = req.json() if data["message"] == "OK": return data["data"], 200 return data["message"], 999 except Exception as e: logger.error(f"访问失败,请重试! {type(e)}: {e}") return None, -1 async def get_character( uid: str, character_ids: List[str], server_id="cn_gf01" ) -> Optional[dict]: try: req = await AsyncHttpx.post( url="https://api-takumi.mihoyo.com/game_record/app/genshin/api/character", headers={ "Accept": "application/json, text/plain, */*", "DS": get_ds( "", { "character_ids": character_ids, "role_id": uid, "server": server_id, }, ), "Origin": "https://webstatic.mihoyo.com", "Cookie": await Genshin.get_user_cookie(int(uid)), "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"), "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1", "x-rpc-client_type": "5", "Referer": "https://webstatic.mihoyo.com/", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,en-US;q=0.8", "X-Requested-With": "com.mihoyo.hyperion", }, json={"character_ids": character_ids, "role_id": uid, "server": server_id}, ) data = req.json() if data["message"] == "OK": return data["data"] except Exception as e: logger.error(f"访问失败,请重试! {type(e)}: {e}") return None def parsed_data( data: dict, ) -> "Optional[List[Dict[str, str]]], Dict[str, str], Optional[List[Dict[str, str]]], Optional[List[Dict[str, str]]]": """ 解析数据 :param data: 数据 """ char_data_list = [] for char in data["avatars"]: _x = { "id": char["id"], "image": char["image"], "name": char["name"], "element": element_mastery[char["element"].lower()], "fetter": char["fetter"], "level": char["level"], "rarity": char["rarity"], "actived_constellation_num": char["actived_constellation_num"], } char_data_list.append(_x) role_data = { "active_day_number": data["stats"]["active_day_number"], # 活跃天数 "achievement_number": data["stats"]["achievement_number"], # 达成成就数量 "win_rate": data["stats"]["win_rate"], "anemoculus_number": data["stats"]["anemoculus_number"], # 风神瞳已收集 "geoculus_number": data["stats"]["geoculus_number"], # 岩神瞳已收集 "avatar_number": data["stats"]["avatar_number"], # 获得角色数量 "way_point_number": data["stats"]["way_point_number"], # 传送点已解锁 "domain_number": data["stats"]["domain_number"], # 秘境解锁数量 "spiral_abyss": data["stats"]["spiral_abyss"], # 深渊当期进度 "precious_chest_number": data["stats"]["precious_chest_number"], # 珍贵宝箱 "luxurious_chest_number": data["stats"]["luxurious_chest_number"], # 华丽宝箱 "exquisite_chest_number": data["stats"]["exquisite_chest_number"], # 精致宝箱 "magic_chest_number": data["stats"]["magic_chest_number"], # 奇馈宝箱 "common_chest_number": data["stats"]["common_chest_number"], # 普通宝箱 "electroculus_number": data["stats"]["electroculus_number"], # 雷神瞳已收集 } world_data_dict = {} for world in data["world_explorations"]: _x = { "level": world["level"], # 声望等级 "exploration_percentage": world["exploration_percentage"], # 探索进度 "image": world["icon"], "name": world["name"], "offerings": world["offerings"], "icon": world["icon"] } world_data_dict[world["name"]] = _x home_data_list = [] for home in data["homes"]: _x = { "level": home["level"], # 最大信任等级 "visit_num": home["visit_num"], # 最高历史访客数 "comfort_num": home["comfort_num"], # 最高洞天仙力 "item_num": home["item_num"], # 已获得摆件数量 "name": home["name"], "icon": home["icon"], "comfort_level_name": home["comfort_level_name"], "comfort_level_icon": home["comfort_level_icon"], } home_data_list.append(_x) return char_data_list, role_data, world_data_dict, home_data_list async def get_mys_data(uid: str, mys_id: Optional[str]) -> Optional[List[Dict]]: """ 获取用户米游社数据 :param uid: 原神uid :param mys_id: 米游社id """ if mys_id: try: req = await AsyncHttpx.get( url=f"https://api-takumi.mihoyo.com/game_record/card/wapi/getGameRecordCard?uid={mys_id}", headers={ "DS": get_ds(f"uid={mys_id}"), "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"), "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1", "x-rpc-client_type": "5", "Referer": "https://webstatic.mihoyo.com/", "Cookie": await Genshin.get_user_cookie(int(uid)) }, ) data = req.json() if data["message"] == "OK": return data["data"]["list"] except Exception as e: logger.error(f"访问失败,请重试! {type(e)}: {e}") return None