mirror of
https://github.com/Ahrimdon/detailed-cod-tracker.git
synced 2024-11-03 16:46:44 -05:00
Merge branch develop into main
This commit is contained in:
commit
e1d5abea1b
15
README.md
15
README.md
@ -67,7 +67,7 @@ If done correctly, this should return the extra API information.
|
|||||||
|
|
||||||
## Command Line Arguments
|
## Command Line Arguments
|
||||||
```
|
```
|
||||||
usage: get_cod_stats.py [-h] -p PLAYER_NAME [-a] [-sl] [-i] [-m] [-c] [-sm] [-csd] [-cmd]
|
usage: get_cod_stats.py [-h] [-p PLAYER_NAME] [-a] [-sl] [-id] [-m] [-i] [-f] [-e] [-cp] [-ca] [-s] [-c] [-sm] [-csd] [-cmd] [-cff] [-cef]
|
||||||
|
|
||||||
Detailed Modern Warfare (2019) Statistics Tool
|
Detailed Modern Warfare (2019) Statistics Tool
|
||||||
|
|
||||||
@ -79,8 +79,15 @@ Data Fetching Options:
|
|||||||
Player's username (with #1234567)
|
Player's username (with #1234567)
|
||||||
-a, --all_stats Fetch all the different types of stats data
|
-a, --all_stats Fetch all the different types of stats data
|
||||||
-sl, --season_loot Fetch only the season loot data
|
-sl, --season_loot Fetch only the season loot data
|
||||||
-i, --identities Fetch only the logged-in identities data
|
-id, --identities Fetch only the logged-in identities data
|
||||||
-m, --maps Fetch only the map list data
|
-m, --maps Fetch only the map list data
|
||||||
|
-i, --info Fetch only general information
|
||||||
|
-f, --friendFeed Fetch only your friend feed
|
||||||
|
-e, --eventFeed Fetch only your event feed
|
||||||
|
-cp, --cod_points Fetch only your COD Point balance
|
||||||
|
-ca, --connected_accounts
|
||||||
|
Fetch only the map list data
|
||||||
|
-s, --settings Fetch only your account settings
|
||||||
|
|
||||||
Data Cleaning Options:
|
Data Cleaning Options:
|
||||||
-c, --clean Beautify all data
|
-c, --clean Beautify all data
|
||||||
@ -89,6 +96,10 @@ Data Cleaning Options:
|
|||||||
Beautify the data and convert to human-readable strings in stats.json
|
Beautify the data and convert to human-readable strings in stats.json
|
||||||
-cmd, --clean_match_data
|
-cmd, --clean_match_data
|
||||||
Beautify the match data and convert to human-readable strings in match_info.json
|
Beautify the match data and convert to human-readable strings in match_info.json
|
||||||
|
-cff, --clean_friend_feed
|
||||||
|
Clean the friend feed data
|
||||||
|
-cef, --clean_event_feed
|
||||||
|
Clean the event feed data
|
||||||
```
|
```
|
||||||
|
|
||||||
## Command Examples
|
## Command Examples
|
||||||
|
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
<span class="|</span>|">|mp-stat-items|kills-value|headshots-value|username|game-mode|kdr-value
|
|
@ -547,30 +547,28 @@ class API:
|
|||||||
class __USER(_Common):
|
class __USER(_Common):
|
||||||
def info(self):
|
def info(self):
|
||||||
if self.loggedIn:
|
if self.loggedIn:
|
||||||
# Assuming 'user_info.json' is the file you've downloaded with the information.
|
# Assuming 'user_info.json' is the file you've downloaded with the information
|
||||||
file_path = 'userInfo.json'
|
file_path = 'userInfo.json'
|
||||||
# Load the JSON content from the local file.
|
# Load the JSON content from the local file
|
||||||
with open(file_path, 'r') as file:
|
with open(file_path, 'r') as file:
|
||||||
rawData = json.load(file)
|
rawData = json.load(file)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
userInfo = rawData['userInfo'] # Accessing the nested 'userInfo' dictionary.
|
userInfo = rawData['userInfo'] # Accessing the nested 'userInfo' dictionary
|
||||||
identities = rawData.get('identities', []) # Accessing the 'identities' if it exists or default to empty list.
|
identities = rawData.get('identities', []) # Accessing the 'identities' if it exists or default to empty list
|
||||||
|
|
||||||
data = {'userName': userInfo['userName'], 'identities': []} # Getting 'userName' from the nested dictionary.
|
data = {'userName': userInfo['userName'], 'identities': []} # Getting 'userName' from the nested dictionary
|
||||||
for i in identities: # Loop through each identity in the 'identities' list.
|
for i in identities: # Loop through each identity in the 'identities' list
|
||||||
data['identities'].append({
|
data['identities'].append({
|
||||||
'platform': i['provider'],
|
'platform': i['provider'],
|
||||||
'gamertag': i['username'],
|
'gamertag': i['username'],
|
||||||
'accountID': i['accountID'] # Assuming 'accountID' exists; otherwise, you might need a default value.
|
'accountID': i['accountID'] # Assuming 'accountID' exists; otherwise, you might need a default value
|
||||||
})
|
})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
# Handle the case where the expected key is not found in the dictionary.
|
# Handle the case where the expected key is not found in the dictionary
|
||||||
print(f"Error: A required field is missing in the data. Details: {str(e)}")
|
print(f"Error: A required field is missing in the data. Details: {str(e)}")
|
||||||
# Re-raise the exception or handle it as required for your application's logic.
|
# Re-raise the exception or handle it as required
|
||||||
raise
|
raise
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
725
cod_api/__init__dev.py
Normal file
725
cod_api/__init__dev.py
Normal file
@ -0,0 +1,725 @@
|
|||||||
|
__version__ = "2.0.1"
|
||||||
|
|
||||||
|
# Imports
|
||||||
|
import asyncio
|
||||||
|
import enum
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
import os
|
||||||
|
from abc import abstractmethod
|
||||||
|
from datetime import datetime
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
import requests
|
||||||
|
from aiohttp import ClientResponseError
|
||||||
|
|
||||||
|
|
||||||
|
# Enums
|
||||||
|
|
||||||
|
class platforms(enum.Enum):
|
||||||
|
All = 'all'
|
||||||
|
Activision = 'acti'
|
||||||
|
Battlenet = 'battle'
|
||||||
|
PSN = 'psn'
|
||||||
|
Steam = 'steam'
|
||||||
|
Uno = 'uno'
|
||||||
|
XBOX = 'xbl'
|
||||||
|
|
||||||
|
|
||||||
|
class games(enum.Enum):
|
||||||
|
ColdWar = 'cw'
|
||||||
|
ModernWarfare = 'mw'
|
||||||
|
ModernWarfare2 = 'mw2'
|
||||||
|
Vanguard = 'vg'
|
||||||
|
Warzone = 'wz'
|
||||||
|
Warzone2 = 'wz2'
|
||||||
|
|
||||||
|
|
||||||
|
class friendActions(enum.Enum):
|
||||||
|
Invite = "invite"
|
||||||
|
Uninvite = "uninvite"
|
||||||
|
Remove = "remove"
|
||||||
|
Block = "block"
|
||||||
|
Unblock = "unblock"
|
||||||
|
|
||||||
|
|
||||||
|
class API:
|
||||||
|
"""
|
||||||
|
Call Of Duty API Wrapper
|
||||||
|
|
||||||
|
Developed by Todo Lodo & Engineer152
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
- Werseter
|
||||||
|
|
||||||
|
Source Code: https://github.com/TodoLodo/cod-python-api
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
# sub classes
|
||||||
|
self.Warzone = self.__WZ()
|
||||||
|
self.ModernWarfare = self.__MW()
|
||||||
|
self.Warzone2 = self.__WZ2()
|
||||||
|
self.ModernWarfare2 = self.__MW2()
|
||||||
|
self.ColdWar = self.__CW()
|
||||||
|
self.Vanguard = self.__VG()
|
||||||
|
self.Shop = self.__SHOP()
|
||||||
|
self.Me = self.__USER()
|
||||||
|
self.Misc = self.__ALT()
|
||||||
|
|
||||||
|
async def loginAsync(self, sso_token: str) -> None:
|
||||||
|
await API._Common.loginAsync(sso_token)
|
||||||
|
|
||||||
|
# Login
|
||||||
|
def login(self, ssoToken: str):
|
||||||
|
API._Common.login(ssoToken)
|
||||||
|
|
||||||
|
class _Common:
|
||||||
|
requestHeaders = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/74.0.3729.169 "
|
||||||
|
"Safari/537.36",
|
||||||
|
"Accept": "application/json",
|
||||||
|
"Connection": "Keep-Alive"
|
||||||
|
}
|
||||||
|
cookies = {"new_SiteId": "cod", "ACT_SSO_LOCALE": "en_US", "country": "US",
|
||||||
|
"ACT_SSO_COOKIE_EXPIRY": "1645556143194"}
|
||||||
|
cachedMappings = None
|
||||||
|
|
||||||
|
fakeXSRF = str(uuid.uuid4())
|
||||||
|
baseUrl: str = "https://my.callofduty.com/api/papi-client"
|
||||||
|
loggedIn: bool = False
|
||||||
|
|
||||||
|
# endPoints
|
||||||
|
|
||||||
|
# game platform lookupType gamertag type
|
||||||
|
fullDataUrl = "/stats/cod/v1/title/%s/platform/%s/%s/%s/profile/type/%s"
|
||||||
|
# game platform lookupType gamertag type start end [?limit=n or '']
|
||||||
|
combatHistoryUrl = "/crm/cod/v2/title/%s/platform/%s/%s/%s/matches/%s/start/%d/end/%d/details"
|
||||||
|
# game platform lookupType gamertag type start end
|
||||||
|
breakdownUrl = "/crm/cod/v2/title/%s/platform/%s/%s/%s/matches/%s/start/%d/end/%d"
|
||||||
|
# game platform lookupType gamertag
|
||||||
|
seasonLootUrl = "/loot/title/%s/platform/%s/%s/%s/status/en"
|
||||||
|
# game platform
|
||||||
|
mapListUrl = "/ce/v1/title/%s/platform/%s/gameType/mp/communityMapData/availability"
|
||||||
|
# game platform type matchId
|
||||||
|
matchInfoUrl = "/crm/cod/v2/title/%s/platform/%s/fullMatch/%s/%d/en"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def loginAsync(sso_token: str) -> None:
|
||||||
|
API._Common.cookies["ACT_SSO_COOKIE"] = sso_token
|
||||||
|
API._Common.baseSsoToken = sso_token
|
||||||
|
r = await API._Common.__Request(f"{API._Common.baseUrl}/crm/cod/v2/identities/{sso_token}")
|
||||||
|
if r['status'] == 'success':
|
||||||
|
API._Common.loggedIn = True
|
||||||
|
else:
|
||||||
|
raise InvalidToken(sso_token)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def login(sso_token: str) -> None:
|
||||||
|
API._Common.cookies["ACT_SSO_COOKIE"] = sso_token
|
||||||
|
API._Common.baseSsoToken = sso_token
|
||||||
|
|
||||||
|
r = requests.get(f"{API._Common.baseUrl}/crm/cod/v2/identities/{sso_token}",
|
||||||
|
headers=API._Common.requestHeaders, cookies=API._Common.cookies)
|
||||||
|
|
||||||
|
if r.json()['status'] == 'success':
|
||||||
|
API._Common.loggedIn = True
|
||||||
|
API._Common.cookies.update(r.cookies)
|
||||||
|
else:
|
||||||
|
raise InvalidToken(sso_token)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sso_token() -> str:
|
||||||
|
return API._Common.cookies["ACT_SSO_COOKIE"]
|
||||||
|
|
||||||
|
# Requests
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def __Request(url):
|
||||||
|
async with aiohttp.client.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=True),
|
||||||
|
timeout=aiohttp.ClientTimeout(total=30)) as session:
|
||||||
|
try:
|
||||||
|
async with session.get(url, cookies=API._Common.cookies,
|
||||||
|
headers=API._Common.requestHeaders) as resp:
|
||||||
|
try:
|
||||||
|
resp.raise_for_status()
|
||||||
|
except ClientResponseError as err:
|
||||||
|
return {'status': 'error', 'data': {'type': type(err), 'message': err.message}}
|
||||||
|
else:
|
||||||
|
API._Common.cookies.update({c.key: c.value for c in session.cookie_jar})
|
||||||
|
return await resp.json()
|
||||||
|
except asyncio.TimeoutError as err:
|
||||||
|
return {'status': 'error', 'data': {'type': type(err), 'message': str(err)}}
|
||||||
|
|
||||||
|
async def __sendRequest(self, url: str):
|
||||||
|
if self.loggedIn:
|
||||||
|
response = await API._Common.__Request(f"{self.baseUrl}{url}")
|
||||||
|
if response['status'] == 'success':
|
||||||
|
response['data'] = await self.__perform_mapping(response['data'])
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
raise NotLoggedIn
|
||||||
|
|
||||||
|
# client name url formatter
|
||||||
|
def __cleanClientName(self, gamertag):
|
||||||
|
return quote(gamertag.encode("utf-8"))
|
||||||
|
|
||||||
|
# helper
|
||||||
|
def __helper(self, platform, gamertag):
|
||||||
|
lookUpType = "gamer"
|
||||||
|
if platform == platforms.Uno:
|
||||||
|
lookUpType = "id"
|
||||||
|
if platform == platforms.Activision:
|
||||||
|
platform = platforms.Uno
|
||||||
|
if platform not in [platforms.Activision, platforms.Battlenet, platforms.Uno, platforms.All, platforms.PSN,
|
||||||
|
platforms.XBOX]:
|
||||||
|
raise InvalidPlatform(platform)
|
||||||
|
else:
|
||||||
|
gamertag = self.__cleanClientName(gamertag)
|
||||||
|
return lookUpType, gamertag, platform
|
||||||
|
|
||||||
|
async def __get_mappings(self):
|
||||||
|
if API._Common.cachedMappings is None:
|
||||||
|
API._Common.cachedMappings = (
|
||||||
|
await API._Common.__Request('https://engineer152.github.io/wz-data/weapon-ids.json'),
|
||||||
|
await API._Common.__Request('https://engineer152.github.io/wz-data/game-modes.json'),
|
||||||
|
await API._Common.__Request('https://engineer152.github.io/wz-data/perks.json'))
|
||||||
|
return API._Common.cachedMappings
|
||||||
|
|
||||||
|
# mapping
|
||||||
|
async def __perform_mapping(self, data):
|
||||||
|
guns, modes, perks = await self.__get_mappings()
|
||||||
|
if not isinstance(data, list) or 'matches' not in data:
|
||||||
|
return data
|
||||||
|
try:
|
||||||
|
for match in data['matches']:
|
||||||
|
# time stamps
|
||||||
|
try:
|
||||||
|
match['utcStartDateTime'] = datetime.fromtimestamp(
|
||||||
|
match['utcStartSeconds']).strftime("%A, %B %d, %Y, %I:%M:%S")
|
||||||
|
match['utcEndDateTime'] = datetime.fromtimestamp(
|
||||||
|
match['utcEndSeconds']).strftime("%A, %B %d, %Y, %I:%M:%S")
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# loadouts list
|
||||||
|
for loadout in match['player']['loadouts']:
|
||||||
|
# weapons
|
||||||
|
if loadout['primaryWeapon']['label'] is None:
|
||||||
|
try:
|
||||||
|
loadout['primaryWeapon']['label'] = guns[loadout['primaryWeapon']['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if loadout['secondaryWeapon']['label'] is None:
|
||||||
|
try:
|
||||||
|
loadout['secondaryWeapon']['label'] = guns[loadout['secondaryWeapon']['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# perks list
|
||||||
|
for perk in loadout['perks']:
|
||||||
|
if perk['label'] is None:
|
||||||
|
try:
|
||||||
|
perk['label'] = perks[perk['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# extra perks list
|
||||||
|
for perk in loadout['extraPerks']:
|
||||||
|
if perk['label'] is None:
|
||||||
|
try:
|
||||||
|
perk['label'] = perks[perk['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# loadout list
|
||||||
|
for loadout in match['player']['loadout']:
|
||||||
|
if loadout['primaryWeapon']['label'] is None:
|
||||||
|
try:
|
||||||
|
loadout['primaryWeapon']['label'] = guns[loadout['primaryWeapon']['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if loadout['secondaryWeapon']['label'] is None:
|
||||||
|
try:
|
||||||
|
loadout['secondaryWeapon']['label'] = guns[loadout['secondaryWeapon']['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# perks list
|
||||||
|
for perk in loadout['perks']:
|
||||||
|
if perk['label'] is None:
|
||||||
|
try:
|
||||||
|
perk['label'] = perks[perk['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# extra perks list
|
||||||
|
for perk in loadout['extraPerks']:
|
||||||
|
if perk['label'] is None:
|
||||||
|
try:
|
||||||
|
perk['label'] = perks[perk['name']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# return mapped or unmapped data
|
||||||
|
return data
|
||||||
|
|
||||||
|
# API Requests
|
||||||
|
async def _fullDataReq(self, game, platform, gamertag, type):
|
||||||
|
lookUpType, gamertag, platform = self.__helper(platform, gamertag)
|
||||||
|
return await self.__sendRequest(self.fullDataUrl % (game, platform.value, lookUpType, gamertag, type))
|
||||||
|
|
||||||
|
async def _combatHistoryReq(self, game, platform, gamertag, type, start, end):
|
||||||
|
lookUpType, gamertag, platform = self.__helper(platform, gamertag)
|
||||||
|
return await self.__sendRequest(
|
||||||
|
self.combatHistoryUrl % (game, platform.value, lookUpType, gamertag, type, start, end))
|
||||||
|
|
||||||
|
async def _breakdownReq(self, game, platform, gamertag, type, start, end):
|
||||||
|
lookUpType, gamertag, platform = self.__helper(platform, gamertag)
|
||||||
|
return await self.__sendRequest(
|
||||||
|
self.breakdownUrl % (game, platform.value, lookUpType, gamertag, type, start, end))
|
||||||
|
|
||||||
|
async def _seasonLootReq(self, game, platform, gamertag):
|
||||||
|
lookUpType, gamertag, platform = self.__helper(platform, gamertag)
|
||||||
|
return await self.__sendRequest(self.seasonLootUrl % (game, platform.value, lookUpType, gamertag))
|
||||||
|
|
||||||
|
async def _mapListReq(self, game, platform):
|
||||||
|
return await self.__sendRequest(self.mapListUrl % (game, platform.value))
|
||||||
|
|
||||||
|
async def _matchInfoReq(self, game, platform, type, matchId):
|
||||||
|
return await self.__sendRequest(self.matchInfoUrl % (game, platform.value, type, matchId))
|
||||||
|
|
||||||
|
class __GameDataCommons(_Common):
|
||||||
|
"""
|
||||||
|
Methods
|
||||||
|
=======
|
||||||
|
Sync
|
||||||
|
----
|
||||||
|
fullData(platform:platforms, gamertag:str)
|
||||||
|
returns player's game data of type dict
|
||||||
|
|
||||||
|
combatHistory(platform:platforms, gamertag:str)
|
||||||
|
returns player's combat history of type dict
|
||||||
|
|
||||||
|
combatHistoryWithDate(platform:platforms, gamertag:str, start:int, end:int)
|
||||||
|
returns player's combat history within the specified timeline of type dict
|
||||||
|
|
||||||
|
breakdown(platform:platforms, gamertag:str)
|
||||||
|
returns player's combat history breakdown of type dict
|
||||||
|
|
||||||
|
breakdownWithDate(platform:platforms, gamertag:str, start:int, end:int)
|
||||||
|
returns player's combat history breakdown within the specified timeline of type dict
|
||||||
|
|
||||||
|
seasonLoot(platform:platforms, gamertag:str)
|
||||||
|
returns player's season loot
|
||||||
|
|
||||||
|
mapList(platform:platforms)
|
||||||
|
returns available maps and available modes for each
|
||||||
|
|
||||||
|
matchInfo(platform:platforms, matchId:int)
|
||||||
|
returns details match details of type dict
|
||||||
|
|
||||||
|
Async
|
||||||
|
----
|
||||||
|
fullDataAsync(platform:platforms, gamertag:str)
|
||||||
|
returns player's game data of type dict
|
||||||
|
|
||||||
|
combatHistoryAsync(platform:platforms, gamertag:str)
|
||||||
|
returns player's combat history of type dict
|
||||||
|
|
||||||
|
combatHistoryWithDateAsync(platform:platforms, gamertag:str, start:int, end:int)
|
||||||
|
returns player's combat history within the specified timeline of type dict
|
||||||
|
|
||||||
|
breakdownAsync(platform:platforms, gamertag:str)
|
||||||
|
returns player's combat history breakdown of type dict
|
||||||
|
|
||||||
|
breakdownWithDateAsync(platform:platforms, gamertag:str, start:int, end:int)
|
||||||
|
returns player's combat history breakdown within the specified timeline of type dict
|
||||||
|
|
||||||
|
seasonLootAsync(platform:platforms, gamertag:str)
|
||||||
|
returns player's season loot
|
||||||
|
|
||||||
|
mapListAsync(platform:platforms)
|
||||||
|
returns available maps and available modes for each
|
||||||
|
|
||||||
|
matchInfoAsync(platform:platforms, matchId:int)
|
||||||
|
returns details match details of type dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init_subclass__(cls, **kwargs):
|
||||||
|
cls.__doc__ = cls.__doc__ + super(cls, cls).__doc__
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def _game(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def _type(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
async def fullDataAsync(self, platform: platforms, gamertag: str):
|
||||||
|
data = await self._fullDataReq(self._game, platform, gamertag, self._type)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def fullData(self, platform: platforms, gamertag: str):
|
||||||
|
return asyncio.run(self.fullDataAsync(platform, gamertag))
|
||||||
|
|
||||||
|
async def combatHistoryAsync(self, platform: platforms, gamertag: str):
|
||||||
|
data = await self._combatHistoryReq(self._game, platform, gamertag, self._type, 0, 0)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def combatHistory(self, platform: platforms, gamertag: str):
|
||||||
|
return asyncio.run(self.combatHistoryAsync(platform, gamertag))
|
||||||
|
|
||||||
|
async def combatHistoryWithDateAsync(self, platform, gamertag: str, start: int, end: int):
|
||||||
|
data = await self._combatHistoryReq(self._game, platform, gamertag, self._type, start, end)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def combatHistoryWithDate(self, platform, gamertag: str, start: int, end: int):
|
||||||
|
return asyncio.run(self.combatHistoryWithDateAsync(platform, gamertag, start, end))
|
||||||
|
|
||||||
|
async def breakdownAsync(self, platform, gamertag: str):
|
||||||
|
data = await self._breakdownReq(self._game, platform, gamertag, self._type, 0, 0)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def breakdown(self, platform, gamertag: str):
|
||||||
|
return asyncio.run(self.breakdownAsync(platform, gamertag))
|
||||||
|
|
||||||
|
async def breakdownWithDateAsync(self, platform, gamertag: str, start: int, end: int):
|
||||||
|
data = await self._breakdownReq(self._game, platform, gamertag, self._type, start, end)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def breakdownWithDate(self, platform, gamertag: str, start: int, end: int):
|
||||||
|
return asyncio.run(self.breakdownWithDateAsync(platform, gamertag, start, end))
|
||||||
|
|
||||||
|
async def matchInfoAsync(self, platform, matchId: int):
|
||||||
|
data = await self._matchInfoReq(self._game, platform, self._type, matchId)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def matchInfo(self, platform, matchId: int):
|
||||||
|
return asyncio.run(self.matchInfoAsync(platform, matchId))
|
||||||
|
|
||||||
|
async def seasonLootAsync(self, platform, gamertag):
|
||||||
|
data = await self._seasonLootReq(self._game, platform, gamertag)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def seasonLoot(self, platform, gamertag):
|
||||||
|
return asyncio.run(self.seasonLootAsync(platform, gamertag))
|
||||||
|
|
||||||
|
async def mapListAsync(self, platform):
|
||||||
|
data = await self._mapListReq(self._game, platform)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def mapList(self, platform):
|
||||||
|
return asyncio.run(self.mapListAsync(platform))
|
||||||
|
# WZ
|
||||||
|
|
||||||
|
class __WZ(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
Warzone class: A class to get players warzone stats, warzone combat history and specific warzone match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: mw or wz
|
||||||
|
gameType: wz
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "mw"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "wz"
|
||||||
|
|
||||||
|
async def seasonLootAsync(self, platform, gamertag):
|
||||||
|
raise InvalidEndpoint
|
||||||
|
|
||||||
|
async def mapListAsync(self, platform):
|
||||||
|
raise InvalidEndpoint
|
||||||
|
|
||||||
|
# WZ2
|
||||||
|
|
||||||
|
class __WZ2(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
Warzone 2 class: A class to get players warzone 2 stats, warzone 2 combat history and specific warzone 2 match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: mw or wz
|
||||||
|
gameType: wz2
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "mw2"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "wz2"
|
||||||
|
|
||||||
|
async def seasonLootAsync(self, platform, gamertag):
|
||||||
|
raise InvalidEndpoint
|
||||||
|
|
||||||
|
async def mapListAsync(self, platform):
|
||||||
|
raise InvalidEndpoint
|
||||||
|
|
||||||
|
# MW
|
||||||
|
|
||||||
|
class __MW(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
ModernWarfare class: A class to get players modernwarfare stats, modernwarfare combat history, a player's modernwarfare season loot, modernwarfare map list and specific modernwarfare match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: mw
|
||||||
|
gameType: mp
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "mw"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "mp"
|
||||||
|
|
||||||
|
# CW
|
||||||
|
|
||||||
|
class __CW(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
ColdWar class: A class to get players coldwar stats, coldwar combat history, a player's coldwar season loot, coldwar map list and specific coldwar match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: cw
|
||||||
|
gameType: mp
|
||||||
|
|
||||||
|
"""
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "cw"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "mp"
|
||||||
|
|
||||||
|
# VG
|
||||||
|
|
||||||
|
class __VG(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
Vanguard class: A class to get players vanguard stats, vanguard combat history, a player's vanguard season loot, vanguard map list and specific vanguard match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: vg
|
||||||
|
gameType: pm
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "vg"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "mp"
|
||||||
|
|
||||||
|
# MW2
|
||||||
|
|
||||||
|
class __MW2(__GameDataCommons):
|
||||||
|
"""
|
||||||
|
ModernWarfare 2 class: A class to get players modernwarfare 2 stats, modernwarfare 2 combat history, a player's modernwarfare 2 season loot, modernwarfare 2 map list and specific modernwarfare 2 match details
|
||||||
|
classCategory: game
|
||||||
|
gameId/gameTitle: mw
|
||||||
|
gameType: mp
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _game(self) -> str:
|
||||||
|
return "mw2"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _type(self) -> str:
|
||||||
|
return "mp"
|
||||||
|
|
||||||
|
# USER
|
||||||
|
class __USER(_Common):
|
||||||
|
def info(self):
|
||||||
|
if self.loggedIn:
|
||||||
|
# First, try to load the user info from a local file if it exists.
|
||||||
|
if os.path.exists('userInfo.json'):
|
||||||
|
with open('userInfo.json', 'r') as file:
|
||||||
|
rawData = json.load(file)
|
||||||
|
else:
|
||||||
|
# If the file doesn't exist, make the HTTP request.
|
||||||
|
rawData = requests.get(f"https://profile.callofduty.com/cod/userInfo/{self.sso_token()}",
|
||||||
|
headers=API._Common.requestHeaders)
|
||||||
|
|
||||||
|
# Process the raw data (either from the file or HTTP response)
|
||||||
|
data = {'userName': rawData['userInfo']['userName'], 'identities': []}
|
||||||
|
for i in rawData['identities']:
|
||||||
|
data['identities'].append({
|
||||||
|
'platform': i['provider'],
|
||||||
|
'gamertag': i['username'],
|
||||||
|
'accountID': i['accountID']
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
raise NotLoggedIn
|
||||||
|
|
||||||
|
def __priv(self):
|
||||||
|
d = self.info()
|
||||||
|
return d['identities'][0]['platform'], quote(d['identities'][0]['gamertag'].encode("utf-8"))
|
||||||
|
|
||||||
|
async def friendFeedAsync(self):
|
||||||
|
p, g = self.__priv()
|
||||||
|
data = await self._Common__sendRequest(
|
||||||
|
f"/userfeed/v1/friendFeed/platform/{p}/gamer/{g}/friendFeedEvents/en")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def friendFeed(self):
|
||||||
|
return asyncio.run(self.friendFeedAsync())
|
||||||
|
|
||||||
|
async def eventFeedAsync(self):
|
||||||
|
data = await self._Common__sendRequest(f"/userfeed/v1/friendFeed/rendered/en/{self.sso_token()}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def eventFeed(self):
|
||||||
|
return asyncio.run(self.eventFeedAsync())
|
||||||
|
|
||||||
|
async def loggedInIdentitiesAsync(self):
|
||||||
|
data = await self._Common__sendRequest(f"/crm/cod/v2/identities/{self.sso_token()}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def loggedInIdentities(self):
|
||||||
|
return asyncio.run(self.loggedInIdentitiesAsync())
|
||||||
|
|
||||||
|
async def codPointsAsync(self):
|
||||||
|
p, g = self.__priv()
|
||||||
|
data = await self._Common__sendRequest(f"/inventory/v1/title/mw/platform/{p}/gamer/{g}/currency")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def codPoints(self):
|
||||||
|
return asyncio.run(self.codPointsAsync())
|
||||||
|
|
||||||
|
async def connectedAccountsAsync(self):
|
||||||
|
p, g = self.__priv()
|
||||||
|
data = await self._Common__sendRequest(f"/crm/cod/v2/accounts/platform/{p}/gamer/{g}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def connectedAccounts(self):
|
||||||
|
return asyncio.run(self.connectedAccountsAsync())
|
||||||
|
|
||||||
|
async def settingsAsync(self):
|
||||||
|
p, g = self.__priv()
|
||||||
|
data = await self._Common__sendRequest(f"/preferences/v1/platform/{p}/gamer/{g}/list")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def settings(self):
|
||||||
|
return asyncio.run(self.settingsAsync())
|
||||||
|
|
||||||
|
# SHOP
|
||||||
|
class __SHOP(_Common):
|
||||||
|
"""
|
||||||
|
Shop class: A class to get bundle details and battle pass loot
|
||||||
|
classCategory: other
|
||||||
|
|
||||||
|
Methods
|
||||||
|
=======
|
||||||
|
Sync
|
||||||
|
----
|
||||||
|
purchasableItems(game: games)
|
||||||
|
returns purchasable items for a specific gameId/gameTitle
|
||||||
|
|
||||||
|
bundleInformation(game: games, bundleId: int)
|
||||||
|
returns bundle details for the specific gameId/gameTitle and bundleId
|
||||||
|
|
||||||
|
battlePassLoot(game: games, platform: platforms, season: int)
|
||||||
|
returns battle pass loot for specific game and season on given platform
|
||||||
|
|
||||||
|
Async
|
||||||
|
----
|
||||||
|
purchasableItemsAsync(game: games)
|
||||||
|
returns purchasable items for a specific gameId/gameTitle
|
||||||
|
|
||||||
|
bundleInformationAsync(game: games, bundleId: int)
|
||||||
|
returns bundle details for the specific gameId/gameTitle and bundleId
|
||||||
|
|
||||||
|
battlePassLootAsync(game: games, platform: platforms, season: int)
|
||||||
|
returns battle pass loot for specific game and season on given platform
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def purchasableItemsAsync(self, game: games):
|
||||||
|
data = await self._Common__sendRequest(f"/inventory/v1/title/{game.value}/platform/uno/purchasable/public/en")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def purchasableItems(self, game: games):
|
||||||
|
return asyncio.run(self.purchasableItemsAsync(game))
|
||||||
|
|
||||||
|
async def bundleInformationAsync(self, game: games, bundleId: int):
|
||||||
|
data = await self._Common__sendRequest(f"/inventory/v1/title/{game.value}/bundle/{bundleId}/en")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def bundleInformation(self, game: games, bundleId: int):
|
||||||
|
return asyncio.run(self.bundleInformationAsync(game, bundleId))
|
||||||
|
|
||||||
|
async def battlePassLootAsync(self, game: games, platform: platforms, season: int):
|
||||||
|
data = await self._Common__sendRequest(
|
||||||
|
f"/loot/title/{game.value}/platform/{platform.value}/list/loot_season_{season}/en")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def battlePassLoot(self, game: games, platform: platforms, season: int):
|
||||||
|
return asyncio.run(self.battlePassLootAsync(game, platform, season))
|
||||||
|
|
||||||
|
# ALT
|
||||||
|
class __ALT(_Common):
|
||||||
|
|
||||||
|
async def searchAsync(self, platform, gamertag: str):
|
||||||
|
lookUpType, gamertag, platform = self._Common__helper(platform, gamertag)
|
||||||
|
data = await self._Common__sendRequest(f"/crm/cod/v2/platform/{platform.value}/username/{gamertag}/search")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def search(self, platform, gamertag: str):
|
||||||
|
return asyncio.run(self.searchAsync(platform, gamertag))
|
||||||
|
|
||||||
|
|
||||||
|
# Exceptions
|
||||||
|
|
||||||
|
class NotLoggedIn(Exception):
|
||||||
|
def __str__(self):
|
||||||
|
return "Not logged in!"
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidToken(Exception):
|
||||||
|
def __init__(self, token):
|
||||||
|
self.token = token
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Token is invalid, token: {self.token}"
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidPlatform(Exception):
|
||||||
|
def __init__(self, platform: platforms):
|
||||||
|
self.message: str
|
||||||
|
if platform == platforms.Steam:
|
||||||
|
self.message = "Steam cannot be used till further updates."
|
||||||
|
else:
|
||||||
|
self.message = "Invalid platform, use platform class!"
|
||||||
|
|
||||||
|
|
||||||
|
super().__init__(self.message)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.message
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidEndpoint(Exception):
|
||||||
|
def __str__(self):
|
||||||
|
return "This endpoint is not available for selected title"
|
||||||
|
|
||||||
|
|
||||||
|
class StatusError(Exception):
|
||||||
|
def __str__(self):
|
||||||
|
return "Status Error, Check if your sso token is valid or try again later."
|
361
cod_api/replacements.py
Normal file
361
cod_api/replacements.py
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
replacements = {
|
||||||
|
# Maps
|
||||||
|
"career": "Career",
|
||||||
|
"mp_hackney_yard": "Hackney Yard (Night)",
|
||||||
|
"mp_aniyah": "Aniyah Palace",
|
||||||
|
"mp_euphrates": "Euphrates Bridge",
|
||||||
|
"mp_raid": "Grazna Raid",
|
||||||
|
"mp_m_pine": "Pine",
|
||||||
|
"mp_m_stack": "Stack",
|
||||||
|
"mp_deadzone": "Arklov Peak",
|
||||||
|
"mp_quarry": "Karst River Quarry",
|
||||||
|
"mp_m_overunder": "Docks",
|
||||||
|
"mp_cave_am": "Azhir Cave",
|
||||||
|
"mp_cave": "Azhir Cave (Night)",
|
||||||
|
"mp_runner": "Gun Runner",
|
||||||
|
"mp_runner_pm": "Gun Runner (Night)",
|
||||||
|
"mp_hackney_am": "Hackney Yard",
|
||||||
|
"mp_piccadilly": "Piccadilly",
|
||||||
|
"mp_spear": "Rammaza",
|
||||||
|
"mp_spear_pm": "Rammaza (Night)",
|
||||||
|
"mp_petrograd": "St. Petrograd",
|
||||||
|
"mp_m_hill": "Hill",
|
||||||
|
"mp_m_king": "King",
|
||||||
|
"mp_m_speedball": "Speedball",
|
||||||
|
"mp_m_showers": "Gulag Showers",
|
||||||
|
"mp_downtown_gw": "Tarvosk District",
|
||||||
|
"mp_m_speed": "Shoot House",
|
||||||
|
"mp_farms2_gw": "Krovnik Farmland",
|
||||||
|
"mp_port2_gw": "Port",
|
||||||
|
"mp_crash": "Crash",
|
||||||
|
"mp_vacant": "Vacant",
|
||||||
|
"mp_shipment": "Shipment",
|
||||||
|
"mp_m_cargo": "Cargo",
|
||||||
|
"mp_m_cage": "Atrium",
|
||||||
|
"mp_m_overwinter": "Docks",
|
||||||
|
"mp_emporium": "Atlas Superstore",
|
||||||
|
"mp_rust": "Rust",
|
||||||
|
"mp_boneyard_gw": "Zhokov Boneyard",
|
||||||
|
"mp_m_fork": "Bazaar",
|
||||||
|
"mp_donetsk": "Verdansk",
|
||||||
|
"mp_hideout": "Khandor Hideout",
|
||||||
|
"loading_mp_hideout": "Khandor Hideout",
|
||||||
|
"mp_aniyah_tac": "Aniyah Incursion",
|
||||||
|
"mp_backlot": "Talsik Backlot",
|
||||||
|
"mp_village": "Hovec Sawmill",
|
||||||
|
"mp_hardhat": "Hardhat",
|
||||||
|
"mp_m_wallco": "Aisle 9",
|
||||||
|
"mp_donetsk": "Verdansk",
|
||||||
|
"mp_scrapyard": "Zhokov Scrapyard",
|
||||||
|
"mp_m_trench": "Trench",
|
||||||
|
"mp_promenade_gw": "Barakett Promenade",
|
||||||
|
"mp_don": "Verdansk",
|
||||||
|
"mp_garden": "Cheshire Park",
|
||||||
|
"mp_oilrig": "Petrov Oil Rig",
|
||||||
|
"mp_harbor": "Suldal Harbor",
|
||||||
|
"mp_layover_gw": "Verdansk International Airport",
|
||||||
|
"mp_m_cornfield": "Livestock",
|
||||||
|
"mp_m_stadium": "Verdansk Stadium",
|
||||||
|
"mp_malyshev": "Mialstor Tank Factory",
|
||||||
|
"mp_malyshev_10v10": "Mialstor Tank Factory",
|
||||||
|
"mp_broadcast": "Broadcast",
|
||||||
|
"mp_riverside_gw": "Verdansk Riverside",
|
||||||
|
"mp_m_train": "Station",
|
||||||
|
"mp_kstenod": "Verdansk (Night)",
|
||||||
|
"mp_escape": "Rebirth",
|
||||||
|
"mp_herat": "Al-Raab Airbase",
|
||||||
|
"mp_killhouse": "Killhouse",
|
||||||
|
"mp_m_drainage": "Drainage",
|
||||||
|
# Gamemodes
|
||||||
|
"war": "Team Deathmatch",
|
||||||
|
"sd": "Search and Destroy",
|
||||||
|
"dom": "Domination",
|
||||||
|
"tdef": "Team Defender",
|
||||||
|
"dm": "Free-for-all",
|
||||||
|
"koth": "Hardpoint",
|
||||||
|
"hq": "Headquarters",
|
||||||
|
"arena": "Gunfight",
|
||||||
|
"arm": "Ground War",
|
||||||
|
"conf": "Kill Confirmed",
|
||||||
|
"cyber": "Cyber Attack",
|
||||||
|
"hc_war": "Team Deathmatch Hardcore",
|
||||||
|
"hc_arena": "Gunfight Hardcore",
|
||||||
|
"hc_arm": "Ground War Hardcore",
|
||||||
|
"hc_conf": "Kill Confirmed Hardcore",
|
||||||
|
"hc_cyber": "Cyber Attack Hardcore",
|
||||||
|
"hc_dm": "Free-for-all Hardcore",
|
||||||
|
"hc_hq": "Headquarters Hardcore",
|
||||||
|
"hc_dom": "Domination Hardcore",
|
||||||
|
"hc_sd": "Search and Destroy Hardcore",
|
||||||
|
"cyber_hc": "Cyber Attack Hardcore",
|
||||||
|
"war_hc": "Team Deathmatch Hardcore",
|
||||||
|
"dom_hc": "Domination Hardcore",
|
||||||
|
"sd_hc": "Search and Destroy Hardcore",
|
||||||
|
"conf_hc": "Kill Confirmed Hardcore",
|
||||||
|
"gun": "Gun Game",
|
||||||
|
"gun_hc": "Gun Game Hardcore",
|
||||||
|
"siege": "Reinforce",
|
||||||
|
"infect": "Infected",
|
||||||
|
"arena_osp": "Gunfight O.S.P.",
|
||||||
|
"hq_hc": "Headquarters Hardcore",
|
||||||
|
"grnd": "Grind",
|
||||||
|
"grind": "Grind",
|
||||||
|
"ctf": "Capture the Flag",
|
||||||
|
"br_all": "All",
|
||||||
|
"br": "Battle Royale",
|
||||||
|
"br_dmz": "Plunder",
|
||||||
|
"br_dmz_38": "Plunder Quads",
|
||||||
|
"br_87": "BR Solos",
|
||||||
|
"br_dmz_104": "Blood Money",
|
||||||
|
"koth_hc": "Hardpoint Hardcore",
|
||||||
|
"br_25": "BR Trios",
|
||||||
|
"br_89": "BR Quads",
|
||||||
|
"br_dmz_76": "Plunder Quads",
|
||||||
|
"br_77": "BR Scopes & Scatterguns",
|
||||||
|
"br_dmz_85": "Plunder Duos",
|
||||||
|
"dd_hc": "Demolition Hardcore",
|
||||||
|
"dd": "Demolition",
|
||||||
|
"br_71": "BR Solos",
|
||||||
|
"br_74": "BR Trios",
|
||||||
|
"br_88": "BR Duos",
|
||||||
|
"brtdm_113": "Warzone Rumble",
|
||||||
|
"brtdm_rmbl": "Warzone Rumble",
|
||||||
|
"br_brsolo": "BR Solos",
|
||||||
|
"br_brduos": "BR Duos",
|
||||||
|
"br_brtrios": "BR Trios",
|
||||||
|
"br_brquads": "BR Quads",
|
||||||
|
"br_dmz_plnbld": "Blood Money",
|
||||||
|
"br_br_real": "Realism Battle Royale",
|
||||||
|
"br_86": "Realism Battle Royale",
|
||||||
|
"br_brthquad": "BR 200 Quads",
|
||||||
|
"br_jugg_brtriojugr": "Juggernaut Royal Trios",
|
||||||
|
"br_dmz_plunquad": "Plunder Quads",
|
||||||
|
"br_dmz_bldmnytrio": "Blood Money Trios",
|
||||||
|
"br_mini_miniroyale": "Mini Royale",
|
||||||
|
"br_brbbsolo": "BR Buyback Solos",
|
||||||
|
"br_jugg_brquadjugr": "Juggernaut Royal Quads",
|
||||||
|
"br_kingslayer_kingsltrios": "King Slayer Trios",
|
||||||
|
"br_truckwar_trwarsquads": "Armored Royale Quads",
|
||||||
|
"br_zxp_zmbroy": "Zombie Royale",
|
||||||
|
"br_brhwntrios": "BR Trick-Or-Trios",
|
||||||
|
"rugby": "Onslaughter",
|
||||||
|
"br_brsolohwn": "BR Solo Survivor",
|
||||||
|
"br_dmz_plndcndy": "Plunder: Candy Collector",
|
||||||
|
"br_jugg_jugpmpkn": "Juggourdnaut Royale",
|
||||||
|
"br_rebirth_rbrthtrios": "Resurgence Trio",
|
||||||
|
"br_rebirth_rbrthduos": "Resurgence Duos",
|
||||||
|
"br_rebirth_rbrthquad": "Rebirth Resurgance Quads",
|
||||||
|
"br_dmz_plndtrios": "Plunder Trios",
|
||||||
|
"br_rebirth_resurgence_trios": "Verdansk Resurgence Trios",
|
||||||
|
"br_mini_rebirth_mini_royale_quads": "Rebirth Mini Royale Quads",
|
||||||
|
"br_bodycount_pwergrb": "Power Grab",
|
||||||
|
"br_rebirth_resurgence_mini": "Verdansk Resurgence Mini",
|
||||||
|
"br_payload_payload": "Payload",
|
||||||
|
"br_mini_rebirth_mini_royale_trios": "Rebirth Mini Royale Trios",
|
||||||
|
"br_x2_br_reveal_x2_event/event_title_x2": "Battle of Verdansk",
|
||||||
|
"br_rumble_clash": "Clash",
|
||||||
|
"br_dbd_dbd": "Iron Trials '84",
|
||||||
|
"br_gxp_gov": "Ghosts of Verdansk",
|
||||||
|
# Weapons
|
||||||
|
"scorestreak": "Scorestreak",
|
||||||
|
"equipment": "Equipment",
|
||||||
|
"gear": "Gear",
|
||||||
|
"weapon_bare_hands": "Bare Hands",
|
||||||
|
"weapon_tactical_rifle": "Tactical Rifle",
|
||||||
|
"weapon_shotgun": "Shotgun",
|
||||||
|
"weapon_sniper": "Sniper",
|
||||||
|
"weapon_lmg": "Light Machine Guns",
|
||||||
|
"weapon_launcher": "Launcher",
|
||||||
|
"weapon_pistol": "Pistol",
|
||||||
|
"weapon_smg": "Submachine Guns",
|
||||||
|
"weapon_melee": "Melee",
|
||||||
|
"weapon_assault_rifle": "Assault Rifle",
|
||||||
|
"attachments": "Attachments",
|
||||||
|
"weapons": "Weapons",
|
||||||
|
"specialist": "Specialist",
|
||||||
|
"weapon": "Weapon",
|
||||||
|
"weapon_special": "Special",
|
||||||
|
"iw8_ar_akilo47": "AK-47",
|
||||||
|
"iw8_ar_kilo433": "Kilo-141",
|
||||||
|
"iw8_ar_mcharlie": "M13",
|
||||||
|
"iw8_ar_falima": "FAL",
|
||||||
|
"iw8_ar_asierra12": "Oden",
|
||||||
|
"iw8_sm_mpapa7": "MP7",
|
||||||
|
"iw8_sm_augolf": "AUG",
|
||||||
|
"iw8_sm_uzulu": "Uzi",
|
||||||
|
"iw8_sh_romeo870": "Model 680",
|
||||||
|
"iw8_sh_charlie725": "725",
|
||||||
|
"iw8_sh_aalpha12": "JAK-12",
|
||||||
|
"iw8_sh_oscar12": "Origin 12",
|
||||||
|
"iw8_lm_pkilo": "PKM",
|
||||||
|
"iw8_lm_mgolf34": "MG34",
|
||||||
|
"iw8_lm_lima86": "SA87",
|
||||||
|
"iw8_lm_dblmg": "MP Juggernaut",
|
||||||
|
"iw8_sn_mike14": "EBR-14",
|
||||||
|
"iw8_sn_delta": "Dragunov",
|
||||||
|
"iw8_sn_alpha50": "AX-50",
|
||||||
|
"iw8_sn_hdromeo": "HDR",
|
||||||
|
"iw8_sn_sbeta": "Mk2 Carbine",
|
||||||
|
"iw8_pi_papa320": "M19",
|
||||||
|
"iw8_pi_cpapa": ".357",
|
||||||
|
"iw8_la_rpapa7": "RPG-7",
|
||||||
|
"iw8_la_juliet": "JOKR",
|
||||||
|
"iw8_la_gromeo": "PILA",
|
||||||
|
"iw8_la_kgolf": "Strela-P",
|
||||||
|
"iw8_me_riotshield": "Riot Shield",
|
||||||
|
"equip_gas_grenade": "Gas Grenade",
|
||||||
|
"equip_snapshot_grenade": "Snapshot Grenade",
|
||||||
|
"equip_decoy": "Decoy Grenade",
|
||||||
|
"equip_smoke": "Smoke Grenade",
|
||||||
|
"equip_concussion": "Stun Grenade",
|
||||||
|
"equip_hb_sensor": "Heartbeat Sensor",
|
||||||
|
"equip_flash": "Flash Grenade",
|
||||||
|
"equip_adrenaline": "Stim",
|
||||||
|
"equip_frag": "Frag Grenade",
|
||||||
|
"equip_thermite": "Thermite",
|
||||||
|
"equip_semtex": "Semtex",
|
||||||
|
"equip_claymore": "Claymore",
|
||||||
|
"equip_c4": "C4",
|
||||||
|
"equip_at_mine": "Proximity Mine",
|
||||||
|
"equip_throwing_knife": "Throwing Knife",
|
||||||
|
"equip_molotov": "Molotov Cocktail",
|
||||||
|
"iw8_knife": "Combat Knife",
|
||||||
|
"weapon_other": "Primary Melee",
|
||||||
|
"iw8_ar_tango21": "RAM-7",
|
||||||
|
"iw8_ar_falpha": "FR 5.56",
|
||||||
|
"iw8_ar_mike4": "M4A1",
|
||||||
|
"iw8_sm_papa90": "P90",
|
||||||
|
"iw8_sm_mpapa5": "MP5",
|
||||||
|
"iw8_sm_beta": "PP19 Bizon",
|
||||||
|
"iw8_sh_dpapa12": "R9-0",
|
||||||
|
"iw8_lm_mgolf36": "Holger-26",
|
||||||
|
"iw8_sn_kilo98": "Kar98k",
|
||||||
|
"iw8_pi_mike1911": "1911",
|
||||||
|
"iw8_pi_golf21": "X16",
|
||||||
|
"iw8_pi_decho": ".50 GS",
|
||||||
|
"weapon_marksman": "Marksman Rifles",
|
||||||
|
"iw8_lm_kilo121": "M91",
|
||||||
|
"iw8_ar_scharlie": "FN Scar 17",
|
||||||
|
"iw8_ar_sierra552": "Grau 5.56",
|
||||||
|
"iw8_sm_smgolf45": "Striker 45",
|
||||||
|
"iw8_pi_mike9a3": "Renetti",
|
||||||
|
"iw8_lm_mkilo3": "Bruen MK9",
|
||||||
|
"iw8_sh_mike26": "VLK Rogue",
|
||||||
|
"iw8_sn_crossbow": "Crossbow",
|
||||||
|
"iw8_sn_sksierra": "SKS",
|
||||||
|
"iw8_ar_galima": "CR-56 AMAX",
|
||||||
|
"iw8_me_kalistick": "Kali Sticks",
|
||||||
|
"iw8_sm_victor": "Fennec Mk9",
|
||||||
|
"iw8_sn_xmike109": "Rytec AMR",
|
||||||
|
"iw8_pi_mike9": "Renetti",
|
||||||
|
"iw8_me_akimboblunt": "Kali Sticks",
|
||||||
|
"iw8_ar_anovember94": "AN-94",
|
||||||
|
"iw8_sm_charlie9": "ISO",
|
||||||
|
"iw8_me_akimboblades": "Dual Kodachis",
|
||||||
|
"iw8_lm_sierrax": "FiNN",
|
||||||
|
"iw8_ar_valpha": "AS VAL",
|
||||||
|
"iw8_sn_romeo700": "SP-R 208",
|
||||||
|
"cruise_predator": "Cruise Missile",
|
||||||
|
"manual_turret": "Shield Turret",
|
||||||
|
"toma_strike": "Cluster Strike",
|
||||||
|
"sentry_gun": "Sentry Gun",
|
||||||
|
"hover_jet": "VTOL Jet",
|
||||||
|
"precision_airstrike": "Precision Airstrike",
|
||||||
|
"juggernaut": "Juggernaut",
|
||||||
|
"pac_sentry": "",
|
||||||
|
"chopper_gunner": "Chopper Gunner",
|
||||||
|
"gunship": "Gunship",
|
||||||
|
"white_phosphorus": "White Phosphorus",
|
||||||
|
"nuke": "Nuke",
|
||||||
|
"chopper_support": "Support Helo",
|
||||||
|
"bradley": "Infantry Assault Vehicle",
|
||||||
|
"uav": "UAV",
|
||||||
|
"directional_uav": "Advanced UAV",
|
||||||
|
"airdrop": "Care Package",
|
||||||
|
"airdrop_multiple": "Emergency Airdrop",
|
||||||
|
"radar_drone_overwatch": "Personal Radar",
|
||||||
|
"scrambler_drone_guard": "Counter UAV",
|
||||||
|
"super_emp_drone": "EMP Drone",
|
||||||
|
"super_trophy": "Trophy System",
|
||||||
|
"super_ammo_drop": "Munitions Box",
|
||||||
|
"super_weapon_drop": "Weapon Drop",
|
||||||
|
"super_fulton": "Cash Deposit Balloon",
|
||||||
|
"super_armor_drop": "Armor Box",
|
||||||
|
"super_select": "Field Upgrade Pro (Any)",
|
||||||
|
"super_tac_insert": "Tactical Insertion",
|
||||||
|
"super_recon_drone": "Recon Drone",
|
||||||
|
"super_deadsilence": "Dead Silence",
|
||||||
|
"super_supply_drop": "Loadout Drop", ### Unsure if this is Loadout Drop
|
||||||
|
"super_tac_cover": "Deployable Cover",
|
||||||
|
"super_support_box": "Stopping Power Rounds",
|
||||||
|
# Accolades
|
||||||
|
# "accoladeData": "Accolades",
|
||||||
|
# "classChanges": "Most classes changed (Evolver)",
|
||||||
|
# "highestAvgAltitude": "Highest average altitude (High Command)",
|
||||||
|
# "killsFromBehind": "Most kills from behind (Flanker)",
|
||||||
|
# "lmgDeaths": "Most LMG deaths (Target Practice)",
|
||||||
|
# "riotShieldDamageAbsorbed": "Most damage absorbed with Riot Shield (Guardian)",
|
||||||
|
# "flashbangHits": "Most Flashbang hits (Blinder)",
|
||||||
|
# "meleeKills": "Most Melee kills (Brawler)",
|
||||||
|
# "tagsLargestBank": "Largest bank (Bank Account)",
|
||||||
|
# "shotgunKills": "Most Shotgun kills (Buckshot)",
|
||||||
|
# "sniperDeaths": "Most Sniper deaths (Zeroed In)",
|
||||||
|
# "timeProne": "Most time spent Prone (Grassy Knoll)",
|
||||||
|
# "killstreakWhitePhosphorousKillsAssists": "Most kills and assists with White Phosphorus (Burnout)",
|
||||||
|
# "shortestLife": "Shortest life (Terminal)",
|
||||||
|
# "deathsFromBehind": "Most deaths from behind (Blindsided)",
|
||||||
|
# "higherRankedKills": "Most kills on higher ranked scoreboard players (Upriser)",
|
||||||
|
# "mostAssists": "Most assists (Wingman)",
|
||||||
|
# "leastKills": "Fewest kills (The Fearful)",
|
||||||
|
# "tagsDenied": "Denied the most tags (Denied)",
|
||||||
|
# "killstreakWheelsonKills": "Most Wheelson kills",
|
||||||
|
# "sniperHeadshots": "Most Sniper headshots (Dead Aim)",
|
||||||
|
# "killstreakJuggernautKills": "Most Juggernaut kills (Heavy Metal)",
|
||||||
|
# "smokesUsed": "Most Smoke Grenades used (Chimney)",
|
||||||
|
# "avengerKills": "Most avenger kills (Avenger)",
|
||||||
|
# "decoyHits": "Most Decoy Grenade hits (Made You Look)",
|
||||||
|
# "killstreakCarePackageUsed": "Most Care Packages called in (Helping Hand)",
|
||||||
|
# "molotovKills": "Most Molotov kills (Arsonist)",
|
||||||
|
# "gasHits": "Most Gas Grenade hits (Gaseous)",
|
||||||
|
# "comebackKills": "Most comebacks (Rally)",
|
||||||
|
# "lmgHeadshots": "Most LMG headshots (LMG Expert)",
|
||||||
|
# "smgDeaths": "Most SMG deaths (Run and Gunned)",
|
||||||
|
# "carrierKills": "Most kills as carrier (Carrier)",
|
||||||
|
# "deployableCoverUsed": "Most Deployable Covers used (Combat Engineer)",
|
||||||
|
# "thermiteKills": "Most Thermite kills (Red Iron)",
|
||||||
|
# "arKills": "Most assault rifle kills (AR Specialist)",
|
||||||
|
# "c4Kills": "Most C4 kills (Handle With Care)",
|
||||||
|
# "suicides": "Most suicides (Accident Prone)",
|
||||||
|
# "clutch": "Most kills as the last alive (Clutched)",
|
||||||
|
# "survivorKills": "Most kills as survivor (Survivalist)",
|
||||||
|
# "killstreakGunshipKills": "Most Gunship kills (Death From Above)",
|
||||||
|
# "timeSpentAsPassenger": "Most time spent as a passenger (Navigator)",
|
||||||
|
# "returns": "Most flags returned (Flag Returner)",
|
||||||
|
# "smgHeadshots": "Most SMG headshots (SMG Expert)",
|
||||||
|
# "launcherDeaths": "Most launcher deaths (Fubar)",
|
||||||
|
# "oneShotOneKills": "Most one shot kills (One Shot Kill)",
|
||||||
|
# "ammoBoxUsed": "Most Munitions Boxes used (Provider)",
|
||||||
|
# #"spawnSelectSquad": "",
|
||||||
|
# "weaponPickups": "Most picked up weapons (Loaner)",
|
||||||
|
# "pointBlankKills": "Most point blank kills (Personal Space)",
|
||||||
|
# "tagsCaptured": "Collected the most tags (Confirmed Kills)",
|
||||||
|
# "killstreakGroundKills": "Most ground based killstreak kills (Ground Control)",
|
||||||
|
# "distanceTraveledInVehicle": "Longest distance travelled in a vehicle (Cross Country)",
|
||||||
|
# "longestLife": "Longest life (Lifer)",
|
||||||
|
# "stunHits": "Most Stun Grenade hits (Stunner)",
|
||||||
|
# "spawnSelectFlag": "Most FOB Spawns (Objective Focused)", # Unsure
|
||||||
|
# "shotgunHeadshots": "Most Shotgun headshots (Boomstick)",
|
||||||
|
# "bombDefused": "Most defuses (Defuser)",
|
||||||
|
# "snapshotHits": "Most Snapshot Grenade hits (Photographer)",
|
||||||
|
# "noKillsWithDeath": "No kills with at least 1 death (Participant)",
|
||||||
|
# "killstreakAUAVAssists": "Most Advanced UAV assists (Target Rich Environment)",
|
||||||
|
# "killstreakPersonalUAVKills": "Most kills with a Personal Radar active (Nothing Personal)",
|
||||||
|
# "tacticalInsertionSpawns": "Most Tactical Insertions used (Revenant)",
|
||||||
|
# "launcherKills": "Most Launcher kills (Explosive)",
|
||||||
|
# "spawnSelectVehicle": "Most vehicle spawns (Oscar Mike)",
|
||||||
|
# "mostKillsLeastDeaths": "Most kills and fewest deaths (MVP)",
|
||||||
|
# "mostKills": "Most kills (The Feared)",
|
||||||
|
# "defends": "Most defend kills (Defense)",
|
||||||
|
# "timeSpentAsDriver": "Most time spent driving (Driver)",
|
||||||
|
# "": "" # WIP - Still adding more
|
||||||
|
}
|
@ -25,3 +25,6 @@ https://my.callofduty.com/api/papi-client/inventory/v1/title/mw/platform/battle/
|
|||||||
https://my.callofduty.com/api/papi-client/crm/cod/v2/accounts/platform/battle/gamer/$PROF/
|
https://my.callofduty.com/api/papi-client/crm/cod/v2/accounts/platform/battle/gamer/$PROF/
|
||||||
|
|
||||||
https://my.callofduty.com/api/papi-client/preferences/v1/platform/battle/gamer/$PROF/list
|
https://my.callofduty.com/api/papi-client/preferences/v1/platform/battle/gamer/$PROF/list
|
||||||
|
|
||||||
|
# Get Bundle Info
|
||||||
|
https://my.callofduty.com/api/papi-client/inventory/v1/title/mw/bundle/400525/en
|
486
get_cod_stats.py
486
get_cod_stats.py
@ -1,8 +1,10 @@
|
|||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
from cod_api import API, platforms
|
from cod_api import API, platforms
|
||||||
|
from cod_api.replacements import replacements
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@ -10,368 +12,6 @@ import datetime
|
|||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||||
|
|
||||||
replacements = {
|
|
||||||
# Maps
|
|
||||||
"career": "Career",
|
|
||||||
"mp_hackney_yard": "Hackney Yard (Night)",
|
|
||||||
"mp_aniyah": "Aniyah Palace",
|
|
||||||
"mp_euphrates": "Euphrates Bridge",
|
|
||||||
"mp_raid": "Grazna Raid",
|
|
||||||
"mp_m_pine": "Pine",
|
|
||||||
"mp_m_stack": "Stack",
|
|
||||||
"mp_deadzone": "Arklov Peak",
|
|
||||||
"mp_quarry": "Karst River Quarry",
|
|
||||||
"mp_m_overunder": "Docks",
|
|
||||||
"mp_cave_am": "Azhir Cave",
|
|
||||||
"mp_cave": "Azhir Cave (Night)",
|
|
||||||
"mp_runner": "Gun Runner",
|
|
||||||
"mp_runner_pm": "Gun Runner (Night)",
|
|
||||||
"mp_hackney_am": "Hackney Yard",
|
|
||||||
"mp_piccadilly": "Piccadilly",
|
|
||||||
"mp_spear": "Rammaza",
|
|
||||||
"mp_spear_pm": "Rammaza (Night)",
|
|
||||||
"mp_petrograd": "St. Petrograd",
|
|
||||||
"mp_m_hill": "Hill",
|
|
||||||
"mp_m_king": "King",
|
|
||||||
"mp_m_speedball": "Speedball",
|
|
||||||
"mp_m_showers": "Gulag Showers",
|
|
||||||
"mp_downtown_gw": "Tarvosk District",
|
|
||||||
"mp_m_speed": "Shoot House",
|
|
||||||
"mp_farms2_gw": "Krovnik Farmland",
|
|
||||||
"mp_port2_gw": "Port",
|
|
||||||
"mp_crash": "Crash",
|
|
||||||
"mp_vacant": "Vacant",
|
|
||||||
"mp_shipment": "Shipment",
|
|
||||||
"mp_m_cargo": "Cargo",
|
|
||||||
"mp_m_cage": "Atrium",
|
|
||||||
"mp_m_overwinter": "Docks",
|
|
||||||
"mp_emporium": "Atlas Superstore",
|
|
||||||
"mp_rust": "Rust",
|
|
||||||
"mp_boneyard_gw": "Zhokov Boneyard",
|
|
||||||
"mp_m_fork": "Bazaar",
|
|
||||||
"mp_donetsk": "Verdansk",
|
|
||||||
"mp_hideout": "Khandor Hideout",
|
|
||||||
"loading_mp_hideout": "Khandor Hideout",
|
|
||||||
"mp_aniyah_tac": "Aniyah Incursion",
|
|
||||||
"mp_backlot": "Talsik Backlot",
|
|
||||||
"mp_village": "Hovec Sawmill",
|
|
||||||
"mp_hardhat": "Hardhat",
|
|
||||||
"mp_m_wallco": "Aisle 9",
|
|
||||||
"mp_donetsk": "Verdansk",
|
|
||||||
"mp_scrapyard": "Zhokov Scrapyard",
|
|
||||||
"mp_m_trench": "Trench",
|
|
||||||
"mp_promenade_gw": "Barakett Promenade",
|
|
||||||
"mp_don": "Verdansk",
|
|
||||||
"mp_garden": "Cheshire Park",
|
|
||||||
"mp_oilrig": "Petrov Oil Rig",
|
|
||||||
"mp_harbor": "Suldal Harbor",
|
|
||||||
"mp_layover_gw": "Verdansk International Airport",
|
|
||||||
"mp_m_cornfield": "Livestock",
|
|
||||||
"mp_m_stadium": "Verdansk Stadium",
|
|
||||||
"mp_malyshev": "Mialstor Tank Factory",
|
|
||||||
"mp_malyshev_10v10": "Mialstor Tank Factory",
|
|
||||||
"mp_broadcast": "Broadcast",
|
|
||||||
"mp_riverside_gw": "Verdansk Riverside",
|
|
||||||
"mp_m_train": "Station",
|
|
||||||
"mp_kstenod": "Verdansk (Night)",
|
|
||||||
"mp_escape": "Rebirth",
|
|
||||||
"mp_herat": "Al-Raab Airbase",
|
|
||||||
"mp_killhouse": "Killhouse",
|
|
||||||
"mp_m_drainage": "Drainage",
|
|
||||||
# Gamemodes
|
|
||||||
"war": "Team Deathmatch",
|
|
||||||
"sd": "Search and Destroy",
|
|
||||||
"dom": "Domination",
|
|
||||||
"tdef": "Team Defender",
|
|
||||||
"dm": "Free-for-all",
|
|
||||||
"koth": "Hardpoint",
|
|
||||||
"hq": "Headquarters",
|
|
||||||
"arena": "Gunfight",
|
|
||||||
"arm": "Ground War",
|
|
||||||
"conf": "Kill Confirmed",
|
|
||||||
"cyber": "Cyber Attack",
|
|
||||||
"hc_war": "Team Deathmatch Hardcore",
|
|
||||||
"hc_arena": "Gunfight Hardcore",
|
|
||||||
"hc_arm": "Ground War Hardcore",
|
|
||||||
"hc_conf": "Kill Confirmed Hardcore",
|
|
||||||
"hc_cyber": "Cyber Attack Hardcore",
|
|
||||||
"hc_dm": "Free-for-all Hardcore",
|
|
||||||
"hc_hq": "Headquarters Hardcore",
|
|
||||||
"hc_dom": "Domination Hardcore",
|
|
||||||
"hc_sd": "Search and Destroy Hardcore",
|
|
||||||
"cyber_hc": "Cyber Attack Hardcore",
|
|
||||||
"war_hc": "Team Deathmatch Hardcore",
|
|
||||||
"dom_hc": "Domination Hardcore",
|
|
||||||
"sd_hc": "Search and Destroy Hardcore",
|
|
||||||
"conf_hc": "Kill Confirmed Hardcore",
|
|
||||||
"gun": "Gun Game",
|
|
||||||
"gun_hc": "Gun Game Hardcore",
|
|
||||||
"siege": "Reinforce",
|
|
||||||
"infect": "Infected",
|
|
||||||
"arena_osp": "Gunfight O.S.P.",
|
|
||||||
"hq_hc": "Headquarters Hardcore",
|
|
||||||
"grnd": "Grind",
|
|
||||||
"grind": "Grind",
|
|
||||||
"ctf": "Capture the Flag",
|
|
||||||
"br_all": "All",
|
|
||||||
"br": "Battle Royale",
|
|
||||||
"br_dmz": "Plunder",
|
|
||||||
"br_dmz_38": "Plunder Quads",
|
|
||||||
"br_87": "BR Solos",
|
|
||||||
"br_dmz_104": "Blood Money",
|
|
||||||
"koth_hc": "Hardpoint Hardcore",
|
|
||||||
"br_25": "BR Trios",
|
|
||||||
"br_89": "BR Quads",
|
|
||||||
"br_dmz_76": "Plunder Quads",
|
|
||||||
"br_77": "BR Scopes & Scatterguns",
|
|
||||||
"br_dmz_85": "Plunder Duos",
|
|
||||||
"dd_hc": "Demolition Hardcore",
|
|
||||||
"dd": "Demolition",
|
|
||||||
"br_71": "BR Solos",
|
|
||||||
"br_74": "BR Trios",
|
|
||||||
"br_88": "BR Duos",
|
|
||||||
"brtdm_113": "Warzone Rumble",
|
|
||||||
"brtdm_rmbl": "Warzone Rumble",
|
|
||||||
"br_brsolo": "BR Solos",
|
|
||||||
"br_brduos": "BR Duos",
|
|
||||||
"br_brtrios": "BR Trios",
|
|
||||||
"br_brquads": "BR Quads",
|
|
||||||
"br_dmz_plnbld": "Blood Money",
|
|
||||||
"br_br_real": "Realism Battle Royale",
|
|
||||||
"br_86": "Realism Battle Royale",
|
|
||||||
"br_brthquad": "BR 200 Quads",
|
|
||||||
"br_jugg_brtriojugr": "Juggernaut Royal Trios",
|
|
||||||
"br_dmz_plunquad": "Plunder Quads",
|
|
||||||
"br_dmz_bldmnytrio": "Blood Money Trios",
|
|
||||||
"br_mini_miniroyale": "Mini Royale",
|
|
||||||
"br_brbbsolo": "BR Buyback Solos",
|
|
||||||
"br_jugg_brquadjugr": "Juggernaut Royal Quads",
|
|
||||||
"br_kingslayer_kingsltrios": "King Slayer Trios",
|
|
||||||
"br_truckwar_trwarsquads": "Armored Royale Quads",
|
|
||||||
"br_zxp_zmbroy": "Zombie Royale",
|
|
||||||
"br_brhwntrios": "BR Trick-Or-Trios",
|
|
||||||
"rugby": "Onslaughter",
|
|
||||||
"br_brsolohwn": "BR Solo Survivor",
|
|
||||||
"br_dmz_plndcndy": "Plunder: Candy Collector",
|
|
||||||
"br_jugg_jugpmpkn": "Juggourdnaut Royale",
|
|
||||||
"br_rebirth_rbrthtrios": "Resurgence Trio",
|
|
||||||
"br_rebirth_rbrthduos": "Resurgence Duos",
|
|
||||||
"br_rebirth_rbrthquad": "Rebirth Resurgance Quads",
|
|
||||||
"br_dmz_plndtrios": "Plunder Trios",
|
|
||||||
"br_rebirth_resurgence_trios": "Verdansk Resurgence Trios",
|
|
||||||
"br_mini_rebirth_mini_royale_quads": "Rebirth Mini Royale Quads",
|
|
||||||
"br_bodycount_pwergrb": "Power Grab",
|
|
||||||
"br_rebirth_resurgence_mini": "Verdansk Resurgence Mini",
|
|
||||||
"br_payload_payload": "Payload",
|
|
||||||
"br_mini_rebirth_mini_royale_trios": "Rebirth Mini Royale Trios",
|
|
||||||
"br_x2_br_reveal_x2_event/event_title_x2": "Battle of Verdansk",
|
|
||||||
"br_rumble_clash": "Clash",
|
|
||||||
"br_dbd_dbd": "Iron Trials '84",
|
|
||||||
"br_gxp_gov": "Ghosts of Verdansk",
|
|
||||||
# Weapons
|
|
||||||
"scorestreak": "Scorestreak",
|
|
||||||
"equipment": "Equipment",
|
|
||||||
"gear": "Gear",
|
|
||||||
"weapon_bare_hands": "Bare Hands",
|
|
||||||
"weapon_tactical_rifle": "Tactical Rifle",
|
|
||||||
"weapon_shotgun": "Shotgun",
|
|
||||||
"weapon_sniper": "Sniper",
|
|
||||||
"weapon_lmg": "Light Machine Guns",
|
|
||||||
"weapon_launcher": "Launcher",
|
|
||||||
"weapon_pistol": "Pistol",
|
|
||||||
"weapon_smg": "Submachine Guns",
|
|
||||||
"weapon_melee": "Melee",
|
|
||||||
"weapon_assault_rifle": "Assault Rifle",
|
|
||||||
"attachments": "Attachments",
|
|
||||||
"weapons": "Weapons",
|
|
||||||
"specialist": "Specialist",
|
|
||||||
"weapon": "Weapon",
|
|
||||||
"weapon_special": "Special",
|
|
||||||
"iw8_ar_akilo47": "AK-47",
|
|
||||||
"iw8_ar_kilo433": "Kilo-141",
|
|
||||||
"iw8_ar_mcharlie": "M13",
|
|
||||||
"iw8_ar_falima": "FAL",
|
|
||||||
"iw8_ar_asierra12": "Oden",
|
|
||||||
"iw8_sm_mpapa7": "MP7",
|
|
||||||
"iw8_sm_augolf": "AUG",
|
|
||||||
"iw8_sm_uzulu": "Uzi",
|
|
||||||
"iw8_sh_romeo870": "Model 680",
|
|
||||||
"iw8_sh_charlie725": "725",
|
|
||||||
"iw8_sh_aalpha12": "JAK-12",
|
|
||||||
"iw8_sh_oscar12": "Origin 12",
|
|
||||||
"iw8_lm_pkilo": "PKM",
|
|
||||||
"iw8_lm_mgolf34": "MG34",
|
|
||||||
"iw8_lm_lima86": "SA87",
|
|
||||||
"iw8_lm_dblmg": "MP Juggernaut",
|
|
||||||
"iw8_sn_mike14": "EBR-14",
|
|
||||||
"iw8_sn_delta": "Dragunov",
|
|
||||||
"iw8_sn_alpha50": "AX-50",
|
|
||||||
"iw8_sn_hdromeo": "HDR",
|
|
||||||
"iw8_sn_sbeta": "Mk2 Carbine",
|
|
||||||
"iw8_pi_papa320": "M19",
|
|
||||||
"iw8_pi_cpapa": ".357",
|
|
||||||
"iw8_la_rpapa7": "RPG-7",
|
|
||||||
"iw8_la_juliet": "JOKR",
|
|
||||||
"iw8_la_gromeo": "PILA",
|
|
||||||
"iw8_la_kgolf": "Strela-P",
|
|
||||||
"iw8_me_riotshield": "Riot Shield",
|
|
||||||
"equip_gas_grenade": "Gas Grenade",
|
|
||||||
"equip_snapshot_grenade": "Snapshot Grenade",
|
|
||||||
"equip_decoy": "Decoy Grenade",
|
|
||||||
"equip_smoke": "Smoke Grenade",
|
|
||||||
"equip_concussion": "Stun Grenade",
|
|
||||||
"equip_hb_sensor": "Heartbeat Sensor",
|
|
||||||
"equip_flash": "Flash Grenade",
|
|
||||||
"equip_adrenaline": "Stim",
|
|
||||||
"equip_frag": "Frag Grenade",
|
|
||||||
"equip_thermite": "Thermite",
|
|
||||||
"equip_semtex": "Semtex",
|
|
||||||
"equip_claymore": "Claymore",
|
|
||||||
"equip_c4": "C4",
|
|
||||||
"equip_at_mine": "Proximity Mine",
|
|
||||||
"equip_throwing_knife": "Throwing Knife",
|
|
||||||
"equip_molotov": "Molotov Cocktail",
|
|
||||||
"iw8_knife": "Combat Knife",
|
|
||||||
"weapon_other": "Primary Melee",
|
|
||||||
"iw8_ar_tango21": "RAM-7",
|
|
||||||
"iw8_ar_falpha": "FR 5.56",
|
|
||||||
"iw8_ar_mike4": "M4A1",
|
|
||||||
"iw8_sm_papa90": "P90",
|
|
||||||
"iw8_sm_mpapa5": "MP5",
|
|
||||||
"iw8_sm_beta": "PP19 Bizon",
|
|
||||||
"iw8_sh_dpapa12": "R9-0",
|
|
||||||
"iw8_lm_mgolf36": "Holger-26",
|
|
||||||
"iw8_sn_kilo98": "Kar98k",
|
|
||||||
"iw8_pi_mike1911": "1911",
|
|
||||||
"iw8_pi_golf21": "X16",
|
|
||||||
"iw8_pi_decho": ".50 GS",
|
|
||||||
"weapon_marksman": "Marksman Rifles",
|
|
||||||
"iw8_lm_kilo121": "M91",
|
|
||||||
"iw8_ar_scharlie": "FN Scar 17",
|
|
||||||
"iw8_ar_sierra552": "Grau 5.56",
|
|
||||||
"iw8_sm_smgolf45": "Striker 45",
|
|
||||||
"iw8_pi_mike9a3": "Renetti",
|
|
||||||
"iw8_lm_mkilo3": "Bruen MK9",
|
|
||||||
"iw8_sh_mike26": "VLK Rogue",
|
|
||||||
"iw8_sn_crossbow": "Crossbow",
|
|
||||||
"iw8_sn_sksierra": "SKS",
|
|
||||||
"iw8_ar_galima": "CR-56 AMAX",
|
|
||||||
"iw8_me_kalistick": "Kali Sticks",
|
|
||||||
"iw8_sm_victor": "Fennec Mk9",
|
|
||||||
"iw8_sn_xmike109": "Rytec AMR",
|
|
||||||
"iw8_pi_mike9": "Renetti",
|
|
||||||
"iw8_me_akimboblunt": "Kali Sticks",
|
|
||||||
"iw8_ar_anovember94": "AN-94",
|
|
||||||
"iw8_sm_charlie9": "ISO",
|
|
||||||
"iw8_me_akimboblades": "Dual Kodachis",
|
|
||||||
"iw8_lm_sierrax": "FiNN",
|
|
||||||
"iw8_ar_valpha": "AS VAL",
|
|
||||||
"iw8_sn_romeo700": "SP-R 208",
|
|
||||||
"cruise_predator": "Cruise Missile",
|
|
||||||
"manual_turret": "Shield Turret",
|
|
||||||
"toma_strike": "Cluster Strike",
|
|
||||||
"sentry_gun": "Sentry Gun",
|
|
||||||
"hover_jet": "VTOL Jet",
|
|
||||||
"precision_airstrike": "Precision Airstrike",
|
|
||||||
"juggernaut": "Juggernaut",
|
|
||||||
"pac_sentry": "",
|
|
||||||
"chopper_gunner": "Chopper Gunner",
|
|
||||||
"gunship": "Gunship",
|
|
||||||
"white_phosphorus": "White Phosphorus",
|
|
||||||
"nuke": "Nuke",
|
|
||||||
"chopper_support": "Support Helo",
|
|
||||||
"bradley": "Infantry Assault Vehicle",
|
|
||||||
"uav": "UAV",
|
|
||||||
"directional_uav": "Advanced UAV",
|
|
||||||
"airdrop": "Care Package",
|
|
||||||
"airdrop_multiple": "Emergency Airdrop",
|
|
||||||
"radar_drone_overwatch": "Personal Radar",
|
|
||||||
"scrambler_drone_guard": "Counter UAV",
|
|
||||||
"super_emp_drone": "EMP Drone",
|
|
||||||
"super_trophy": "Trophy System",
|
|
||||||
"super_ammo_drop": "Munitions Box",
|
|
||||||
"super_weapon_drop": "Weapon Drop",
|
|
||||||
"super_fulton": "Cash Deposit Balloon",
|
|
||||||
"super_armor_drop": "Armor Box",
|
|
||||||
"super_select": "Field Upgrade Pro (Any)",
|
|
||||||
"super_tac_insert": "Tactical Insertion",
|
|
||||||
"super_recon_drone": "Recon Drone",
|
|
||||||
"super_deadsilence": "Dead Silence",
|
|
||||||
"super_supply_drop": "Loadout Drop", ### Unsure if this is Loadout Drop
|
|
||||||
"super_tac_cover": "Deployable Cover",
|
|
||||||
"super_support_box": "Stopping Power Rounds",
|
|
||||||
# Accolades
|
|
||||||
# "accoladeData": "Accolades",
|
|
||||||
# "classChanges": "Most classes changed (Evolver)",
|
|
||||||
# "highestAvgAltitude": "Highest average altitude (High Command)",
|
|
||||||
# "killsFromBehind": "Most kills from behind (Flanker)",
|
|
||||||
# "lmgDeaths": "Most LMG deaths (Target Practice)",
|
|
||||||
# "riotShieldDamageAbsorbed": "Most damage absorbed with Riot Shield (Guardian)",
|
|
||||||
# "flashbangHits": "Most Flashbang hits (Blinder)",
|
|
||||||
# "meleeKills": "Most Melee kills (Brawler)",
|
|
||||||
# "tagsLargestBank": "Largest bank (Bank Account)",
|
|
||||||
# "shotgunKills": "Most Shotgun kills (Buckshot)",
|
|
||||||
# "sniperDeaths": "Most Sniper deaths (Zeroed In)",
|
|
||||||
# "timeProne": "Most time spent Prone (Grassy Knoll)",
|
|
||||||
# "killstreakWhitePhosphorousKillsAssists": "Most kills and assists with White Phosphorus (Burnout)",
|
|
||||||
# "shortestLife": "Shortest life (Terminal)",
|
|
||||||
# "deathsFromBehind": "Most deaths from behind (Blindsided)",
|
|
||||||
# "higherRankedKills": "Most kills on higher ranked scoreboard players (Upriser)",
|
|
||||||
# "mostAssists": "Most assists (Wingman)",
|
|
||||||
# "leastKills": "Fewest kills (The Fearful)",
|
|
||||||
# "tagsDenied": "Denied the most tags (Denied)",
|
|
||||||
# "killstreakWheelsonKills": "Most Wheelson kills",
|
|
||||||
# "sniperHeadshots": "Most Sniper headshots (Dead Aim)",
|
|
||||||
# "killstreakJuggernautKills": "Most Juggernaut kills (Heavy Metal)",
|
|
||||||
# "smokesUsed": "Most Smoke Grenades used (Chimney)",
|
|
||||||
# "avengerKills": "Most avenger kills (Avenger)",
|
|
||||||
# "decoyHits": "Most Decoy Grenade hits (Made You Look)",
|
|
||||||
# "killstreakCarePackageUsed": "Most Care Packages called in (Helping Hand)",
|
|
||||||
# "molotovKills": "Most Molotov kills (Arsonist)",
|
|
||||||
# "gasHits": "Most Gas Grenade hits (Gaseous)",
|
|
||||||
# "comebackKills": "Most comebacks (Rally)",
|
|
||||||
# "lmgHeadshots": "Most LMG headshots (LMG Expert)",
|
|
||||||
# "smgDeaths": "Most SMG deaths (Run and Gunned)",
|
|
||||||
# "carrierKills": "Most kills as carrier (Carrier)",
|
|
||||||
# "deployableCoverUsed": "Most Deployable Covers used (Combat Engineer)",
|
|
||||||
# "thermiteKills": "Most Thermite kills (Red Iron)",
|
|
||||||
# "arKills": "Most assault rifle kills (AR Specialist)",
|
|
||||||
# "c4Kills": "Most C4 kills (Handle With Care)",
|
|
||||||
# "suicides": "Most suicides (Accident Prone)",
|
|
||||||
# "clutch": "Most kills as the last alive (Clutched)",
|
|
||||||
# "survivorKills": "Most kills as survivor (Survivalist)",
|
|
||||||
# "killstreakGunshipKills": "Most Gunship kills (Death From Above)",
|
|
||||||
# "timeSpentAsPassenger": "Most time spent as a passenger (Navigator)",
|
|
||||||
# "returns": "Most flags returned (Flag Returner)",
|
|
||||||
# "smgHeadshots": "Most SMG headshots (SMG Expert)",
|
|
||||||
# "launcherDeaths": "Most launcher deaths (Fubar)",
|
|
||||||
# "oneShotOneKills": "Most one shot kills (One Shot Kill)",
|
|
||||||
# "ammoBoxUsed": "Most Munitions Boxes used (Provider)",
|
|
||||||
# #"spawnSelectSquad": "",
|
|
||||||
# "weaponPickups": "Most picked up weapons (Loaner)",
|
|
||||||
# "pointBlankKills": "Most point blank kills (Personal Space)",
|
|
||||||
# "tagsCaptured": "Collected the most tags (Confirmed Kills)",
|
|
||||||
# "killstreakGroundKills": "Most ground based killstreak kills (Ground Control)",
|
|
||||||
# "distanceTraveledInVehicle": "Longest distance travelled in a vehicle (Cross Country)",
|
|
||||||
# "longestLife": "Longest life (Lifer)",
|
|
||||||
# "stunHits": "Most Stun Grenade hits (Stunner)",
|
|
||||||
# "spawnSelectFlag": "Most FOB Spawns (Objective Focused)", # Unsure
|
|
||||||
# "shotgunHeadshots": "Most Shotgun headshots (Boomstick)",
|
|
||||||
# "bombDefused": "Most defuses (Defuser)",
|
|
||||||
# "snapshotHits": "Most Snapshot Grenade hits (Photographer)",
|
|
||||||
# "noKillsWithDeath": "No kills with at least 1 death (Participant)",
|
|
||||||
# "killstreakAUAVAssists": "Most Advanced UAV assists (Target Rich Environment)",
|
|
||||||
# "killstreakPersonalUAVKills": "Most kills with a Personal Radar active (Nothing Personal)",
|
|
||||||
# "tacticalInsertionSpawns": "Most Tactical Insertions used (Revenant)",
|
|
||||||
# "launcherKills": "Most Launcher kills (Explosive)",
|
|
||||||
# "spawnSelectVehicle": "Most vehicle spawns (Oscar Mike)",
|
|
||||||
# "mostKillsLeastDeaths": "Most kills and fewest deaths (MVP)",
|
|
||||||
# "mostKills": "Most kills (The Feared)",
|
|
||||||
# "defends": "Most defend kills (Defense)",
|
|
||||||
# "timeSpentAsDriver": "Most time spent driving (Driver)",
|
|
||||||
# "": "" # WIP - Still adding more
|
|
||||||
}
|
|
||||||
|
|
||||||
# Initiating the API class
|
# Initiating the API class
|
||||||
api = API()
|
api = API()
|
||||||
COOKIE_FILE = 'cookie.txt'
|
COOKIE_FILE = 'cookie.txt'
|
||||||
@ -383,7 +23,7 @@ def save_to_file(data, filename, dir_name='stats'):
|
|||||||
with open(os.path.join(dir_name, filename), 'w') as json_file:
|
with open(os.path.join(dir_name, filename), 'w') as json_file:
|
||||||
json.dump(data, json_file, indent=4)
|
json.dump(data, json_file, indent=4)
|
||||||
|
|
||||||
def get_and_save_data(player_name=None, all_stats=False, season_loot=False, identities=False, maps=False):
|
def get_and_save_data(player_name=None, all_stats=False, season_loot=False, identities=False, maps=False, info=False, friendFeed=False, eventFeed=False, cod_points=False, connected_accounts=False, settings=False):
|
||||||
# Create the stats directory if it doesn't exist
|
# Create the stats directory if it doesn't exist
|
||||||
DIR_NAME = 'stats'
|
DIR_NAME = 'stats'
|
||||||
if not os.path.exists(DIR_NAME):
|
if not os.path.exists(DIR_NAME):
|
||||||
@ -398,6 +38,12 @@ def get_and_save_data(player_name=None, all_stats=False, season_loot=False, iden
|
|||||||
with open(COOKIE_FILE, 'w') as f:
|
with open(COOKIE_FILE, 'w') as f:
|
||||||
f.write(api_key)
|
f.write(api_key)
|
||||||
|
|
||||||
|
# # Check if userInfo.json exists, create it if it doesn't
|
||||||
|
USER_INFO_FILE = os.path.join('userInfo.json')
|
||||||
|
# if not os.path.exists(USER_INFO_FILE):
|
||||||
|
# with open(USER_INFO_FILE, 'w') as f:
|
||||||
|
# pass # Creates an empty file
|
||||||
|
|
||||||
# If player_name is not provided via command line, get it from user input
|
# If player_name is not provided via command line, get it from user input
|
||||||
if not player_name:
|
if not player_name:
|
||||||
player_name = input("Please enter the player's username (with #1234567): ")
|
player_name = input("Please enter the player's username (with #1234567): ")
|
||||||
@ -407,25 +53,47 @@ def get_and_save_data(player_name=None, all_stats=False, season_loot=False, iden
|
|||||||
|
|
||||||
# Retrieve data from API
|
# Retrieve data from API
|
||||||
# First, determine if any specific optional arguments were given
|
# First, determine if any specific optional arguments were given
|
||||||
if not (all_stats or season_loot or identities or maps):
|
if not (all_stats or season_loot or identities or maps or info or friendFeed or eventFeed or cod_points or connected_accounts or settings):
|
||||||
# If no specific optional arguments are given, then default behavior:
|
# If no specific optional arguments are given, then default behavior:
|
||||||
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||||
save_to_file(player_stats, 'stats.json')
|
save_to_file(player_stats, 'stats.json')
|
||||||
save_to_file(match_info, 'match_info.json')
|
save_to_file(match_info, 'match_info.json')
|
||||||
elif all_stats:
|
elif all_stats: # If the all_stats argument is given:
|
||||||
# If the all_stats argument is given:
|
if os.path.exists(USER_INFO_FILE): # Check if the userInfo.json file exists
|
||||||
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
season_loot_data = api.ModernWarfare.seasonLoot(platforms.Activision, player_name)
|
||||||
season_loot_data = api.ModernWarfare.seasonLoot(platforms.Activision, player_name)
|
identities_data = api.Me.loggedInIdentities()
|
||||||
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
||||||
identities_data = api.Me.loggedInIdentities()
|
info = api.Me.info()
|
||||||
save_to_file(player_stats, 'stats.json')
|
friendFeed = api.Me.friendFeed()
|
||||||
save_to_file(match_info, 'match_info.json')
|
eventFeed = api.Me.eventFeed()
|
||||||
save_to_file(season_loot_data, 'season_loot.json')
|
cod_points = api.Me.codPoints()
|
||||||
save_to_file(map_list, 'map_list.json')
|
connectedAccounts = api.Me.connectedAccounts()
|
||||||
save_to_file(identities_data, 'identities.json')
|
settings = api.Me.settings()
|
||||||
|
save_to_file(player_stats, 'stats.json')
|
||||||
|
save_to_file(match_info, 'match_info.json')
|
||||||
|
save_to_file(season_loot_data, 'season_loot.json')
|
||||||
|
save_to_file(map_list, 'map_list.json')
|
||||||
|
save_to_file(identities_data, 'identities.json')
|
||||||
|
save_to_file(info, 'info.json')
|
||||||
|
save_to_file(friendFeed, 'friendFeed.json')
|
||||||
|
save_to_file(eventFeed, 'eventFeed.json')
|
||||||
|
save_to_file(cod_points, 'cp.json')
|
||||||
|
save_to_file(connectedAccounts, 'connectedAccounts.json')
|
||||||
|
save_to_file(settings, 'settings.json')
|
||||||
|
else:
|
||||||
|
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||||
|
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||||
|
season_loot_data = api.ModernWarfare.seasonLoot(platforms.Activision, player_name)
|
||||||
|
identities_data = api.Me.loggedInIdentities()
|
||||||
|
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
||||||
|
save_to_file(player_stats, 'stats.json')
|
||||||
|
save_to_file(match_info, 'match_info.json')
|
||||||
|
save_to_file(season_loot_data, 'season_loot.json')
|
||||||
|
save_to_file(map_list, 'map_list.json')
|
||||||
|
save_to_file(identities_data, 'identities.json')
|
||||||
else:
|
else:
|
||||||
# For other specific optional arguments:
|
# For other specific optional arguments:
|
||||||
if season_loot:
|
if season_loot:
|
||||||
@ -438,23 +106,58 @@ def get_and_save_data(player_name=None, all_stats=False, season_loot=False, iden
|
|||||||
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
||||||
save_to_file(map_list, 'map_list.json')
|
save_to_file(map_list, 'map_list.json')
|
||||||
|
|
||||||
|
if info:
|
||||||
|
info = api.Me.info()
|
||||||
|
save_to_file(info, 'info.json')
|
||||||
|
if friendFeed:
|
||||||
|
friendFeed = api.Me.friendFeed()
|
||||||
|
save_to_file(friendFeed, 'friendFeed.json')
|
||||||
|
if eventFeed:
|
||||||
|
eventFeed = api.Me.eventFeed()
|
||||||
|
save_to_file(eventFeed, 'eventFeed.json')
|
||||||
|
if cod_points:
|
||||||
|
cod_points = api.Me.codPoints()
|
||||||
|
save_to_file(cod_points, 'cp.json')
|
||||||
|
if connected_accounts:
|
||||||
|
connectedAccounts = api.Me.connectedAccounts()
|
||||||
|
save_to_file(connectedAccounts, 'connectedAccounts.json')
|
||||||
|
if settings:
|
||||||
|
settings = api.Me.settings()
|
||||||
|
save_to_file(settings, 'settings.json')
|
||||||
|
|
||||||
# Save results to a JSON file inside the stats directory
|
# Save results to a JSON file inside the stats directory
|
||||||
def recursive_key_replace(obj, replacements):
|
def recursive_key_replace(obj):
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
new_obj = {}
|
new_obj = {}
|
||||||
for key, value in obj.items():
|
for key, value in obj.items():
|
||||||
new_key = replacements.get(key, key)
|
new_key = replacements.get(key, key)
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
new_value = replacements.get(value, value)
|
new_value = replacements.get(value, value)
|
||||||
new_obj[new_key] = recursive_key_replace(new_value, replacements)
|
new_obj[new_key] = recursive_key_replace(new_value)
|
||||||
else:
|
else:
|
||||||
new_obj[new_key] = recursive_key_replace(value, replacements)
|
new_obj[new_key] = recursive_key_replace(value)
|
||||||
return new_obj
|
return new_obj
|
||||||
elif isinstance(obj, list):
|
elif isinstance(obj, list):
|
||||||
return [recursive_key_replace(item, replacements) for item in obj]
|
return [recursive_key_replace(item) for item in obj]
|
||||||
else:
|
else:
|
||||||
return replacements.get(obj, obj) if isinstance(obj, str) else obj
|
return replacements.get(obj, obj) if isinstance(obj, str) else obj
|
||||||
|
|
||||||
|
def clean_json_files(*filenames, dir_name='stats'):
|
||||||
|
regex_pattern = r'<span class="|</span>|">|mp-stat-items|kills-value|headshots-value|username|game-mode|kdr-value'
|
||||||
|
replace = ''
|
||||||
|
|
||||||
|
for filename in filenames:
|
||||||
|
file_path = os.path.join(dir_name, filename)
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
with open(file_path, 'r') as file:
|
||||||
|
content = file.read()
|
||||||
|
modified_content = re.sub(regex_pattern, replace, content)
|
||||||
|
with open(file_path, 'w') as file:
|
||||||
|
file.write(modified_content)
|
||||||
|
print(f"Cleaned {filename}.")
|
||||||
|
else:
|
||||||
|
print(f"{filename} does not exist, skipping.")
|
||||||
|
|
||||||
def sort_data(data):
|
def sort_data(data):
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
@ -558,7 +261,7 @@ def beautify_data():
|
|||||||
with open(file_path, 'r') as file:
|
with open(file_path, 'r') as file:
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
replace_time_and_duration_recursive(data)
|
replace_time_and_duration_recursive(data)
|
||||||
data = recursive_key_replace(data, replacements)
|
data = recursive_key_replace(data)
|
||||||
data = sort_data(data)
|
data = sort_data(data)
|
||||||
with open(file_path, 'w') as file:
|
with open(file_path, 'w') as file:
|
||||||
json.dump(data, file, indent=4)
|
json.dump(data, file, indent=4)
|
||||||
@ -569,7 +272,7 @@ def beautify_match_data():
|
|||||||
with open(file_path, 'r') as file:
|
with open(file_path, 'r') as file:
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
replace_time_and_duration_recursive(data)
|
replace_time_and_duration_recursive(data)
|
||||||
data = recursive_key_replace(data, replacements)
|
data = recursive_key_replace(data)
|
||||||
with open(file_path, 'w') as file:
|
with open(file_path, 'w') as file:
|
||||||
json.dump(data, file, indent=4)
|
json.dump(data, file, indent=4)
|
||||||
print(f"Keys replaced in {file_path}.")
|
print(f"Keys replaced in {file_path}.")
|
||||||
@ -639,14 +342,22 @@ def main():
|
|||||||
group_data.add_argument("-p", "--player_name", type=str, help="Player's username (with #1234567)")
|
group_data.add_argument("-p", "--player_name", type=str, help="Player's username (with #1234567)")
|
||||||
group_data.add_argument("-a", "--all_stats", action="store_true", help="Fetch all the different types of stats data")
|
group_data.add_argument("-a", "--all_stats", action="store_true", help="Fetch all the different types of stats data")
|
||||||
group_data.add_argument("-sl", "--season_loot", action="store_true", help="Fetch only the season loot data")
|
group_data.add_argument("-sl", "--season_loot", action="store_true", help="Fetch only the season loot data")
|
||||||
group_data.add_argument("-i", "--identities", action="store_true", help="Fetch only the logged-in identities data")
|
group_data.add_argument("-id", "--identities", action="store_true", help="Fetch only the logged-in identities data")
|
||||||
group_data.add_argument("-m", "--maps", action="store_true", help="Fetch only the map list data")
|
group_data.add_argument("-m", "--maps", action="store_true", help="Fetch only the map list data")
|
||||||
|
group_data.add_argument("-i", "--info", action="store_true", help="Fetch only general information")
|
||||||
|
group_data.add_argument("-f", "--friendFeed", action="store_true", help="Fetch only your friend feed")
|
||||||
|
group_data.add_argument("-e", "--eventFeed", action="store_true", help="Fetch only your event feed")
|
||||||
|
group_data.add_argument("-cp", "--cod_points", action="store_true", help="Fetch only your COD Point balance")
|
||||||
|
group_data.add_argument("-ca", "--connected_accounts", action="store_true", help="Fetch only the map list data")
|
||||||
|
group_data.add_argument("-s", "--settings", action="store_true", help="Fetch only your account settings")
|
||||||
|
|
||||||
# Add arguments for Cleaning Options
|
# Add arguments for Cleaning Options
|
||||||
group_cleaning.add_argument("-c", "--clean", action="store_true", help="Beautify all data")
|
group_cleaning.add_argument("-c", "--clean", action="store_true", help="Beautify all data")
|
||||||
group_cleaning.add_argument("-sm", "--split_matches", action="store_true", help="Split the matches into separate JSON files within the 'matches' subfolder")
|
group_cleaning.add_argument("-sm", "--split_matches", action="store_true", help="Split the matches into separate JSON files within the 'matches' subfolder")
|
||||||
group_cleaning.add_argument("-csd", "--clean_stats_data", action="store_true", help="Beautify the data and convert to human-readable strings in stats.json")
|
group_cleaning.add_argument("-csd", "--clean_stats_data", action="store_true", help="Beautify the data and convert to human-readable strings in stats.json")
|
||||||
group_cleaning.add_argument("-cmd", "--clean_match_data", action="store_true", help="Beautify the match data and convert to human-readable strings in match_info.json")
|
group_cleaning.add_argument("-cmd", "--clean_match_data", action="store_true", help="Beautify the match data and convert to human-readable strings in match_info.json")
|
||||||
|
group_cleaning.add_argument("-cff", "--clean_friend_feed", action="store_true", help="Clean the friend feed data")
|
||||||
|
group_cleaning.add_argument("-cef", "--clean_event_feed", action="store_true", help="Clean the event feed data")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -669,8 +380,13 @@ def main():
|
|||||||
elif args.clean:
|
elif args.clean:
|
||||||
beautify_data()
|
beautify_data()
|
||||||
beautify_match_data()
|
beautify_match_data()
|
||||||
|
clean_json_files('friendFeed.json', 'eventFeed.json')
|
||||||
|
elif args.clean_friend_feed:
|
||||||
|
clean_json_files('friendFeed.json')
|
||||||
|
elif args.clean_event_feed:
|
||||||
|
clean_json_files('eventFeed.json')
|
||||||
else:
|
else:
|
||||||
get_and_save_data(args.player_name, args.all_stats, args.season_loot, args.identities, args.maps)
|
get_and_save_data(args.player_name, args.all_stats, args.season_loot, args.identities, args.maps, args.info, args.friendFeed, args.eventFeed, args.cod_points, args.connected_accounts, args.settings)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
Loading…
Reference in New Issue
Block a user