Compare commits

...

59 Commits
v1.0.0 ... main

Author SHA1 Message Date
Rim
29d4929098 chore(cod_api_tool.py): fix userInfo.json path 2025-02-28 02:22:05 -05:00
Rim
e4d65e3c3f chore(build.py): complete code refactor
complete code refactor by Claude Sonnet 3.7
2025-02-28 02:21:12 -05:00
Rim
ae9498a2e7 chore(README.md): update readme 2025-02-28 01:54:41 -05:00
Rim
8f95e49713 chore(build.py): fix script name... oops... 2025-02-28 01:47:32 -05:00
Rim
26f4c50049 fix(build.py): fixed build script not including replacements.json 2025-02-28 01:39:30 -05:00
Rim
590f4cc3bd chore(cod_api_tool.py): complete code refactor
complete code refactor by Claude Sonnet 3.7
2025-02-28 01:38:58 -05:00
Rim
6893ccbdd4 maint(): fix naming error 2025-01-04 12:39:02 -05:00
Rim
7bbb86a565 fix(setup.py): deprecated package error 2025-01-04 12:25:31 -05:00
Rim
fbfa8df406 maint(): get_cod_stats --> cod_api_tool 2025-01-04 12:06:33 -05:00
Rim
cb0a75cf68 maint(): refactor directory structure 2025-01-04 12:04:28 -05:00
Rim
c3e0db32d8 maint(curl_userInfo.ps1): update curl command - must include cookies.txt file now 2025-01-04 11:27:34 -05:00
Rim
1d7424979b maint(): change replacement handling from python to json 2025-01-04 10:22:45 -05:00
Rim
87a0a36162 maint(): refactor directory structure & update build scripts 2025-01-04 09:36:16 -05:00
Rim
3775324e18 maint(): minor adjustments 2025-01-04 06:15:50 -05:00
Rim
4ef07f5ead Merge branch 'develop' 2025-01-04 06:02:11 -05:00
Rim
f135c96f72 maint(): update baseURL 2025-01-04 04:44:30 -05:00
Rim
dc68740f4b Allow for setting timezone to convert to 2023-12-25 22:18:47 -05:00
Rim
49916431cf Add timezone for other conversion 2023-12-25 21:59:55 -05:00
Rim
8d6f763f15 Add time conversion for feeds 2023-12-25 21:54:29 -05:00
Rim
b4d305d531 Update replacement strings, add more prettifying logic 2023-12-25 21:26:55 -05:00
Rim
290852d839 Update menu logic, adjust regex 2023-12-25 20:17:11 -05:00
Rim
7208e07bad Add option menu alongside arguments for ease of use 2023-12-25 19:44:48 -05:00
Rim
a41ccd0e15 Update README.md for new version 2023-12-25 09:11:59 -05:00
Rim
e1d5abea1b Merge branch develop into main 2023-12-25 09:01:46 -05:00
Rim
abc3f4ee58 Update readme, add new arguments, add conditional checks whether user has userInfo.json 2023-12-25 08:57:25 -05:00
Rim
8b9db62b9e Remove redundant API call, add userinfo arguments 2023-12-25 08:38:28 -05:00
Rim
aec4b9fe9c New way of handling key replacements 2023-12-25 07:49:55 -05:00
Rim
06dde8f550 Cleanup cod_api additions 2023-12-25 07:41:32 -05:00
Rim
3bdbefd124 Add userInfo tutorial to README.md 2023-12-25 05:51:10 -05:00
Rim
3a2ac5f9f8 Add userInfo tutorial to README.md 2023-12-25 05:50:26 -05:00
Rim
1382242d86 Update examples 2023-12-25 05:32:20 -05:00
Rim
6ef5db6ead Add regex to sanitize userInfo 2023-12-25 05:32:07 -05:00
Rim
e550ab4920 Update examples 2023-12-25 05:25:07 -05:00
Rim
b16feeb844 Add regex to sanitize userInfo 2023-12-25 05:19:22 -05:00
Rim
91b886fe1f Pretty scripts, begin README for how to obtain userInfo.json 2023-12-25 05:15:25 -05:00
Rim
d90b2715bc Add dev api 2023-12-25 05:01:44 -05:00
Rim
135bc421d2 whoops 2023-12-25 04:49:37 -05:00
Rim
639ae2beea Revert get_cod_stats.py to main branch 2023-12-25 04:44:16 -05:00
Rim
7589c25d4e Pretty scripts, begin README for how to obtain userInfo.json 2023-12-25 04:41:15 -05:00
Rim
aef8d07cbc Add support for more former depricated api calls 2023-12-25 04:14:59 -05:00
Rim
95a3fdad46 Add support for more former depricated api calls 2023-12-25 04:14:29 -05:00
Rim
f683dfcc3c Remove redundant API call, whoops 2023-12-25 04:02:32 -05:00
Rim
563b2c28f7 Add python build script, use modified api, add dev scripts, add regex for cleaning feeds, allow for api calls using userinfo 2023-12-25 03:57:17 -05:00
Ahrimdon
0aadb24ff3 Update examples for latest release 2023-11-22 00:01:17 -05:00
Ahrimdon
9b55016313 Added time conversions for seconds values 2023-11-21 05:15:15 -05:00
Ahrimdon
716c271e50 Update replacement list, add new API links for reference 2023-10-19 05:55:45 -04:00
Ahrimdon
d06efd39b4 Update README.me 2023-10-14 05:06:47 -04:00
Ahrimdon
4d38a2aa09 Update README.me 2023-10-14 05:06:09 -04:00
Ahrimdon
35264c11bf Update README.me 2023-10-14 05:05:43 -04:00
Ahrimdon
0d7c30ae01 Update README.me 2023-10-14 05:05:10 -04:00
Ahrimdon
18ab6f4ebd Update README.me 2023-10-14 05:04:41 -04:00
Ahrimdon
3c536727be Update README.me 2023-10-14 05:02:51 -04:00
Ahrimdon
3383006742 Fix issue with parsing match data 2023-10-14 05:00:16 -04:00
Ahrimdon
614212a63f Update README.md 2023-10-14 04:35:12 -04:00
Ahrimdon
12e8fec29f Update binary 2023-10-14 04:14:08 -04:00
Ahrimdon
073753122a Update README.md 2023-10-14 04:13:23 -04:00
Ahrimdon
d2abc4105d Update README.md 2023-10-14 04:05:49 -04:00
Ahrimdon
e99d6581e1 Update README.md 2023-10-14 04:01:41 -04:00
Ahrimdon
825cc17025 Added more cmdline arguments, match splitting, added duration and match time conversions, fintuned code. 2023-10-14 03:45:34 -04:00
121 changed files with 58257 additions and 37055 deletions

6
.gitignore vendored
View File

@ -1,5 +1,9 @@
__pycache__
uninstall.*
venv.*
/cod_pics
/venv
/HTML
/stats
/userInfo.json
/cookie*
/bin

163
README.md
View File

@ -1,49 +1,134 @@
# Modern Warfare 2019 Detailed Statistic Tracker
# Modern Warfare 2019 Advanced Statistics Tracker
Tired of visiting [cod.tracker.gg](https://cod.tracker.gg/modern-warfare) to check your stats? With this repository, you'll never have to visit that site again.
Access comprehensive Call of Duty statistics directly from your command line. No more visiting third-party tracking websites when you can retrieve **every statistic** Call of Duty records in under a minute.
Get every single statistic Call of Duty tracks in ONE PLACE, in under a minute!
> View example outputs in the `/examples/` directory
This repository is still a work in progress.
## Features
Prerequisites
-------------
- `Python 3.x` *(optional)*
- A Web Browser *(Tested with Chromium)*
- Call of Duty Account
- Account API security settings set to open
- ~~[Curl](https://curl.se/download.html) ***(Installed by default on Windows)***~~
- **Complete Statistics Access**: Download detailed player statistics including lifetime stats, match history, and seasonal rewards
- **Enhanced Sorting**: Sort statistics more effectively than the in-game Barracks
- **Human-Readable Formats**: Convert timestamps and code names to user-friendly formats
- **Detailed Match History**: Split match data into separate files for easier analysis
- **Game Information**: Access lists of all maps and game modes in current rotation
## Prerequisites
- Call of Duty account with API security settings set to "Open"
- Web browser (Chromium-based recommended)
- Python 3.x (optional, tested with Python 3.9.13)
## Installation Options
### Option 1: Download the Latest Release (Recommended)
1. Download `cod_api_tool.exe` from the [latest release](https://github.com/Ahrimdon/detailed-cod-tracker/releases/latest)
2. Open a command prompt in the download directory
3. Execute the tool using the syntax below:
Command Line Arguments
-----
```
usage: get_cod_stats.py [-h] [--replace-data] [--replace-match-data] [--player-name PLAYER_NAME]
optional arguments:
-h, --help show this help message and exit
--replace-data Beautify the data in stats.json
--replace-match-data Beautify the match data in match_info.json
--player-name PLAYER_NAME
Player's username (with #1234567)
cod_api_tool.exe [arguments]
```
Gathering Detailed Stats
-------------
- Go to [Call of Duty's Website](https://www.callofduty.com/) and login with your account
- Once logged in, press `F12` for your browsers developer tools. Then go to `Application --> Storage --> Cookies --> https://www.callofduty.com` and find `ACT_SSO_COOKIE`
- Copy the Value into the into the `COOKIE_VALUE` variable in either `get_stats.bat` or `get_stats.ps1` (This will authenticate you)
- Replace the `PROF` variable with your profile's Activision ID in the following format - `PlayerName%0000000`
* *The `%` replaces the `#` in the usual Activision ID*
- Once stats are downloaded, run `beautify_json.py` to beautify the JSON output and then `beautify_data.py` to sort and replace the JSON keys into a human readable string
> If you don't have Python installed, you can run the executable versions of the scripts `beautify_json.exe` and `beautify_data.exe`
### Option 2: Clone the Repository
Sorting
-------------
* Game Modes are sorted by *Time Played* in descending order
* Weapons are sorted by *Kills* in descending order
* Field Upgrades are sorted by *Uses* in descending order
* Lethal and Tactical equipment are sorted by *Uses* in descending order
* Lethal and Support Scorestreaks by *Times Awarded* in descending order
* Accolades sorted in descending order
1. Clone the repository:
```
git clone https://github.com/Ahrimdon/detailed-cod-tracker.git
cd detailed-cod-tracker
```
> To see an example, look at `example.json`
2. Run the setup script:
```
python setup.py
```
## Authentication Setup
### Obtaining your ACT_SSO_COOKIE
1. Log in to [Call of Duty](https://www.callofduty.com)
2. Open developer tools (F12)
3. Navigate to: Application → Storage → Cookies → https://www.callofduty.com/
4. Copy the value of `ACT_SSO_COOKIE`
5. Provide this value when prompted by the tool
### Setting up userInfo.json (Required for Advanced Features)
Due to recent API changes, additional steps are required for certain features:
1. Navigate to `https://profile.callofduty.com/cod/userInfo/{ACT_SSO_COOKIE}` (replace with your actual cookie)
2. Copy the entire content
3. Create a file named `userInfo.json` in the tool's directory
4. Paste the content and remove `userInfo(` from the beginning and `);` from the end
- Alternatively, use the regex pattern in `sanitize_userInfo_regex.txt`
5. Run the tool with the `-a` flag to access advanced features
## Command Line Reference
```
usage: cod_api_tool.py [-h] [-tz {GMT,EST,CST,PST}] [-p PLAYER_NAME] [-a]
[-sl] [-id] [-m] [-i] [-f] [-e] [-cp] [-ca] [-s] [-c]
[-sm] [-csd] [-cmd] [-cff] [-cef]
```
### Default Options
| Argument | Description |
|----------|-------------|
| `-h`, `--help` | Show help message and exit |
| `-tz`, `--timezone` | Specify timezone (GMT, EST, CST, PST) |
### Data Fetching Options
| Argument | Description |
|----------|-------------|
| `-p PLAYER_NAME`, `--player_name PLAYER_NAME` | Target player's username (with #1234567) |
| `-a`, `--all_stats` | Fetch all available statistics |
| `-sl`, `--season_loot` | Fetch only seasonal reward data |
| `-id`, `--identities` | Fetch only logged-in identities data |
| `-m`, `--maps` | Fetch only map list data |
| `-i`, `--info` | Fetch only general information |
| `-f`, `--friendFeed` | Fetch only friend feed |
| `-e`, `--eventFeed` | Fetch only event feed |
| `-cp`, `--cod_points` | Fetch only COD Point balance |
| `-ca`, `--connected_accounts` | Fetch only connected accounts data |
| `-s`, `--settings` | Fetch only account settings |
### Data Processing Options
| Argument | Description |
|----------|-------------|
| `-c`, `--clean` | Beautify all data |
| `-sm`, `--split_matches` | Split matches into separate JSON files |
| `-csd`, `--clean_stats_data` | Beautify stats.json data |
| `-cmd`, `--clean_match_data` | Beautify match_info.json data |
| `-cff`, `--clean_friend_feed` | Clean friend feed data |
| `-cef`, `--clean_event_feed` | Clean event feed data |
## Examples
**Basic Usage: Retrieve Player Statistics**
```
cod_api_tool.exe -p YourUsername#1234567
```
**Full Data Collection with Cleaning**
```
cod_api_tool.exe -p YourUsername#1234567 -a -c -sm
```
**Process Existing Data**
```
cod_api_tool.exe -c -sm
```
> All data is saved to the `/stats/` directory
## Advanced Sorting
The tool offers enhanced sorting capabilities:
- Game modes sorted by **Time Played** (descending)
- Weapons sorted by **Kills** (descending)
- Field upgrades sorted by **Uses** (descending)
- Equipment (lethal and tactical) sorted by **Uses** (descending)
- Scorestreaks sorted by **Times Awarded** (descending)
- Accolades sorted in descending order

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 770 B

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

View File

@ -1,10 +0,0 @@
@echo off
cd /d %~dp0 :: Change directory to the location of this batch file
call venv\Scripts\activate :: Activate the virtual environment
pyinstaller --noconfirm --onefile --console --icon "assets\build\icon\icon.ico" get_cod_stats.py --distpath="bin" -n "get_cod_stats"
rmdir /s /q build
del /q "get_cod_stats.spec"
pause

46
build.py Normal file
View File

@ -0,0 +1,46 @@
import os
import sys
import shutil
import subprocess
import PyInstaller.__main__
# Initialize constants
SCRIPT = "cod_api_tool.py"
ICON = "assets/icon.ico"
NAME = "cod_api_tool"
DIST_PATH = "bin/build"
# Get absolute paths to data files
script_dir = os.path.abspath(os.path.dirname(__file__))
charset_normalizer_data = os.path.join('deps', 'frequencies.json')
replacements_json = os.path.join(script_dir, 'data', 'replacements.json')
# Verify replacements.json exists before building
if not os.path.exists(replacements_json):
print(f"ERROR: {replacements_json} not found. Make sure this file exists.")
sys.exit(1)
# 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,
# This is the correct way to add the data file - preserve the directory structure
'--add-data', f"{charset_normalizer_data};charset_normalizer/assets",
'--add-data', f"{replacements_json};data" # Note: using 'data' as the destination folder
])
# Clean up the build directory and spec file
shutil.rmtree('build')
os.remove(f'{NAME}.spec')
print(f"Build completed successfully. Executable is in {DIST_PATH}/{NAME}.exe")
input("Press Enter to continue...")

909
cod_api/PKG-INFO Normal file
View File

@ -0,0 +1,909 @@
Metadata-Version: 2.2
Name: cod_api
Version: 2.0.2
Summary: Call Of Duty API.
Home-page: https://codapi.dev/
Author: Todo Lodo
Author-email: me@todolodo.xyz
Maintainer: Engineer15
Maintainer-email: engineergamer15@gmail.com
License: GPL-3.0
Project-URL: Source Code, https://github.com/TodoLodo2089/cod-python-api
Project-URL: Issue Tracker, https://github.com/TodoLodo2089/cod-python-api/issues
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Description-Content-Type: text/x-rst
License-File: LICENSE
===================
**cod-python-api**
===================
.. meta::
:description: Call Of Duty API Library for python with the implementation of both public and private API used by activision on callofduty.com
:key: CallOfDuty API, CallOfDuty python API, CallOfDuty python
.. image:: https://github.com/TodoLodo/cod-python-api/actions/workflows/codeql-analysis.yml/badge.svg?branch=main
:target: https://github.com/TodoLodo/cod-python-api.git
.. image:: https://img.shields.io/endpoint?url=https://cod-python-api.todolodo.xyz/stats?q=version
:target: https://badge.fury.io/py/cod-api
.. image:: https://img.shields.io/endpoint?url=https://cod-python-api.todolodo.xyz/stats?q=downloads
:target: https://badge.fury.io/gh/TodoLodo2089%2Fcod-python-api
------------------------------------------------------------------------------------------------------------------------
**Call Of Duty API Library** for **python** with the implementation of both public and private API used by activision on
callofduty.com
====
Devs
====
* `Todo Lodo`_
* `Engineer15`_
.. _Todo Lodo: https://todolodo.xyz
.. _Engineer15: https://github.com/Engineer152
============
Contributors
============
* `Werseter`_
.. _Werseter: https://github.com/Werseter
===============
Partnered Code
===============
`Node-CallOfDuty`_ by: `Lierrmm`_
.. _Node-CallOfDuty: https://github.com/Lierrmm/Node-CallOfDuty
.. _Lierrmm: https://github.com/Lierrmm
=============
Documentation
=============
This package can be used directly as a python file or as a python library.
Installation
============
Install cod-api library using `pip`_:
.. code-block:: bash
pip install -U cod-api
.. _pip: https://pip.pypa.io/en/stable/getting-started/
Usage
=====
Initiation
----------
Import module with its classes:
.. code-block:: python
from cod_api import API
api = API()
.. _`logged in`:
Login with your sso token:
.. code-block:: python
api.login('Your sso token')
Your sso token can be found by longing in at `callofduty`_, opening dev tools (ctr+shift+I), going to Applications >
Storage > Cookies > https://callofduty.com, filter to search 'ACT_SSO_COOKIE' and copy the value.
.. _callofduty: https://my.callofduty.com/
Game/Other sub classes
----------------------
Following importation and initiation of the class ``API``, its associated subclasses can be called by
``API.subClassName``.
Below are the available sub classes:
+-------------------+----------+
| sub class | category |
+===================+==========+
|* `ColdWar`_ | game |
+-------------------+----------+
|* `ModernWarfare`_ | game |
+-------------------+----------+
|* `ModernWarfare2`_| game |
+-------------------+----------+
|* `Vanguard`_ | game |
+-------------------+----------+
|* `Warzone`_ | game |
+-------------------+----------+
|* `Warzone2`_ | game |
+-------------------+----------+
|* `Me`_ | other |
+-------------------+----------+
|* `Shop`_ | other |
+-------------------+----------+
|* `Misc`_ | other |
+-------------------+----------+
For a detailed description, ``__doc__`` (docstring) of each sub class can be called as shown below:
.. _`ColdWar`:
``ColdWar``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ColdWar.__doc__)
.. _`ModernWarfare`:
``ModernWarfare``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ModernWarfare.__doc__)
.. _`ModernWarfare2`:
``ModernWarfare2``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ModernWarfare2.__doc__)
.. _`Vanguard`:
``Vanguard``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Vanguard.__doc__)
.. _`Warzone`:
``Warzone``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Warzone.__doc__)
.. _`Warzone2`:
``Warzone2``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Warzone2.__doc__)
.. _`Me`:
``Me``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Me.__doc__)
.. _`Shop`:
``Shop``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Shop.__doc__)
.. _`Misc`:
``Misc``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Misc.__doc__)
Full Profile History
--------------------
Any sub class of ``API`` that is of game category, has methods to check a player's combat history.
Note that before calling any sub class methods of ``API`` you must be `logged in`_.
Main method is ``fullData()`` and ``fullDataAsync()`` which is available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2``, ``Vanguard``, ``Warzone`` and ``Warzone2`` classes.
Here's an example for retrieving **Warzone** full profile history of a player whose gamer tag is **Username#1234** on platform
**Battlenet**:
.. code-block:: python
from cod_api import API, platforms
import asyncio
## sync
# initiating the API class
api = API()
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
profile = api.Warzone.fullData(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(profile)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
profile = await api.Warzone.fullDataAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(profile)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Combat History
--------------
Main methods are ``combatHistory()`` and ``combatHistoryWithDate()`` for sync environments and ``combatHistoryAsync()``
and ``combatHistoryWithDateAsync()`` for async environments which are available for all ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2``, ``Vanguard``, ``Warzone`` and ``Warzone2`` classes.
The ``combatHistory()`` and ``combatHistoryAsync()`` takes 2 input parameters which are ``platform`` and ``gamertag`` of
type `cod_api.platforms`_ and string respectively.
Here's an example for retrieving **Warzone** combat history of a player whose gamer tag is **Username#1234** on platform
**Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
hist = api.Warzone.combatHistory(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
hist = await api.Warzone.combatHistoryAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
The ``combatHistoryWithDate()`` and ``combatHistoryWithDateAsync()`` takes 4 input parameters which are ``platform``,
``gamertag``, ``start`` and ``end`` of type `cod_api.platforms`_, string, int and int respectively.
``start`` and ``end`` parameters are utc timestamps in microseconds.
Here's an example for retrieving **ModernWarfare** combat history of a player whose gamer tag is **Username#1234567** on
platform **Activision** with in the timestamps **1657919309** (Friday, 15 July 2022 21:08:29) and **1657949309**
(Saturday, 16 July 2022 05:28:29):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
hist = api.Warzone.combatHistoryWithDate(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
hist = await api.Warzone.combatHistoryWithDateAsync(platforms.Battlenet, "Username#1234", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Additionally the methods ``breakdown()`` and ``breakdownWithDate()`` for sync environments and ``breakdownAsync()`` and
``breakdownWithDateAsync()`` for async environments, can be used to retrieve combat history without details, where only
the platform played on, game title, UTC timestamp, type ID, match ID and map ID is returned for every match. These
methods are available for all ``ColdWar``, ``ModernWarfare``, ``ModernWarfare2``, ``Vanguard``, ``Warzone`` and
``Warzone2`` classes.
The ``breakdown()`` and `breakdownAsync()`` takes 2 input parameters which are ``platform`` and ``gamertag`` of type
`cod_api.platforms`_ and string respectively.
Here's an example for retrieving **Warzone** combat history breakdown of a player whose gamer tag is **Username#1234**
on platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history breakdown
hist_b = api.Warzone.breakdown(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist_b)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history breakdown
hist_b = await api.Warzone.breakdownAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist_b)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
The ``breakdownWithDate()`` and ``breakdownWithDateAsync()`` takes 4 input parameters which are ``platform``,
``gamertag``, ``start`` and ``end`` of type `cod_api.platforms`_, string, int and int respectively.
``start`` and ``end`` parameters are utc timestamps in microseconds.
Here's an example for retrieving **ModernWarfare** combat history breakdown of a player whose gamer tag is
**Username#1234567** on platform **Activision** with in the timestamps **1657919309** (Friday, 15 July 2022 21:08:29)
and **1657949309** (Saturday, 16 July 2022 05:28:29):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history breakdown
hist_b = api.Warzone.breakdownWithDate(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist_b)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history breakdown
hist_b = await api.Warzone.breakdownWithDateAsync(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist_b)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Match Details
-------------
To retrieve details of a specific match, the method ``matchInfo()`` for sync environments and ``matchInfoAsync()`` for
async environments can be used. These methods are available for all ``ColdWar``, ``ModernWarfare``, ``ModernWarfare2``,
``Vanguard``, ``Warzone`` and ``Warzone2`` classes. Details returned by this method contains additional data than that
of details returned by the **combat history** methods for a single match.
The ``matchInfo()`` and ``matchInfoAsync()`` takes 2 input parameters which are ``platform`` and ``matchId`` of type
`cod_api.platforms`_ and integer respectively.
*Optionally the match ID can be retrieved during your gameplay where it will be visible on bottom left corner*
Here's an example for retrieving **Warzone** match details of a match where its id is **9484583876389482453**
on platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving match details
details = api.Warzone.matchInfo(platforms.Battlenet, 9484583876389482453) # returns data of type dict
# printing results to console
print(details)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving match details
details = await api.Warzone.matchInfoAsync(platforms.Battlenet, 9484583876389482453) # returns data of type dict
# printing results to console
print(details)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Season Loot
-----------
Using the ``seasonLoot()`` for sync environments and ``seasonLootAsync()`` for async environments, player's obtained
season loot can be retrieved for a specific game and this method is available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2`` and ``Vanguard`` classes.
The ``seasonLoot()`` and ``seasonLootAsync()`` takes 2 input parameters which are ``platform`` and ``matchId`` of type
`cod_api.platforms`_ and integer respectively.
Here's an example for retrieving **ColdWar** season loot obtained by a player whose gamer tag is **Username#1234** on
platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving season loot
loot = api.ColdWar.seasonLoot(platforms.Battlenet, "Username#1234") # returns data of type dict)
# printing results to console
print(loot)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving season loot
loot = await api.ColdWar.seasonLootAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(loot)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Map List
--------
Using the ``mapList()`` for sync environments and ``mapListAsync()`` for async environments, all the maps and its
available modes can be retrieved for a specific game. These methods are available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2`` and ``Vanguard`` classes.
The ``mapList()`` and ``mapListAsync()`` takes 1 input parameters which is ``platform`` of type `cod_api.platforms`_.
Here's an example for retrieving **Vanguard** map list and available modes respectively on platform PlayStation
(**PSN**):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving maps and respective modes available
maps = api.Vanguard.mapList(platforms.PSN) # returns data of type dict
# printing results to console
print(maps)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving season loot
maps = await api.Vanguard.mapListAsync(platforms.PSN) # returns data of type dict
# printing results to console
print(maps)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
.. _cod_api.platforms:
platforms
---------
``platforms`` is an enum class available in ``cod_api`` which is used to specify the platform in certain method calls.
Available ``platforms`` are as follows:
+----------------------+----------------------------------------+
|Platform | Remarks |
+======================+========================================+
|platforms.All | All (no usage till further updates) |
+----------------------+----------------------------------------+
|platforms.Activision | Activision |
+----------------------+----------------------------------------+
|platforms.Battlenet | Battlenet |
+----------------------+----------------------------------------+
|platforms.PSN | PlayStation |
+----------------------+----------------------------------------+
|platforms.Steam | Steam (no usage till further updates) |
+----------------------+----------------------------------------+
|platforms.Uno | Uno (activision unique id) |
+----------------------+----------------------------------------+
|platforms.XBOX | Xbox |
+----------------------+----------------------------------------+
``platforms`` can be imported and used as follows:
.. code-block:: python
from cod_api import platforms
platforms.All # All (no usage till further updates)
platforms.Activision # Activision
platforms.Battlenet # Battlenet
platforms.PSN # PlayStation
platforms.Steam # Steam (no usage till further updates)
platforms.Uno # Uno (activision unique id)
platforms.XBOX # Xbox
User Info
----------
Using the ``info()`` method in sub class ``Me`` of ``API`` user information can be retrieved of the sso-token logged in
with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
# login in with sso token
api.login('your_sso_token')
# retrieving user info
userInfo = api.Me.info() # returns data of type dict
# printing results to console
print(userInfo)
User Friend Feed
----------------
Using the methods, ``friendFeed()`` for sync environments and ``friendFeedAsync()`` for async environments, in sub class
``Me`` of ``API``, user's friend feed can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user friend feed
friendFeed = api.Me.friendFeed() # returns data of type dict
# printing results to console
print(friendFeed)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user friend feed
friendFeed = await api.Me.friendFeedAsync() # returns data of type dict
# printing results to console
print(friendFeed)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Event Feed
----------------
Using the methods ``eventFeed()`` for sync environments and ``eventFeedAsync()`` for async environments, in sub class
``Me`` of ``API`` user's event feed can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user event feed
eventFeed = api.Me.eventFeed() # returns data of type dict
# printing results to console
print(eventFeed)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user event feed
eventFeed = await api.Me.eventFeedAsync() # returns data of type dict
# printing results to console
print(eventFeed)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Identities
----------------
Using the methods ``loggedInIdentities()`` for sync environments and ``loggedInIdentitiesAsync()`` for async
environments, in sub class ``Me`` of ``API`` user's identities can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user identities
identities = api.Me.loggedInIdentities() # returns data of type dict
# printing results to console
print(identities)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user identities
identities = await api.Me.loggedInIdentitiesAsync() # returns data of type dict
# printing results to console
print(identities)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User COD Points
----------------
Using the methods ``codPoints()`` for sync environments and ``codPointsAsync()`` for async environments, in sub class
``Me`` of ``API`` user's cod points can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user cod points
cp = api.Me.codPoints() # returns data of type dict
# printing results to console
print(cp)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user cod points
cp = await api.Me.codPointsAsync() # returns data of type dict
# printing results to console
print(cp)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Accounts
----------------
Using the methods ``connectedAccounts()`` for sync environments and ``connectedAccountsAsync()`` for async environments,
in sub class ``Me`` of ``API`` user's connected accounts can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user connected accounts
accounts = api.Me.connectedAccounts() # returns data of type dict
# printing results to console
print(accounts)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user connected accounts
accounts = await api.Me.connectedAccountsAsync() # returns data of type dict
# printing results to console
print(accounts)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User settings
----------------
Using the methods ``settings()`` for sync environments and ``settingsAsync()`` for async environments, in sub class
``Me`` of ``API`` user's settings can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user settings
settings = api.Me.settings() # returns data of type dict
# printing results to console
print(settings)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user settings
settings = await api.Me.settingsAsync() # returns data of type dict
# printing results to console
print(settings)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
-------------------------------------------------------------------------------------------------------------------------------
Donate
======
* `Donate Todo Lodo`_
* `Donate Engineer152`_
* `Donate Werseter`_
.. _Donate Todo Lodo: https://www.buymeacoffee.com/todolodo2089
.. _Donate Engineer152: https://www.paypal.com/paypalme/engineer15
.. _Donate Werseter: https://paypal.me/werseter

9
cod_api/build.bat Normal file
View File

@ -0,0 +1,9 @@
@echo off
cd /d %~dp0 :: Change directory to the location of this batch file
call ../venv/Scripts/activate :: Activate the virtual environment
python -m build
mv dist/cod_api-2.0.2-py3-none-any.whl ../deps/.
pause

View File

@ -0,0 +1,916 @@
Metadata-Version: 2.1
Name: cod_api
Version: 2.0.2
Summary: Call Of Duty API.
Home-page: https://codapi.dev/
Author: Todo Lodo
Author-email: me@todolodo.xyz
Maintainer: Engineer15
Maintainer-email: engineergamer15@gmail.com
License: GPL-3.0
Project-URL: Source Code, https://github.com/TodoLodo2089/cod-python-api
Project-URL: Issue Tracker, https://github.com/TodoLodo2089/cod-python-api/issues
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: asyncio
Requires-Dist: aiohttp
Requires-Dist: datetime
Requires-Dist: requests
Requires-Dist: uuid
Requires-Dist: urllib3
Requires-Dist: enum34
===================
**cod-python-api**
===================
.. meta::
:description: Call Of Duty API Library for python with the implementation of both public and private API used by activision on callofduty.com
:key: CallOfDuty API, CallOfDuty python API, CallOfDuty python
.. image:: https://github.com/TodoLodo/cod-python-api/actions/workflows/codeql-analysis.yml/badge.svg?branch=main
:target: https://github.com/TodoLodo/cod-python-api.git
.. image:: https://img.shields.io/endpoint?url=https://cod-python-api.todolodo.xyz/stats?q=version
:target: https://badge.fury.io/py/cod-api
.. image:: https://img.shields.io/endpoint?url=https://cod-python-api.todolodo.xyz/stats?q=downloads
:target: https://badge.fury.io/gh/TodoLodo2089%2Fcod-python-api
------------------------------------------------------------------------------------------------------------------------
**Call Of Duty API Library** for **python** with the implementation of both public and private API used by activision on
callofduty.com
====
Devs
====
* `Todo Lodo`_
* `Engineer15`_
.. _Todo Lodo: https://todolodo.xyz
.. _Engineer15: https://github.com/Engineer152
============
Contributors
============
* `Werseter`_
.. _Werseter: https://github.com/Werseter
===============
Partnered Code
===============
`Node-CallOfDuty`_ by: `Lierrmm`_
.. _Node-CallOfDuty: https://github.com/Lierrmm/Node-CallOfDuty
.. _Lierrmm: https://github.com/Lierrmm
=============
Documentation
=============
This package can be used directly as a python file or as a python library.
Installation
============
Install cod-api library using `pip`_:
.. code-block:: bash
pip install -U cod-api
.. _pip: https://pip.pypa.io/en/stable/getting-started/
Usage
=====
Initiation
----------
Import module with its classes:
.. code-block:: python
from cod_api import API
api = API()
.. _`logged in`:
Login with your sso token:
.. code-block:: python
api.login('Your sso token')
Your sso token can be found by longing in at `callofduty`_, opening dev tools (ctr+shift+I), going to Applications >
Storage > Cookies > https://callofduty.com, filter to search 'ACT_SSO_COOKIE' and copy the value.
.. _callofduty: https://my.callofduty.com/
Game/Other sub classes
----------------------
Following importation and initiation of the class ``API``, its associated subclasses can be called by
``API.subClassName``.
Below are the available sub classes:
+-------------------+----------+
| sub class | category |
+===================+==========+
|* `ColdWar`_ | game |
+-------------------+----------+
|* `ModernWarfare`_ | game |
+-------------------+----------+
|* `ModernWarfare2`_| game |
+-------------------+----------+
|* `Vanguard`_ | game |
+-------------------+----------+
|* `Warzone`_ | game |
+-------------------+----------+
|* `Warzone2`_ | game |
+-------------------+----------+
|* `Me`_ | other |
+-------------------+----------+
|* `Shop`_ | other |
+-------------------+----------+
|* `Misc`_ | other |
+-------------------+----------+
For a detailed description, ``__doc__`` (docstring) of each sub class can be called as shown below:
.. _`ColdWar`:
``ColdWar``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ColdWar.__doc__)
.. _`ModernWarfare`:
``ModernWarfare``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ModernWarfare.__doc__)
.. _`ModernWarfare2`:
``ModernWarfare2``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.ModernWarfare2.__doc__)
.. _`Vanguard`:
``Vanguard``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Vanguard.__doc__)
.. _`Warzone`:
``Warzone``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Warzone.__doc__)
.. _`Warzone2`:
``Warzone2``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Warzone2.__doc__)
.. _`Me`:
``Me``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Me.__doc__)
.. _`Shop`:
``Shop``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Shop.__doc__)
.. _`Misc`:
``Misc``:
.. code-block:: python
from cod_api import API
api = API()
# print out the docstring
print(api.Misc.__doc__)
Full Profile History
--------------------
Any sub class of ``API`` that is of game category, has methods to check a player's combat history.
Note that before calling any sub class methods of ``API`` you must be `logged in`_.
Main method is ``fullData()`` and ``fullDataAsync()`` which is available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2``, ``Vanguard``, ``Warzone`` and ``Warzone2`` classes.
Here's an example for retrieving **Warzone** full profile history of a player whose gamer tag is **Username#1234** on platform
**Battlenet**:
.. code-block:: python
from cod_api import API, platforms
import asyncio
## sync
# initiating the API class
api = API()
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
profile = api.Warzone.fullData(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(profile)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
profile = await api.Warzone.fullDataAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(profile)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Combat History
--------------
Main methods are ``combatHistory()`` and ``combatHistoryWithDate()`` for sync environments and ``combatHistoryAsync()``
and ``combatHistoryWithDateAsync()`` for async environments which are available for all ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2``, ``Vanguard``, ``Warzone`` and ``Warzone2`` classes.
The ``combatHistory()`` and ``combatHistoryAsync()`` takes 2 input parameters which are ``platform`` and ``gamertag`` of
type `cod_api.platforms`_ and string respectively.
Here's an example for retrieving **Warzone** combat history of a player whose gamer tag is **Username#1234** on platform
**Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
hist = api.Warzone.combatHistory(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
hist = await api.Warzone.combatHistoryAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
The ``combatHistoryWithDate()`` and ``combatHistoryWithDateAsync()`` takes 4 input parameters which are ``platform``,
``gamertag``, ``start`` and ``end`` of type `cod_api.platforms`_, string, int and int respectively.
``start`` and ``end`` parameters are utc timestamps in microseconds.
Here's an example for retrieving **ModernWarfare** combat history of a player whose gamer tag is **Username#1234567** on
platform **Activision** with in the timestamps **1657919309** (Friday, 15 July 2022 21:08:29) and **1657949309**
(Saturday, 16 July 2022 05:28:29):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history
hist = api.Warzone.combatHistoryWithDate(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history
hist = await api.Warzone.combatHistoryWithDateAsync(platforms.Battlenet, "Username#1234", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Additionally the methods ``breakdown()`` and ``breakdownWithDate()`` for sync environments and ``breakdownAsync()`` and
``breakdownWithDateAsync()`` for async environments, can be used to retrieve combat history without details, where only
the platform played on, game title, UTC timestamp, type ID, match ID and map ID is returned for every match. These
methods are available for all ``ColdWar``, ``ModernWarfare``, ``ModernWarfare2``, ``Vanguard``, ``Warzone`` and
``Warzone2`` classes.
The ``breakdown()`` and `breakdownAsync()`` takes 2 input parameters which are ``platform`` and ``gamertag`` of type
`cod_api.platforms`_ and string respectively.
Here's an example for retrieving **Warzone** combat history breakdown of a player whose gamer tag is **Username#1234**
on platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history breakdown
hist_b = api.Warzone.breakdown(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist_b)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history breakdown
hist_b = await api.Warzone.breakdownAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(hist_b)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
The ``breakdownWithDate()`` and ``breakdownWithDateAsync()`` takes 4 input parameters which are ``platform``,
``gamertag``, ``start`` and ``end`` of type `cod_api.platforms`_, string, int and int respectively.
``start`` and ``end`` parameters are utc timestamps in microseconds.
Here's an example for retrieving **ModernWarfare** combat history breakdown of a player whose gamer tag is
**Username#1234567** on platform **Activision** with in the timestamps **1657919309** (Friday, 15 July 2022 21:08:29)
and **1657949309** (Saturday, 16 July 2022 05:28:29):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving combat history breakdown
hist_b = api.Warzone.breakdownWithDate(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist_b)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving combat history breakdown
hist_b = await api.Warzone.breakdownWithDateAsync(platforms.Activision, "Username#1234567", 1657919309, 1657949309) # returns data of type dict
# printing results to console
print(hist_b)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Match Details
-------------
To retrieve details of a specific match, the method ``matchInfo()`` for sync environments and ``matchInfoAsync()`` for
async environments can be used. These methods are available for all ``ColdWar``, ``ModernWarfare``, ``ModernWarfare2``,
``Vanguard``, ``Warzone`` and ``Warzone2`` classes. Details returned by this method contains additional data than that
of details returned by the **combat history** methods for a single match.
The ``matchInfo()`` and ``matchInfoAsync()`` takes 2 input parameters which are ``platform`` and ``matchId`` of type
`cod_api.platforms`_ and integer respectively.
*Optionally the match ID can be retrieved during your gameplay where it will be visible on bottom left corner*
Here's an example for retrieving **Warzone** match details of a match where its id is **9484583876389482453**
on platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving match details
details = api.Warzone.matchInfo(platforms.Battlenet, 9484583876389482453) # returns data of type dict
# printing results to console
print(details)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving match details
details = await api.Warzone.matchInfoAsync(platforms.Battlenet, 9484583876389482453) # returns data of type dict
# printing results to console
print(details)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Season Loot
-----------
Using the ``seasonLoot()`` for sync environments and ``seasonLootAsync()`` for async environments, player's obtained
season loot can be retrieved for a specific game and this method is available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2`` and ``Vanguard`` classes.
The ``seasonLoot()`` and ``seasonLootAsync()`` takes 2 input parameters which are ``platform`` and ``matchId`` of type
`cod_api.platforms`_ and integer respectively.
Here's an example for retrieving **ColdWar** season loot obtained by a player whose gamer tag is **Username#1234** on
platform **Battlenet**:
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving season loot
loot = api.ColdWar.seasonLoot(platforms.Battlenet, "Username#1234") # returns data of type dict)
# printing results to console
print(loot)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving season loot
loot = await api.ColdWar.seasonLootAsync(platforms.Battlenet, "Username#1234") # returns data of type dict
# printing results to console
print(loot)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
Map List
--------
Using the ``mapList()`` for sync environments and ``mapListAsync()`` for async environments, all the maps and its
available modes can be retrieved for a specific game. These methods are available for ``ColdWar``, ``ModernWarfare``,
``ModernWarfare2`` and ``Vanguard`` classes.
The ``mapList()`` and ``mapListAsync()`` takes 1 input parameters which is ``platform`` of type `cod_api.platforms`_.
Here's an example for retrieving **Vanguard** map list and available modes respectively on platform PlayStation
(**PSN**):
.. code-block:: python
from cod_api import API, platforms
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving maps and respective modes available
maps = api.Vanguard.mapList(platforms.PSN) # returns data of type dict
# printing results to console
print(maps)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving season loot
maps = await api.Vanguard.mapListAsync(platforms.PSN) # returns data of type dict
# printing results to console
print(maps)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
.. _cod_api.platforms:
platforms
---------
``platforms`` is an enum class available in ``cod_api`` which is used to specify the platform in certain method calls.
Available ``platforms`` are as follows:
+----------------------+----------------------------------------+
|Platform | Remarks |
+======================+========================================+
|platforms.All | All (no usage till further updates) |
+----------------------+----------------------------------------+
|platforms.Activision | Activision |
+----------------------+----------------------------------------+
|platforms.Battlenet | Battlenet |
+----------------------+----------------------------------------+
|platforms.PSN | PlayStation |
+----------------------+----------------------------------------+
|platforms.Steam | Steam (no usage till further updates) |
+----------------------+----------------------------------------+
|platforms.Uno | Uno (activision unique id) |
+----------------------+----------------------------------------+
|platforms.XBOX | Xbox |
+----------------------+----------------------------------------+
``platforms`` can be imported and used as follows:
.. code-block:: python
from cod_api import platforms
platforms.All # All (no usage till further updates)
platforms.Activision # Activision
platforms.Battlenet # Battlenet
platforms.PSN # PlayStation
platforms.Steam # Steam (no usage till further updates)
platforms.Uno # Uno (activision unique id)
platforms.XBOX # Xbox
User Info
----------
Using the ``info()`` method in sub class ``Me`` of ``API`` user information can be retrieved of the sso-token logged in
with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
# login in with sso token
api.login('your_sso_token')
# retrieving user info
userInfo = api.Me.info() # returns data of type dict
# printing results to console
print(userInfo)
User Friend Feed
----------------
Using the methods, ``friendFeed()`` for sync environments and ``friendFeedAsync()`` for async environments, in sub class
``Me`` of ``API``, user's friend feed can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user friend feed
friendFeed = api.Me.friendFeed() # returns data of type dict
# printing results to console
print(friendFeed)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user friend feed
friendFeed = await api.Me.friendFeedAsync() # returns data of type dict
# printing results to console
print(friendFeed)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Event Feed
----------------
Using the methods ``eventFeed()`` for sync environments and ``eventFeedAsync()`` for async environments, in sub class
``Me`` of ``API`` user's event feed can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user event feed
eventFeed = api.Me.eventFeed() # returns data of type dict
# printing results to console
print(eventFeed)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user event feed
eventFeed = await api.Me.eventFeedAsync() # returns data of type dict
# printing results to console
print(eventFeed)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Identities
----------------
Using the methods ``loggedInIdentities()`` for sync environments and ``loggedInIdentitiesAsync()`` for async
environments, in sub class ``Me`` of ``API`` user's identities can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user identities
identities = api.Me.loggedInIdentities() # returns data of type dict
# printing results to console
print(identities)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user identities
identities = await api.Me.loggedInIdentitiesAsync() # returns data of type dict
# printing results to console
print(identities)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User COD Points
----------------
Using the methods ``codPoints()`` for sync environments and ``codPointsAsync()`` for async environments, in sub class
``Me`` of ``API`` user's cod points can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user cod points
cp = api.Me.codPoints() # returns data of type dict
# printing results to console
print(cp)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user cod points
cp = await api.Me.codPointsAsync() # returns data of type dict
# printing results to console
print(cp)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User Accounts
----------------
Using the methods ``connectedAccounts()`` for sync environments and ``connectedAccountsAsync()`` for async environments,
in sub class ``Me`` of ``API`` user's connected accounts can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user connected accounts
accounts = api.Me.connectedAccounts() # returns data of type dict
# printing results to console
print(accounts)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user connected accounts
accounts = await api.Me.connectedAccountsAsync() # returns data of type dict
# printing results to console
print(accounts)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
User settings
----------------
Using the methods ``settings()`` for sync environments and ``settingsAsync()`` for async environments, in sub class
``Me`` of ``API`` user's settings can be retrieved of the sso-token logged in with
.. code-block:: python
from cod_api import API
# initiating the API class
api = API()
## sync
# login in with sso token
api.login('your_sso_token')
# retrieving user settings
settings = api.Me.settings() # returns data of type dict
# printing results to console
print(settings)
## async
# in an async function
async def example():
# login in with sso token
await api.loginAsync('your_sso_token')
# retrieving user settings
settings = await api.Me.settingsAsync() # returns data of type dict
# printing results to console
print(settings)
# CALL THE example FUNCTION IN AN ASYNC ENVIRONMENT
-------------------------------------------------------------------------------------------------------------------------------
Donate
======
* `Donate Todo Lodo`_
* `Donate Engineer152`_
* `Donate Werseter`_
.. _Donate Todo Lodo: https://www.buymeacoffee.com/todolodo2089
.. _Donate Engineer152: https://www.paypal.com/paypalme/engineer15
.. _Donate Werseter: https://paypal.me/werseter

View File

@ -0,0 +1,11 @@
LICENSE
README.rst
setup.cfg
setup.py
cod_api/__init__.py
cod_api/__init__dev.py
cod_api.egg-info/PKG-INFO
cod_api.egg-info/SOURCES.txt
cod_api.egg-info/dependency_links.txt
cod_api.egg-info/requires.txt
cod_api.egg-info/top_level.txt

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,7 @@
asyncio
aiohttp
datetime
requests
uuid
urllib3
enum34

View File

@ -0,0 +1 @@
cod_api

730
cod_api/cod_api/__init__.py Normal file
View File

@ -0,0 +1,730 @@
__version__ = "2.0.2"
# 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://profile.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
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."

View File

@ -0,0 +1,725 @@
__version__ = "2.0.2"
# 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://profile.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."

24
cod_api/setup.cfg Normal file
View File

@ -0,0 +1,24 @@
[metadata]
version = attr: cod_api.__version__
description-file = README.rst
url = https://codapi.dev/
project_urls =
Source Code = https://github.com/TodoLodo2089/cod-python-api
Issue Tracker = https://github.com/TodoLodo2089/cod-python-api/issues
license = GPL-3.0
author = Todo Lodo
author_email = me@todolodo.xyz
maintainer = Engineer15
maintainer_email = engineergamer15@gmail.com
description = Call Of Duty API.
long_description = file: README.rst
long_description_content_type = text/x-rst
classifiers =
Intended Audience :: Developers
Operating System :: OS Independent
Programming Language :: Python
[egg_info]
tag_build =
tag_date = 0

657
cod_api_tool.py Normal file
View File

@ -0,0 +1,657 @@
import re
import sys
import json
import os
import argparse
from cod_api import API, platforms
import asyncio
import datetime
# Configure asyncio for Windows
if os.name == 'nt':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# Constants
COOKIE_FILE = 'cookie.txt'
STATS_DIR = 'stats'
MATCH_DIR = 'matches'
REPLACEMENTS_FILE = 'data/replacements.json'
TIMEZONE_OPTIONS = ["GMT", "EST", "CST", "PST"]
# Initialize API
api = API()
class CodStatsManager:
"""Main class to manage COD API interactions and data processing."""
def __init__(self):
self._ensure_directories_exist()
self.replacements = self._load_replacements()
self.api_key = self._get_api_key()
api.login(self.api_key)
def _ensure_directories_exist(self):
"""Ensure necessary directories exist."""
if not os.path.exists(STATS_DIR):
os.makedirs(STATS_DIR)
match_dir_path = os.path.join(STATS_DIR, MATCH_DIR)
if not os.path.exists(match_dir_path):
os.makedirs(match_dir_path)
def _load_replacements(self):
"""Load replacements from the JSON file."""
# First, handle running as PyInstaller executable
if getattr(sys, 'frozen', False):
# If running as bundle (frozen)
bundle_dir = sys._MEIPASS
replacements_path = os.path.join(bundle_dir, 'data', 'replacements.json')
else:
# If running as a normal Python script
replacements_path = REPLACEMENTS_FILE
if not os.path.exists(replacements_path):
raise FileNotFoundError(f"{replacements_path} not found. Ensure it exists in the script's directory.")
with open(replacements_path, 'r') as file:
return json.load(file)
def _get_api_key(self):
"""Get API key from file or user input."""
if os.path.exists(COOKIE_FILE):
with open(COOKIE_FILE, 'r') as f:
return f.read().strip()
else:
api_key = input("Please enter your ACT_SSO_COOKIE: ")
with open(COOKIE_FILE, 'w') as f:
f.write(api_key)
return api_key
def save_to_file(self, data, filename):
"""Save data to a JSON file."""
file_path = os.path.join(STATS_DIR, filename)
with open(file_path, 'w') as json_file:
json.dump(data, json_file, indent=4)
print(f"Data saved to {file_path}")
def get_player_name(self):
"""Get player name from user input."""
return input("Please enter the player's username (with #1234567): ")
def fetch_data(self, player_name=None, **options):
"""Fetch data based on specified options."""
if not player_name:
player_name = self.get_player_name()
# If no specific option is selected, fetch basic stats
if not any(options.values()):
self._fetch_basic_stats(player_name)
return
# If all_stats option is selected, fetch everything
if options.get('all_stats'):
self._fetch_all_stats(player_name)
return
# Otherwise, fetch only requested data
self._fetch_specific_data(player_name, options)
def _fetch_basic_stats(self, player_name):
"""Fetch basic player stats and match history."""
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
self.save_to_file(player_stats, 'stats.json')
self.save_to_file(match_info, 'match_info.json')
def _fetch_all_stats(self, player_name):
"""Fetch all available stats for a player."""
# Basic stats
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)
# Player-specific data
identities_data = api.Me.loggedInIdentities()
map_list = api.ModernWarfare.mapList(platforms.Activision)
# Save basic data
self.save_to_file(player_stats, 'stats.json')
self.save_to_file(match_info, 'match_info.json')
self.save_to_file(season_loot_data, 'season_loot.json')
self.save_to_file(map_list, 'map_list.json')
self.save_to_file(identities_data, 'identities.json')
# Check if userInfo.json exists to determine if we should fetch additional data
user_info_file = os.path.join('userInfo.json')
if os.path.exists(user_info_file):
# Additional user data
info = api.Me.info()
friend_feed = api.Me.friendFeed()
event_feed = api.Me.eventFeed()
cod_points = api.Me.codPoints()
connected_accounts = api.Me.connectedAccounts()
settings = api.Me.settings()
# Save additional data
self.save_to_file(info, 'info.json')
self.save_to_file(friend_feed, 'friendFeed.json')
self.save_to_file(event_feed, 'eventFeed.json')
self.save_to_file(cod_points, 'cp.json')
self.save_to_file(connected_accounts, 'connectedAccounts.json')
def _fetch_specific_data(self, player_name, options):
"""Fetch specific data based on provided options."""
endpoints = {
'season_loot': (api.ModernWarfare.seasonLoot, [platforms.Activision, player_name], 'season_loot.json'),
'identities': (api.Me.loggedInIdentities, [], 'identities.json'),
'maps': (api.ModernWarfare.mapList, [platforms.Activision], 'map_list.json'),
'info': (api.Me.info, [], 'info.json'),
'friendFeed': (api.Me.friendFeed, [], 'friendFeed.json'),
'eventFeed': (api.Me.eventFeed, [], 'eventFeed.json'),
'cod_points': (api.Me.codPoints, [], 'cp.json'),
'connected_accounts': (api.Me.connectedAccounts, [], 'connectedAccounts.json'),
'settings': (api.Me.settings, [], 'settings.json')
}
for option, value in options.items():
if value and option in endpoints:
func, args, filename = endpoints[option]
data = func(*args)
self.save_to_file(data, filename)
def beautify_all_data(self, timezone='GMT'):
"""Beautify all data files."""
self.beautify_stats_data(timezone)
self.beautify_match_data(timezone)
self.beautify_feed_data(timezone)
self.clean_json_files('friendFeed.json', 'eventFeed.json')
print("All data beautified successfully.")
def beautify_stats_data(self, timezone='GMT'):
"""Beautify stats data."""
file_path = os.path.join(STATS_DIR, 'stats.json')
if not os.path.exists(file_path):
print(f"File {file_path} not found. Skipping beautification.")
return
with open(file_path, 'r') as file:
data = json.load(file)
# Convert times and durations
self._replace_time_and_duration_recursive(data, timezone)
# Replace keys with more readable names
data = self._recursive_key_replace(data)
# Sort data by relevant metrics
data = self._sort_data(data)
# Save modified data
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
print(f"Keys sorted and replaced in {file_path}.")
def beautify_match_data(self, timezone='GMT'):
"""Beautify match data."""
file_path = os.path.join(STATS_DIR, 'match_info.json')
if not os.path.exists(file_path):
print(f"File {file_path} not found. Skipping beautification.")
return
with open(file_path, 'r') as file:
data = json.load(file)
# Convert times and durations
self._replace_time_and_duration_recursive(data, timezone)
# Replace keys with more readable names
data = self._recursive_key_replace(data)
# Save modified data
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
print(f"Keys replaced in {file_path}.")
def beautify_feed_data(self, timezone='GMT'):
"""Beautify feed data files."""
for feed_file in ['friendFeed.json', 'eventFeed.json']:
file_path = os.path.join(STATS_DIR, feed_file)
if not os.path.exists(file_path):
print(f"{feed_file} does not exist, skipping.")
continue
with open(file_path, 'r') as file:
data = json.load(file)
# Convert times and durations
self._replace_time_and_duration_recursive(data, timezone)
# Replace keys with more readable names
data = self._recursive_key_replace(data)
# Save modified data
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
print(f"Keys sorted and replaced in {feed_file}.")
def split_matches_into_files(self, timezone='GMT'):
"""Split match data into separate files."""
matches_dir = os.path.join(STATS_DIR, MATCH_DIR)
if not os.path.exists(matches_dir):
os.makedirs(matches_dir)
match_info_path = os.path.join(STATS_DIR, 'match_info.json')
if not os.path.exists(match_info_path):
print(f"Match info file not found at {match_info_path}. Skipping split.")
return
with open(match_info_path, 'r') as file:
data = json.load(file)
matches = data.get('data', {}).get('matches', [])
if not matches:
print("No matches found to split.")
return
# Check if time conversion is needed
sample_match = matches[0]
needs_time_conversion = (
isinstance(sample_match.get("utcStartSeconds"), int) or
isinstance(sample_match.get("utcEndSeconds"), int) or
isinstance(sample_match.get("duration"), int)
)
if needs_time_conversion:
print("Converting match timestamps to human-readable format...")
self._replace_time_and_duration_recursive(data, timezone)
# Update the main match file
with open(match_info_path, 'w') as file:
json.dump(data, file, indent=4)
# Process each match
for idx, match in enumerate(matches):
# Create a copy to avoid modifying the original data
match_copy = dict(match)
# Remove large loadout data to keep files smaller
if 'player' in match_copy:
match_copy['player'].pop('loadouts', None)
match_copy['player'].pop('loadout', None)
# Save to individual file
file_name = f"match_{idx + 1}.json"
file_path = os.path.join(matches_dir, file_name)
with open(file_path, 'w') as match_file:
json.dump(match_copy, match_file, indent=4)
print(f"Matches split into {len(matches)} separate files in {matches_dir}.")
def clean_json_files(self, *filenames):
"""Clean JSON files by removing HTML-like tags and entities."""
regex_pattern = r'<span class="|</span>|">|mp-stat-items|kills-value|headshots-value|username|game-mode|kdr-value|accuracy-value'
replace = ''
for filename in filenames:
file_path = os.path.join(STATS_DIR, filename)
if not os.path.exists(file_path):
print(f"{filename} does not exist, skipping.")
continue
with open(file_path, 'r') as file:
content = file.read()
# Replace unwanted patterns
modified_content = re.sub(regex_pattern, replace, content)
# Save cleaned content
with open(file_path, 'w') as file:
file.write(modified_content)
print(f"Removed unreadable strings from {filename}.")
def _recursive_key_replace(self, obj):
"""Recursively replace keys and values with more readable versions."""
if isinstance(obj, dict):
new_obj = {}
for key, value in obj.items():
new_key = self.replacements.get(key, key)
if isinstance(value, str):
new_value = self.replacements.get(value, value)
new_obj[new_key] = self._recursive_key_replace(new_value)
else:
new_obj[new_key] = self._recursive_key_replace(value)
return new_obj
elif isinstance(obj, list):
return [self._recursive_key_replace(item) for item in obj]
else:
return self.replacements.get(obj, obj) if isinstance(obj, str) else obj
def _sort_data(self, data):
"""Sort data by meaningful metrics for better readability."""
if isinstance(data, dict):
for key, value in data.items():
if key == "mode":
# Sort game modes by time played
data[key] = dict(sorted(
value.items(),
key=lambda item: item[1]['properties']['timePlayed'],
reverse=True
))
elif key in ["Assault Rifles", "Shotguns", "Marksman Rifles", "Snipers", "LMGs", "Launchers", "Pistols", "SMGs", "Melee"]:
# Sort weapons by kills
data[key] = dict(sorted(
value.items(),
key=lambda item: item[1]['properties']['kills'],
reverse=True
))
elif key in ["Field Upgrades", "Tactical Equipment", "Lethal Equipment"]:
# Sort equipment by uses
data[key] = dict(sorted(
value.items(),
key=lambda item: item[1]['properties']['uses'],
reverse=True
))
elif key == "Scorestreaks":
# Sort scorestreaks by awarded count
for subcategory, scorestreaks in value.items():
data[key][subcategory] = dict(sorted(
scorestreaks.items(),
key=lambda item: item[1]['properties']['awardedCount'],
reverse=True
))
elif key == "Accolades":
# Sort accolades by count
if 'properties' in value:
data[key]['properties'] = dict(sorted(
value['properties'].items(),
key=lambda item: item[1],
reverse=True
))
else:
# Recursively sort nested data
data[key] = self._sort_data(value)
return data
def _replace_time_and_duration_recursive(self, data, timezone):
"""Recursively replace epoch times with human-readable formats."""
time_keys = [
"timePlayedTotal", "timePlayed", "objTime", "time", "timeProne",
"timeSpentAsPassenger", "timeSpentAsDriver", "timeOnPoint",
"timeWatchingKillcams", "timeCrouched", "timesSelectedAsSquadLeader",
"longestTimeSpentOnWeapon", "avgLifeTime", "percentTimeMoving"
]
date_keys = ["date", "updated", "originalDate"]
if isinstance(data, list):
for item in data:
self._replace_time_and_duration_recursive(item, timezone)
elif isinstance(data, dict):
for key, value in data.items():
if key in date_keys:
data[key] = self._epoch_milli_to_human_readable(value, timezone)
elif key in time_keys:
data[key] = self._convert_duration_seconds(value)
elif key == "utcStartSeconds":
data[key] = self._epoch_to_human_readable(value, timezone)
elif key == "utcEndSeconds":
data[key] = self._epoch_to_human_readable(value, timezone)
elif key == "duration":
data[key] = self._convert_duration_milliseconds(value)
else:
self._replace_time_and_duration_recursive(value, timezone)
def _epoch_milli_to_human_readable(self, epoch_millis, timezone='GMT'):
"""Convert epoch milliseconds to human-readable date string."""
if isinstance(epoch_millis, str):
return epoch_millis
dt_object = datetime.datetime.utcfromtimestamp(epoch_millis / 1000.0)
return self._format_datetime(dt_object, timezone)
def _epoch_to_human_readable(self, epoch_timestamp, timezone='GMT'):
"""Convert epoch seconds to human-readable date string."""
if isinstance(epoch_timestamp, str):
return epoch_timestamp
dt_object = datetime.datetime.utcfromtimestamp(epoch_timestamp)
return self._format_datetime(dt_object, timezone)
def _format_datetime(self, dt_object, timezone):
"""Format datetime object based on timezone."""
timezone_offsets = {
'GMT': 0,
'EST': -4,
'CST': -5,
'PST': -8
}
if timezone not in timezone_offsets:
raise ValueError(f"Unsupported timezone: {timezone}")
# Apply timezone offset
dt_object -= datetime.timedelta(hours=timezone_offsets[timezone])
# Format date string
return f"{timezone}: {dt_object.strftime('%A, %B %d, %Y %I:%M:%S %p')}"
def _convert_duration_milliseconds(self, milliseconds):
"""Convert milliseconds to a human-readable duration string."""
if isinstance(milliseconds, str) and "Minutes" in milliseconds:
return milliseconds # Already converted
seconds, milliseconds = divmod(milliseconds, 1000)
minutes, seconds = divmod(seconds, 60)
return f"{minutes} Minutes {seconds} Seconds {milliseconds} Milliseconds"
def _convert_duration_seconds(self, seconds):
"""Convert seconds to a human-readable duration string."""
if isinstance(seconds, str):
return seconds # Already converted
days, seconds = divmod(seconds, 86400)
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
days = int(days)
hours = int(hours)
minutes = int(minutes)
seconds = int(seconds)
return f"{days} Days {hours} Hours {minutes} Minutes {seconds} Seconds"
def _ensure_json_serializable(self, obj):
"""Recursively convert objects to JSON serializable types."""
if isinstance(obj, dict):
return {key: self._ensure_json_serializable(value) for key, value in obj.items()}
elif isinstance(obj, list):
return [self._ensure_json_serializable(item) for item in obj]
elif isinstance(obj, tuple):
return [self._ensure_json_serializable(item) for item in obj]
elif isinstance(obj, (int, float, str, bool, type(None))):
return obj
else:
# Convert any other type to string representation
return str(obj)
class CLI:
"""Command Line Interface manager."""
def __init__(self, stats_manager):
self.stats_manager = stats_manager
self.help_text = """
Obtaining your ACT_SSO_COOKIE
- Go to https://www.callofduty.com and login with your account
- Once logged in, press F12 for your browsers developer tools. Then go to Application --> Storage --> Cookies --> https://www.callofduty.com and find ACT_SSO_COOKIE
- Enter the value when prompted
"""
def display_menu(self):
"""Display the main menu and get user choice."""
print("\nBeautify Options:")
print("1) Beautify all data")
print("2) Split matches into separate files")
print("\nOptions Requiring Player Name:")
print("3) Get all stats")
print("4) Get identities")
print("5) Get general information")
print("6) Get friend feed")
print("7) Get event feed")
print("8) Get COD Point balance")
print("9) Get connected accounts")
print("10) Get account settings")
print("\nOptions Not Requiring Player Name:")
print("11) Get season loot")
print("12) Get map list")
print("\n0) Exit")
try:
choice = int(input("Enter your choice: "))
return choice
except ValueError:
print("Please enter a valid number.")
return -1
def handle_menu_choice(self, choice):
"""Handle the user's menu choice."""
if choice == 0:
print("Exiting...")
return False
if choice in [3, 4, 5, 6, 7, 8, 9, 10, 11]:
player_name = input("Please enter the player's username (with #1234567): ")
options = {
3: {'all_stats': True},
4: {'season_loot': True},
5: {'identities': True},
6: {'info': True},
7: {'friendFeed': True},
8: {'eventFeed': True},
9: {'cod_points': True},
10: {'connected_accounts': True},
11: {'settings': True}
}
if choice in options:
self.stats_manager.fetch_data(player_name=player_name, **options[choice])
elif choice == 1:
self.stats_manager.beautify_all_data()
elif choice == 2:
self.stats_manager.split_matches_into_files()
elif choice == 12:
self.stats_manager.fetch_data(season_loot=True)
elif choice == 13:
self.stats_manager.fetch_data(maps=True)
else:
print("Invalid choice. Please try again.")
return True
return True
def run_interactive_mode(self):
"""Run the interactive menu mode."""
running = True
while running:
choice = self.display_menu()
running = self.handle_menu_choice(choice)
def setup_argument_parser(self):
"""Set up command line argument parser."""
parser = argparse.ArgumentParser(
description="Detailed Modern Warfare (2019) Statistics Tool",
epilog=self.help_text,
formatter_class=argparse.RawDescriptionHelpFormatter
)
# Group arguments for better help display
group_default = parser.add_argument_group("Default Options")
group_data = parser.add_argument_group("Data Fetching Options")
group_cleaning = parser.add_argument_group("Data Cleaning Options")
# Default options
group_default.add_argument(
"-tz", "--timezone",
type=str,
default="GMT",
choices=TIMEZONE_OPTIONS,
help="Specify the timezone (GMT, EST, CST, PST)"
)
# Data fetching options
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("-sl", "--season_loot", action="store_true", help="Fetch only the season loot 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("-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 connected accounts data")
group_data.add_argument("-s", "--settings", action="store_true", help="Fetch only your account settings")
# Data cleaning options
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 matches into separate JSON files")
group_cleaning.add_argument("-csd", "--clean_stats_data", action="store_true", help="Beautify stats.json data")
group_cleaning.add_argument("-cmd", "--clean_match_data", action="store_true", help="Beautify match_info.json data")
group_cleaning.add_argument("-cff", "--clean_friend_feed", action="store_true", help="Clean friend feed data")
group_cleaning.add_argument("-cef", "--clean_event_feed", action="store_true", help="Clean event feed data")
return parser
def run_cli_mode(self, args):
"""Run the command line mode with parsed arguments."""
# Prioritize cleaning operations
if args.clean:
self.stats_manager.beautify_all_data(timezone=args.timezone)
elif args.clean_stats_data:
self.stats_manager.beautify_stats_data(timezone=args.timezone)
elif args.clean_match_data:
self.stats_manager.beautify_match_data(timezone=args.timezone)
elif args.split_matches:
self.stats_manager.split_matches_into_files(timezone=args.timezone)
elif args.clean_friend_feed:
self.stats_manager.clean_json_files('friendFeed.json')
elif args.clean_event_feed:
self.stats_manager.clean_json_files('eventFeed.json')
else:
# Data fetching operations
options = {
'all_stats': args.all_stats,
'season_loot': args.season_loot,
'identities': args.identities,
'maps': args.maps,
'info': args.info,
'friendFeed': args.friendFeed,
'eventFeed': args.eventFeed,
'cod_points': args.cod_points,
'connected_accounts': args.connected_accounts,
'settings': args.settings
}
self.stats_manager.fetch_data(args.player_name, **options)
def main():
"""Main entry point for the application."""
stats_manager = CodStatsManager()
cli = CLI(stats_manager)
# Parse command line arguments
if len(sys.argv) > 1:
parser = cli.setup_argument_parser()
args = parser.parse_args()
cli.run_cli_mode(args)
else:
# Run interactive mode
cli.run_interactive_mode()
if __name__ == "__main__":
main()

View File

@ -1,16 +0,0 @@
# Get Stats Using Battle.NET (Requires Numbers)
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/$PROF/profile/type/mp
# Get Stats Using PSN
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/psn/gamer/$PROF/profile/type/mp
# Get Stats Using Xbox Live
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/xbl/gamer/$PROF/profile/type/mp
---
# Get Recent Games
https://my.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/gamer/$PROF/matches/mp/start/0/end/0/details
# 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

2185
data/everything.json Normal file

File diff suppressed because it is too large Load Diff

336
data/replacements.json Normal file
View File

@ -0,0 +1,336 @@
{
"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_crash2": "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_backlot2": "Talsik Backlot",
"mp_village2": "Hovec Sawmill",
"mp_hardhat": "Hardhat",
"mp_m_wallco2": "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_broadcast2": "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",
"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",
"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",
"super_tac_cover": "Deployable Cover",
"super_support_box": "Stopping Power Rounds",
"mp_stat": "Statistic",
"session_start": "Session Start",
"uno": "PC",
"psn": "Playstation Network",
"xbl": "Xbox Live",
"mw": "Modern Warfare",
"cw": "Cold War",
"mp_cartel": "Cartel",
"mp_tank": "Garrison",
"mp_miami": "Miami",
"mp_moscow": "Moscow",
"mp_satellite": "Satellite",
"mp_kgb": "Checkmate",
"wz_forest": "Ruka",
"wz_ski_slopes": "Alpine",
"mp_nuketown6": "Nuketown '84",
"mp_tundra": "Crossroads",
"mp_black_sea": "Armada",
"mp_mall": "The Pines",
"mp_raid_rm": "Raid",
"mp_sm_berlin_tunnel": "U-Bahn",
"mp_sm_finance": "KGB",
"mp_sm_game_show": "Game Show",
"mp_sm_central": "ICBM",
"wz_sanatorium": "Sanatorium",
"nuketown6_holiday": "Nuketown '84 Holiday",
"mp_express_rm": "Express",
"mp_apocalypse": "Apocalypse",
"mp_sm_market": "Mansion",
"mp_miami_strike": "Miami Strike",
"wz_golova": "Golova",
"mp_cliffhanger": "Yamantau",
"mp_sm_gas_station": "Diesel",
"wz_duga": "Duga",
"mp_village_rm": "Standoff",
"mp_sm_amsterdam": "Amsterdam",
"mp_dune": "Collateral",
"mp_hijacked_rm": "Hijacked",
"mp_paintball_rm": "Rush",
"mp_sm_deptstore": "Showroom",
"mp_slums_rm": "Slums",
"mp_echelon": "Echelon",
"mp_drivein_rm": "Drive In",
"mp_zoo_rm": "Zoo",
"mp_firebase": "Deprogram",
"mp_amerika": "Amerika",
"mp_sm_vault": "Gluboko",
"mp_don4_pm": "Nuketown '84 Halloween"
}

BIN
deps/build-1.2.2.post1-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
deps/cod_api-2.0.2-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
deps/colorama-0.4.6-py2.py3-none-any.whl vendored Normal file

Binary file not shown.

1
deps/frequencies.json vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
deps/packaging-24.2-py3-none-any.whl vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
deps/tomli-2.2.1-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
deps/zipp-3.21.0-py3-none-any.whl vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,17 @@
{
"status": "success",
"data": {
"battle": {
"username": "Ahrimdon#1597"
},
"xbl": {
"username": "Ahrimdon"
},
"uno": {
"username": "Ahrimdon"
},
"psn": {
"username": "MrCodBlackOp"
}
}
}

6
examples/cp.json Normal file
View File

@ -0,0 +1,6 @@
{
"status": "success",
"data": {
"codPoints": 5700
}
}

10647
examples/eventFeed.json Normal file

File diff suppressed because it is too large Load Diff

326
examples/friendFeed.json Normal file
View File

@ -0,0 +1,326 @@
{
"status": "success",
"data": [
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703499115338,
"category": "session_start",
"meta": {},
"rendered": "Ahrimdon started playing",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703398406507,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 10.0
},
"map": "mp_m_showers",
"matchId": "6346764813811873465",
"platform": "battle"
},
"rendered": "Ahrimdon got a 10.00 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703397057815,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 3.25
},
"map": "mp_m_stadium",
"matchId": "1253304090523704633",
"platform": "battle"
},
"rendered": "Ahrimdon got a 3.25 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703396034738,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"headshots": 5,
"kdr": 5.0
},
"map": "mp_m_speedball",
"matchId": "16921360291940233410",
"platform": "battle"
},
"rendered": "Ahrimdon got a 5.00 K/D ratio and 5 headshots in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703310964439,
"category": "mp_stat",
"meta": {
"mode": "koth_hc",
"stats": {
"kills": 83,
"headshots": 6
},
"map": "mp_m_speed",
"matchId": "4333210471980766910",
"platform": "battle"
},
"rendered": "Ahrimdon got 83 kills and 6 headshots in Hardpoint Hardcore",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703309848353,
"category": "mp_stat",
"meta": {
"mode": "koth_hc",
"stats": {
"kills": 93,
"headshots": 9
},
"map": "mp_shipment",
"matchId": "53293821470583620",
"platform": "battle"
},
"rendered": "Ahrimdon got 93 kills and 9 headshots in Hardpoint Hardcore",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703231662091,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 10.0
},
"map": "mp_m_showers",
"matchId": "1714429472903851618",
"platform": "battle"
},
"rendered": "Ahrimdon got a 10.00 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1703231348675,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 3.0
},
"map": "mp_m_stack",
"matchId": "17843164909224689417",
"platform": "battle"
},
"rendered": "Ahrimdon got a 3.00 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1702446836018,
"category": "mp_stat",
"meta": {
"mode": "koth_hc",
"stats": {
"kills": 62
},
"map": "mp_shipment",
"matchId": "2643440332264386069",
"platform": "battle"
},
"rendered": "Ahrimdon got 62 kills in Hardpoint Hardcore",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1702446115555,
"category": "mp_stat",
"meta": {
"mode": "koth_hc",
"stats": {
"kills": 63,
"headshots": 8
},
"map": "mp_m_speed",
"matchId": "6687312168970461455",
"platform": "battle"
},
"rendered": "Ahrimdon got 63 kills and 8 headshots in Hardpoint Hardcore",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1702441743189,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 2.5
},
"map": "mp_m_hill",
"matchId": "3293821657448840747",
"platform": "battle"
},
"rendered": "Ahrimdon got a 2.50 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1702360821785,
"category": "mp_stat",
"meta": {
"mode": "koth_hc",
"stats": {
"kills": 29
},
"map": "mp_m_speed",
"matchId": "16966673968984783119",
"platform": "battle"
},
"rendered": "Ahrimdon got 29 kills in Hardpoint Hardcore",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
},
{
"": "Ahrimdon",
"platform": "uno",
"title": "mw",
"date": 1702359430707,
"category": "mp_stat",
"meta": {
"mode": "arena",
"stats": {
"kdr": 2.2
},
"map": "mp_m_trench",
"matchId": "7447697542955973023",
"platform": "battle"
},
"rendered": "Ahrimdon got a 2.20 K/D ratio in Gunfight",
"topFavorite": false,
"favorited": false,
"favoriteData": {},
"reactions": {
"userReaction": null,
"counts": {},
"updated": 0
}
}
]
}

View File

@ -14,7 +14,7 @@
"title": "mw",
"platform": "battle",
"username": "Ahrimdon#1597",
"activeDate": 1696755151000,
"activeDate": 1703398831000,
"activityType": "mp",
"id": null
},

30
examples/info.json Normal file
View File

@ -0,0 +1,30 @@
{
"userName": "Ahrimdon#1597",
"identities": [
{
"platform": "battle",
"gamertag": "Ahrimdon#1597",
"accountID": null
},
{
"platform": "psn",
"gamertag": "MrCodBlackOp",
"accountID": null
},
{
"platform": "uno",
"gamertag": "Ahrimdon",
"accountID": null
},
{
"platform": "xbl",
"gamertag": "Ahrimdon",
"accountID": null
},
{
"platform": "youtube",
"gamertag": null,
"accountID": null
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 06:13:59 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 06:20:31 AM",
"map": "King",
"mode": "Gunfight",
"matchID": "14662302365900114747",
"duration": "6 Minutes 32 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 5,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 358560.0,
"one_shot_kill": 127808.0,
"mode_x_last_alive": 303584.0,
"mode_x_eliminate": 358512.0,
"stunned_kill": 230784.0,
"kill_jumper": 120400.0,
"headshot": 303536.0,
"match_complete": 259088.0,
"firstblood": 230640.0,
"match_complete_win": 360800.0,
"first_place_kill": 358608.0,
"longshot": 127904.0
},
"nemesis": "ShmackDaddyFrank",
"mostKilled": "ShmackDaddyFrank",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 8.0,
"medalXp": 2750.0,
"matchXp": 1498.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 850.0,
"accuracy": 0.13812154696132597,
"wallBangs": 0.0,
"shotsLanded": 25.0,
"score": 850.0,
"totalXp": 5098.0,
"headshots": 2.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 116.17312072892939,
"distanceTraveled": 1471.8298,
"deaths": 7.0,
"kdRatio": 1.1428571428571428,
"shotsMissed": 156.0,
"timePlayed": "0 Days 0 Hours 7 Minutes 19 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 91.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 2.0,
"damageDone": 1090.0,
"shotsFired": 181.0,
"damageTaken": 802.0
},
"weaponStats": {
"RAM-7": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 8.0,
"shots": 14.0,
"startingWeaponXp": 94500.0,
"deaths": 1.0,
"xpEarned": 90.0
},
".357": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 9.0,
"shots": 3.0,
"startingWeaponXp": 44700.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"1911": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 8.0,
"startingWeaponXp": 33000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Crossbow": {
"hits": 0.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 2.0,
"startingWeaponXp": 48300.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"FiNN": {
"hits": 2.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 18.0,
"startingWeaponXp": 79800.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"Model 680": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 4.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"Fennec Mk9": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 2.0,
"startingWeaponXp": 70700.0,
"deaths": 1.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,120 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:41:49 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:54:35 AM",
"map": "Shoot House",
"mode": "Hardpoint Hardcore",
"matchID": "4333210471980766910",
"duration": "12 Minutes 46 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "loss",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 250,
"team2Score": 246,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 757824.0,
"one_shot_kill": 766384.0,
"slide_kill": 701216.0,
"mode_x_assault": 766336.0,
"pointblank": 456272.0,
"revenge": 766288.0,
"double": 734400.0,
"mode_hp_secure": 735952.0,
"mode_x_wipeout": 433056.0,
"streak_5": 432960.0,
"avenger": 637600.0,
"comeback": 621888.0,
"save_teammate": 757872.0,
"triple": 705728.0,
"kill_jumper": 456224.0,
"buzzkill": 752688.0,
"mode_dom_secure_assist": 609248.0,
"headshot": 752640.0,
"air_to_air_kill": 458656.0,
"match_complete": 771904.0,
"mode_x_defend": 681968.0,
"quad_feed": 433056.0,
"first_place_kill": 734480.0,
"longshot": 158592.0
},
"nemesis": "zey",
"mostKilled": "zey",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 83.0,
"medalXp": 10860.0,
"matchXp": 2853.0,
"averageSpeedDuringMatch": 254.4378,
"scoreXp": 8970.0,
"accuracy": 0.10728744939271255,
"wallBangs": 4.0,
"shotsLanded": 106.0,
"score": 13930.0,
"totalXp": 22723.0,
"headshots": 6.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 1026.7813267813267,
"distanceTraveled": 12013.973,
"deaths": 52.0,
"kdRatio": 1.5961538461538463,
"shotsMissed": 882.0,
"timePlayed": "0 Days 0 Hours 13 Minutes 34 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 323.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 38 Seconds",
"miscXp": 0.0,
"longestStreak": 8.0,
"damageDone": 2414.0,
"shotsFired": 988.0,
"damageTaken": 1763.0
},
"weaponStats": {
"semtex_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"iw8_pi_mike": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 2.0,
"startingWeaponXp": 42900.0,
"deaths": 2.0,
"xpEarned": 0.0
},
"CR-56 AMAX": {
"hits": 75.0,
"kills": 55.0,
"headshots": 3.0,
"loadoutIndex": 1.0,
"shots": 619.0,
"startingWeaponXp": 105000.0,
"deaths": 30.0,
"xpEarned": 6600.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,136 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:25:38 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:36:00 AM",
"map": "Shipment",
"mode": "Hardpoint Hardcore",
"matchID": "53293821470583620",
"duration": "10 Minutes 22 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 181,
"team2Score": 117,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"slide_kill": 617088.0,
"seven": 63760.0,
"mode_x_wipeout": 603744.0,
"mode_hp_quick_cap": 325936.0,
"streak_5": 274576.0,
"posthumous": 603744.0,
"kill_jumper": 541936.0,
"headshot": 444928.0,
"four": 533232.0,
"mode_x_defend": 598768.0,
"five": 215888.0,
"longshot": 211344.0,
"grenade_double": 603744.0,
"low_health_kill": 598816.0,
"one_shot_kill": 532944.0,
"six": 63008.0,
"revenge": 603648.0,
"mode_x_assault": 603744.0,
"pointblank": 616992.0,
"double": 603552.0,
"mode_hp_secure": 597120.0,
"match_complete_win": 627440.0,
"avenger": 541184.0,
"save_teammate": 603744.0,
"streak_10": 215088.0,
"triple": 598736.0,
"buzzkill": 595488.0,
"item_impact": 45616.0,
"explosive_stick": 601392.0,
"first_place_kill": 617040.0
},
"nemesis": "Degeneracy",
"mostKilled": "juscraig21",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 93.0,
"medalXp": 9155.0,
"matchXp": 3470.0,
"averageSpeedDuringMatch": 202.14351,
"scoreXp": 9680.0,
"accuracy": 0.10581222056631892,
"wallBangs": 1.0,
"shotsLanded": 142.0,
"score": 12225.0,
"totalXp": 22485.0,
"headshots": 9.0,
"assists": 7.0,
"rank": 54.0,
"scorePerMinute": 1125.0,
"distanceTraveled": 3085.4763,
"deaths": 54.0,
"kdRatio": 1.7222222222222223,
"shotsMissed": 1200.0,
"timePlayed": "0 Days 0 Hours 10 Minutes 52 Seconds",
"executions": 0.0,
"suicides": 3.0,
"seasonRank": 11.0,
"nearmisses": 464.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 35 Seconds",
"miscXp": 0.0,
"longestStreak": 11.0,
"damageDone": 3062.0,
"shotsFired": 1342.0,
"damageTaken": 1705.0
},
"weaponStats": {
"semtex_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"iw8_sm_secho": {
"hits": 120.0,
"kills": 60.0,
"headshots": 8.0,
"loadoutIndex": 1.0,
"shots": 1123.0,
"startingWeaponXp": 77500.0,
"deaths": 38.0,
"xpEarned": 7350.0
},
"iw8_pi_mike": {
"hits": 4.0,
"kills": 4.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 48.0,
"startingWeaponXp": 42900.0,
"deaths": 2.0,
"xpEarned": 480.0
},
"Uzi": {
"hits": 15.0,
"kills": 15.0,
"headshots": 1.0,
"loadoutIndex": 0.0,
"shots": 134.0,
"startingWeaponXp": 72900.0,
"deaths": 12.0,
"xpEarned": 1920.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,96 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:13:41 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:16:36 AM",
"map": "King",
"mode": "Gunfight",
"matchID": "14856044705402585331",
"duration": "2 Minutes 55 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "loss",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 0,
"team2Score": 6,
"isPresentAtEnd": false,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"match_complete": 27792.0
},
"nemesis": "XD",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 0.0,
"medalXp": 250.0,
"matchXp": 156.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 0.0,
"accuracy": 0.06666666666666667,
"wallBangs": 0.0,
"shotsLanded": 1.0,
"score": 0.0,
"totalXp": 406.0,
"headshots": 0.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 0.0,
"distanceTraveled": 1462.4934,
"deaths": 3.0,
"kdRatio": 0.0,
"shotsMissed": 14.0,
"timePlayed": "0 Days 0 Hours 1 Minutes 55 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 0.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 0.0,
"damageDone": 29.0,
"shotsFired": 15.0,
"damageTaken": 300.0
},
"weaponStats": {
"molotov_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"Kar98k": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 0.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"FN Scar 17": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 15.0,
"startingWeaponXp": 97100.0,
"deaths": 2.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,113 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:08:32 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:11:32 AM",
"map": "King",
"mode": "Gunfight",
"matchID": "13009305297202702316",
"duration": "3 Minutes 0 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 0,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"mode_x_last_alive": 46704.0,
"mode_x_eliminate": 163168.0,
"kill_jumper": 39792.0,
"firstblood": 39696.0,
"match_complete_win": 165456.0,
"avenger": 46656.0,
"first_place_kill": 163120.0,
"longshot": 131936.0
},
"mostKilled": "WEEBZ71",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 4.0,
"medalXp": 1335.0,
"matchXp": 776.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 575.0,
"accuracy": 0.1346153846153846,
"wallBangs": 0.0,
"shotsLanded": 14.0,
"score": 575.0,
"totalXp": 2686.0,
"headshots": 0.0,
"assists": 3.0,
"rank": 54.0,
"scorePerMinute": 152.65486725663715,
"distanceTraveled": 1177.6459,
"deaths": 0.0,
"kdRatio": 4.0,
"shotsMissed": 90.0,
"timePlayed": "0 Days 0 Hours 3 Minutes 46 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 76.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 4.0,
"damageDone": 592.0,
"shotsFired": 104.0,
"damageTaken": 0.0
},
"weaponStats": {
"Renetti": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 20.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"semtex_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"FR 5.56": {
"hits": 2.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 39.0,
"startingWeaponXp": 97100.0,
"deaths": 0.0,
"xpEarned": 90.0
},
".50 GS": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 4.0,
"startingWeaponXp": 46500.0,
"deaths": 0.0,
"xpEarned": 90.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,138 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:03:05 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:06:35 AM",
"map": "Atrium",
"mode": "Gunfight",
"matchID": "17739886360827594237",
"duration": "3 Minutes 30 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 3,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 154176.0,
"one_shot_kill": 53936.0,
"mode_x_eliminate": 183808.0,
"pointblank": 138800.0,
"stunned_kill": 179776.0,
"match_complete_win": 186192.0,
"save_teammate": 72784.0,
"mode_x_last_alive": 183856.0,
"headshot": 54032.0,
"match_complete": 122576.0,
"firstblood": 179680.0,
"first_place_kill": 179824.0,
"longshot": 54080.0
},
"mostKilled": "Pretzelninja",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 9.0,
"medalXp": 2010.0,
"matchXp": 507.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 900.0,
"accuracy": 0.17142857142857143,
"wallBangs": 0.0,
"shotsLanded": 24.0,
"score": 900.0,
"totalXp": 3417.0,
"headshots": 1.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 209.30232558139534,
"distanceTraveled": 256.33984,
"deaths": 3.0,
"kdRatio": 3.0,
"shotsMissed": 116.0,
"timePlayed": "0 Days 0 Hours 4 Minutes 18 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 66.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 4.0,
"damageDone": 910.0,
"shotsFired": 140.0,
"damageTaken": 500.0
},
"weaponStats": {
"RAM-7": {
"hits": 8.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 7.0,
"shots": 30.0,
"startingWeaponXp": 94500.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"Renetti": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 2.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"X16": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 3.0,
"startingWeaponXp": 34600.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"725": {
"hits": 1.0,
"kills": 2.0,
"headshots": 1.0,
"loadoutIndex": 3.0,
"shots": 2.0,
"startingWeaponXp": 66300.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"AX-50": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 1.0,
"startingWeaponXp": 41200.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Holger-26": {
"hits": 7.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 87.0,
"startingWeaponXp": 77500.0,
"deaths": 1.0,
"xpEarned": 180.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,123 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:57:58 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 05:00:54 AM",
"map": "Atrium",
"mode": "Gunfight",
"matchID": "13409265659952302407",
"duration": "2 Minutes 56 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 1,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 132656.0,
"mode_x_last_alive": 132704.0,
"mode_x_eliminate": 156224.0,
"pointblank": 20128.0,
"firstblood": 91984.0,
"match_complete_win": 158608.0,
"streak_5": 92080.0,
"first_place_kill": 67536.0
},
"mostKilled": "AoKBraxton",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 7.0,
"medalXp": 1860.0,
"matchXp": 653.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 775.0,
"accuracy": 0.19047619047619047,
"wallBangs": 0.0,
"shotsLanded": 24.0,
"score": 775.0,
"totalXp": 3288.0,
"headshots": 0.0,
"assists": 2.0,
"rank": 54.0,
"scorePerMinute": 207.5892857142857,
"distanceTraveled": 411.2783,
"deaths": 1.0,
"kdRatio": 7.0,
"shotsMissed": 102.0,
"timePlayed": "0 Days 0 Hours 3 Minutes 44 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 70.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 7.0,
"damageDone": 726.0,
"shotsFired": 126.0,
"damageTaken": 249.0
},
"weaponStats": {
"1911": {
"hits": 5.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 18.0,
"startingWeaponXp": 33000.0,
"deaths": 1.0,
"xpEarned": 360.0
},
"X16": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 21.0,
"startingWeaponXp": 34600.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"SA87": {
"hits": 4.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 27.0,
"startingWeaponXp": 75200.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Kilo-141": {
"hits": 4.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 4.0,
"shots": 36.0,
"startingWeaponXp": 107700.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"R9-0": {
"hits": 3.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 3.0,
"startingWeaponXp": 58000.0,
"deaths": 0.0,
"xpEarned": 360.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,146 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:50:16 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 04:56:08 AM",
"map": "Drainage",
"mode": "Gunfight",
"matchID": "2733388683349347716",
"duration": "5 Minutes 52 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "loss",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 3,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 116080.0,
"one_shot_kill": 280560.0,
"mode_x_last_alive": 115984.0,
"mode_x_eliminate": 308224.0,
"headshot": 116032.0,
"match_complete": 326864.0,
"match_complete_win": 289216.0,
"firstblood": 280464.0,
"first_place_kill": 308176.0,
"longshot": 214880.0
},
"nemesis": "Fearless_Russian",
"mostKilled": "grvndd",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 6.0,
"medalXp": 2175.0,
"matchXp": 1375.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 725.0,
"accuracy": 0.184,
"wallBangs": 0.0,
"shotsLanded": 23.0,
"score": 725.0,
"totalXp": 4275.0,
"headshots": 1.0,
"assists": 3.0,
"rank": 54.0,
"scorePerMinute": 109.02255639097744,
"distanceTraveled": 1645.0175,
"deaths": 6.0,
"kdRatio": 1.0,
"shotsMissed": 102.0,
"timePlayed": "0 Days 0 Hours 6 Minutes 39 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 58.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 2.0,
"damageDone": 956.0,
"shotsFired": 125.0,
"damageTaken": 684.0
},
"weaponStats": {
"Mk2 Carbine": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 2.0,
"startingWeaponXp": 62100.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Renetti": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 6.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"PKM": {
"hits": 8.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 44.0,
"startingWeaponXp": 77500.0,
"deaths": 1.0,
"xpEarned": 180.0
},
"MP5": {
"hits": 2.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 8.0,
"startingWeaponXp": 77500.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"HDR": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 1.0,
"startingWeaponXp": 37800.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"M19": {
"hits": 2.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 20.0,
"startingWeaponXp": 33000.0,
"deaths": 2.0,
"xpEarned": 0.0
},
"CR-56 AMAX": {
"hits": 4.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 24.0,
"startingWeaponXp": 105000.0,
"deaths": 1.0,
"xpEarned": 180.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,136 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:41:45 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 04:47:59 AM",
"map": "Docks",
"mode": "Gunfight",
"matchID": "17696020629569265329",
"duration": "6 Minutes 14 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 4,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 287936.0,
"mode_x_eliminate": 346960.0,
"pointblank": 347056.0,
"kill_jumper": 347056.0,
"headshot": 287840.0,
"match_complete": 293216.0,
"firstblood": 312976.0,
"match_complete_win": 349344.0,
"first_place_kill": 347056.0,
"longshot": 194240.0,
"save_teammate": 347008.0
},
"mostKilled": "UTC_Makaveli93",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 9.0,
"medalXp": 2520.0,
"matchXp": 1430.0,
"averageSpeedDuringMatch": 153.73769,
"scoreXp": 900.0,
"accuracy": 0.24615384615384617,
"wallBangs": 0.0,
"shotsLanded": 32.0,
"score": 900.0,
"totalXp": 4850.0,
"headshots": 1.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 128.26603325415678,
"distanceTraveled": 527.61633,
"deaths": 5.0,
"kdRatio": 1.8,
"shotsMissed": 98.0,
"timePlayed": "0 Days 0 Hours 7 Minutes 1 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 66.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 29 Seconds",
"miscXp": 0.0,
"longestStreak": 4.0,
"damageDone": 896.0,
"shotsFired": 130.0,
"damageTaken": 550.0
},
"weaponStats": {
"Renetti": {
"hits": 4.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 11.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
".50 GS": {
"hits": 2.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 4.0,
"startingWeaponXp": 46500.0,
"deaths": 1.0,
"xpEarned": 180.0
},
"AUG": {
"hits": 10.0,
"kills": 3.0,
"headshots": 1.0,
"loadoutIndex": 8.0,
"shots": 56.0,
"startingWeaponXp": 77500.0,
"deaths": 1.0,
"xpEarned": 540.0
},
"EBR-14": {
"hits": 2.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 3.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"FiNN": {
"hits": 5.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 22.0,
"startingWeaponXp": 79800.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Model 680": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 7.0,
"shots": 1.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,145 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:36:07 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 04:40:04 AM",
"map": "Verdansk Stadium",
"mode": "Gunfight",
"matchID": "5316410820875242057",
"duration": "3 Minutes 57 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 1,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 117840.0,
"mode_x_last_alive": 161984.0,
"mode_x_eliminate": 208128.0,
"headshot": 208176.0,
"match_complete": 87296.0,
"firstblood": 208080.0,
"match_complete_win": 218880.0,
"avenger": 58240.0,
"first_place_kill": 161936.0,
"longshot": 2544.0
},
"mostKilled": "Espresso Depreso",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 6.0,
"medalXp": 1890.0,
"matchXp": 1228.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 625.0,
"accuracy": 0.16312056737588654,
"wallBangs": 0.0,
"shotsLanded": 23.0,
"score": 625.0,
"totalXp": 3743.0,
"headshots": 3.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 132.5088339222615,
"distanceTraveled": 2179.325,
"deaths": 1.0,
"kdRatio": 6.0,
"shotsMissed": 118.0,
"timePlayed": "0 Days 0 Hours 4 Minutes 43 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 80.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 3.0,
"damageDone": 728.0,
"shotsFired": 141.0,
"damageTaken": 265.0
},
"weaponStats": {
"Renetti": {
"hits": 3.0,
"kills": 1.0,
"headshots": 1.0,
"loadoutIndex": 0.0,
"shots": 13.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"M13": {
"hits": 7.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 48.0,
"startingWeaponXp": 107700.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"X16": {
"hits": 2.0,
"kills": 1.0,
"headshots": 1.0,
"loadoutIndex": 6.0,
"shots": 5.0,
"startingWeaponXp": 34600.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"SA87": {
"hits": 3.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 4.0,
"shots": 14.0,
"startingWeaponXp": 75200.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"JAK-12": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 1.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"frag_grenade_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"Uzi": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 15.0,
"startingWeaponXp": 72900.0,
"deaths": 0.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,114 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:29:20 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 04:34:13 AM",
"map": "Station",
"mode": "Gunfight",
"matchID": "3415184556073956365",
"duration": "4 Minutes 53 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 1,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 139504.0,
"slide_kill": 90384.0,
"mode_x_last_alive": 272736.0,
"mode_x_eliminate": 272832.0,
"pointblank": 272688.0,
"match_complete": 165248.0,
"firstblood": 215776.0,
"match_complete_win": 275120.0,
"first_place_kill": 272784.0
},
"mostKilled": "Chancethegabper",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 8.0,
"medalXp": 1655.0,
"matchXp": 1453.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 875.0,
"accuracy": 0.22448979591836735,
"wallBangs": 0.0,
"shotsLanded": 33.0,
"score": 875.0,
"totalXp": 3983.0,
"headshots": 0.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 153.95894428152494,
"distanceTraveled": 1028.6318,
"deaths": 2.0,
"kdRatio": 4.0,
"shotsMissed": 114.0,
"timePlayed": "0 Days 0 Hours 5 Minutes 41 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 76.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 4.0,
"damageDone": 926.0,
"shotsFired": 147.0,
"damageTaken": 275.0
},
"weaponStats": {
"AS VAL": {
"hits": 5.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 63.0,
"startingWeaponXp": 68500.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"Crossbow": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 3.0,
"startingWeaponXp": 48300.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"M19": {
"hits": 8.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 15.0,
"startingWeaponXp": 33000.0,
"deaths": 0.0,
"xpEarned": 315.0
},
"Holger-26": {
"hits": 8.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 17.0,
"startingWeaponXp": 77500.0,
"deaths": 0.0,
"xpEarned": 360.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,116 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 06:09:01 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 06:12:07 AM",
"map": "Gulag Showers",
"mode": "Gunfight",
"matchID": "6346764813811873465",
"duration": "3 Minutes 6 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 0,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 111360.0,
"one_shot_kill": 169152.0,
"mode_x_last_alive": 32864.0,
"mode_x_eliminate": 169200.0,
"firstblood": 152336.0,
"match_complete_win": 171488.0,
"streak_5": 82896.0,
"first_place_kill": 169248.0,
"throwingknife_kill": 82848.0,
"longshot": 152480.0,
"streak_10": 169296.0
},
"mostKilled": "Krawry",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 10.0,
"medalXp": 2505.0,
"matchXp": 926.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 1000.0,
"accuracy": 0.18181818181818182,
"wallBangs": 0.0,
"shotsLanded": 20.0,
"score": 1000.0,
"totalXp": 4431.0,
"headshots": 0.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 258.62068965517244,
"distanceTraveled": 1678.2056,
"deaths": 0.0,
"kdRatio": 10.0,
"shotsMissed": 90.0,
"timePlayed": "0 Days 0 Hours 3 Minutes 52 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 62.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 10.0,
"damageDone": 950.0,
"shotsFired": 110.0,
"damageTaken": 240.0
},
"weaponStats": {
"Renetti": {
"hits": 5.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 26.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"throwingknife_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"SP-R 208": {
"hits": 2.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 4.0,
"startingWeaponXp": 72900.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"AK-47": {
"hits": 6.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 33.0,
"startingWeaponXp": 105000.0,
"deaths": 0.0,
"xpEarned": 360.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,110 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 04:20:23 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 04:26:58 AM",
"map": "Livestock",
"mode": "Gunfight",
"matchID": "2081370177425210286",
"duration": "6 Minutes 35 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 3,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"mode_x_eliminate": 368352.0,
"headshot": 368400.0,
"match_complete_win": 370640.0,
"firstblood": 368304.0,
"first_place_kill": 368448.0
},
"mostKilled": "AD",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 1.0,
"medalXp": 545.0,
"matchXp": 562.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 175.0,
"accuracy": 0.4166666666666667,
"wallBangs": 0.0,
"shotsLanded": 5.0,
"score": 175.0,
"totalXp": 1282.0,
"headshots": 1.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 57.69230769230769,
"distanceTraveled": 1978.1707,
"deaths": 2.0,
"kdRatio": 0.5,
"shotsMissed": 7.0,
"timePlayed": "0 Days 0 Hours 3 Minutes 2 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 6.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 1.0,
"damageDone": 191.0,
"shotsFired": 12.0,
"damageTaken": 200.0
},
"weaponStats": {
"Renetti": {
"hits": 1.0,
"kills": 1.0,
"headshots": 1.0,
"loadoutIndex": 3.0,
"shots": 1.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
".50 GS": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 2.0,
"startingWeaponXp": 46500.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"AX-50": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 1.0,
"startingWeaponXp": 41200.0,
"deaths": 1.0,
"xpEarned": 135.0
},
"JAK-12": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 8.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,133 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 06:01:05 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 06:07:08 AM",
"map": "Hill",
"mode": "Gunfight",
"matchID": "15937623934231999740",
"duration": "6 Minutes 3 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 3,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"mode_x_last_alive": 89952.0,
"mode_x_eliminate": 158576.0,
"match_complete": 198176.0,
"firstblood": 158528.0,
"match_complete_win": 160864.0,
"first_place_kill": 158624.0,
"longshot": 7872.0,
"mode_dom_secure_neutral": 292816.0
},
"mostKilled": "Deny",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 3.0,
"medalXp": 1430.0,
"matchXp": 970.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 350.0,
"accuracy": 0.125,
"wallBangs": 0.0,
"shotsLanded": 12.0,
"score": 350.0,
"totalXp": 2750.0,
"headshots": 0.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 51.470588235294116,
"distanceTraveled": 1166.2561,
"deaths": 4.0,
"kdRatio": 0.75,
"shotsMissed": 84.0,
"timePlayed": "0 Days 0 Hours 6 Minutes 48 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 44.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 1.0,
"damageDone": 343.0,
"shotsFired": 96.0,
"damageTaken": 453.0
},
"weaponStats": {
"Bruen MK9": {
"hits": 3.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 49.0,
"startingWeaponXp": 82200.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"molotov_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"Kar98k": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 0.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"AK-47": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 6.0,
"startingWeaponXp": 105000.0,
"deaths": 1.0,
"xpEarned": 90.0
},
".50 GS": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 7.0,
"shots": 5.0,
"startingWeaponXp": 46500.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"PP19 Bizon": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 14.0,
"startingWeaponXp": 60000.0,
"deaths": 1.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,166 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 05:51:34 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 05:58:40 AM",
"map": "Station",
"mode": "Gunfight",
"matchID": "18110501888267967862",
"duration": "7 Minutes 6 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 5,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 223888.0,
"one_shot_kill": 15360.0,
"mode_x_eliminate": 394928.0,
"kill_jumper": 223936.0,
"headshot": 207184.0,
"match_complete": 341360.0,
"firstblood": 296736.0,
"match_complete_win": 397216.0,
"first_place_kill": 296736.0,
"save_teammate": 223792.0,
"grenade_double": 296736.0
},
"mostKilled": "REAPER REEFBACK",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 9.0,
"medalXp": 2500.0,
"matchXp": 1983.0,
"averageSpeedDuringMatch": 88.17954,
"scoreXp": 975.0,
"accuracy": 0.1949685534591195,
"wallBangs": 0.0,
"shotsLanded": 31.0,
"score": 975.0,
"totalXp": 5458.0,
"headshots": 2.0,
"assists": 2.0,
"rank": 54.0,
"scorePerMinute": 123.67864693446089,
"distanceTraveled": 1425.6935,
"deaths": 6.0,
"kdRatio": 1.5,
"shotsMissed": 128.0,
"timePlayed": "0 Days 0 Hours 7 Minutes 53 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 110.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 23 Seconds",
"miscXp": 0.0,
"longestStreak": 3.0,
"damageDone": 1020.0,
"shotsFired": 159.0,
"damageTaken": 772.0
},
"weaponStats": {
"Mk2 Carbine": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 5.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"Renetti": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 8.0,
"shots": 12.0,
"startingWeaponXp": 54000.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"semtex_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 7.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"X16": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 1.0,
"startingWeaponXp": 34600.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"M13": {
"hits": 4.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 47.0,
"startingWeaponXp": 107700.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"molotov_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 9.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
},
"MG34": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 9.0,
"shots": 1.0,
"startingWeaponXp": 77500.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"MP7": {
"hits": 4.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 18.0,
"startingWeaponXp": 70700.0,
"deaths": 2.0,
"xpEarned": 0.0
},
"Origin 12": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 8.0,
"shots": 3.0,
"startingWeaponXp": 62100.0,
"deaths": 1.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,136 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 05:43:28 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 05:49:39 AM",
"map": "Verdansk Stadium",
"mode": "Gunfight",
"matchID": "1253304090523704633",
"duration": "6 Minutes 11 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 4,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 343264.0,
"mode_x_last_alive": 343216.0,
"mode_x_eliminate": 343312.0,
"stunned_kill": 125616.0,
"headshot": 343168.0,
"match_complete": 205648.0,
"firstblood": 331568.0,
"match_complete_win": 345504.0,
"streak_5": 300656.0,
"first_place_kill": 343312.0,
"longshot": 18592.0
},
"mostKilled": "Sinister_vibez",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 13.0,
"medalXp": 2825.0,
"matchXp": 1700.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 1325.0,
"accuracy": 0.21518987341772153,
"wallBangs": 1.0,
"shotsLanded": 34.0,
"score": 1300.0,
"totalXp": 5850.0,
"headshots": 3.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 187.05035971223023,
"distanceTraveled": 605.7957,
"deaths": 4.0,
"kdRatio": 3.25,
"shotsMissed": 124.0,
"timePlayed": "0 Days 0 Hours 6 Minutes 57 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 76.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 7.0,
"damageDone": 1227.0,
"shotsFired": 158.0,
"damageTaken": 549.0
},
"weaponStats": {
"MG34": {
"hits": 9.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 4.0,
"shots": 56.0,
"startingWeaponXp": 77500.0,
"deaths": 2.0,
"xpEarned": 360.0
},
".50 GS": {
"hits": 3.0,
"kills": 2.0,
"headshots": 1.0,
"loadoutIndex": 8.0,
"shots": 8.0,
"startingWeaponXp": 46500.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"EBR-14": {
"hits": 3.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 5.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"CR-56 AMAX": {
"hits": 3.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 35.0,
"startingWeaponXp": 105000.0,
"deaths": 1.0,
"xpEarned": 180.0
},
"PP19 Bizon": {
"hits": 7.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 20.0,
"startingWeaponXp": 60000.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"frag_grenade_mp": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 8.0,
"shots": 0.0,
"startingWeaponXp": 0.0,
"deaths": 0.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,73 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 05:41:29 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 05:41:55 AM",
"map": "mp_m_wallco2",
"mode": "Gunfight",
"matchID": "12718453956080109439",
"duration": "0 Minutes 26 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "none",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 0,
"team2Score": 0,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {},
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 0.0,
"medalXp": 0.0,
"matchXp": 0.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 0.0,
"accuracy": 0.0,
"wallBangs": 0.0,
"shotsLanded": 0.0,
"score": 0.0,
"totalXp": 0.0,
"headshots": 0.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 0.0,
"distanceTraveled": 1620.1016,
"deaths": 0.0,
"kdRatio": 0.0,
"shotsMissed": 39.0,
"timePlayed": "0 Days 0 Hours 1 Minutes 7 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 0.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 0.0,
"damageDone": 0.0,
"shotsFired": 39.0,
"damageTaken": 0.0
},
"weaponStats": {
"FR 5.56": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 39.0,
"startingWeaponXp": 97100.0,
"deaths": 0.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,117 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 05:35:41 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 05:39:29 AM",
"map": "Trench",
"mode": "Gunfight",
"matchID": "9728985686232441920",
"duration": "3 Minutes 48 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "allies",
"gameBattle": false,
"team1Score": 6,
"team2Score": 1,
"isPresentAtEnd": true,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"low_health_kill": 130048.0,
"one_shot_kill": 64416.0,
"mode_x_last_alive": 90544.0,
"gun_butt": 129952.0,
"mode_x_eliminate": 207808.0,
"kill_jumper": 64512.0,
"match_complete": 187600.0,
"match_complete_win": 210144.0,
"firstblood": 106656.0,
"streak_5": 106752.0,
"first_place_kill": 130096.0,
"longshot": 151856.0
},
"mostKilled": "d-fresh810",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 8.0,
"medalXp": 2180.0,
"matchXp": 1150.0,
"averageSpeedDuringMatch": 0.0,
"scoreXp": 875.0,
"accuracy": 0.22794117647058823,
"wallBangs": 0.0,
"shotsLanded": 31.0,
"score": 875.0,
"totalXp": 4205.0,
"headshots": 0.0,
"assists": 1.0,
"rank": 54.0,
"scorePerMinute": 191.60583941605842,
"distanceTraveled": 1500.3002,
"deaths": 2.0,
"kdRatio": 4.0,
"shotsMissed": 105.0,
"timePlayed": "0 Days 0 Hours 4 Minutes 34 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 73.0,
"percentTimeMoving": "0 Days 0 Hours 0 Minutes 0 Seconds",
"miscXp": 0.0,
"longestStreak": 7.0,
"damageDone": 955.0,
"shotsFired": 136.0,
"damageTaken": 334.0
},
"weaponStats": {
"SP-R 208": {
"hits": 1.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 7.0,
"startingWeaponXp": 72900.0,
"deaths": 1.0,
"xpEarned": 135.0
},
"MP7": {
"hits": 11.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 2.0,
"shots": 27.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"M19": {
"hits": 3.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 6.0,
"shots": 13.0,
"startingWeaponXp": 33000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"JAK-12": {
"hits": 2.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 5.0,
"shots": 3.0,
"startingWeaponXp": 70700.0,
"deaths": 1.0,
"xpEarned": 0.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,127 @@
{
"utcStartSeconds": "GMT: Sunday, December 24, 2023 05:27:32 AM",
"utcEndSeconds": "GMT: Sunday, December 24, 2023 05:32:35 AM",
"map": "Speedball",
"mode": "Gunfight",
"matchID": "16921360291940233410",
"duration": "5 Minutes 3 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "win",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 2,
"team2Score": 6,
"isPresentAtEnd": true,
"player": {
"team": "axis",
"rank": 66.0,
"awards": {
"low_health_kill": 280032.0,
"one_shot_kill": 45152.0,
"mode_x_last_alive": 279936.0,
"mode_x_eliminate": 280032.0,
"pointblank": 76448.0,
"headshot": 250816.0,
"match_complete": 223488.0,
"match_complete_win": 282224.0,
"firstblood": 159728.0,
"streak_5": 122000.0,
"first_place_kill": 250960.0,
"longshot": 279984.0
},
"mostKilled": "CHUTE138BFP",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 10.0,
"medalXp": 2480.0,
"matchXp": 1546.0,
"averageSpeedDuringMatch": 134.92415,
"scoreXp": 1000.0,
"accuracy": 0.22131147540983606,
"wallBangs": 0.0,
"shotsLanded": 27.0,
"score": 1000.0,
"totalXp": 5026.0,
"headshots": 5.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 172.41379310344826,
"distanceTraveled": 806.2849,
"deaths": 2.0,
"kdRatio": 5.0,
"shotsMissed": 95.0,
"timePlayed": "0 Days 0 Hours 5 Minutes 48 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 74.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 35 Seconds",
"miscXp": 0.0,
"longestStreak": 7.0,
"damageDone": 1016.0,
"shotsFired": 122.0,
"damageTaken": 349.0
},
"weaponStats": {
"1911": {
"hits": 6.0,
"kills": 2.0,
"headshots": 0.0,
"loadoutIndex": 3.0,
"shots": 30.0,
"startingWeaponXp": 33000.0,
"deaths": 0.0,
"xpEarned": 360.0
},
"SP-R 208": {
"hits": 0.0,
"kills": 0.0,
"headshots": 0.0,
"loadoutIndex": 1.0,
"shots": 3.0,
"startingWeaponXp": 72900.0,
"deaths": 1.0,
"xpEarned": 0.0
},
"AUG": {
"hits": 3.0,
"kills": 1.0,
"headshots": 1.0,
"loadoutIndex": 5.0,
"shots": 16.0,
"startingWeaponXp": 77500.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"M19": {
"hits": 4.0,
"kills": 1.0,
"headshots": 1.0,
"loadoutIndex": 7.0,
"shots": 21.0,
"startingWeaponXp": 33000.0,
"deaths": 0.0,
"xpEarned": 180.0
},
"JAK-12": {
"hits": 2.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 7.0,
"shots": 4.0,
"startingWeaponXp": 70700.0,
"deaths": 0.0,
"xpEarned": 180.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

View File

@ -0,0 +1,86 @@
{
"utcStartSeconds": "GMT: Saturday, December 23, 2023 05:56:36 AM",
"utcEndSeconds": "GMT: Saturday, December 23, 2023 06:06:15 AM",
"map": "Shipment",
"mode": "Hardpoint Hardcore",
"matchID": "10568859084251588825",
"duration": "9 Minutes 39 Seconds 0 Milliseconds",
"playlistName": null,
"version": 1,
"gameType": "mp",
"result": "loss",
"winningTeam": "axis",
"gameBattle": false,
"team1Score": 46,
"team2Score": 250,
"isPresentAtEnd": false,
"player": {
"team": "allies",
"rank": 66.0,
"awards": {
"one_shot_kill": 45312.0,
"pointblank": 35472.0,
"mode_x_assault": 35424.0,
"triple": 38912.0,
"kill_jumper": 10304.0,
"double": 45280.0,
"four": 40528.0,
"mode_hp_secure": 35392.0,
"streak_5": 44784.0,
"avenger": 38848.0
},
"nemesis": "zey",
"mostKilled": "Igetsbusy00",
"username": "Ahrimdon",
"uno": "19568270",
"clantag": "Bettr",
"platform": "battlenet",
"killstreakUsage": {}
},
"playerStats": {
"kills": 9.0,
"medalXp": 750.0,
"matchXp": 0.0,
"averageSpeedDuringMatch": 192.57266,
"scoreXp": 900.0,
"accuracy": 0.12162162162162163,
"wallBangs": 0.0,
"shotsLanded": 9.0,
"score": 1060.0,
"totalXp": 1650.0,
"headshots": 0.0,
"assists": 0.0,
"rank": 54.0,
"scorePerMinute": 766.2650602409639,
"distanceTraveled": 1192.0525,
"deaths": 4.0,
"kdRatio": 2.25,
"shotsMissed": 65.0,
"timePlayed": "0 Days 0 Hours 1 Minutes 23 Seconds",
"executions": 0.0,
"suicides": 0.0,
"seasonRank": 11.0,
"nearmisses": 30.0,
"percentTimeMoving": "0 Days 0 Hours 1 Minutes 30 Seconds",
"miscXp": 0.0,
"longestStreak": 6.0,
"damageDone": 248.0,
"shotsFired": 74.0,
"damageTaken": 125.0
},
"weaponStats": {
"CR-56 AMAX": {
"hits": 1.0,
"kills": 1.0,
"headshots": 0.0,
"loadoutIndex": 0.0,
"shots": 5.0,
"startingWeaponXp": 105000.0,
"deaths": 2.0,
"xpEarned": 360.0
}
},
"allPlayers": null,
"Gunfight": false,
"privateMatch": false
}

36
examples/settings.json Normal file
View File

@ -0,0 +1,36 @@
{
"status": "success",
"data": {
"battle": {
"signon_visible": "friends",
"data_visible": "all",
"searchable": "all"
},
"xbl": {
"signon_visible": "friends",
"data_visible": "all",
"searchable": "all"
},
"uno": {
"push_gift_activity": "all",
"push_cod_updates": "all",
"push_intel_activity": "all",
"push_cod_events": "all",
"push_fav_signon": "all",
"push_ops_activity": "all",
"push_cod_news": "all",
"searchable": "all",
"signon_visible": "friends",
"push_intel_updates": "all",
"push_cwl_updates": "all",
"push_fav_activity": "all",
"push_ops_updates": "all",
"data_visible": "friends_tourneys"
},
"psn": {
"signon_visible": "friends",
"data_visible": "friends_tourneys",
"searchable": "all"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,380 +0,0 @@
import json
import os
import argparse
from cod_api import API, platforms
import asyncio
# Prevent Async error from showing
if os.name == 'nt':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
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
}
# Initiating the API class
api = API()
COOKIE_FILE = 'cookie.txt'
def get_and_save_data(player_name=None):
# Create the stats directory if it doesn't exist
DIR_NAME = 'stats'
if not os.path.exists(DIR_NAME):
os.makedirs(DIR_NAME)
# 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)
# If player_name is not provided via command line, get it from user input
if not player_name:
player_name = input("Please enter the player's username (with #1234567): ")
# Login with sso token
api.login(api_key)
# Retrieve data from API
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 inside the stats directory
with open(os.path.join(DIR_NAME, 'stats.json'), 'w') as json_file:
json.dump(player_stats, json_file, indent=4)
with open(os.path.join(DIR_NAME, 'match_info.json'), 'w') as json_file:
json.dump(match_info, json_file, indent=4)
with open(os.path.join(DIR_NAME, 'season_loot.json'), 'w') as json_file:
json.dump(season_loot, json_file, indent=4)
with open(os.path.join(DIR_NAME, 'map_list.json'), 'w') as json_file:
json.dump(map_list, json_file, indent=4)
with open(os.path.join(DIR_NAME, 'identities.json'), 'w') as json_file:
json.dump(identities, json_file, indent=4)
def recursive_key_replace(obj, replacements):
if isinstance(obj, dict):
new_obj = {}
for key, value in obj.items():
new_key = replacements.get(key, key)
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):
return [recursive_key_replace(item, replacements) for item in obj]
else:
return replacements.get(obj, obj) if isinstance(obj, str) else obj
def sort_data(data):
if isinstance(data, dict):
for key, value in data.items():
if key == "mode":
data[key] = dict(sorted(value.items(), key=lambda item: item[1]['properties']['timePlayed'], reverse=True))
elif key in ["Assault Rifles", "Shotguns", "Marksman Rifles", "Snipers", "LMGs", "Launchers", "Pistols", "SMGs", "Melee"]:
data[key] = dict(sorted(value.items(), key=lambda item: item[1]['properties']['kills'], reverse=True))
elif key in ["Field Upgrades"]:
data[key] = dict(sorted(value.items(), key=lambda item: item[1]['properties']['uses'], reverse=True))
elif key in ["Tactical Equipment", "Lethal Equipment"]:
data[key] = dict(sorted(value.items(), key=lambda item: item[1]['properties']['uses'], reverse=True))
elif key == "Scorestreaks":
for subcategory, scorestreaks in value.items():
data[key][subcategory] = dict(sorted(scorestreaks.items(), key=lambda item: item[1]['properties']['awardedCount'], reverse=True))
elif key == "Accolades":
if 'properties' in value:
data[key]['properties'] = dict(sorted(value['properties'].items(), key=lambda item: item[1], reverse=True))
else:
# Recursive call to handle nested dictionaries
data[key] = sort_data(value)
return data
def beautify_data():
file_path = "stats.json"
with open(file_path, 'r') as file:
data = json.load(file)
data = recursive_key_replace(data, replacements)
data = sort_data(data)
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
print(f"Keys sorted and replaced in {file_path}!")
def beautify_match_data():
file_path = "match_info.json"
with open(file_path, 'r') as file:
data = json.load(file)
data = recursive_key_replace(data, replacements)
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
print(f"Keys replaced in {file_path}!")
def main():
# Define the block of quote text to display in the help command
help_text = """
Obtaining your ACT_SSO_COOKIE
- Go to https://www.callofduty.com and login with your account
- Once logged in, press F12 for your browsers developer tools. Then go to Application --> Storage --> Cookies --> https://www.callofduty.com and find ACT_SSO_COOKIE
- Enter the value when prompted
"""
parser = argparse.ArgumentParser(description="COD Data Tool", epilog=help_text, formatter_class=argparse.RawDescriptionHelpFormatter)
# Add arguments for your commands
parser.add_argument("--replace-data", action="store_true", help="Beautify the data in stats.json")
parser.add_argument("--replace-match-data", action="store_true", help="Beautify the match data in match_info.json")
parser.add_argument("--player-name", type=str, help="Player's username (with #1234567)")
args = parser.parse_args()
if args.replace_data:
beautify_data()
elif args.replace_match_data:
beautify_match_data()
else:
get_and_save_data(args.player_name)
if __name__ == "__main__":
main()

298
ref/beautify_data.py Normal file
View 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}!")

View 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
ref/convert_epoch.py Normal file
View 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'))

30
ref/curl/curl_links.txt Normal file
View File

@ -0,0 +1,30 @@
# Get Stats Using Battle.NET (Requires Numbers)
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/$PROF/profile/type/mp
# Get Stats Using PSN
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/psn/gamer/$PROF/profile/type/mp
# Get Stats Using Xbox Live
https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/xbl/gamer/$PROF/profile/type/mp
# Get Recent Games
https://my.callofduty.com/api/papi-client/crm/cod/v2/title/mw/platform/battle/gamer/$PROF/matches/mp/start/0/end/0/details
# 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 friendFeedEvents
https://my.callofduty.com/api/papi-client/userfeed/v1/friendFeed/platform/battle/gamer/$PROF/friendFeedEvents/en
# Get eventFeed
https://my.callofduty.com/api/papi-client/userfeed/v1/friendFeed/rendered/en/{acct_sso_token}
# Get CP
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
# Get Bundle Info
https://my.callofduty.com/api/papi-client/inventory/v1/title/mw/bundle/400525/en

View File

@ -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"
@ -8,6 +8,4 @@ $URL = "AddLinkHere"
$USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
$OUTPUT_FILE = "stats.json"
curl -v $URL -H "Cookie: ACT_SSO_COOKIE=$COOKIE_VALUE" -H "User-Agent: $USER_AGENT" -o $OUTPUT_FILE
# Replace
curl -v $URL -H "Cookie: ACT_SSO_COOKIE=$COOKIE_VALUE" -H "User-Agent: $USER_AGENT" -o $OUTPUT_FILE

45
ref/fetch_playerdata.py Normal file
View 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)

139
setup.py
View File

@ -1,47 +1,112 @@
#!/usr/bin/env python3
"""
Setup script for Modern Warfare 2019 Advanced Statistics Tracker.
Creates a virtual environment and installs required dependencies.
"""
import os
import subprocess
import sys
import venv
from pathlib import Path
def deps_exists():
return os.path.exists('deps')
def create_venv():
venv.create('venv', with_pip=True)
# Create activation scripts
with open("venv.ps1", "w") as f:
f.write("venv\\Scripts\\Activate.ps1")
def check_dependencies():
"""Check if the dependencies directory exists."""
deps_dir = Path('deps')
if not deps_dir.exists():
print("Error: 'deps' directory not found!")
print("Please ensure the dependencies directory exists before running setup.")
sys.exit(1)
return deps_dir
with open("venv.bat", "w") as f:
f.write("venv\\Scripts\\activate")
def upgrade_pip():
subprocess.check_call([os.path.join('venv', 'Scripts', 'pip'), 'install', '--no-index', '--find-links=deps', 'pip'])
def install_wheel():
subprocess.check_call([os.path.join('venv', 'Scripts', 'pip'), 'install', '--no-index', '--find-links=deps', 'wheel'])
def install_requirements_in_venv():
# Use the full path to the wheel file
wheel_path = os.path.join('src', 'cod_api-2.0.1-py3-none-any.whl')
subprocess.check_call([os.path.join('venv', 'Scripts', 'pip'), 'install', '--no-index', '--find-links=deps', wheel_path])
def create_virtual_environment():
"""Create and configure a Python virtual environment."""
print("Creating virtual environment...")
venv_dir = Path('venv')
def install_build_dependencies():
subprocess.check_call([os.path.join('venv', 'Scripts', 'pip'), 'install', '--no-index', '--find-links=deps', 'pyinstaller'])
subprocess.check_call([os.path.join('venv', 'Scripts', 'pip'), 'uninstall', 'enum34', '-y'])
# Create the virtual environment with pip
venv.create(venv_dir, with_pip=True)
# Create activation scripts for different platforms
scripts = {
"venv.ps1": "venv\\Scripts\\Activate.ps1",
"venv.bat": "venv\\Scripts\\activate",
"venv.sh": "source venv/bin/activate" # Added for Unix/Linux users
}
for filename, content in scripts.items():
with open(filename, "w") as f:
f.write(content)
return venv_dir
def get_pip_path(venv_dir):
"""Get the platform-specific path to pip in the virtual environment."""
if sys.platform == 'win32':
return venv_dir / 'Scripts' / 'pip'
return venv_dir / 'bin' / 'pip'
def install_packages(pip_path, deps_dir):
"""Install required packages from the local dependencies directory."""
print("Installing base packages...")
base_packages = ['pip', 'wheel', 'build', 'pyinstaller']
subprocess.check_call([
str(pip_path), 'install',
'--no-index',
f'--find-links={deps_dir}',
*base_packages
])
print("Installing COD API package...")
cod_api_wheel = 'cod_api-2.0.2-py3-none-any.whl'
subprocess.check_call([
str(pip_path), 'install',
'--no-index',
f'--find-links={deps_dir}',
str(deps_dir / cod_api_wheel)
])
def clean_environment(pip_path):
"""Remove deprecated or conflicting packages."""
print("Removing deprecated packages...")
deprecated_packages = ['enum34']
subprocess.check_call([
str(pip_path), 'uninstall', *deprecated_packages, '-y'
])
def main():
"""Main setup function."""
print("Starting setup for Modern Warfare 2019 Statistics Tracker...")
# Check for dependencies directory
deps_dir = check_dependencies()
# Create and configure the virtual environment
venv_dir = create_virtual_environment()
# Get the appropriate pip path
pip_path = get_pip_path(venv_dir)
# Install required packages
install_packages(pip_path, deps_dir)
# Clean up environment
clean_environment(pip_path)
print("\nSetup completed successfully!")
print(f"To activate the virtual environment, run:")
if sys.platform == 'win32':
print(" - PowerShell: .\\venv.ps1")
print(" - Command Prompt: venv.bat")
else:
print(" - Bash/Zsh: source venv.sh")
if __name__ == "__main__":
if not deps_exists():
print("Error: 'deps' directory does not exist!")
exit(1)
print("Creating virtual environment...")
create_venv()
print("Upgrading pip...")
upgrade_pip()
print("Installing wheel...")
install_wheel()
print("Installing packages in the virtual environment...")
install_requirements_in_venv() # Call the function to install the requirements
print("Installing build dependencies...")
install_build_dependencies()
print("Setup complete.")
main()

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More