mirror of
https://github.com/Ahrimdon/detailed-cod-tracker.git
synced 2024-11-25 00:41:58 -05:00
Add python build script, use modified api, add dev scripts, add regex for cleaning feeds, allow for api calls using userinfo
This commit is contained in:
parent
0aadb24ff3
commit
563b2c28f7
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,4 +3,4 @@ uninstall.*
|
||||
venv.*
|
||||
/venv
|
||||
/HTML
|
||||
/legacy
|
||||
/stats
|
36
build.py
Normal file
36
build.py
Normal file
@ -0,0 +1,36 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import PyInstaller.__main__
|
||||
|
||||
# Constants for your project
|
||||
SCRIPT = "get_cod_stats.py"
|
||||
ICON = "assets/build/icon/icon.ico"
|
||||
NAME = "get_cod_stats"
|
||||
DIST_PATH = "bin"
|
||||
|
||||
# Path to the 'frequencies.json' file within the charset_normalizer package
|
||||
charset_normalizer_data = os.path.join('deps', 'frequencies.json')
|
||||
|
||||
# Activate the virtual environment
|
||||
venv_activation_script = os.path.join(os.getcwd(), 'venv', 'Scripts', 'activate')
|
||||
subprocess.call(venv_activation_script, shell=True)
|
||||
|
||||
# Run PyInstaller
|
||||
PyInstaller.__main__.run([
|
||||
SCRIPT,
|
||||
'--name', NAME,
|
||||
'--noconfirm',
|
||||
'--onefile',
|
||||
'--console',
|
||||
'--icon', ICON,
|
||||
'--distpath', DIST_PATH,
|
||||
'--add-data', f"{charset_normalizer_data};charset_normalizer/assets"
|
||||
])
|
||||
|
||||
# Clean up the build directory and spec file
|
||||
shutil.rmtree('build', ignore_errors=True)
|
||||
os.remove('get_cod_stats.spec')
|
||||
|
||||
# Optional: Pause at the end (like the 'pause' in batch script)
|
||||
input("Press Enter to continue...")
|
1
clean_friend_feed_regex.txt
Normal file
1
clean_friend_feed_regex.txt
Normal file
@ -0,0 +1 @@
|
||||
<span class="|</span>|">|mp-stat-items|kills-value|headshots-value|username|game-mode|kdr-value
|
732
cod_api/__init__.py
Normal file
732
cod_api/__init__.py
Normal file
@ -0,0 +1,732 @@
|
||||
__version__ = "2.0.1"
|
||||
|
||||
# Imports
|
||||
import asyncio
|
||||
import enum
|
||||
import json
|
||||
import uuid
|
||||
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:
|
||||
# Assuming 'user_info.json' is the file you've downloaded with the information.
|
||||
file_path = 'userInfo.json'
|
||||
# Load the JSON content from the local file.
|
||||
with open(file_path, 'r') as file:
|
||||
rawData = json.load(file)
|
||||
|
||||
try:
|
||||
userInfo = rawData['userInfo'] # Accessing the nested 'userInfo' dictionary.
|
||||
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.
|
||||
for i in identities: # Loop through each identity in the 'identities' list.
|
||||
data['identities'].append({
|
||||
'platform': i['provider'],
|
||||
'gamertag': i['username'],
|
||||
'accountID': i['accountID'] # Assuming 'accountID' exists; otherwise, you might need a default value.
|
||||
})
|
||||
|
||||
return data
|
||||
|
||||
except KeyError as e:
|
||||
# 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)}")
|
||||
# Re-raise the exception or handle it as required for your application's logic.
|
||||
raise
|
||||
|
||||
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."
|
2185
data/everything.json
Normal file
2185
data/everything.json
Normal file
File diff suppressed because it is too large
Load Diff
298
depricated_dev_scripts/beautify_data.py
Normal file
298
depricated_dev_scripts/beautify_data.py
Normal file
@ -0,0 +1,298 @@
|
||||
import json
|
||||
|
||||
def replace_and_sort_keys_in_json(file_path, replacements):
|
||||
"""Replace keys in the JSON file based on the replacements dictionary and sort Accolades."""
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
def recursive_key_replace(obj, replacements):
|
||||
if isinstance(obj, dict):
|
||||
new_obj = {}
|
||||
for key, value in obj.items():
|
||||
new_key = replacements.get(key, key)
|
||||
new_obj[new_key] = recursive_key_replace(value, replacements)
|
||||
|
||||
if new_key == "mode": # Sort Game Modes by 'timePlayed' in descending order
|
||||
sorted_modes = dict(sorted(new_obj[new_key].items(), key=lambda item: item[1]['properties']['timePlayed'], reverse=True))
|
||||
new_obj[new_key] = sorted_modes
|
||||
|
||||
if new_key in ["Assault Rifles", "Shotguns", "Marksman Rifles", "Snipers", "LMGs", "Launchers", "Pistols", "SMGs", "Melee"]: # Sort Weapons by 'kills' in descending order
|
||||
sorted_weapons = dict(sorted(new_obj[new_key].items(), key=lambda item: item[1]['properties']['kills'], reverse=True))
|
||||
new_obj[new_key] = sorted_weapons
|
||||
|
||||
if new_key in ["Field Upgrades"]: # Sort Field Upgrades by 'uses' in descending order
|
||||
sorted_fieldupgrades = dict(sorted(new_obj[new_key].items(), key=lambda item: item[1]['properties']['uses'], reverse=True))
|
||||
new_obj[new_key] = sorted_fieldupgrades
|
||||
|
||||
if new_key in ["Tactical Equipment", "Lethal Equipment"]: # Sort Lethal and Tactical equipment by 'uses' in descending order
|
||||
sorted_equipment = dict(sorted(new_obj[new_key].items(), key=lambda item: item[1]['properties']['uses'], reverse=True))
|
||||
new_obj[new_key] = sorted_equipment
|
||||
|
||||
if new_key == "Scorestreaks": # Sort Lethal and Support Scorestreaks by 'awardedCount' in descending order
|
||||
for subcategory, scorestreaks in new_obj[new_key].items():
|
||||
sorted_scorestreaks = dict(sorted(scorestreaks.items(), key=lambda item: item[1]['properties']['awardedCount'], reverse=True))
|
||||
new_obj[new_key][subcategory] = sorted_scorestreaks
|
||||
|
||||
# Sort Accolades in descending order
|
||||
if new_key == "Accolades":
|
||||
sorted_accolades = dict(sorted(new_obj[new_key]['properties'].items(), key=lambda item: item[1], reverse=True))
|
||||
new_obj[new_key]['properties'] = sorted_accolades
|
||||
|
||||
return new_obj
|
||||
elif isinstance(obj, list):
|
||||
for index, value in enumerate(obj):
|
||||
obj[index] = recursive_key_replace(value, replacements)
|
||||
return obj
|
||||
|
||||
data = recursive_key_replace(data, replacements)
|
||||
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Define the keys to be replaced and their replacements
|
||||
replacements = {
|
||||
# Gamemodes
|
||||
"dom": "Domination",
|
||||
"hc_dom": "Hardcore Domination",
|
||||
"war": "Team Deathmatch",
|
||||
"hc_war": "Hardcore Team Deathmatch",
|
||||
"hq": "Headquarters",
|
||||
"hc_hq": "Hardcore Headquarters",
|
||||
"conf": "Kill Confirmed",
|
||||
"hc_conf": "Hardcore Kill Confirmed",
|
||||
"koth": "Hardpoint",
|
||||
"koth_hc": "Hardcore Hardpoint",
|
||||
"sd": "Search and Destroy",
|
||||
"hc_sd": "Hardcore Search and Destroy",
|
||||
"cyber": "Cyber Attack",
|
||||
"hc_cyber": "Hardcore Cyber Attack",
|
||||
"grnd": "Grind",
|
||||
"arm": "Ground War",
|
||||
"infect": "Infected",
|
||||
"gun": "Gun Game",
|
||||
"arena": "Gunfight",
|
||||
"br": "Battle Royale (Warzone)",
|
||||
"br_dmz": "Plunder",
|
||||
"br_all": "Battle Royale (Warzone & Plunder)",
|
||||
# Weapons
|
||||
"weapon_assault_rifle": "Assault Rifles",
|
||||
"weapon_shotgun": "Shotguns",
|
||||
"weapon_marksman": "Marksman Rifles",
|
||||
"weapon_sniper": "Snipers",
|
||||
"tacticals": "Tactical Equipment",
|
||||
"lethals": "Lethal Equipment",
|
||||
"weapon_lmg": "LMGs",
|
||||
"weapon_launcher": "Launchers",
|
||||
"supers": "Field Upgrades",
|
||||
"weapon_pistol": "Pistols",
|
||||
"weapon_other": "Primary Melee",
|
||||
"weapon_smg": "SMGs",
|
||||
"weapon_melee": "Melee",
|
||||
"scorestreakData": "Scorestreaks",
|
||||
"lethalScorestreakData": "Lethal Scorestreaks",
|
||||
"supportScorestreakData": "Support Scorestreaks",
|
||||
# Guns
|
||||
## Assault Rifles
|
||||
"iw8_ar_tango21": "RAM-7",
|
||||
"iw8_ar_mike4": "M4A1",
|
||||
"iw8_ar_valpha": "AS VAL",
|
||||
"iw8_ar_falpha": "FR 5.56",
|
||||
"iw8_ar_mcharlie": "M13",
|
||||
"iw8_ar_akilo47": "AK-47",
|
||||
"iw8_ar_asierra12": "Oden",
|
||||
"iw8_ar_galima": "CR-56 AMAX",
|
||||
"iw8_ar_sierra552": "Grau 5.56",
|
||||
"iw8_ar_falima": "FAL",
|
||||
"iw8_ar_anovember94": "AN-94",
|
||||
"iw8_ar_kilo433": "Kilo 141",
|
||||
"iw8_ar_scharlie": "FN Scar 17",
|
||||
"iw8_sh_mike26": "VLK Rogue",
|
||||
## Shotguns
|
||||
"iw8_sh_charlie725": "725",
|
||||
"iw8_sh_oscar12": "Origin 12 Shotgun",
|
||||
"iw8_sh_aalpha12": "JAK-12",
|
||||
"iw8_sh_romeo870": "Model 680",
|
||||
"iw8_sh_dpapa12": "R9-0 Shotgun",
|
||||
## Marksman Rifles
|
||||
"iw8_sn_sbeta": "MK2 Carbine",
|
||||
"iw8_sn_crossbow": "Crossbow",
|
||||
"iw8_sn_romeo700": "SP-R 208",
|
||||
"iw8_sn_kilo98": "Kar98k",
|
||||
"iw8_sn_mike14": "EBR-14",
|
||||
"iw8_sn_sksierra": "SKS",
|
||||
## Sniper Rifles
|
||||
"iw8_sn_alpha50": "AX-50",
|
||||
"iw8_sn_hdromeo": "HDR",
|
||||
"iw8_sn_delta": "Dragunov",
|
||||
"iw8_sn_xmike109": "Rytec AMR",
|
||||
## Tactical Equipment
|
||||
"equip_gas_grenade": "Gas Grenade",
|
||||
"equip_snapshot_grenade": "Snapshot Grenade",
|
||||
"equip_decoy": "Decoy Grenade",
|
||||
"equip_smoke": "Smoke Grenade",
|
||||
"equip_concussion": "Concussion Grenade",
|
||||
"equip_hb_sensor": "Heartbeat Sensor",
|
||||
"equip_flash": "Flash Grenade",
|
||||
"equip_adrenaline": "Stim",
|
||||
## Lethal Equipment
|
||||
"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": "Mototov Cocktail",
|
||||
## LMGs
|
||||
"iw8_lm_kilo121": "M91",
|
||||
"iw8_lm_mkilo3": "Bruen Mk9",
|
||||
"iw8_lm_mgolf34": "MG34",
|
||||
"iw8_lm_lima86": "SA87",
|
||||
"iw8_lm_pkilo": "PKM",
|
||||
"iw8_lm_sierrax": "FiNN LMG",
|
||||
"iw8_lm_mgolf36": "Holger-26",
|
||||
# "": "", ### RAAL LMG not implemented
|
||||
## Launchers
|
||||
"iw8_la_gromeo": "PILA",
|
||||
"iw8_la_rpapa7": "RPG-7",
|
||||
"iw8_la_juliet": "JOKR",
|
||||
"iw8_la_kgolf": "Strela-P",
|
||||
# "": "", ### Unknown Launcher
|
||||
## Field Upgrades
|
||||
"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",
|
||||
## Pistols
|
||||
"iw8_pi_cpapa": ".357",
|
||||
"iw8_pi_mike9": "Renetti",
|
||||
"iw8_pi_mike1911": "1911",
|
||||
"iw8_pi_golf21": "X16",
|
||||
"iw8_pi_decho": ".50 GS",
|
||||
"iw8_pi_papa320": "M19",
|
||||
# "": "", ### Sykov not implemented
|
||||
## Primary Melee
|
||||
"iw8_me_riotshield": "Riot Shield",
|
||||
## SMGs
|
||||
"iw8_sm_mpapa7": "MP7",
|
||||
"iw8_sm_augolf": "AUG",
|
||||
"iw8_sm_papa90": "P90",
|
||||
"iw8_sm_charlie9": "ISO",
|
||||
"iw8_sm_mpapa5": "MP5",
|
||||
"iw8_sm_smgolf45": "Striker 45",
|
||||
"iw8_sm_beta": "PP19 Bizon",
|
||||
"iw8_sm_victor": "Fennec",
|
||||
"iw8_sm_uzulu": "Uzi",
|
||||
# "": "", ### CX9 not implemented
|
||||
## Melee
|
||||
"iw8_me_akimboblunt": "Kali Sticks",
|
||||
"iw8_me_akimboblades": "Dual Kodachis",
|
||||
"iw8_knife": "Knife",
|
||||
# Scorestreaks
|
||||
"precision_airstrike": "Precision Airstrike",
|
||||
"cruise_predator": "Cruise Missile",
|
||||
"manual_turret": "Shield Turret",
|
||||
"white_phosphorus": "White Phosphorus",
|
||||
"hover_jet": "VTOL Jet",
|
||||
"chopper_gunner": "Chopper Gunner",
|
||||
"gunship": "Gunship",
|
||||
"sentry_gun": "Sentry Gun",
|
||||
"toma_strike": "Cluster Strike",
|
||||
"nuke": "Nuke",
|
||||
"juggernaut": "Juggernaut",
|
||||
"pac_sentry": "Wheelson",
|
||||
"chopper_support": "Support Helo",
|
||||
"bradley": "Infantry Assault Vehicle",
|
||||
"airdrop": "Care Package",
|
||||
"radar_drone_overwatch": "Personal Radar",
|
||||
"scrambler_drone_guard": "Counter UAV",
|
||||
"uav": "UAV",
|
||||
"airdrop_multiple": "Emergency Airdrop",
|
||||
"directional_uav": "Advanced UAV",
|
||||
# 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
|
||||
}
|
||||
|
||||
file_path = "stats.json"
|
||||
|
||||
replace_and_sort_keys_in_json(file_path, replacements)
|
||||
print(f"Keys sorted and replaced in {file_path}!")
|
283
depricated_dev_scripts/beautify_data_match_info.py
Normal file
283
depricated_dev_scripts/beautify_data_match_info.py
Normal file
@ -0,0 +1,283 @@
|
||||
import json
|
||||
|
||||
def replace_and_sort_keys_in_json(file_path, replacements):
|
||||
"""Replace keys and values in the JSON file based on the replacements dictionary."""
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
def recursive_key_replace(obj, replacements):
|
||||
if isinstance(obj, dict):
|
||||
new_obj = {}
|
||||
for key, value in obj.items():
|
||||
# Replace the key
|
||||
new_key = replacements.get(key, key)
|
||||
|
||||
# Check if the value is a string and replace if necessary
|
||||
if isinstance(value, str):
|
||||
new_value = replacements.get(value, value)
|
||||
new_obj[new_key] = recursive_key_replace(new_value, replacements)
|
||||
else:
|
||||
new_obj[new_key] = recursive_key_replace(value, replacements)
|
||||
|
||||
return new_obj
|
||||
elif isinstance(obj, list):
|
||||
for index, value in enumerate(obj):
|
||||
obj[index] = recursive_key_replace(value, replacements)
|
||||
else:
|
||||
# If the object is a string, check and replace
|
||||
if isinstance(obj, str):
|
||||
return replacements.get(obj, obj)
|
||||
return obj
|
||||
|
||||
data = recursive_key_replace(data, replacements)
|
||||
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Define the keys to be replaced and their replacements
|
||||
replacements = {
|
||||
# Gamemodes
|
||||
"dom": "Domination",
|
||||
"hc_dom": "Hardcore Domination",
|
||||
"war": "Team Deathmatch",
|
||||
"hc_war": "Hardcore Team Deathmatch",
|
||||
"hq": "Headquarters",
|
||||
"hc_hq": "Hardcore Headquarters",
|
||||
"conf": "Kill Confirmed",
|
||||
"hc_conf": "Hardcore Kill Confirmed",
|
||||
"koth": "Hardpoint",
|
||||
"koth_hc": "Hardcore Hardpoint",
|
||||
"sd": "Search and Destroy",
|
||||
"hc_sd": "Hardcore Search and Destroy",
|
||||
"cyber": "Cyber Attack",
|
||||
"hc_cyber": "Hardcore Cyber Attack",
|
||||
"grnd": "Grind",
|
||||
"arm": "Ground War",
|
||||
"infect": "Infected",
|
||||
"gun": "Gun Game",
|
||||
"arena": "Gunfight",
|
||||
"br": "Battle Royale (Warzone)",
|
||||
"br_dmz": "Plunder",
|
||||
"br_all": "Battle Royale (Warzone & Plunder)",
|
||||
# Weapons
|
||||
"weapon_assault_rifle": "Assault Rifles",
|
||||
"weapon_shotgun": "Shotguns",
|
||||
"weapon_marksman": "Marksman Rifles",
|
||||
"weapon_sniper": "Snipers",
|
||||
"tacticals": "Tactical Equipment",
|
||||
"lethals": "Lethal Equipment",
|
||||
"weapon_lmg": "LMGs",
|
||||
"weapon_launcher": "Launchers",
|
||||
"supers": "Field Upgrades",
|
||||
"weapon_pistol": "Pistols",
|
||||
"weapon_other": "Primary Melee",
|
||||
"weapon_smg": "SMGs",
|
||||
"weapon_melee": "Melee",
|
||||
"scorestreakData": "Scorestreaks",
|
||||
"lethalScorestreakData": "Lethal Scorestreaks",
|
||||
"supportScorestreakData": "Support Scorestreaks",
|
||||
# Guns
|
||||
## Assault Rifles
|
||||
"iw8_ar_tango21": "RAM-7",
|
||||
"iw8_ar_mike4": "M4A1",
|
||||
"iw8_ar_valpha": "AS VAL",
|
||||
"iw8_ar_falpha": "FR 5.56",
|
||||
"iw8_ar_mcharlie": "M13",
|
||||
"iw8_ar_akilo47": "AK-47",
|
||||
"iw8_ar_asierra12": "Oden",
|
||||
"iw8_ar_galima": "CR-56 AMAX",
|
||||
"iw8_ar_sierra552": "Grau 5.56",
|
||||
"iw8_ar_falima": "FAL",
|
||||
"iw8_ar_anovember94": "AN-94",
|
||||
"iw8_ar_kilo433": "Kilo 141",
|
||||
"iw8_ar_scharlie": "FN Scar 17",
|
||||
"iw8_sh_mike26": "VLK Rogue",
|
||||
## Shotguns
|
||||
"iw8_sh_charlie725": "725",
|
||||
"iw8_sh_oscar12": "Origin 12 Shotgun",
|
||||
"iw8_sh_aalpha12": "JAK-12",
|
||||
"iw8_sh_romeo870": "Model 680",
|
||||
"iw8_sh_dpapa12": "R9-0 Shotgun",
|
||||
## Marksman Rifles
|
||||
"iw8_sn_sbeta": "MK2 Carbine",
|
||||
"iw8_sn_crossbow": "Crossbow",
|
||||
"iw8_sn_romeo700": "SP-R 208",
|
||||
"iw8_sn_kilo98": "Kar98k",
|
||||
"iw8_sn_mike14": "EBR-14",
|
||||
"iw8_sn_sksierra": "SKS",
|
||||
## Sniper Rifles
|
||||
"iw8_sn_alpha50": "AX-50",
|
||||
"iw8_sn_hdromeo": "HDR",
|
||||
"iw8_sn_delta": "Dragunov",
|
||||
"iw8_sn_xmike109": "Rytec AMR",
|
||||
## Tactical Equipment
|
||||
"equip_gas_grenade": "Gas Grenade",
|
||||
"equip_snapshot_grenade": "Snapshot Grenade",
|
||||
"equip_decoy": "Decoy Grenade",
|
||||
"equip_smoke": "Smoke Grenade",
|
||||
"equip_concussion": "Concussion Grenade",
|
||||
"equip_hb_sensor": "Heartbeat Sensor",
|
||||
"equip_flash": "Flash Grenade",
|
||||
"equip_adrenaline": "Stim",
|
||||
## Lethal Equipment
|
||||
"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": "Mototov Cocktail",
|
||||
## LMGs
|
||||
"iw8_lm_kilo121": "M91",
|
||||
"iw8_lm_mkilo3": "Bruen Mk9",
|
||||
"iw8_lm_mgolf34": "MG34",
|
||||
"iw8_lm_lima86": "SA87",
|
||||
"iw8_lm_pkilo": "PKM",
|
||||
"iw8_lm_sierrax": "FiNN LMG",
|
||||
"iw8_lm_mgolf36": "Holger-26",
|
||||
# "": "", ### RAAL LMG not implemented
|
||||
## Launchers
|
||||
"iw8_la_gromeo": "PILA",
|
||||
"iw8_la_rpapa7": "RPG-7",
|
||||
"iw8_la_juliet": "JOKR",
|
||||
"iw8_la_kgolf": "Strela-P",
|
||||
# "": "", ### Unknown Launcher
|
||||
## Field Upgrades
|
||||
"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",
|
||||
## Pistols
|
||||
"iw8_pi_cpapa": ".357",
|
||||
"iw8_pi_mike9": "Renetti",
|
||||
"iw8_pi_mike1911": "1911",
|
||||
"iw8_pi_golf21": "X16",
|
||||
"iw8_pi_decho": ".50 GS",
|
||||
"iw8_pi_papa320": "M19",
|
||||
# "": "", ### Sykov not implemented
|
||||
## Primary Melee
|
||||
"iw8_me_riotshield": "Riot Shield",
|
||||
## SMGs
|
||||
"iw8_sm_mpapa7": "MP7",
|
||||
"iw8_sm_augolf": "AUG",
|
||||
"iw8_sm_papa90": "P90",
|
||||
"iw8_sm_charlie9": "ISO",
|
||||
"iw8_sm_mpapa5": "MP5",
|
||||
"iw8_sm_smgolf45": "Striker 45",
|
||||
"iw8_sm_beta": "PP19 Bizon",
|
||||
"iw8_sm_victor": "Fennec",
|
||||
"iw8_sm_uzulu": "Uzi",
|
||||
# "": "", ### CX9 not implemented
|
||||
## Melee
|
||||
"iw8_me_akimboblunt": "Kali Sticks",
|
||||
"iw8_me_akimboblades": "Dual Kodachis",
|
||||
"iw8_knife": "Knife",
|
||||
# Scorestreaks
|
||||
"precision_airstrike": "Precision Airstrike",
|
||||
"cruise_predator": "Cruise Missile",
|
||||
"manual_turret": "Shield Turret",
|
||||
"white_phosphorus": "White Phosphorus",
|
||||
"hover_jet": "VTOL Jet",
|
||||
"chopper_gunner": "Chopper Gunner",
|
||||
"gunship": "Gunship",
|
||||
"sentry_gun": "Sentry Gun",
|
||||
"toma_strike": "Cluster Strike",
|
||||
"nuke": "Nuke",
|
||||
"juggernaut": "Juggernaut",
|
||||
"pac_sentry": "Wheelson",
|
||||
"chopper_support": "Support Helo",
|
||||
"bradley": "Infantry Assault Vehicle",
|
||||
"airdrop": "Care Package",
|
||||
"radar_drone_overwatch": "Personal Radar",
|
||||
"scrambler_drone_guard": "Counter UAV",
|
||||
"uav": "UAV",
|
||||
"airdrop_multiple": "Emergency Airdrop",
|
||||
"directional_uav": "Advanced UAV",
|
||||
# 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
|
||||
}
|
||||
|
||||
file_path = "match_info.json"
|
||||
|
||||
replace_and_sort_keys_in_json(file_path, replacements)
|
||||
print(f"Keys replaced in {file_path}!")
|
20
depricated_dev_scripts/convert_epoch.py
Normal file
20
depricated_dev_scripts/convert_epoch.py
Normal file
@ -0,0 +1,20 @@
|
||||
import datetime
|
||||
|
||||
def epoch_to_human_readable(epoch_timestamp, timezone='GMT'):
|
||||
# Convert the epoch timestamp to a datetime object
|
||||
dt_object = datetime.datetime.utcfromtimestamp(epoch_timestamp)
|
||||
|
||||
# Format the datetime object to a human-readable string
|
||||
if timezone == 'GMT':
|
||||
date_str = dt_object.strftime("GMT: %A, %B %d, %Y %I:%M:%S %p")
|
||||
elif timezone == 'EST':
|
||||
dt_object -= datetime.timedelta(hours=4) # Subtract 5 hours from GMT to get EST
|
||||
date_str = dt_object.strftime("EST: %A, %B %d, %Y %I:%M:%S %p")
|
||||
else:
|
||||
raise ValueError("Unsupported timezone!")
|
||||
|
||||
return date_str
|
||||
|
||||
epoch_timestamp = 1697528478724
|
||||
print(epoch_to_human_readable(epoch_timestamp))
|
||||
print(epoch_to_human_readable(epoch_timestamp, 'EST'))
|
@ -15,8 +15,14 @@ https://my.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/ga
|
||||
# Get Maps & Game Modes (No $PROF Variable Needed)
|
||||
https://my.callofduty.com/api/papi-client/ce/v1/title/mw/platform/battle/gameType/mp/communityMapData/availability
|
||||
|
||||
# Get Match Stats
|
||||
https://www.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/fullMatch/mp/matchID/it
|
||||
|
||||
# Leaderboard
|
||||
https://www.callofduty.com/api/papi-client/leaderboards/v2/title/mw/platform/battle/time/alltime/type/core/mode/career/page/1
|
||||
# Get friendFeedEvents
|
||||
https://my.callofduty.com/api/papi-client/userfeed/v1/friendFeed/platform/battle/gamer/$PROF/friendFeedEvents/en
|
||||
|
||||
https://my.callofduty.com/api/papi-client/userfeed/v1/friendFeed/rendered/en/{acct_sso_token}
|
||||
|
||||
https://my.callofduty.com/api/papi-client/inventory/v1/title/mw/platform/battle/gamer/$PROF/currency
|
||||
|
||||
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
|
@ -1,5 +1,5 @@
|
||||
# Set your default values here
|
||||
$PROF = "Ahrimdon%231597" # The % replaces the # for the Activision ID (e.g. Ahrimdon%231597)
|
||||
$PROF = "" # The % replaces the # for the Activision ID (e.g. Ahrimdon%231597)
|
||||
# You do not need numbers for PSN or XBL
|
||||
# Delete $PROF when getting maps and game modes.
|
||||
$COOKIE_VALUE = "ACCT_SSO_COOKIE"
|
45
depricated_dev_scripts/fetch_playerdata.py
Normal file
45
depricated_dev_scripts/fetch_playerdata.py
Normal file
@ -0,0 +1,45 @@
|
||||
import json
|
||||
import os
|
||||
from cod_api import API, platforms
|
||||
|
||||
# initiating the API class
|
||||
api = API()
|
||||
|
||||
COOKIE_FILE = 'cookie.txt'
|
||||
|
||||
# Check if cookie file exists
|
||||
if os.path.exists(COOKIE_FILE):
|
||||
with open(COOKIE_FILE, 'r') as f:
|
||||
api_key = f.read().strip()
|
||||
else:
|
||||
api_key = input("Please enter your ACT_SSO_COOKIE: ")
|
||||
with open(COOKIE_FILE, 'w') as f:
|
||||
f.write(api_key)
|
||||
|
||||
# Get player name from user
|
||||
player_name = input("Please enter the player's username (with #1234567): ")
|
||||
|
||||
# login with sso token
|
||||
api.login(api_key)
|
||||
|
||||
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||
season_loot = api.ModernWarfare.seasonLoot(platforms.Activision, player_name)
|
||||
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
||||
identities = api.Me.loggedInIdentities()
|
||||
|
||||
# Save results to a JSON file
|
||||
with open('stats.json', 'w') as json_file:
|
||||
json.dump(player_stats, json_file, indent=4)
|
||||
|
||||
with open('match_info.json', 'w') as json_file:
|
||||
json.dump(match_info, json_file, indent=4)
|
||||
|
||||
with open('season_loot.json', 'w') as json_file:
|
||||
json.dump(season_loot, json_file, indent=4)
|
||||
|
||||
with open('map_list.json', 'w') as json_file:
|
||||
json.dump(map_list, json_file, indent=4)
|
||||
|
||||
with open('identities.json', 'w') as json_file:
|
||||
json.dump(identities, json_file, indent=4)
|
1
deps/frequencies.json
vendored
Normal file
1
deps/frequencies.json
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user