import httpx import re from typing import Any, Dict, Optional from .get_bf6_data import * from .tracker_data import * async def get_data_bf3(player, player_id, user_id, platform): url = f"https://api.gametools.network/bf3/all/?format_values=true&playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false&lang=en-us" url = f"https://api.gametools.network/bf3/all/?format_values=true&name={player}&platform={platform}&skip_battlelog=false&lang=en-us" async with httpx.AsyncClient(timeout=10.0) as client: # 创建两个并发任务 task_id = asyncio.create_task(client.get(url_by_id)) task_name = asyncio.create_task(client.get(url_by_name)) # 等待第一个完成的任务 done, pending = await asyncio.wait( [task_id, task_name], return_when=asyncio.FIRST_COMPLETED ) # 取消未完成的任务 for task in pending: task.cancel() # 检查已完成的任务是否成功且无 errors for task in done: try: response = await task if response.status_code == 200: data = response.json() if 'errors' not in data: logger.info(f"成功获取数据({'ID' if task is task_id else 'Name'}方式)") return data except (httpx.RequestError, ValueError) as e: logger.warning(f"请求或解析失败: {e}") if pending: pass # 如果所有尝试都失败,返回错误 return {"errors": ["未找到玩家"]} async def get_data_bf4(player, player_id, user_id, platform): url_by_id = f"https://api.gametools.network/bf4/all/?format_values=true&playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false&lang=en-us" url_by_name = f"https://api.gametools.network/bf4/all/?format_values=true&name={player}&platform={platform}&skip_battlelog=false&lang=en-us" async with httpx.AsyncClient(timeout=10.0) as client: # 创建两个并发任务 task_id = asyncio.create_task(client.get(url_by_id)) task_name = asyncio.create_task(client.get(url_by_name)) # 等待第一个完成的任务 done, pending = await asyncio.wait( [task_id, task_name], return_when=asyncio.FIRST_COMPLETED ) # 取消未完成的任务 for task in pending: task.cancel() # 检查已完成的任务是否成功且无 errors for task in done: try: response = await task if response.status_code == 200: data = response.json() if 'errors' not in data: logger.info(f"成功获取数据({'ID' if task is task_id else 'Name'}方式)") return data except (httpx.RequestError, ValueError) as e: logger.warning(f"请求或解析失败: {e}") if pending: pass # 如果所有尝试都失败,返回错误 return {"errors": ["未找到玩家"]} async def get_data_bf1(player, player_id, user_id, platform): url_by_id = f"https://api.gametools.network/bf1/all/?format_values=true&playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false&lang=en-us" url_by_name = f"https://api.gametools.network/bf1/all/?format_values=true&name={player}&platform={platform}&skip_battlelog=false&lang=en-us" async with httpx.AsyncClient(timeout=10.0) as client: # 创建两个并发任务 task_id = asyncio.create_task(client.get(url_by_id)) task_name = asyncio.create_task(client.get(url_by_name)) # 等待第一个完成的任务 done, pending = await asyncio.wait( [task_id, task_name], return_when=asyncio.FIRST_COMPLETED ) # 取消未完成的任务 for task in pending: task.cancel() # 检查已完成的任务是否成功且无 errors for task in done: try: response = await task if response.status_code == 200: data = response.json() if 'errors' not in data: logger.info(f"成功获取数据({'ID' if task is task_id else 'Name'}方式)") return data except (httpx.RequestError, ValueError) as e: logger.warning(f"请求或解析失败: {e}") if pending: pass # 如果所有尝试都失败,返回错误 return {"errors": ["未找到玩家"]} async def get_data_bfv(player, player_id, user_id, platform): url_by_id = f"https://api.gametools.network/bfv/all/?format_values=true&playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false&lang=en-us" url_by_name = f"https://api.gametools.network/bfv/all/?format_values=true&name={player}&platform={platform}&skip_battlelog=false&lang=en-us" async with httpx.AsyncClient(timeout=10.0) as client: # 创建两个并发任务 task_id = asyncio.create_task(client.get(url_by_id)) task_name = asyncio.create_task(client.get(url_by_name)) # 等待第一个完成的任务 done, pending = await asyncio.wait( [task_id, task_name], return_when=asyncio.FIRST_COMPLETED ) # 取消未完成的任务 for task in pending: task.cancel() # 检查已完成的任务是否成功且无 errors for task in done: try: response = await task if response.status_code == 200: data = response.json() if 'errors' not in data: logger.info(f"成功获取数据({'ID' if task is task_id else 'Name'}方式)") return data except (httpx.RequestError, ValueError) as e: logger.warning(f"请求或解析失败: {e}") if pending: pass # 如果所有尝试都失败,返回错误 return {"errors": ["未找到玩家"]} async def get_data_bf6(player_name, player_id, user_id, platform): # 构造两个 URL url_by_id = f"https://api.gametools.network/bf6/all/?format_values=true&playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false&lang=en-us" url_by_name = f"https://api.gametools.network/bf6/all/?format_values=true&name={player_name}&platform={platform}&skip_battlelog=false&lang=en-us" async with httpx.AsyncClient(timeout=10.0) as client: # 创建两个并发任务 task_id = asyncio.create_task(client.get(url_by_id)) task_name = asyncio.create_task(client.get(url_by_name)) # 等待第一个完成的任务 done, pending = await asyncio.wait( [task_id, task_name], return_when=asyncio.FIRST_COMPLETED ) # 取消未完成的任务 for task in pending: task.cancel() # 检查已完成的任务是否成功且无 errors for task in done: try: response = await task if response.status_code == 200: data = response.json() if 'errors' not in data: logger.info(f"成功获取数据({'ID' if task is task_id else 'Name'}方式)") return data except (httpx.RequestError, ValueError) as e: logger.warning(f"请求或解析失败: {e}") if pending: pass # 如果所有尝试都失败,返回错误 return {"errors": ["未找到玩家"]} async def get_player_info_by_name(user_name, platform): user_info_url = f"https://api.gametools.network/bfglobal/player/?name={user_name}&platform={platform}&skip_battlelog=false" payload = {} headers = { 'accept': 'application/json' } logger.info(f"查询用户请求url:{user_info_url}") response = requests.request("GET", user_info_url, headers=headers, data=payload) user_info_json = json.loads(response.text) return user_info_json async def get_player_info_by_ea_id(player_id, user_id, platform): url = f"https://api.gametools.network/bfglobal/player/?playerid={player_id}&oid={user_id}&platform={platform}&skip_battlelog=false" payload = {} headers = { 'accept': 'application/json' } response = requests.request("GET", url, headers=headers, data=payload) user_info_json = json.loads(response.text) return user_info_json def normalize_name(name: str) -> str: """统一用户名格式(大小写 + 空格)""" return (name or "").strip().lower() def extract_rank(status: str) -> int: """从 status 中提取 Rank 数值""" if not status: return 0 match = re.search(r'Rank\s+(\d+)', status) return int(match.group(1)) if match else 0 async def get_bf6_rank(player,player_id, user_id, platform): url_by_name = f"https://api.gametools.network/bf6/profile/?name={player}&playerid=1234&nucleus_id=1234&platform=ea&skip_battlelog=true&lang=en-us" url_by_id = f"https://api.gametools.network/bf6/profile/?name={player}&playerid=1234&nucleus_id=1234&platform=ea&skip_battlelog=true&lang=en-us" payload = {} headers = { 'accept': 'application/json' } response = requests.request("GET", url, headers=headers, data=payload) result: Dict[str, Any] = response.json().get("playerProfiles") logger.info(f"Tracker用户信息:{result}") if not result or "errors" in result: logger.warning(f"查询失败或返回错误: {player}") return 0 data = result.get("data") or [] if not data: logger.info(f"未搜索到用户: {player}") return 0 norm_player = normalize_name(player) # 评分函数(核心策略) def score(r: Dict[str, Any]) -> int: if not r or not r.get("status"): return -1 name = normalize_name(r.get("platformUserHandle")) platform = r.get("platformSlug") s = 0 # 用户名匹配权重(最高优先级) if name == norm_player: s += 100 elif norm_player in name: s += 50 # 平台权重(次优先级) if platform == "origin": s += 20 return s # 选出最优 candidate target: Optional[Dict[str, Any]] = max(data, key=score, default=None) if not target or score(target) <= 0: logger.info(f"未匹配到有效用户: {player}") return 0 # 提取信息 name = target.get("platformUserHandle") uid = target.get("titleUserId") status = target.get("status", "") rank = extract_rank(status) user_info = { "name": name, "uid": uid, "rank": rank, "platform": target.get("platformSlug"), } logger.info(f"最终匹配用户: {user_info}") return rank