修改btr请求方法,增加单独调用方法,与发送请求解耦
This commit is contained in:
parent
9e60caaeeb
commit
1782190afa
@ -1,4 +1,4 @@
|
|||||||
# import time
|
import time
|
||||||
|
|
||||||
from nonebot import on_command, require
|
from nonebot import on_command, require
|
||||||
from nonebot.adapters import Message
|
from nonebot.adapters import Message
|
||||||
|
|||||||
@ -4,41 +4,29 @@ from pathlib import Path
|
|||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
from nonebot import logger
|
from nonebot import logger
|
||||||
from curl_cffi import AsyncSession, CurlError
|
from curl_cffi import AsyncSession, CurlError
|
||||||
|
import random
|
||||||
|
|
||||||
|
try:
|
||||||
|
import browser_cookie3
|
||||||
|
except ImportError:
|
||||||
|
browser_cookie3 = None # 可选,如果没安装则 fallback 到 cookies.txt
|
||||||
|
|
||||||
# ---------- 配置 ----------
|
# ---------- 配置 ----------
|
||||||
url_search = "https://api.tracker.gg/api/v2/bf6/standard/search?platform={platform}&query={name}"
|
|
||||||
url_overview = "https://api.tracker.gg/api/v2/bf6/standard/profile/ign/{param}"
|
|
||||||
file_path = os.path.dirname(__file__).replace("\\", "/")
|
file_path = os.path.dirname(__file__).replace("\\", "/")
|
||||||
exported_cookie_path = Path(f"{file_path}/cookies/tracker.txt") # 你导出的 cookies.txt
|
exported_cookie_path = Path(f"{file_path}/cookies/tracker.txt") # 你导出的 cookies.txt
|
||||||
CUSTOM_UA = """Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"""
|
CUSTOM_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
|
||||||
|
|
||||||
|
|
||||||
# 你从抓包复制下来的完整请求头(不需要改格式)
|
|
||||||
RAW_BROWSER_HEADERS = """
|
RAW_BROWSER_HEADERS = """
|
||||||
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
|
sec-ch-ua-platform: "Windows"
|
||||||
accept-encoding: gzip, deflate, br, zstd
|
|
||||||
accept-language: zh-CN,zh;q=0.9
|
|
||||||
cache-control: max-age=0
|
|
||||||
referer: https://account.tracker.gg/
|
|
||||||
sec-ch-ua: "Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"
|
sec-ch-ua: "Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"
|
||||||
sec-ch-ua-mobile: ?0
|
sec-ch-ua-mobile: ?0
|
||||||
sec-ch-ua-platform: "Windows"
|
|
||||||
sec-fetch-dest: document
|
|
||||||
sec-fetch-mode: navigate
|
|
||||||
sec-fetch-site: same-origin
|
|
||||||
sec-fetch-user: ?1
|
|
||||||
upgrade-insecure-requests: 1
|
|
||||||
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
|
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
|
||||||
""" # ← 这里可以直接粘贴你浏览器的 headers(不用转义)
|
"""
|
||||||
|
|
||||||
# =============================================================
|
# ======================
|
||||||
|
|
||||||
|
|
||||||
def parse_raw_headers(raw: str) -> Dict[str, str]:
|
def parse_raw_headers(raw: str) -> Dict[str, str]:
|
||||||
"""
|
|
||||||
将抓包的多行 headers 文本解析为 Python dict
|
|
||||||
自动去除 :authority、:method、:path、:scheme 等伪头
|
|
||||||
"""
|
|
||||||
headers = {}
|
headers = {}
|
||||||
skip_prefix = (":authority", ":method", ":path", ":scheme")
|
skip_prefix = (":authority", ":method", ":path", ":scheme")
|
||||||
for line in raw.strip().splitlines():
|
for line in raw.strip().splitlines():
|
||||||
@ -54,9 +42,6 @@ def parse_raw_headers(raw: str) -> Dict[str, str]:
|
|||||||
|
|
||||||
|
|
||||||
def load_cookies_from_txt(path: Path) -> List[Dict[str, str]]:
|
def load_cookies_from_txt(path: Path) -> List[Dict[str, str]]:
|
||||||
"""
|
|
||||||
从 cookies.txt 文件读取 cookies(支持 Netscape 格式 / name=value 格式)
|
|
||||||
"""
|
|
||||||
cookies = []
|
cookies = []
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
return cookies
|
return cookies
|
||||||
@ -74,6 +59,15 @@ def load_cookies_from_txt(path: Path) -> List[Dict[str, str]]:
|
|||||||
return cookies
|
return cookies
|
||||||
|
|
||||||
|
|
||||||
|
def load_browser_cookies(domain="tracker.gg") -> List[Dict[str, str]]:
|
||||||
|
if not browser_cookie3:
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
return [{"name": c.name, "value": c.value} for c in browser_cookie3.chrome(domain_name=domain)]
|
||||||
|
except Exception:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def build_cookie_header(cookies: List[Dict[str, str]]) -> str:
|
def build_cookie_header(cookies: List[Dict[str, str]]) -> str:
|
||||||
return "; ".join(f"{c['name']}={c['value']}" for c in cookies)
|
return "; ".join(f"{c['name']}={c['value']}" for c in cookies)
|
||||||
|
|
||||||
@ -83,27 +77,35 @@ def build_headers(
|
|||||||
cookies: Optional[List[Dict[str, str]]] = None,
|
cookies: Optional[List[Dict[str, str]]] = None,
|
||||||
ua_override: Optional[str] = None,
|
ua_override: Optional[str] = None,
|
||||||
) -> Dict[str, str]:
|
) -> Dict[str, str]:
|
||||||
"""
|
|
||||||
综合生成请求头:
|
|
||||||
1. 从 RAW_BROWSER_HEADERS 解析 headers
|
|
||||||
2. 若存在 cookies,则替换 cookie 字段
|
|
||||||
3. 若存在 ua_override,则覆盖 UA 字段
|
|
||||||
"""
|
|
||||||
headers = parse_raw_headers(raw_headers)
|
headers = parse_raw_headers(raw_headers)
|
||||||
|
|
||||||
|
# 强制改成 XHR 请求风格
|
||||||
|
headers.update({
|
||||||
|
"accept": "application/json, text/plain, */*",
|
||||||
|
"origin": "https://tracker.gg",
|
||||||
|
"referer": "https://tracker.gg/",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "same-site",
|
||||||
|
})
|
||||||
|
|
||||||
if cookies:
|
if cookies:
|
||||||
headers["cookie"] = build_cookie_header(cookies)
|
headers["cookie"] = build_cookie_header(cookies)
|
||||||
|
|
||||||
if ua_override:
|
if ua_override:
|
||||||
headers["user-agent"] = ua_override
|
headers["user-agent"] = ua_override
|
||||||
|
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
async def fetch_with_cookies(url: str, headers: dict, impersonate: str = "chrome110", timeout: int = 15):
|
async def fetch_with_cookies(url: str, headers: dict, impersonate: str = "chrome110", timeout: int = 15):
|
||||||
async with AsyncSession() as session:
|
async with AsyncSession() as session:
|
||||||
try:
|
try:
|
||||||
|
await asyncio.sleep(random.uniform(0.5, 1.2)) # 模拟浏览器请求间隔
|
||||||
response = await session.get(url, headers=headers, impersonate=impersonate, timeout=timeout)
|
response = await session.get(url, headers=headers, impersonate=impersonate, timeout=timeout)
|
||||||
|
|
||||||
|
# 重试一次,防止偶尔 CF 拦截
|
||||||
|
if getattr(response, "status_code", 0) in (403, 429):
|
||||||
|
await asyncio.sleep(2)
|
||||||
|
response = await session.get(url, headers=headers, impersonate=impersonate, timeout=timeout)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
except CurlError as e:
|
except CurlError as e:
|
||||||
return {"error": f"cURL 错误: {e}"}
|
return {"error": f"cURL 错误: {e}"}
|
||||||
@ -128,9 +130,13 @@ def is_challenge_response(resp) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
async def search_user_with_fallback(url: str):
|
async def search_user_with_fallback(url: str):
|
||||||
cookies = load_cookies_from_txt(exported_cookie_path)
|
# 1️⃣ 优先尝试浏览器 cookie
|
||||||
headers = build_headers(RAW_BROWSER_HEADERS, cookies=cookies, ua_override=CUSTOM_UA)
|
cookies = load_browser_cookies()
|
||||||
|
# 2️⃣ 如果浏览器 cookie 不存在,再 fallback 到 cookies.txt
|
||||||
|
if not cookies:
|
||||||
|
cookies = load_cookies_from_txt(exported_cookie_path)
|
||||||
|
|
||||||
|
headers = build_headers(RAW_BROWSER_HEADERS, cookies=cookies, ua_override=CUSTOM_UA)
|
||||||
logger.info(f"请求 URL: {url}")
|
logger.info(f"请求 URL: {url}")
|
||||||
logger.info(f"使用 headers 字段数: {len(headers)}")
|
logger.info(f"使用 headers 字段数: {len(headers)}")
|
||||||
|
|
||||||
@ -139,242 +145,9 @@ async def search_user_with_fallback(url: str):
|
|||||||
logger.warning("⚠️ Cloudflare 拦截或 cookies 失效。")
|
logger.warning("⚠️ Cloudflare 拦截或 cookies 失效。")
|
||||||
if isinstance(resp, dict):
|
if isinstance(resp, dict):
|
||||||
return resp
|
return resp
|
||||||
return {"status": resp.status_code, "preview": resp.text[:200]}
|
return {"status": getattr(resp, "status_code", None), "preview": getattr(resp, "text", "")[:200]}
|
||||||
else:
|
else:
|
||||||
logger.info("✅ 请求成功。")
|
logger.info("✅ 请求成功。")
|
||||||
return getattr(resp, "json", lambda: resp)() if hasattr(resp, "json") else resp
|
return getattr(resp, "json", lambda: resp)() if hasattr(resp, "json") else resp
|
||||||
|
|
||||||
|
|
||||||
async def format_data(response, search_type):
|
|
||||||
status = ""
|
|
||||||
|
|
||||||
platform_info = response['data']['platformInfo']
|
|
||||||
segments = response['data']['segments']
|
|
||||||
|
|
||||||
overview = ""
|
|
||||||
weapons = []
|
|
||||||
vehicles = []
|
|
||||||
gamemodes = []
|
|
||||||
gadgets = []
|
|
||||||
kits = []
|
|
||||||
maps = []
|
|
||||||
|
|
||||||
for segment in segments:
|
|
||||||
if segment['type'] == 'overview':
|
|
||||||
overview = segment
|
|
||||||
elif segment['type'] == 'weapon':
|
|
||||||
weapons.append(segment)
|
|
||||||
elif segment['type'] == 'vehicle':
|
|
||||||
vehicles.append(segment)
|
|
||||||
elif segment['type'] == 'gamemode':
|
|
||||||
gamemodes.append(segment)
|
|
||||||
elif segment['type'] == 'gadget':
|
|
||||||
gadgets.append(segment)
|
|
||||||
elif segment['type'] == 'kit':
|
|
||||||
kits.append(segment)
|
|
||||||
elif segment['type'] == 'level':
|
|
||||||
maps.append(segment)
|
|
||||||
if search_type == 0:
|
|
||||||
status = await get_overview(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps)
|
|
||||||
if search_type == 1:
|
|
||||||
status = await get_weapons(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps)
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
async def get_user_id_2_data(title_id, search_type):
|
|
||||||
url = url_overview.format(param=title_id)
|
|
||||||
info = await search_user_with_fallback(url)
|
|
||||||
info = await format_data(info, search_type)
|
|
||||||
return info
|
|
||||||
|
|
||||||
|
|
||||||
# 调用此方法获取格式化后的数据(调用此方法即可)
|
|
||||||
async def get_info(player, search_type):
|
|
||||||
# 先使用橘子搜索
|
|
||||||
url = url_search.format(platform="orign", name=player)
|
|
||||||
result = await search_user_with_fallback(url)
|
|
||||||
# 无结果再使用steam搜索
|
|
||||||
if "errors" in result:
|
|
||||||
url = url_search.format(platform="steam", name=player)
|
|
||||||
result = await search_user_with_fallback(url)
|
|
||||||
title_id_list = []
|
|
||||||
logger.warning(result)
|
|
||||||
if "errors" in result:
|
|
||||||
return 3, '查询异常'
|
|
||||||
for res in result['data']:
|
|
||||||
if res['status'] is not None:
|
|
||||||
name = res['platformUserHandle']
|
|
||||||
uid = res['titleUserId']
|
|
||||||
status = res['status'].strip().split('•', 1)[0].replace("Rank", "")
|
|
||||||
user = {
|
|
||||||
'name': name,
|
|
||||||
'rank': status,
|
|
||||||
'uid': uid,
|
|
||||||
}
|
|
||||||
title_id_list.append(user)
|
|
||||||
if len(title_id_list) > 1:
|
|
||||||
user_list = sorted(title_id_list, key=lambda k: k['rank'], reverse=True)
|
|
||||||
msg = '\n'.join(f'用户名:{info["name"]}-等级:{info["rank"]}-UID:{info["uid"]}\n' for info in user_list)
|
|
||||||
logger.info(f"检测到多个同名用户{msg}")
|
|
||||||
return 0, title_id_list
|
|
||||||
elif len(title_id_list) == 1:
|
|
||||||
logger.info(f"单用户{title_id_list}")
|
|
||||||
info = await get_user_id_2_data(title_id_list[0]['uid'], search_type)
|
|
||||||
return 1, info
|
|
||||||
else:
|
|
||||||
logger.info(f"未查询到用户")
|
|
||||||
return 2, '未查询到用户'
|
|
||||||
|
|
||||||
|
|
||||||
async def get_overview(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
|
||||||
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_weapon = {
|
|
||||||
"名称": top_kill_weapon['metadata']['name'],
|
|
||||||
"击杀": top_kill_weapon['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
|
||||||
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
|
||||||
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
|
||||||
}
|
|
||||||
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_vehicle = {
|
|
||||||
"名称": top_kill_vehicle['metadata']['name'],
|
|
||||||
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
|
||||||
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
|
||||||
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
|
||||||
|
|
||||||
}
|
|
||||||
shot_count = overview['stats']['shotsFired']['value']
|
|
||||||
hit_count = overview['stats']['shotsHit']['value']
|
|
||||||
logger.info(f"开火数:{shot_count}")
|
|
||||||
logger.info(f"命中数:{hit_count}")
|
|
||||||
acc = round((hit_count / shot_count) * 100, 2)
|
|
||||||
logger.info(f"命中率:{acc}%")
|
|
||||||
player_info = {
|
|
||||||
'玩家名称': platform_info['platformUserHandle'],
|
|
||||||
'游玩平台': platform_info['platformSlug'],
|
|
||||||
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
|
||||||
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
|
||||||
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
|
||||||
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
|
||||||
'对局得分': overview['stats']['score']['displayValue'],
|
|
||||||
'玩家K/D': overview['stats']['kdRatio']['value'],
|
|
||||||
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
|
||||||
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
|
||||||
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
|
||||||
'击杀总计': overview['stats']['kills']['displayValue'],
|
|
||||||
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
|
||||||
'游戏助攻': overview['stats']['assists']['displayValue'],
|
|
||||||
'救援数量': overview['stats']['revives']['displayValue'],
|
|
||||||
'最高连杀': overview['stats']['multiKills']['value'],
|
|
||||||
'命中率': f"{acc}%",
|
|
||||||
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
|
||||||
'最佳武器': best_weapon,
|
|
||||||
'最佳载具': best_vehicle,
|
|
||||||
}
|
|
||||||
return player_info
|
|
||||||
|
|
||||||
|
|
||||||
async def get_weapons(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
|
||||||
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_weapon = {
|
|
||||||
"名称": top_kill_weapon['metadata']['name'],
|
|
||||||
"击杀": top_kill_weapon['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
|
||||||
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
|
||||||
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
|
||||||
}
|
|
||||||
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_vehicle = {
|
|
||||||
"名称": top_kill_vehicle['metadata']['name'],
|
|
||||||
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
|
||||||
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
|
||||||
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
|
||||||
|
|
||||||
}
|
|
||||||
shot_count = overview['stats']['shotsFired']['value']
|
|
||||||
hit_count = overview['stats']['shotsHit']['value']
|
|
||||||
logger.info(f"开火数:{shot_count}")
|
|
||||||
logger.info(f"命中数:{hit_count}")
|
|
||||||
acc = round((hit_count / shot_count) * 100, 2)
|
|
||||||
logger.info(f"命中率:{acc}%")
|
|
||||||
player_info = {
|
|
||||||
'玩家名称': platform_info['platformUserHandle'],
|
|
||||||
'游玩平台': platform_info['platformSlug'],
|
|
||||||
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
|
||||||
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
|
||||||
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
|
||||||
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
|
||||||
'对局得分': overview['stats']['score']['displayValue'],
|
|
||||||
'玩家K/D': overview['stats']['kdRatio']['value'],
|
|
||||||
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
|
||||||
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
|
||||||
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
|
||||||
'击杀总计': overview['stats']['kills']['displayValue'],
|
|
||||||
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
|
||||||
'游戏助攻': overview['stats']['assists']['displayValue'],
|
|
||||||
'救援数量': overview['stats']['revives']['displayValue'],
|
|
||||||
'最高连杀': overview['stats']['multiKills']['value'],
|
|
||||||
'命中率': f"{acc}%",
|
|
||||||
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
|
||||||
'最佳武器': best_weapon,
|
|
||||||
'最佳载具': best_vehicle,
|
|
||||||
}
|
|
||||||
return player_info
|
|
||||||
|
|
||||||
|
|
||||||
async def get_vehicles(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
|
||||||
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_weapon = {
|
|
||||||
"名称": top_kill_weapon['metadata']['name'],
|
|
||||||
"击杀": top_kill_weapon['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
|
||||||
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
|
||||||
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
|
||||||
}
|
|
||||||
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
|
||||||
best_vehicle = {
|
|
||||||
"名称": top_kill_vehicle['metadata']['name'],
|
|
||||||
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
|
||||||
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
|
||||||
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
|
||||||
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
|
||||||
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
|
||||||
|
|
||||||
}
|
|
||||||
shot_count = overview['stats']['shotsFired']['value']
|
|
||||||
hit_count = overview['stats']['shotsHit']['value']
|
|
||||||
logger.info(f"开火数:{shot_count}")
|
|
||||||
logger.info(f"命中数:{hit_count}")
|
|
||||||
acc = round((hit_count / shot_count) * 100, 2)
|
|
||||||
logger.info(f"命中率:{acc}%")
|
|
||||||
player_info = {
|
|
||||||
'玩家名称': platform_info['platformUserHandle'],
|
|
||||||
'游玩平台': platform_info['platformSlug'],
|
|
||||||
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
|
||||||
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
|
||||||
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
|
||||||
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
|
||||||
'对局得分': overview['stats']['score']['displayValue'],
|
|
||||||
'玩家K/D': overview['stats']['kdRatio']['value'],
|
|
||||||
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
|
||||||
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
|
||||||
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
|
||||||
'击杀总计': overview['stats']['kills']['displayValue'],
|
|
||||||
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
|
||||||
'游戏助攻': overview['stats']['assists']['displayValue'],
|
|
||||||
'救援数量': overview['stats']['revives']['displayValue'],
|
|
||||||
'最高连杀': overview['stats']['multiKills']['value'],
|
|
||||||
'命中率': f"{acc}%",
|
|
||||||
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
|
||||||
'最佳武器': best_weapon,
|
|
||||||
'最佳载具': best_vehicle,
|
|
||||||
}
|
|
||||||
return player_info
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import json
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from .bf6_data import *
|
from .get_bf6_data import *
|
||||||
|
|
||||||
|
|
||||||
async def get_data_bf3(user_name, platform):
|
async def get_data_bf3(user_name, platform):
|
||||||
|
|||||||
247
src/plugins/bf_bot/get_bf6_data.py
Normal file
247
src/plugins/bf_bot/get_bf6_data.py
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Dict, Optional
|
||||||
|
from nonebot import logger
|
||||||
|
from curl_cffi import AsyncSession, CurlError
|
||||||
|
from .bf6_data import *
|
||||||
|
import json
|
||||||
|
|
||||||
|
url_search = "https://api.tracker.gg/api/v2/bf6/standard/search?platform={platform}&query={name}"
|
||||||
|
url_overview = "https://api.tracker.gg/api/v2/bf6/standard/profile/ign/{param}"
|
||||||
|
|
||||||
|
|
||||||
|
async def format_data(response, search_type):
|
||||||
|
status = ""
|
||||||
|
|
||||||
|
platform_info = response['data']['platformInfo']
|
||||||
|
segments = response['data']['segments']
|
||||||
|
|
||||||
|
overview = ""
|
||||||
|
weapons = []
|
||||||
|
vehicles = []
|
||||||
|
gamemodes = []
|
||||||
|
gadgets = []
|
||||||
|
kits = []
|
||||||
|
maps = []
|
||||||
|
|
||||||
|
for segment in segments:
|
||||||
|
if segment['type'] == 'overview':
|
||||||
|
overview = segment
|
||||||
|
elif segment['type'] == 'weapon':
|
||||||
|
weapons.append(segment)
|
||||||
|
elif segment['type'] == 'vehicle':
|
||||||
|
vehicles.append(segment)
|
||||||
|
elif segment['type'] == 'gamemode':
|
||||||
|
gamemodes.append(segment)
|
||||||
|
elif segment['type'] == 'gadget':
|
||||||
|
gadgets.append(segment)
|
||||||
|
elif segment['type'] == 'kit':
|
||||||
|
kits.append(segment)
|
||||||
|
elif segment['type'] == 'level':
|
||||||
|
maps.append(segment)
|
||||||
|
if search_type == 0:
|
||||||
|
status = await get_overview(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps)
|
||||||
|
if search_type == 1:
|
||||||
|
status = await get_weapons(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps)
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
async def get_user_id_2_data(title_id, search_type):
|
||||||
|
url = url_overview.format(param=title_id)
|
||||||
|
info = await search_user_with_fallback(url)
|
||||||
|
info = await format_data(info, search_type)
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
# 调用此方法获取格式化后的数据(调用此方法即可)
|
||||||
|
async def get_info(player, search_type):
|
||||||
|
# 先使用橘子搜索
|
||||||
|
url = url_search.format(platform="orign", name=player)
|
||||||
|
result = await search_user_with_fallback(url)
|
||||||
|
# 无结果再使用steam搜索
|
||||||
|
if "errors" in result:
|
||||||
|
url = url_search.format(platform="steam", name=player)
|
||||||
|
result = await search_user_with_fallback(url)
|
||||||
|
title_id_list = []
|
||||||
|
logger.info(f"查询结果: {json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||||
|
if "errors" in result:
|
||||||
|
return 3, '查询异常'
|
||||||
|
for res in result['data']:
|
||||||
|
if res['status'] is not None:
|
||||||
|
name = res['platformUserHandle']
|
||||||
|
uid = res['titleUserId']
|
||||||
|
status = res['status'].strip().split('•', 1)[0].replace("Rank", "")
|
||||||
|
user = {
|
||||||
|
'name': name,
|
||||||
|
'rank': status,
|
||||||
|
'uid': uid,
|
||||||
|
}
|
||||||
|
title_id_list.append(user)
|
||||||
|
if len(title_id_list) > 1:
|
||||||
|
user_list = sorted(title_id_list, key=lambda k: int(k['rank']), reverse=True)
|
||||||
|
msg = '\n'.join(f'用户名:{info["name"]}-等级:{info["rank"]}-UID:{info["uid"]}' for info in user_list)
|
||||||
|
logger.info(f"检测到多个同名用户\n{msg}")
|
||||||
|
return 0, title_id_list
|
||||||
|
elif len(title_id_list) == 1:
|
||||||
|
logger.info(f"单用户{title_id_list}")
|
||||||
|
info = await get_user_id_2_data(title_id_list[0]['uid'], search_type)
|
||||||
|
logger.info(f"查询结果: {json.dumps(info, ensure_ascii=False, indent=2)}")
|
||||||
|
return 1, info
|
||||||
|
else:
|
||||||
|
logger.info(f"未查询到用户")
|
||||||
|
return 2, '未查询到用户'
|
||||||
|
|
||||||
|
|
||||||
|
async def get_overview(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
||||||
|
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_weapon = {
|
||||||
|
"名称": top_kill_weapon['metadata']['name'],
|
||||||
|
"击杀": top_kill_weapon['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
||||||
|
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
||||||
|
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
||||||
|
}
|
||||||
|
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_vehicle = {
|
||||||
|
"名称": top_kill_vehicle['metadata']['name'],
|
||||||
|
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
||||||
|
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
||||||
|
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
||||||
|
|
||||||
|
}
|
||||||
|
shot_count = overview['stats']['shotsFired']['value']
|
||||||
|
hit_count = overview['stats']['shotsHit']['value']
|
||||||
|
logger.info(f"开火数:{shot_count}")
|
||||||
|
logger.info(f"命中数:{hit_count}")
|
||||||
|
acc = round((hit_count / shot_count) * 100, 2)
|
||||||
|
logger.info(f"命中率:{acc}%")
|
||||||
|
player_info = {
|
||||||
|
'玩家名称': platform_info['platformUserHandle'],
|
||||||
|
'游玩平台': platform_info['platformSlug'],
|
||||||
|
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
||||||
|
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
||||||
|
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
||||||
|
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
||||||
|
'对局得分': overview['stats']['score']['displayValue'],
|
||||||
|
'玩家K/D': overview['stats']['kdRatio']['value'],
|
||||||
|
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
||||||
|
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
||||||
|
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
||||||
|
'击杀总计': overview['stats']['kills']['displayValue'],
|
||||||
|
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
||||||
|
'游戏助攻': overview['stats']['assists']['displayValue'],
|
||||||
|
'救援数量': overview['stats']['revives']['displayValue'],
|
||||||
|
'最高连杀': overview['stats']['multiKills']['value'],
|
||||||
|
'命中率': f"{acc}%",
|
||||||
|
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
||||||
|
'最佳武器': best_weapon,
|
||||||
|
'最佳载具': best_vehicle,
|
||||||
|
}
|
||||||
|
return player_info
|
||||||
|
|
||||||
|
|
||||||
|
async def get_weapons(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
||||||
|
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_weapon = {
|
||||||
|
"名称": top_kill_weapon['metadata']['name'],
|
||||||
|
"击杀": top_kill_weapon['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
||||||
|
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
||||||
|
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
||||||
|
}
|
||||||
|
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_vehicle = {
|
||||||
|
"名称": top_kill_vehicle['metadata']['name'],
|
||||||
|
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
||||||
|
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
||||||
|
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
||||||
|
|
||||||
|
}
|
||||||
|
shot_count = overview['stats']['shotsFired']['value']
|
||||||
|
hit_count = overview['stats']['shotsHit']['value']
|
||||||
|
logger.info(f"开火数:{shot_count}")
|
||||||
|
logger.info(f"命中数:{hit_count}")
|
||||||
|
acc = round((hit_count / shot_count) * 100, 2)
|
||||||
|
logger.info(f"命中率:{acc}%")
|
||||||
|
player_info = {
|
||||||
|
'玩家名称': platform_info['platformUserHandle'],
|
||||||
|
'游玩平台': platform_info['platformSlug'],
|
||||||
|
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
||||||
|
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
||||||
|
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
||||||
|
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
||||||
|
'对局得分': overview['stats']['score']['displayValue'],
|
||||||
|
'玩家K/D': overview['stats']['kdRatio']['value'],
|
||||||
|
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
||||||
|
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
||||||
|
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
||||||
|
'击杀总计': overview['stats']['kills']['displayValue'],
|
||||||
|
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
||||||
|
'游戏助攻': overview['stats']['assists']['displayValue'],
|
||||||
|
'救援数量': overview['stats']['revives']['displayValue'],
|
||||||
|
'最高连杀': overview['stats']['multiKills']['value'],
|
||||||
|
'命中率': f"{acc}%",
|
||||||
|
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
||||||
|
'最佳武器': best_weapon,
|
||||||
|
'最佳载具': best_vehicle,
|
||||||
|
}
|
||||||
|
return player_info
|
||||||
|
|
||||||
|
|
||||||
|
async def get_vehicles(platform_info, overview, weapons, vehicles, gamemodes, gadgets, kits, maps):
|
||||||
|
top_kill_weapon = sorted(weapons, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_weapon = {
|
||||||
|
"名称": top_kill_weapon['metadata']['name'],
|
||||||
|
"击杀": top_kill_weapon['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_weapon['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_weapon['stats']['timePlayed']['displayValue'],
|
||||||
|
"爆头率": top_kill_weapon['stats']['headshotPercentage']['displayValue'],
|
||||||
|
"命中率": top_kill_weapon['stats']['shotsAccuracy']['displayValue']
|
||||||
|
}
|
||||||
|
top_kill_vehicle = sorted(vehicles, key=lambda k: k['stats']['kills']['value'], reverse=True)[0]
|
||||||
|
best_vehicle = {
|
||||||
|
"名称": top_kill_vehicle['metadata']['name'],
|
||||||
|
"击杀": top_kill_vehicle['stats']['kills']['value'],
|
||||||
|
"KPM": top_kill_vehicle['stats']['killsPerMinute']['value'],
|
||||||
|
"时长": top_kill_vehicle['stats']['timePlayed']['displayValue'],
|
||||||
|
"碾压": top_kill_vehicle['stats']['roadKills']['value'],
|
||||||
|
"摧毁": top_kill_vehicle['stats']['destroyedWith']['value'],
|
||||||
|
|
||||||
|
}
|
||||||
|
shot_count = overview['stats']['shotsFired']['value']
|
||||||
|
hit_count = overview['stats']['shotsHit']['value']
|
||||||
|
logger.info(f"开火数:{shot_count}")
|
||||||
|
logger.info(f"命中数:{hit_count}")
|
||||||
|
acc = round((hit_count / shot_count) * 100, 2)
|
||||||
|
logger.info(f"命中率:{acc}%")
|
||||||
|
player_info = {
|
||||||
|
'玩家名称': platform_info['platformUserHandle'],
|
||||||
|
'游玩平台': platform_info['platformSlug'],
|
||||||
|
'游戏等级': overview['stats']['careerPlayerRank']['displayValue'],
|
||||||
|
'游玩时长': overview['stats']['timePlayed']['displayValue'],
|
||||||
|
'游玩场次': overview['stats']['matchesPlayed']['displayValue'],
|
||||||
|
'对局胜率': overview['stats']['wlPercentage']['displayValue'],
|
||||||
|
'对局得分': overview['stats']['score']['displayValue'],
|
||||||
|
'玩家K/D': overview['stats']['kdRatio']['value'],
|
||||||
|
'玩家KPM': overview['stats']['killsPerMinute']['value'],
|
||||||
|
'玩家SPM': overview['stats']['scorePerMinute']['value'],
|
||||||
|
'真人击杀': overview['stats']['playerKills']['displayValue'],
|
||||||
|
'击杀总计': overview['stats']['kills']['displayValue'],
|
||||||
|
'目标占领': overview['stats']['objectivesCaptured']['value'],
|
||||||
|
'游戏助攻': overview['stats']['assists']['displayValue'],
|
||||||
|
'救援数量': overview['stats']['revives']['displayValue'],
|
||||||
|
'最高连杀': overview['stats']['multiKills']['value'],
|
||||||
|
'命中率': f"{acc}%",
|
||||||
|
'爆头率': overview['stats']['headshotPercentage']['displayValue'],
|
||||||
|
'最佳武器': best_weapon,
|
||||||
|
'最佳载具': best_vehicle,
|
||||||
|
}
|
||||||
|
return player_info
|
||||||
@ -1,5 +1,7 @@
|
|||||||
from bf6_data import *
|
from get_bf6_data import *
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
name = "A.R.O.N.A"
|
# name = "A.R.O.N.A"
|
||||||
|
name = "Dog"
|
||||||
|
|
||||||
asyncio.run(get_info(name, 0))
|
asyncio.run(get_info(name, 0))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user