From cf32fa4d29e53a066e0ed5574ed759ed4a9b9ed5 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Sun, 13 Feb 2022 23:48:55 +0100 Subject: [PATCH 01/61] add guns --- siegeapi/constants/guns.py | 337 +++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 siegeapi/constants/guns.py diff --git a/siegeapi/constants/guns.py b/siegeapi/constants/guns.py new file mode 100644 index 0000000..1da599e --- /dev/null +++ b/siegeapi/constants/guns.py @@ -0,0 +1,337 @@ +# Icon url: f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.icon_url}" + +GUNS_DICT = { + "primary": { + # AR's + "AK-12": { + "type": "Assault Rifle", + "icon_url": "7KAZZgnpqD07y47jVVXEuh/e0d7e67101f8f966aa6e1c59e835454f/AK-12.png", + }, + "SC3000K": { + "type": "Assault Rifle", + "icon_url": "7x7eDTm2NNpfGiFMrfQqEX/9898e74c780537be3ca6d88db32ea21e/F2000.png", + }, + "V308": { + "type": "Assault Rifle", + "icon_url": "5YBZe76NUDO32eF66wW90g/488c315743d59230962a4d67618223d6/V308.png", + }, + "416-C CARBINE": { + "type": "Assault Rifle", + "icon_url": "2I86r2a2QD8EHTZVZnxcxy/2913450ba952a16c29fac1f5ce58ba1a/416-C_Carbine.png", + }, + "556XI": { + "type": "Assault Rifle", + "icon_url": "2dgpAeAWb3SkZV7rxDbVdQ/fa32323256b7c6f8a1977d3f71e7d4b2/556xi.png", + }, + "M762": { + "type": "Assault Rifle", + "icon_url": "4oWAgi7tgQP1Tq0HooRtye/9109a74921ee17610d4bd85a61582823/M762.png", + }, + "TYPE-89": { + "type": "Assault Rifle", + "icon_url": "7wLf325q9amF8bnVP1QGr0/2faff1a197f90dcded4472852a317d6b/Type-89.png", + }, + "M4": { + "type": "Assault Rifle", + "icon_url": "3jhi90ycmuc8mAiuSXFoCi/bcf354459e7becd6ede52ee97917c832/M4.png", + }, + "PARA-308": { + "type": "Assault Rifle", + "icon_url": "6ub8y2Cs5EYhVPfDWuVVkW/82ca131a41ee4ba2e0b75f2dc52ed9e3/PARA-308.png", + }, + "SPEAR .308": { + "type": "Assault Rifle", + "icon_url": "29LjYuJ4s6yA8k9Uv2u28C/89ec812559e7d74b7c269279f4c46d92/Spear_.308.png", + }, + "AK-74M": { + "type": "Assault Rifle", + "icon_url": "1j5HiQP8aFphTe65fqDdg0/23eecb5c603c5ba9f59fc6cbc5e4a531/AK-74M.png", + }, + "AR33": { + "type": "Assault Rifle", + "icon_url": "16U6xEvX8I5xQd9duveBLN/45d22960872cfa3fb6be9eb47fa0be4e/AR33.png", + }, + "L85A2": { + "type": "Assault Rifle", + "icon_url": "5vYQpoyk36foDzDq49jBd0/1479a2d7189e545555ceccecf6bd7cc3/L85A2.png", + }, + "G36C": { + "type": "Assault Rifle", + "icon_url": "2SZoqSXKoNPvZFIJsFsDE5/cb109885bf19c8697abf832f10cfd9a6/G36C.png", + }, + "COMMANDO 9": { + "type": "Assault Rifle", + "icon_url": "4P9dpUph5w3MSsLNnW6be/04baba24990fcb75a9c0bcfd01b7d190/Commando_9.png", + }, + + # Submachine Guns + "9mm C1": { + "type": "Submachine Gun", + "icon_url": "60sbThKtOpNOwKu3OP0oGV/672fd9263f7786402a0d855273473a6f/9mm_C1.png", + }, + "AUG A3": { + "type": "Submachine Gun", + "icon_url": "3W9XJdMOgpHSw55HfwRSAv/cf8f220678d503e6c3e535c00b2e636a/AUG_A3.png", + }, + "VECTOR .45 ACP": { + "type": "Submachine Gun", + "icon_url": "7D1cDf13FqUhoLihzvuPln/068aa7e507155598449c58c0a49a90d6/Vector_.45_ACP.png", + }, + "M12": { + "type": "Submachine Gun", + "icon_url": "4FxqA5pa8JY9QQ7FEcjwPw/ffc779fcde5b970e7b95db6653637dab/M12.png", + }, + "FMG-9": { + "type": "Submachine Gun", + "icon_url": "0oneJNsBR06QjuowxwtHG/bd3b391c6eec2bd615f2ed83197a13ac/FMG-9.png", + }, + "PDW9": { + "type": "Submachine Gun", + "icon_url": "4yYCuRnduMq35CTHfq6wwU/b7d49cdbcb05917e014c99efeaadd33b/PDW9.png", + }, + "MP5": { + "type": "Submachine Gun", + "icon_url": "60YbOvSBQt6ZUlu8YDXoZm/51ef3857b2986de700262432e8433714/MP5.png", + }, + "MPX": { + "type": "Submachine Gun", + "icon_url": "5HFewpAJ8npDDCKFnEadhL/d398bb477d6b56fe41bfdb5862ed31c0/MPX.png", + }, + "MP7": { + "type": "Submachine Gun", + "icon_url": "3a4dgTWGdiJqALhtRp4pKy/f2568d3de3cfe7e4b53179e8653cd2a2/MP7.png", + }, + "T-5 SMG": { + "type": "Submachine Gun", + "icon_url": "1Ne8bvX8BdCALevWKMllQN/4baa3e79d323de134dd182e0272b9c3b/T-5_SMG.png", + }, + "K1A": { + "type": "Submachine Gun", + "icon_url": "5mUa2p8WXbiyD71qUI8sGk/ed753b6f0ae30ab5737486dfcf32ee9f/K1A.png", + }, + "Mx4 Storm": { + "type": "Submachine Gun", + "icon_url": "4qRh1frGkQZxNyeKA4D6n1/20f89cd1d9953f06207b7340ea77fb17/Mx4_Storm.png", + }, + "UZK50GI": { + "type": "Submachine Gun", + "icon_url": "5WMIsPUWTXprZnAwctPsTt/f1c652b681e7e9ba6ba66bcd29e12a76/uzk50gi.png", + }, + "9x19VSN": { + "type": "Submachine Gun", + "icon_url": "42gH96xTTYaTZsfXI3c0wL/a7edbf11af97091ee884b68e59fe6a4f/9x19VSN.png", + }, + "MP5K": { + "type": "Submachine Gun", + "icon_url": "1pk8nOI7ybQjYOSI4fuzOm/fcd78df0f729be545e75c09aae85c360/MP5K.png", + }, + + # Marksman Rifles + "SR-25": { + "type": "Marksman Rifle", + "icon_url": "3H3sICdj6BK8LhtQPRd2aJ/26826ebba73e0e5fd503256d069f3256/SR-25.png", + }, + "AR-15.50": { + "type": "Marksman Rifle", + "icon_url": "4lGGEGZLkbldz114Wl5hCo/78a04c46654f80fae03e730bd79f3563/AR-15.50.png", + }, + "417": { + "type": "Marksman Rifle", + "icon_url": "5djkS4YtAtOF0vBmg0T60x/ea2b1ff7e5367e66c99bc7ad7e95bfe3/417.png", + }, + "Mk 14 EBR": { + "type": "Marksman Rifle", + "icon_url": "6KIMqp5dA95z1RI3PrG9jv/eb939638169811a3fa858a44e6e5d97e/Mk_14_EBR.png", + }, + + # Shotguns + "ACS12": { + "type": "Shotgun", + "icon_url": "13z63kT1NLzn1U99o7WC4T/8655d3200f24b87246c36f2622603457/ACS12_PB.png", + }, + "M590A1": { + "type": "Shotgun", + "icon_url": "2zRHmgqENNiZqXQxC9Rsbj/e6542407c642f9b7c5a4546afb6db30a/M590A1.png", + }, + "M870": { + "type": "Shotgun", + "icon_url": "2rkU6g4Rlg0e0U4rczWGTV/a51589a54c43f476d8eb984c0ea881e9/M870.png", + }, + "TCSG12": { + "type": "Shotgun", + "icon_url": "2NDbY7BTBJ9R09LUilTlRf/3728337cd3ba14ed6ab9de0c22e879af/TCSG12.png", + }, + # Yep, twice, because Ubi doesn't know how their own guns are named :) + "FO-12": { + "type": "Shotgun", + "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + }, + "F0-12": { + "type": "Shotgun", + "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + }, + "SIX12": { + "type": "Shotgun", + "icon_url": "2v6MwsHwjOZ5Muid53lyfN/e5f1c4997db93abfe3ac356fce23376c/SIX12.png", + }, + "M1014": { + "type": "Shotgun", + "icon_url": "2pUiVbwNnQnDTesmWXktqW/f27c1fab9a354bb89cbe309a688f5e02/M1014.png", + }, + "SG-CQB": { + "type": "Shotgun", + "icon_url": "5JoL3b36Fsztt9Q2XYmrbJ/dacec96948d3f8fe92914a69b9aac593/SG-CQB.png", + }, + + # Light Machine Guns + "G8A1": { + "type": "Light Machine Gun", + "icon_url": "4TIb7oeJesaROOOfTlCBaZ/ffd6a802f9a779a0d39b2122c49b3254/G8A1.png", + }, + "LMG-E": { + "type": "Light Machine Gun", + "icon_url": "7JVJIew6t3iKwgByvrFXyi/7ba44dfda28b525506633e453104a604/LMG-E.png", + }, + "M249 SAW": { + "type": "Light Machine Gun", + "icon_url": "3p0oG7GsLIoHaRullf7xsF/e2a9e135af63e8897355023cd34538c4/M249_SAW.png", + }, + "ALDA 5.56": { + "type": "Light Machine Gun", + "icon_url": "39yB6TFl9ph6Rb4bDV4lqK/7f9b3abf8dff19bacc026a7212849ca4/ALDA_5.56.png", + }, + + # Gadget + "CCE SHIELD": { + "type": "Gadget", + "icon_url": "5mmGgrYdJJHw2moBIEW9An/64e9727d959d7afdbb4fb06e2f75574a/CCE_Shield.png", + }, + # Shield + "Le Roc": { + "type": "Shield", + "icon_url": "1bmXJOakdA6SOrGxBKA70T/1e489e366d6db287f475963df2040d3d/Extendable-Shield.png" + }, + # Ops ability + "FLASH SHIELD": { + "type": "Ops ability", + "icon_url": "7qmWjGZayvK4t6E80Gvu7g/8b789d6d639744dce100c2cfb9709e6a/G52-Tactical_Shield.png" + }, + # None + "None": { + "type": "None", + "icon_url": "yeah_lmao.png" + }, + }, + "secondary": { + # Shotguns + "SUPER SHORTY": { + "type": "Shotgun", + "icon_url": "7Dq8LDmIxAveRqXM17orUW/cbd96b47cd8ca74a7827b16ef73fe7cf/r6-operator-weapon-sa-supershorty.png", + }, + "ITA12S": { + "type": "Shotgun", + "icon_url": "5G4DroaSdqHzJWCe7qqbHZ/5dd2e03f853182c78a1e7fcbc642f0cf/ITA12S.png", + }, + + # Machine Pistols + "SMG-11": { + "type": "Machine Pistol", + "icon_url": "3WExw7Kepz9uAiWAbWW457/875fc631a3cf9fcc2849d9db2989cbcd/SMG-11.png", + }, + "SMG-12": { + "type": "Machine Pistol", + "icon_url": "EwJgB7KdgOb6dDm7ro33u/b73f0890f992c1a365210f08efcc6db5/SMG-12.png", + }, + "BEARING 9": { + "type": "Machine Pistol", + "icon_url": "4mdftEOh5Vu9KhhpgKLKrT/abedcc75868774018295ec2a08a7b3de/Bearing_9.png", + }, + "C75 Auto": { + "type": "Machine Pistol", + "icon_url": "3wUuefwPjU705mZkTdJ9UH/8ccb11884cfa34c176ac5500af139177/C75_Auto.png", + }, + "SPSMG9": { + "type": "Machine Pistol", + "icon_url": "5EtwSgylXckBNg4n6gDR9J/bc6fc6c5c12ae11da59aee95828ebd76/SPSMG9.png", + }, + + # Pistols + "M45 MEUSOC": { + "type": "Pistol", + "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", + }, + "GSH-18": { + "type": "Pistol", + "icon_url": "5s5Q33j3MNcXf9lwfxfd7m/4eb3a6af1d431481b6ddcec44fbc7602/GSh-18.png", + }, + "5.7 USG": { + "type": "Pistol", + "icon_url": "tkYcSAJSe5yGkeUhzZqBO/e81feb86df4a7eb6951052bec26b6ed7/5.7_USG.png", + }, + "KERATOS .357": { + "type": "Pistol", + "icon_url": "15caVAsSCr8Rsb5Hid36uc/59632c4f90727931041ced62a620018b/Keratos_.357.png", + }, + "P9": { + "type": "Pistol", + "icon_url": "6Fd1cl17KA0CtgodEiiY6v/d0f145ea72f2aacbd04260ba7d8f1c74/P9.png", + }, + "P229": { + "type": "Pistol", + "icon_url": "76ja0RxqzHW9PpvWgpG7Sk/cb753b50b20fe67deaef54d8b2a46b54/P229.png", + }, + "Q-929": { + "type": "Pistol", + "icon_url": "2fRVszR5yGDHbV0AL8muso/0838dac90b66aa810daa49d36382fb64/Q-929.png", + }, + "P12": { + "type": "Pistol", + "icon_url": "2mpM7rah7rwEW0bViIirUC/ed9caa4db58421519fa4db390b1aa164/P12.png", + }, + "PMM": { + "type": "Pistol", + "icon_url": "3y4LIwwm8YNQHAv8oOkWCK/a2375901cee34e68fa39c976d85de8aa/PMM.png", + }, + "1911 TACOPS": { + "type": "Pistol", + "icon_url": "189UukZ6fVnvQR6LJtLYry/6eec29603d5b7b0ca8cab6ac0ef083ac/1911_TACOPS.png", + }, + "LFP586": { + "type": "Pistol", + "icon_url": "1zc7UtdBfCZakwbiYqBvSz/1fd3f1584de38ca7c9315d498f094276/LFP586.png", + }, + "PRB92": { + "type": "Pistol", + "icon_url": "dl28J1HsE7mzhj66pmd5D/b8d8fc48d2dde13154047de94abbd8ca/PRB92.png", + }, + "Bailiff 410": { + "type": "Pistol", + "icon_url": "N8FLbo4fsNyBe8msKgRhT/8f403dc0b58087bcafab786dd95ba33f/Bailiff_410.png", + }, + "D-50": { + "type": "Pistol", + "icon_url": "6mMQRDsrComRFa7bC6cNkG/8cd17e545e3d28dcc11a040d000cfa16/D-50.png", + }, + "P-10C": { + "type": "Pistol", + "icon_url": "2l4qwB50zSFhFZVYRLNwqg/20df8114f69f96f2adc54779ccc5bbaa/P-10C.png", + }, + "P226 MK 25": { + "type": "Pistol", + "icon_url": "RTQvPQcywlRwUS1FjIKCX/6fc72fee2191c2e723276bc10ae4114e/P226_Mk_25.png", + }, + "SDP 9mm": { + "type": "Pistol", + "icon_url": "Tgsdyz3XEqmgUYi9aZZgb/6755f4da7af7a7179ffab92acf8d477e/SDP_9mm.png", + }, + "RG15": { + "type": "Pistol", + "icon_url": "2LNSsp7B7wUnnPUweir7Jm/9f66d53be7a63a17a55253a0bea6eec1/RG15.png", + }, + ".44 Mag Semi-Auto": { + "type": "Pistol", + "icon_url": "6W3Jz0YcQzbZ6BOPr7VVel/4c67f342964132a652f7d5821e887050/.44_Mag_Semi-Auto.png", + }, + + } +} From 94c920153a7e1f7ce15dca57af80dc006fb5c5f7 Mon Sep 17 00:00:00 2001 From: Michal Mikulec <20823071+CNDRD@users.noreply.github.com> Date: Mon, 14 Feb 2022 14:02:46 +0100 Subject: [PATCH 02/61] rename weapons to weapon_types --- siegeapi/player.py | 2 +- siegeapi/weapon_types.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 siegeapi/weapon_types.py diff --git a/siegeapi/player.py b/siegeapi/player.py index 16c5d29..5cd654e 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -2,7 +2,7 @@ from .exceptions import InvalidRequest from .ranks import Rank, _get_rank_constants from .gamemode import Gamemode -from .weapons import Weapon +from .weapon_types import Weapon from .operators import Operator from .trends import Trends, TrendBlockDuration diff --git a/siegeapi/weapon_types.py b/siegeapi/weapon_types.py new file mode 100644 index 0000000..2739e11 --- /dev/null +++ b/siegeapi/weapon_types.py @@ -0,0 +1,39 @@ +from typing import Callable + + +class WeaponTypes: + """ Weapon Types """ + ASSAULT_RIFLE: int = 1 + SUBMACHINE_GUN: int = 2 + LIGHT_MACHINE_GUN: int = 3 + MARKSMAN_RIFLE: int = 4 + HANDGUN: int = 5 + SHOTGUN: int = 6 + MACHINE_PISTOL: int = 7 + + +WeaponNames = { + 1: "Assault Rifle", + 2: "Submachine Gun", + 3: "Light Machine Gun", + 4: "Marksman Rifle", + 5: "Handgun", + 6: "Shotgun", + 7: "Machine Pistol" +} + + +class Weapon: + def __init__(self, weapon_type, stats=None): + self.type = weapon_type + self.name = WeaponNames.get(self.type, "Unknown") + + stat_name: Callable[[str], str] = lambda name: f"weapontypepvp_{name}:{self.type}:infinite" + stats = stats or {} + self.kills = stats.get(stat_name("kills"), 0) + self.headshots = stats.get(stat_name("headshot"), 0) + self.hits = stats.get(stat_name("bullethit"), 0) + self.shots = stats.get(stat_name("bulletfired"), 0) + + def get_dict(self) -> dict[str: str | int]: + return vars(self) From eec4fd27706f280dda346847a7bb035b93ccf926 Mon Sep 17 00:00:00 2001 From: Michal Mikulec <20823071+CNDRD@users.noreply.github.com> Date: Mon, 14 Feb 2022 14:07:07 +0100 Subject: [PATCH 03/61] rename Weapon to WeaponType --- siegeapi/constants/__init__.py | 1 + siegeapi/constants/guns.py | 2 +- siegeapi/player.py | 4 ++-- siegeapi/weapon_types.py | 2 +- siegeapi/weapons.py | 41 +++------------------------------- 5 files changed, 8 insertions(+), 42 deletions(-) diff --git a/siegeapi/constants/__init__.py b/siegeapi/constants/__init__.py index 945374e..9e3a00b 100644 --- a/siegeapi/constants/__init__.py +++ b/siegeapi/constants/__init__.py @@ -2,3 +2,4 @@ from .seasons import seasons from .operators import operator_dict from .app_ids import SIEGE_APP_IDS +from .guns import WEAPONS_DICT diff --git a/siegeapi/constants/guns.py b/siegeapi/constants/guns.py index 1da599e..de155f8 100644 --- a/siegeapi/constants/guns.py +++ b/siegeapi/constants/guns.py @@ -1,6 +1,6 @@ # Icon url: f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.icon_url}" -GUNS_DICT = { +WEAPONS_DICT = { "primary": { # AR's "AK-12": { diff --git a/siegeapi/player.py b/siegeapi/player.py index 5cd654e..1312abd 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -2,7 +2,7 @@ from .exceptions import InvalidRequest from .ranks import Rank, _get_rank_constants from .gamemode import Gamemode -from .weapon_types import Weapon +from .weapon_types import WeaponType from .operators import Operator from .trends import Trends, TrendBlockDuration @@ -351,7 +351,7 @@ async def load_weapon_types(self, data=None) -> None: raise InvalidRequest(f"Missing key results in returned JSON object {str(data)}") data = data["results"][self.id] - self.weapons = [Weapon(i, data) for i in range(1, 8)] + self.weapons = [WeaponType(i, data) for i in range(1, 8)] async def load_all_operators(self) -> dict[str: Operator]: # ask the api for all the basic stat names WITHOUT a postfix to ask for all (I assume) diff --git a/siegeapi/weapon_types.py b/siegeapi/weapon_types.py index 2739e11..17cffc1 100644 --- a/siegeapi/weapon_types.py +++ b/siegeapi/weapon_types.py @@ -23,7 +23,7 @@ class WeaponTypes: } -class Weapon: +class WeaponType: def __init__(self, weapon_type, stats=None): self.type = weapon_type self.name = WeaponNames.get(self.type, "Unknown") diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 2739e11..f76acf6 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -1,39 +1,4 @@ -from typing import Callable + from .constants import WEAPONS_DICT - -class WeaponTypes: - """ Weapon Types """ - ASSAULT_RIFLE: int = 1 - SUBMACHINE_GUN: int = 2 - LIGHT_MACHINE_GUN: int = 3 - MARKSMAN_RIFLE: int = 4 - HANDGUN: int = 5 - SHOTGUN: int = 6 - MACHINE_PISTOL: int = 7 - - -WeaponNames = { - 1: "Assault Rifle", - 2: "Submachine Gun", - 3: "Light Machine Gun", - 4: "Marksman Rifle", - 5: "Handgun", - 6: "Shotgun", - 7: "Machine Pistol" -} - - -class Weapon: - def __init__(self, weapon_type, stats=None): - self.type = weapon_type - self.name = WeaponNames.get(self.type, "Unknown") - - stat_name: Callable[[str], str] = lambda name: f"weapontypepvp_{name}:{self.type}:infinite" - stats = stats or {} - self.kills = stats.get(stat_name("kills"), 0) - self.headshots = stats.get(stat_name("headshot"), 0) - self.hits = stats.get(stat_name("bullethit"), 0) - self.shots = stats.get(stat_name("bulletfired"), 0) - - def get_dict(self) -> dict[str: str | int]: - return vars(self) + class Weapon: + ... \ No newline at end of file From 9b6e81d33dc52ddb36df81ad03da4e970223d70b Mon Sep 17 00:00:00 2001 From: Michal Mikulec <20823071+CNDRD@users.noreply.github.com> Date: Mon, 14 Feb 2022 14:25:49 +0100 Subject: [PATCH 04/61] lay groundwork for weapons --- siegeapi/player.py | 8 +++++++- siegeapi/weapons.py | 28 +++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 1312abd..e59b043 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -5,6 +5,7 @@ from .weapon_types import WeaponType from .operators import Operator from .trends import Trends, TrendBlockDuration +from .weapons import Weapons from .constants import * import aiohttp @@ -54,6 +55,10 @@ def create_trends_url(self, block_duration: TrendBlockDuration) -> str: def create_online_status_url(self) -> str: return f"https://public-ubiservices.ubi.com/v1/users/onlineStatuses?UserIds={self.player_ids}" + def create_weapons_url(self) -> str: + return f"https://r6s-stats.ubisoft.com/v1/current/weapons/{self.player_ids}?" \ + f"gameMode=all,ranked,casual,unranked&platform=PC&teamRole=all" + class PlayerBatch: """ Accumulates requests for multiple players' stats in to a single request, saving time """ @@ -151,7 +156,8 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.casuals: dict = {} self.operators: dict = {} self.gamemodes: dict = {} - self.weapons: list = [] + self.weapon_types: list = [] + self.weapons: Weapons | None = None self.casual: Gamemode | None = None self.ranked: Gamemode | None = None diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index f76acf6..7ba9f1d 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -1,4 +1,26 @@ - from .constants import WEAPONS_DICT +from .constants import WEAPONS_DICT - class Weapon: - ... \ No newline at end of file + +class Weapon: + def __init__(self, data): + self.name: str = data.get("weaponName") + self.kills: int = data.get("kills") + self.headshots: int = data.get("headshots") + self.hs_accuracy: float = data.get("headshotAccuracy") + self.rounds_played: int = data.get("roundsPlayed") + self.rounds_won: int = data.get("roundsWon") + self.rounds_lost: float = data.get("roundsLost") + self.rounds_with_kill: float = data.get("roundsWithAKill") + self.rounds_with_multi_kill: float = data.get("roundsWithMultiKill") + + weapon = WEAPONS_DICT.get(self.name) + self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" + self.type: str = weapon.get("type") + + +class WeaponSlots: + ... + + +class Weapons: + ... From bc58a282ad01f07bbe91859ea6a7264c0f846c64 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 19:05:01 +0100 Subject: [PATCH 05/61] rename guns.py to weapons.py --- siegeapi/constants/__init__.py | 2 +- siegeapi/constants/{guns.py => weapons.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename siegeapi/constants/{guns.py => weapons.py} (100%) diff --git a/siegeapi/constants/__init__.py b/siegeapi/constants/__init__.py index 9e3a00b..3e2b2a9 100644 --- a/siegeapi/constants/__init__.py +++ b/siegeapi/constants/__init__.py @@ -2,4 +2,4 @@ from .seasons import seasons from .operators import operator_dict from .app_ids import SIEGE_APP_IDS -from .guns import WEAPONS_DICT +from .weapons import WEAPONS_DICT diff --git a/siegeapi/constants/guns.py b/siegeapi/constants/weapons.py similarity index 100% rename from siegeapi/constants/guns.py rename to siegeapi/constants/weapons.py From df698212b0d9b9290b127dd98bb9d04ff423ac62 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 19:06:16 +0100 Subject: [PATCH 06/61] v2 babeee --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f6f9fbc..da211c3 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,11 @@ from setuptools import setup, find_packages -readme = '' with open('README.md') as f: long_description = f.read() setup( name="siegeapi", - version="1.2.1", + version="2.0.0", url="https://github.com/CNDRD/siege-api", description="Rainbow Six Siege API interface", author="CNDRD", From 7866777798cb3507a617fd568266de45905cc7b1 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 20:02:43 +0100 Subject: [PATCH 07/61] move weapon type stats to stat_names.py --- siegeapi/constants/stat_names.py | 7 +++++++ siegeapi/player.py | 28 +++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/siegeapi/constants/stat_names.py b/siegeapi/constants/stat_names.py index 683d60a..bc67c47 100644 --- a/siegeapi/constants/stat_names.py +++ b/siegeapi/constants/stat_names.py @@ -90,3 +90,10 @@ "PPvETimePlayed", "PTotalTimePlayed" ] + +WEAPON_TYPE_STATS = [ + "weapontypepvp_kills", + "weapontypepvp_headshot", + "weapontypepvp_bulletfired", + "weapontypepvp_bullethit" +] diff --git a/siegeapi/player.py b/siegeapi/player.py index e59b043..2aec9f2 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -18,7 +18,7 @@ def __init__(self, spaceid, platform_url, player_ids): self.platform_url: str = platform_url self.player_ids: list[str] = player_ids - def fetch_statistic_url(self, statistics) -> str: + def fetch_statistic_url(self, statistics: list) -> str: return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ f"populations={self.player_ids}&statistics={','.join(statistics)}" @@ -34,16 +34,17 @@ def create_casual_url(self, region, season) -> str: return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/r6karma/players?" \ f"board_id=pvp_casual&profile_ids={self.player_ids}®ion_id={region}&season_id={season}" - def create_operator_url(self, statistics) -> str: + def create_operator_url(self, statistics: list) -> str: return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ - f"populations={self.player_ids}&statistics={statistics}" + f"populations={self.player_ids}&statistics={','.join(statistics)}" - def create_weapon_type_url(self) -> str: + def create_weapon_type_url(self, statistics: list) -> str: return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ - f"populations={self.player_ids}&statistics=weapontypepvp_kills,weapontypepvp_headshot,weapontypepvp_bulletfired,weapontypepvp_bullethit" + f"populations={self.player_ids}&statistics={','.join(statistics)}" def create_playtime_url(self, statistics) -> str: - return f"https://public-ubiservices.ubi.com/v1/profiles/stats?profileIds={self.player_ids}&spaceId={self.spaceid}&statNames={','.join(statistics)}" + return f"https://public-ubiservices.ubi.com/v1/profiles/stats?" \ + f"profileIds={self.player_ids}&spaceId={self.spaceid}&statNames={','.join(statistics)}" def create_level_only_url(self) -> str: return f"https://public-ubiservices.ubi.com/v1/profiles/{self.player_ids}/stats/PClearanceLevel?spaceId={self.spaceid}" @@ -114,7 +115,6 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.userid: str = data.get("userId") self.platform: str = data.get("platformType") self.platform_url: str = PlatformURLNames[self.platform] - self.spaceid: str = self.auth.spaceids[self.platform] self.url_builder: UrlBuilder = UrlBuilder(self.spaceid, self.platform_url, self.id) self.profile_pic_url: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" @@ -165,10 +165,6 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.trends: Trends | None = None - self.sessions_played: int = 0 - self.first_time_played: datetime = datetime.datetime.min - self.last_time_played: datetime = datetime.datetime.max - async def is_currently_online(self) -> dict[str: bool | str]: """Checks if the user is currently in game and if the user is 'online' / 'away' / 'dnd'""" data = await self.auth.get(self.url_builder.create_online_status_url()) @@ -221,7 +217,7 @@ async def _fetch_statistics(self, statistics: list, data=None) -> dict[str: str async def load_general(self) -> None: """ Loads players' general stats """ - stats = await self._fetch_statistics(stat_names.GENERAL_URL_STATS) + stats = await self._fetch_statistics(GENERAL_URL_STATS) statname: str = "generalpvp_" self.deaths = stats.get(f"{statname}death", 0) @@ -303,7 +299,7 @@ async def load_rank(self, region='emea', season=-1, data=None) -> Rank: async def _load_thunt(self) -> None: """ Loads the players' stats for terrorist hunt""" - stats = await self._fetch_statistics(stat_names.THUNT_URL_STATS) + stats = await self._fetch_statistics(THUNT_URL_STATS) self.thunt = Gamemode("terrohunt") @@ -340,7 +336,7 @@ async def _load_thunt(self) -> None: async def load_gamemodes(self) -> None: """ Loads the totals for players' ranked, casual and thunt gamemodes """ - stats = await self._fetch_statistics(stat_names.RANKED_CASUAL_URL_STATS) + stats = await self._fetch_statistics(RANKED_CASUAL_URL_STATS) self.ranked = Gamemode("ranked", stats) self.casual = Gamemode("casual", stats) @@ -350,7 +346,7 @@ async def load_weapon_types(self, data=None) -> None: """ Load the players' weapon type stats """ if not data: - data = await self.auth.get(self.url_builder.create_weapon_type_url()) + data = await self.auth.get(self.url_builder.create_weapon_type_url(WEAPON_TYPE_STATS)) self._last_data = data if "results" not in data or self.id not in data["results"]: @@ -368,8 +364,6 @@ async def load_all_operators(self) -> dict[str: Operator]: for ability in operator_dict[op]["unique_stats"]: statistics.append(f"{ability['id']}:{operator_dict[op]['id']}:infinite") - statistics = ",".join(statistics) - data = await self.auth.get(self.url_builder.create_operator_url(statistics)) if "results" not in data or self.id not in data["results"]: From 2aca8449a517c8bc363bbaaf189e30df6fd470dd Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 20:03:00 +0100 Subject: [PATCH 08/61] add y7s1 op --- siegeapi/constants/operators.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/siegeapi/constants/operators.py b/siegeapi/constants/operators.py index 22c316f..55ce2f1 100644 --- a/siegeapi/constants/operators.py +++ b/siegeapi/constants/operators.py @@ -1,4 +1,23 @@ operator_dict = { + "azami": { + "name": "Azami", + "safename": "azami", + "year": "Y7S1", + "health": 2, + "armor": 2, + "unit": "UNAFFILIATED", + "country_code": "JP", + "roles": [], + "side": "defender", + "id": "", + "icon_url": "", + "unique_stats": [ + { + "id": "operatorpvp_azami_something", + "name": "Kiba Barrier something" + } + ] + }, "thorn": { "name": "Thorn", "safename": "thorn", @@ -12,7 +31,7 @@ "Secure" ], "side": "defender", - "id": "A00:A00", + "id": "", "icon_url": "https://i.imgur.com/w5DB6xs.png", "unique_stats": [ { From d10e03d12424e0166b683d1a07be53420b46ead4 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 20:03:23 +0100 Subject: [PATCH 09/61] more pfp urls --- siegeapi/player.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 2aec9f2..6f203df 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -117,8 +117,11 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.platform_url: str = PlatformURLNames[self.platform] self.spaceid: str = self.auth.spaceids[self.platform] self.url_builder: UrlBuilder = UrlBuilder(self.spaceid, self.platform_url, self.id) - self.profile_pic_url: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" - self.profile_pic_url_tall: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_tall.png" # 500×500 + + self.profile_pic_url_146: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" + self.profile_pic_url_256: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" + self.profile_pic_url_500: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_tall.png" + self.profile_pic_url: str = self.profile_pic_url_256 self.name: str = data.get("nameOnPlatform") self.xp: int = 0 From d7af01d61f2e4c1e5cc34d34727c709fe5085a32 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 20:05:07 +0100 Subject: [PATCH 10/61] rename thunt loading method to public (once again) --- siegeapi/player.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 6f203df..d275e5e 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -300,7 +300,7 @@ async def load_rank(self, region='emea', season=-1, data=None) -> Rank: else: raise InvalidRequest(f"Missing players key in returned JSON object {str(data)}") - async def _load_thunt(self) -> None: + async def load_thunt(self) -> None: """ Loads the players' stats for terrorist hunt""" stats = await self._fetch_statistics(THUNT_URL_STATS) @@ -343,7 +343,7 @@ async def load_gamemodes(self) -> None: self.ranked = Gamemode("ranked", stats) self.casual = Gamemode("casual", stats) - await self._load_thunt() + await self.load_thunt() async def load_weapon_types(self, data=None) -> None: """ Load the players' weapon type stats """ From 70349e17252df773f0eefb6ce0dcd6caebcbdcdf Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 20:06:49 +0100 Subject: [PATCH 11/61] why was this still here --- siegeapi/player.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index d275e5e..0cb2b4e 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -109,7 +109,6 @@ async def _proxy(*args, **kwargs): class Player: def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.auth: aiohttp.ClientSession() = auth - self._last_data = None self.id: str = data.get("profileId") self.userid: str = data.get("userId") @@ -203,7 +202,6 @@ async def _fetch_statistics(self, statistics: list, data=None) -> dict[str: str if not data: data = await self.auth.get(self.url_builder.fetch_statistic_url(statistics)) - self._last_data = data if "results" not in data or self.id not in data["results"]: raise InvalidRequest(f"Missing results key in returned JSON object {str(data)}") @@ -253,7 +251,6 @@ async def load_level(self, data=None) -> None: if not data: data = await self.auth.get(self.url_builder.create_level_url()) - self._last_data = data if "player_profiles" in data and len(data["player_profiles"]) > 0: # self.xp = data["player_profiles"][0].get("xp", 0) @@ -267,7 +264,6 @@ async def load_casual(self, region='emea', season=-1, data=None) -> Rank: if not data: data = await self.auth.get(self.url_builder.create_casual_url(region, season)) - self._last_data = data if season < 0: season = len(seasons) + season @@ -286,7 +282,6 @@ async def load_rank(self, region='emea', season=-1, data=None) -> Rank: if not data: data = await self.auth.get(self.url_builder.create_rank_url(region, season)) - self._last_data = data if season < 0: season = len(seasons) + season @@ -350,7 +345,6 @@ async def load_weapon_types(self, data=None) -> None: if not data: data = await self.auth.get(self.url_builder.create_weapon_type_url(WEAPON_TYPE_STATS)) - self._last_data = data if "results" not in data or self.id not in data["results"]: raise InvalidRequest(f"Missing key results in returned JSON object {str(data)}") From b2db1809c6fd94f9f317e71a6890a92c1dfee7e5 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 21:39:48 +0100 Subject: [PATCH 12/61] merge thunt into Gamemode --- siegeapi/constants/stat_names.py | 6 ++--- siegeapi/player.py | 45 +++----------------------------- 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/siegeapi/constants/stat_names.py b/siegeapi/constants/stat_names.py index bc67c47..9dd78fd 100644 --- a/siegeapi/constants/stat_names.py +++ b/siegeapi/constants/stat_names.py @@ -25,7 +25,7 @@ "generalpvp_blindkills" ] -RANKED_CASUAL_URL_STATS = [ +RANKED_CASUAL_THUNT_URL_STATS = [ "casualpvp_matchwon", "casualpvp_matchlost", "casualpvp_timeplayed", @@ -37,10 +37,8 @@ "rankedpvp_timeplayed", "rankedpvp_matchplayed", "rankedpvp_kills", - "rankedpvp_death" -] + "rankedpvp_death", -THUNT_URL_STATS = [ "generalpve_dbnoassists", "generalpve_death", "generalpve_revive", diff --git a/siegeapi/player.py b/siegeapi/player.py index 0cb2b4e..b42b613 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -295,50 +295,13 @@ async def load_rank(self, region='emea', season=-1, data=None) -> Rank: else: raise InvalidRequest(f"Missing players key in returned JSON object {str(data)}") - async def load_thunt(self) -> None: - """ Loads the players' stats for terrorist hunt""" - stats = await self._fetch_statistics(THUNT_URL_STATS) - - self.thunt = Gamemode("terrohunt") - - statname = "generalpve_" - self.thunt.deaths = stats.get(f"{statname}death", 0) - self.thunt.penetration_kills = stats.get(f"{statname}penetrationkills", 0) - self.thunt.matches_won = stats.get(f"{statname}matchwon", 0) - self.thunt.bullets_hit = stats.get(f"{statname}bullethit", 0) - self.thunt.melee_kills = stats.get(f"{statname}meleekills", 0) - self.thunt.bullets_fired = stats.get(f"{statname}bulletfired", 0) - self.thunt.matches_played = stats.get(f"{statname}matchplayed", 0) - self.thunt.kill_assists = stats.get(f"{statname}killassists", 0) - self.thunt.time_played = stats.get(f"{statname}timeplayed", 0) - self.thunt.revives = stats.get(f"{statname}revive", 0) - self.thunt.kills = stats.get(f"{statname}kills", 0) - self.thunt.headshots = stats.get(f"{statname}headshot", 0) - self.thunt.matches_lost = stats.get(f"{statname}matchlost", 0) - self.thunt.dbno_assists = stats.get(f"{statname}dbnoassists", 0) - self.thunt.suicides = stats.get(f"{statname}suicide", 0) - self.thunt.barricades_deployed = stats.get(f"{statname}barricadedeployed", 0) - self.thunt.reinforcements_deployed = stats.get(f"{statname}reinforcementdeploy", 0) - self.thunt.total_xp = stats.get(f"{statname}totalxp", 0) - self.thunt.rappel_breaches = stats.get(f"{statname}rappelbreach", 0) - self.thunt.distance_travelled = stats.get(f"{statname}distancetravelled", 0) - self.thunt.revives_denied = stats.get(f"{statname}revivedenied", 0) - self.thunt.dbnos = stats.get(f"{statname}dbno", 0) - self.thunt.gadgets_destroyed = stats.get(f"{statname}gadgetdestroy", 0) - self.thunt.areas_secured = stats.get(f"{statname}servershacked", 0) - self.thunt.areas_defended = stats.get(f"{statname}serverdefender", 0) - self.thunt.areas_contested = stats.get(f"{statname}serveraggression", 0) - self.thunt.hostages_rescued = stats.get(f"{statname}hostagerescue", 0) - self.thunt.hostages_defended = stats.get(f"{statname}hostagedefense", 0) - self.thunt.blind_kills = stats.get(f"{statname}blindkills", 0) - - async def load_gamemodes(self) -> None: + async def load_gamemodes(self) -> (Gamemode, Gamemode, Gamemode): """ Loads the totals for players' ranked, casual and thunt gamemodes """ - stats = await self._fetch_statistics(RANKED_CASUAL_URL_STATS) - + stats = await self._fetch_statistics(RANKED_CASUAL_THUNT_URL_STATS) self.ranked = Gamemode("ranked", stats) self.casual = Gamemode("casual", stats) - await self.load_thunt() + self.thunt = Gamemode("terrohunt", stats) + return self.ranked, self.casual, self.thunt async def load_weapon_types(self, data=None) -> None: """ Load the players' weapon type stats """ From 696ccbb99366f38afbecd9951dc541629c823826 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 21:41:38 +0100 Subject: [PATCH 13/61] restructure the dict --- siegeapi/constants/weapons.py | 651 +++++++++++++++++----------------- 1 file changed, 325 insertions(+), 326 deletions(-) diff --git a/siegeapi/constants/weapons.py b/siegeapi/constants/weapons.py index de155f8..7835f56 100644 --- a/siegeapi/constants/weapons.py +++ b/siegeapi/constants/weapons.py @@ -1,337 +1,336 @@ -# Icon url: f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.icon_url}" WEAPONS_DICT = { - "primary": { - # AR's - "AK-12": { - "type": "Assault Rifle", - "icon_url": "7KAZZgnpqD07y47jVVXEuh/e0d7e67101f8f966aa6e1c59e835454f/AK-12.png", - }, - "SC3000K": { - "type": "Assault Rifle", - "icon_url": "7x7eDTm2NNpfGiFMrfQqEX/9898e74c780537be3ca6d88db32ea21e/F2000.png", - }, - "V308": { - "type": "Assault Rifle", - "icon_url": "5YBZe76NUDO32eF66wW90g/488c315743d59230962a4d67618223d6/V308.png", - }, - "416-C CARBINE": { - "type": "Assault Rifle", - "icon_url": "2I86r2a2QD8EHTZVZnxcxy/2913450ba952a16c29fac1f5ce58ba1a/416-C_Carbine.png", - }, - "556XI": { - "type": "Assault Rifle", - "icon_url": "2dgpAeAWb3SkZV7rxDbVdQ/fa32323256b7c6f8a1977d3f71e7d4b2/556xi.png", - }, - "M762": { - "type": "Assault Rifle", - "icon_url": "4oWAgi7tgQP1Tq0HooRtye/9109a74921ee17610d4bd85a61582823/M762.png", - }, - "TYPE-89": { - "type": "Assault Rifle", - "icon_url": "7wLf325q9amF8bnVP1QGr0/2faff1a197f90dcded4472852a317d6b/Type-89.png", - }, - "M4": { - "type": "Assault Rifle", - "icon_url": "3jhi90ycmuc8mAiuSXFoCi/bcf354459e7becd6ede52ee97917c832/M4.png", - }, - "PARA-308": { - "type": "Assault Rifle", - "icon_url": "6ub8y2Cs5EYhVPfDWuVVkW/82ca131a41ee4ba2e0b75f2dc52ed9e3/PARA-308.png", - }, - "SPEAR .308": { - "type": "Assault Rifle", - "icon_url": "29LjYuJ4s6yA8k9Uv2u28C/89ec812559e7d74b7c269279f4c46d92/Spear_.308.png", - }, - "AK-74M": { - "type": "Assault Rifle", - "icon_url": "1j5HiQP8aFphTe65fqDdg0/23eecb5c603c5ba9f59fc6cbc5e4a531/AK-74M.png", - }, - "AR33": { - "type": "Assault Rifle", - "icon_url": "16U6xEvX8I5xQd9duveBLN/45d22960872cfa3fb6be9eb47fa0be4e/AR33.png", - }, - "L85A2": { - "type": "Assault Rifle", - "icon_url": "5vYQpoyk36foDzDq49jBd0/1479a2d7189e545555ceccecf6bd7cc3/L85A2.png", - }, - "G36C": { - "type": "Assault Rifle", - "icon_url": "2SZoqSXKoNPvZFIJsFsDE5/cb109885bf19c8697abf832f10cfd9a6/G36C.png", - }, - "COMMANDO 9": { - "type": "Assault Rifle", - "icon_url": "4P9dpUph5w3MSsLNnW6be/04baba24990fcb75a9c0bcfd01b7d190/Commando_9.png", - }, - # Submachine Guns - "9mm C1": { - "type": "Submachine Gun", - "icon_url": "60sbThKtOpNOwKu3OP0oGV/672fd9263f7786402a0d855273473a6f/9mm_C1.png", - }, - "AUG A3": { - "type": "Submachine Gun", - "icon_url": "3W9XJdMOgpHSw55HfwRSAv/cf8f220678d503e6c3e535c00b2e636a/AUG_A3.png", - }, - "VECTOR .45 ACP": { - "type": "Submachine Gun", - "icon_url": "7D1cDf13FqUhoLihzvuPln/068aa7e507155598449c58c0a49a90d6/Vector_.45_ACP.png", - }, - "M12": { - "type": "Submachine Gun", - "icon_url": "4FxqA5pa8JY9QQ7FEcjwPw/ffc779fcde5b970e7b95db6653637dab/M12.png", - }, - "FMG-9": { - "type": "Submachine Gun", - "icon_url": "0oneJNsBR06QjuowxwtHG/bd3b391c6eec2bd615f2ed83197a13ac/FMG-9.png", - }, - "PDW9": { - "type": "Submachine Gun", - "icon_url": "4yYCuRnduMq35CTHfq6wwU/b7d49cdbcb05917e014c99efeaadd33b/PDW9.png", - }, - "MP5": { - "type": "Submachine Gun", - "icon_url": "60YbOvSBQt6ZUlu8YDXoZm/51ef3857b2986de700262432e8433714/MP5.png", - }, - "MPX": { - "type": "Submachine Gun", - "icon_url": "5HFewpAJ8npDDCKFnEadhL/d398bb477d6b56fe41bfdb5862ed31c0/MPX.png", - }, - "MP7": { - "type": "Submachine Gun", - "icon_url": "3a4dgTWGdiJqALhtRp4pKy/f2568d3de3cfe7e4b53179e8653cd2a2/MP7.png", - }, - "T-5 SMG": { - "type": "Submachine Gun", - "icon_url": "1Ne8bvX8BdCALevWKMllQN/4baa3e79d323de134dd182e0272b9c3b/T-5_SMG.png", - }, - "K1A": { - "type": "Submachine Gun", - "icon_url": "5mUa2p8WXbiyD71qUI8sGk/ed753b6f0ae30ab5737486dfcf32ee9f/K1A.png", - }, - "Mx4 Storm": { - "type": "Submachine Gun", - "icon_url": "4qRh1frGkQZxNyeKA4D6n1/20f89cd1d9953f06207b7340ea77fb17/Mx4_Storm.png", - }, - "UZK50GI": { - "type": "Submachine Gun", - "icon_url": "5WMIsPUWTXprZnAwctPsTt/f1c652b681e7e9ba6ba66bcd29e12a76/uzk50gi.png", - }, - "9x19VSN": { - "type": "Submachine Gun", - "icon_url": "42gH96xTTYaTZsfXI3c0wL/a7edbf11af97091ee884b68e59fe6a4f/9x19VSN.png", - }, - "MP5K": { - "type": "Submachine Gun", - "icon_url": "1pk8nOI7ybQjYOSI4fuzOm/fcd78df0f729be545e75c09aae85c360/MP5K.png", - }, + # Primary Weapons + # AR's + "AK-12": { + "type": "Assault Rifle", + "icon_url": "7KAZZgnpqD07y47jVVXEuh/e0d7e67101f8f966aa6e1c59e835454f/AK-12.png", + }, + "SC3000K": { + "type": "Assault Rifle", + "icon_url": "7x7eDTm2NNpfGiFMrfQqEX/9898e74c780537be3ca6d88db32ea21e/F2000.png", + }, + "V308": { + "type": "Assault Rifle", + "icon_url": "5YBZe76NUDO32eF66wW90g/488c315743d59230962a4d67618223d6/V308.png", + }, + "416-C CARBINE": { + "type": "Assault Rifle", + "icon_url": "2I86r2a2QD8EHTZVZnxcxy/2913450ba952a16c29fac1f5ce58ba1a/416-C_Carbine.png", + }, + "556XI": { + "type": "Assault Rifle", + "icon_url": "2dgpAeAWb3SkZV7rxDbVdQ/fa32323256b7c6f8a1977d3f71e7d4b2/556xi.png", + }, + "M762": { + "type": "Assault Rifle", + "icon_url": "4oWAgi7tgQP1Tq0HooRtye/9109a74921ee17610d4bd85a61582823/M762.png", + }, + "TYPE-89": { + "type": "Assault Rifle", + "icon_url": "7wLf325q9amF8bnVP1QGr0/2faff1a197f90dcded4472852a317d6b/Type-89.png", + }, + "M4": { + "type": "Assault Rifle", + "icon_url": "3jhi90ycmuc8mAiuSXFoCi/bcf354459e7becd6ede52ee97917c832/M4.png", + }, + "PARA-308": { + "type": "Assault Rifle", + "icon_url": "6ub8y2Cs5EYhVPfDWuVVkW/82ca131a41ee4ba2e0b75f2dc52ed9e3/PARA-308.png", + }, + "SPEAR .308": { + "type": "Assault Rifle", + "icon_url": "29LjYuJ4s6yA8k9Uv2u28C/89ec812559e7d74b7c269279f4c46d92/Spear_.308.png", + }, + "AK-74M": { + "type": "Assault Rifle", + "icon_url": "1j5HiQP8aFphTe65fqDdg0/23eecb5c603c5ba9f59fc6cbc5e4a531/AK-74M.png", + }, + "AR33": { + "type": "Assault Rifle", + "icon_url": "16U6xEvX8I5xQd9duveBLN/45d22960872cfa3fb6be9eb47fa0be4e/AR33.png", + }, + "L85A2": { + "type": "Assault Rifle", + "icon_url": "5vYQpoyk36foDzDq49jBd0/1479a2d7189e545555ceccecf6bd7cc3/L85A2.png", + }, + "G36C": { + "type": "Assault Rifle", + "icon_url": "2SZoqSXKoNPvZFIJsFsDE5/cb109885bf19c8697abf832f10cfd9a6/G36C.png", + }, + "COMMANDO 9": { + "type": "Assault Rifle", + "icon_url": "4P9dpUph5w3MSsLNnW6be/04baba24990fcb75a9c0bcfd01b7d190/Commando_9.png", + }, - # Marksman Rifles - "SR-25": { - "type": "Marksman Rifle", - "icon_url": "3H3sICdj6BK8LhtQPRd2aJ/26826ebba73e0e5fd503256d069f3256/SR-25.png", - }, - "AR-15.50": { - "type": "Marksman Rifle", - "icon_url": "4lGGEGZLkbldz114Wl5hCo/78a04c46654f80fae03e730bd79f3563/AR-15.50.png", - }, - "417": { - "type": "Marksman Rifle", - "icon_url": "5djkS4YtAtOF0vBmg0T60x/ea2b1ff7e5367e66c99bc7ad7e95bfe3/417.png", - }, - "Mk 14 EBR": { - "type": "Marksman Rifle", - "icon_url": "6KIMqp5dA95z1RI3PrG9jv/eb939638169811a3fa858a44e6e5d97e/Mk_14_EBR.png", - }, + # Submachine Guns + "9mm C1": { + "type": "Submachine Gun", + "icon_url": "60sbThKtOpNOwKu3OP0oGV/672fd9263f7786402a0d855273473a6f/9mm_C1.png", + }, + "AUG A3": { + "type": "Submachine Gun", + "icon_url": "3W9XJdMOgpHSw55HfwRSAv/cf8f220678d503e6c3e535c00b2e636a/AUG_A3.png", + }, + "VECTOR .45 ACP": { + "type": "Submachine Gun", + "icon_url": "7D1cDf13FqUhoLihzvuPln/068aa7e507155598449c58c0a49a90d6/Vector_.45_ACP.png", + }, + "M12": { + "type": "Submachine Gun", + "icon_url": "4FxqA5pa8JY9QQ7FEcjwPw/ffc779fcde5b970e7b95db6653637dab/M12.png", + }, + "FMG-9": { + "type": "Submachine Gun", + "icon_url": "0oneJNsBR06QjuowxwtHG/bd3b391c6eec2bd615f2ed83197a13ac/FMG-9.png", + }, + "PDW9": { + "type": "Submachine Gun", + "icon_url": "4yYCuRnduMq35CTHfq6wwU/b7d49cdbcb05917e014c99efeaadd33b/PDW9.png", + }, + "MP5": { + "type": "Submachine Gun", + "icon_url": "60YbOvSBQt6ZUlu8YDXoZm/51ef3857b2986de700262432e8433714/MP5.png", + }, + "MPX": { + "type": "Submachine Gun", + "icon_url": "5HFewpAJ8npDDCKFnEadhL/d398bb477d6b56fe41bfdb5862ed31c0/MPX.png", + }, + "MP7": { + "type": "Submachine Gun", + "icon_url": "3a4dgTWGdiJqALhtRp4pKy/f2568d3de3cfe7e4b53179e8653cd2a2/MP7.png", + }, + "T-5 SMG": { + "type": "Submachine Gun", + "icon_url": "1Ne8bvX8BdCALevWKMllQN/4baa3e79d323de134dd182e0272b9c3b/T-5_SMG.png", + }, + "K1A": { + "type": "Submachine Gun", + "icon_url": "5mUa2p8WXbiyD71qUI8sGk/ed753b6f0ae30ab5737486dfcf32ee9f/K1A.png", + }, + "Mx4 Storm": { + "type": "Submachine Gun", + "icon_url": "4qRh1frGkQZxNyeKA4D6n1/20f89cd1d9953f06207b7340ea77fb17/Mx4_Storm.png", + }, + "UZK50GI": { + "type": "Submachine Gun", + "icon_url": "5WMIsPUWTXprZnAwctPsTt/f1c652b681e7e9ba6ba66bcd29e12a76/uzk50gi.png", + }, + "9x19VSN": { + "type": "Submachine Gun", + "icon_url": "42gH96xTTYaTZsfXI3c0wL/a7edbf11af97091ee884b68e59fe6a4f/9x19VSN.png", + }, + "MP5K": { + "type": "Submachine Gun", + "icon_url": "1pk8nOI7ybQjYOSI4fuzOm/fcd78df0f729be545e75c09aae85c360/MP5K.png", + }, - # Shotguns - "ACS12": { - "type": "Shotgun", - "icon_url": "13z63kT1NLzn1U99o7WC4T/8655d3200f24b87246c36f2622603457/ACS12_PB.png", - }, - "M590A1": { - "type": "Shotgun", - "icon_url": "2zRHmgqENNiZqXQxC9Rsbj/e6542407c642f9b7c5a4546afb6db30a/M590A1.png", - }, - "M870": { - "type": "Shotgun", - "icon_url": "2rkU6g4Rlg0e0U4rczWGTV/a51589a54c43f476d8eb984c0ea881e9/M870.png", - }, - "TCSG12": { - "type": "Shotgun", - "icon_url": "2NDbY7BTBJ9R09LUilTlRf/3728337cd3ba14ed6ab9de0c22e879af/TCSG12.png", - }, - # Yep, twice, because Ubi doesn't know how their own guns are named :) - "FO-12": { - "type": "Shotgun", - "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", - }, - "F0-12": { - "type": "Shotgun", - "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", - }, - "SIX12": { - "type": "Shotgun", - "icon_url": "2v6MwsHwjOZ5Muid53lyfN/e5f1c4997db93abfe3ac356fce23376c/SIX12.png", - }, - "M1014": { - "type": "Shotgun", - "icon_url": "2pUiVbwNnQnDTesmWXktqW/f27c1fab9a354bb89cbe309a688f5e02/M1014.png", - }, - "SG-CQB": { - "type": "Shotgun", - "icon_url": "5JoL3b36Fsztt9Q2XYmrbJ/dacec96948d3f8fe92914a69b9aac593/SG-CQB.png", - }, + # Marksman Rifles + "SR-25": { + "type": "Marksman Rifle", + "icon_url": "3H3sICdj6BK8LhtQPRd2aJ/26826ebba73e0e5fd503256d069f3256/SR-25.png", + }, + "AR-15.50": { + "type": "Marksman Rifle", + "icon_url": "4lGGEGZLkbldz114Wl5hCo/78a04c46654f80fae03e730bd79f3563/AR-15.50.png", + }, + "417": { + "type": "Marksman Rifle", + "icon_url": "5djkS4YtAtOF0vBmg0T60x/ea2b1ff7e5367e66c99bc7ad7e95bfe3/417.png", + }, + "Mk 14 EBR": { + "type": "Marksman Rifle", + "icon_url": "6KIMqp5dA95z1RI3PrG9jv/eb939638169811a3fa858a44e6e5d97e/Mk_14_EBR.png", + }, - # Light Machine Guns - "G8A1": { - "type": "Light Machine Gun", - "icon_url": "4TIb7oeJesaROOOfTlCBaZ/ffd6a802f9a779a0d39b2122c49b3254/G8A1.png", - }, - "LMG-E": { - "type": "Light Machine Gun", - "icon_url": "7JVJIew6t3iKwgByvrFXyi/7ba44dfda28b525506633e453104a604/LMG-E.png", - }, - "M249 SAW": { - "type": "Light Machine Gun", - "icon_url": "3p0oG7GsLIoHaRullf7xsF/e2a9e135af63e8897355023cd34538c4/M249_SAW.png", - }, - "ALDA 5.56": { - "type": "Light Machine Gun", - "icon_url": "39yB6TFl9ph6Rb4bDV4lqK/7f9b3abf8dff19bacc026a7212849ca4/ALDA_5.56.png", - }, + # Shotguns + "ACS12": { + "type": "Shotgun", + "icon_url": "13z63kT1NLzn1U99o7WC4T/8655d3200f24b87246c36f2622603457/ACS12_PB.png", + }, + "M590A1": { + "type": "Shotgun", + "icon_url": "2zRHmgqENNiZqXQxC9Rsbj/e6542407c642f9b7c5a4546afb6db30a/M590A1.png", + }, + "M870": { + "type": "Shotgun", + "icon_url": "2rkU6g4Rlg0e0U4rczWGTV/a51589a54c43f476d8eb984c0ea881e9/M870.png", + }, + "TCSG12": { + "type": "Shotgun", + "icon_url": "2NDbY7BTBJ9R09LUilTlRf/3728337cd3ba14ed6ab9de0c22e879af/TCSG12.png", + }, + # Yep, twice, because Ubi doesn't know how their own guns are named :) + "FO-12": { + "type": "Shotgun", + "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + }, + "F0-12": { + "type": "Shotgun", + "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + }, + "SIX12": { + "type": "Shotgun", + "icon_url": "2v6MwsHwjOZ5Muid53lyfN/e5f1c4997db93abfe3ac356fce23376c/SIX12.png", + }, + "M1014": { + "type": "Shotgun", + "icon_url": "2pUiVbwNnQnDTesmWXktqW/f27c1fab9a354bb89cbe309a688f5e02/M1014.png", + }, + "SG-CQB": { + "type": "Shotgun", + "icon_url": "5JoL3b36Fsztt9Q2XYmrbJ/dacec96948d3f8fe92914a69b9aac593/SG-CQB.png", + }, + + # Light Machine Guns + "G8A1": { + "type": "Light Machine Gun", + "icon_url": "4TIb7oeJesaROOOfTlCBaZ/ffd6a802f9a779a0d39b2122c49b3254/G8A1.png", + }, + "LMG-E": { + "type": "Light Machine Gun", + "icon_url": "7JVJIew6t3iKwgByvrFXyi/7ba44dfda28b525506633e453104a604/LMG-E.png", + }, + "M249 SAW": { + "type": "Light Machine Gun", + "icon_url": "3p0oG7GsLIoHaRullf7xsF/e2a9e135af63e8897355023cd34538c4/M249_SAW.png", + }, + "ALDA 5.56": { + "type": "Light Machine Gun", + "icon_url": "39yB6TFl9ph6Rb4bDV4lqK/7f9b3abf8dff19bacc026a7212849ca4/ALDA_5.56.png", + }, + + # Gadget + "CCE SHIELD": { + "type": "Gadget", + "icon_url": "5mmGgrYdJJHw2moBIEW9An/64e9727d959d7afdbb4fb06e2f75574a/CCE_Shield.png", + }, + # Shield + "Le Roc": { + "type": "Shield", + "icon_url": "1bmXJOakdA6SOrGxBKA70T/1e489e366d6db287f475963df2040d3d/Extendable-Shield.png" + }, + # Ops ability + "FLASH SHIELD": { + "type": "Ops ability", + "icon_url": "7qmWjGZayvK4t6E80Gvu7g/8b789d6d639744dce100c2cfb9709e6a/G52-Tactical_Shield.png" + }, + # None + "None": { + "type": "None", + "icon_url": "yeah_lmao.png" + }, - # Gadget - "CCE SHIELD": { - "type": "Gadget", - "icon_url": "5mmGgrYdJJHw2moBIEW9An/64e9727d959d7afdbb4fb06e2f75574a/CCE_Shield.png", - }, - # Shield - "Le Roc": { - "type": "Shield", - "icon_url": "1bmXJOakdA6SOrGxBKA70T/1e489e366d6db287f475963df2040d3d/Extendable-Shield.png" - }, - # Ops ability - "FLASH SHIELD": { - "type": "Ops ability", - "icon_url": "7qmWjGZayvK4t6E80Gvu7g/8b789d6d639744dce100c2cfb9709e6a/G52-Tactical_Shield.png" - }, - # None - "None": { - "type": "None", - "icon_url": "yeah_lmao.png" - }, - }, - "secondary": { - # Shotguns - "SUPER SHORTY": { - "type": "Shotgun", - "icon_url": "7Dq8LDmIxAveRqXM17orUW/cbd96b47cd8ca74a7827b16ef73fe7cf/r6-operator-weapon-sa-supershorty.png", - }, - "ITA12S": { - "type": "Shotgun", - "icon_url": "5G4DroaSdqHzJWCe7qqbHZ/5dd2e03f853182c78a1e7fcbc642f0cf/ITA12S.png", - }, + # Secondary Weapons + # Shotguns + "SUPER SHORTY": { + "type": "Shotgun", + "icon_url": "7Dq8LDmIxAveRqXM17orUW/cbd96b47cd8ca74a7827b16ef73fe7cf/r6-operator-weapon-sa-supershorty.png", + }, + "ITA12S": { + "type": "Shotgun", + "icon_url": "5G4DroaSdqHzJWCe7qqbHZ/5dd2e03f853182c78a1e7fcbc642f0cf/ITA12S.png", + }, - # Machine Pistols - "SMG-11": { - "type": "Machine Pistol", - "icon_url": "3WExw7Kepz9uAiWAbWW457/875fc631a3cf9fcc2849d9db2989cbcd/SMG-11.png", - }, - "SMG-12": { - "type": "Machine Pistol", - "icon_url": "EwJgB7KdgOb6dDm7ro33u/b73f0890f992c1a365210f08efcc6db5/SMG-12.png", - }, - "BEARING 9": { - "type": "Machine Pistol", - "icon_url": "4mdftEOh5Vu9KhhpgKLKrT/abedcc75868774018295ec2a08a7b3de/Bearing_9.png", - }, - "C75 Auto": { - "type": "Machine Pistol", - "icon_url": "3wUuefwPjU705mZkTdJ9UH/8ccb11884cfa34c176ac5500af139177/C75_Auto.png", - }, - "SPSMG9": { - "type": "Machine Pistol", - "icon_url": "5EtwSgylXckBNg4n6gDR9J/bc6fc6c5c12ae11da59aee95828ebd76/SPSMG9.png", - }, + # Machine Pistols + "SMG-11": { + "type": "Machine Pistol", + "icon_url": "3WExw7Kepz9uAiWAbWW457/875fc631a3cf9fcc2849d9db2989cbcd/SMG-11.png", + }, + "SMG-12": { + "type": "Machine Pistol", + "icon_url": "EwJgB7KdgOb6dDm7ro33u/b73f0890f992c1a365210f08efcc6db5/SMG-12.png", + }, + "BEARING 9": { + "type": "Machine Pistol", + "icon_url": "4mdftEOh5Vu9KhhpgKLKrT/abedcc75868774018295ec2a08a7b3de/Bearing_9.png", + }, + "C75 Auto": { + "type": "Machine Pistol", + "icon_url": "3wUuefwPjU705mZkTdJ9UH/8ccb11884cfa34c176ac5500af139177/C75_Auto.png", + }, + "SPSMG9": { + "type": "Machine Pistol", + "icon_url": "5EtwSgylXckBNg4n6gDR9J/bc6fc6c5c12ae11da59aee95828ebd76/SPSMG9.png", + }, - # Pistols - "M45 MEUSOC": { - "type": "Pistol", - "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", - }, - "GSH-18": { - "type": "Pistol", - "icon_url": "5s5Q33j3MNcXf9lwfxfd7m/4eb3a6af1d431481b6ddcec44fbc7602/GSh-18.png", - }, - "5.7 USG": { - "type": "Pistol", - "icon_url": "tkYcSAJSe5yGkeUhzZqBO/e81feb86df4a7eb6951052bec26b6ed7/5.7_USG.png", - }, - "KERATOS .357": { - "type": "Pistol", - "icon_url": "15caVAsSCr8Rsb5Hid36uc/59632c4f90727931041ced62a620018b/Keratos_.357.png", - }, - "P9": { - "type": "Pistol", - "icon_url": "6Fd1cl17KA0CtgodEiiY6v/d0f145ea72f2aacbd04260ba7d8f1c74/P9.png", - }, - "P229": { - "type": "Pistol", - "icon_url": "76ja0RxqzHW9PpvWgpG7Sk/cb753b50b20fe67deaef54d8b2a46b54/P229.png", - }, - "Q-929": { - "type": "Pistol", - "icon_url": "2fRVszR5yGDHbV0AL8muso/0838dac90b66aa810daa49d36382fb64/Q-929.png", - }, - "P12": { - "type": "Pistol", - "icon_url": "2mpM7rah7rwEW0bViIirUC/ed9caa4db58421519fa4db390b1aa164/P12.png", - }, - "PMM": { - "type": "Pistol", - "icon_url": "3y4LIwwm8YNQHAv8oOkWCK/a2375901cee34e68fa39c976d85de8aa/PMM.png", - }, - "1911 TACOPS": { - "type": "Pistol", - "icon_url": "189UukZ6fVnvQR6LJtLYry/6eec29603d5b7b0ca8cab6ac0ef083ac/1911_TACOPS.png", - }, - "LFP586": { - "type": "Pistol", - "icon_url": "1zc7UtdBfCZakwbiYqBvSz/1fd3f1584de38ca7c9315d498f094276/LFP586.png", - }, - "PRB92": { - "type": "Pistol", - "icon_url": "dl28J1HsE7mzhj66pmd5D/b8d8fc48d2dde13154047de94abbd8ca/PRB92.png", - }, - "Bailiff 410": { - "type": "Pistol", - "icon_url": "N8FLbo4fsNyBe8msKgRhT/8f403dc0b58087bcafab786dd95ba33f/Bailiff_410.png", - }, - "D-50": { - "type": "Pistol", - "icon_url": "6mMQRDsrComRFa7bC6cNkG/8cd17e545e3d28dcc11a040d000cfa16/D-50.png", - }, - "P-10C": { - "type": "Pistol", - "icon_url": "2l4qwB50zSFhFZVYRLNwqg/20df8114f69f96f2adc54779ccc5bbaa/P-10C.png", - }, - "P226 MK 25": { - "type": "Pistol", - "icon_url": "RTQvPQcywlRwUS1FjIKCX/6fc72fee2191c2e723276bc10ae4114e/P226_Mk_25.png", - }, - "SDP 9mm": { - "type": "Pistol", - "icon_url": "Tgsdyz3XEqmgUYi9aZZgb/6755f4da7af7a7179ffab92acf8d477e/SDP_9mm.png", - }, - "RG15": { - "type": "Pistol", - "icon_url": "2LNSsp7B7wUnnPUweir7Jm/9f66d53be7a63a17a55253a0bea6eec1/RG15.png", - }, - ".44 Mag Semi-Auto": { - "type": "Pistol", - "icon_url": "6W3Jz0YcQzbZ6BOPr7VVel/4c67f342964132a652f7d5821e887050/.44_Mag_Semi-Auto.png", - }, + # Pistols + "M45 MEUSOC": { + "type": "Pistol", + "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", + }, + "GSH-18": { + "type": "Pistol", + "icon_url": "5s5Q33j3MNcXf9lwfxfd7m/4eb3a6af1d431481b6ddcec44fbc7602/GSh-18.png", + }, + "5.7 USG": { + "type": "Pistol", + "icon_url": "tkYcSAJSe5yGkeUhzZqBO/e81feb86df4a7eb6951052bec26b6ed7/5.7_USG.png", + }, + "KERATOS .357": { + "type": "Pistol", + "icon_url": "15caVAsSCr8Rsb5Hid36uc/59632c4f90727931041ced62a620018b/Keratos_.357.png", + }, + "P9": { + "type": "Pistol", + "icon_url": "6Fd1cl17KA0CtgodEiiY6v/d0f145ea72f2aacbd04260ba7d8f1c74/P9.png", + }, + "P229": { + "type": "Pistol", + "icon_url": "76ja0RxqzHW9PpvWgpG7Sk/cb753b50b20fe67deaef54d8b2a46b54/P229.png", + }, + "Q-929": { + "type": "Pistol", + "icon_url": "2fRVszR5yGDHbV0AL8muso/0838dac90b66aa810daa49d36382fb64/Q-929.png", + }, + "P12": { + "type": "Pistol", + "icon_url": "2mpM7rah7rwEW0bViIirUC/ed9caa4db58421519fa4db390b1aa164/P12.png", + }, + "PMM": { + "type": "Pistol", + "icon_url": "3y4LIwwm8YNQHAv8oOkWCK/a2375901cee34e68fa39c976d85de8aa/PMM.png", + }, + "1911 TACOPS": { + "type": "Pistol", + "icon_url": "189UukZ6fVnvQR6LJtLYry/6eec29603d5b7b0ca8cab6ac0ef083ac/1911_TACOPS.png", + }, + "LFP586": { + "type": "Pistol", + "icon_url": "1zc7UtdBfCZakwbiYqBvSz/1fd3f1584de38ca7c9315d498f094276/LFP586.png", + }, + "PRB92": { + "type": "Pistol", + "icon_url": "dl28J1HsE7mzhj66pmd5D/b8d8fc48d2dde13154047de94abbd8ca/PRB92.png", + }, + "Bailiff 410": { + "type": "Pistol", + "icon_url": "N8FLbo4fsNyBe8msKgRhT/8f403dc0b58087bcafab786dd95ba33f/Bailiff_410.png", + }, + "D-50": { + "type": "Pistol", + "icon_url": "6mMQRDsrComRFa7bC6cNkG/8cd17e545e3d28dcc11a040d000cfa16/D-50.png", + }, + "P-10C": { + "type": "Pistol", + "icon_url": "2l4qwB50zSFhFZVYRLNwqg/20df8114f69f96f2adc54779ccc5bbaa/P-10C.png", + }, + "P226 MK 25": { + "type": "Pistol", + "icon_url": "RTQvPQcywlRwUS1FjIKCX/6fc72fee2191c2e723276bc10ae4114e/P226_Mk_25.png", + }, + "SDP 9mm": { + "type": "Pistol", + "icon_url": "Tgsdyz3XEqmgUYi9aZZgb/6755f4da7af7a7179ffab92acf8d477e/SDP_9mm.png", + }, + "RG15": { + "type": "Pistol", + "icon_url": "2LNSsp7B7wUnnPUweir7Jm/9f66d53be7a63a17a55253a0bea6eec1/RG15.png", + }, + ".44 Mag Semi-Auto": { + "type": "Pistol", + "icon_url": "6W3Jz0YcQzbZ6BOPr7VVel/4c67f342964132a652f7d5821e887050/.44_Mag_Semi-Auto.png", + }, - } } From 960399e6a4a9a8914dca4ce921b4a7efdbe7ec50 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 21:42:02 +0100 Subject: [PATCH 14/61] accommodate thunt in this class --- siegeapi/gamemode.py | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/siegeapi/gamemode.py b/siegeapi/gamemode.py index e3bbd5b..94790f2 100644 --- a/siegeapi/gamemode.py +++ b/siegeapi/gamemode.py @@ -4,15 +4,47 @@ class Gamemode: def __init__(self, name, stats=None): self.name = name - statname = f"{name}pvp_" + if name == "ranked" or name == "casual": + statname = f"{name}pvp_" + stats = stats or {} + self.won = stats.get(f"{statname}matchwon", 0) + self.lost = stats.get(f"{statname}matchlost", 0) + self.time_played = stats.get(f"{statname}timeplayed", 0) + self.played = stats.get(f"{statname}matchplayed", 0) + self.kills = stats.get(f"{statname}kills", 0) + self.deaths = stats.get(f"{statname}death", 0) - stats = stats or {} - self.won = stats.get(f"{statname}matchwon", 0) - self.lost = stats.get(f"{statname}matchlost", 0) - self.time_played = stats.get(f"{statname}timeplayed", 0) - self.played = stats.get(f"{statname}matchplayed", 0) - self.kills = stats.get(f"{statname}kills", 0) - self.deaths = stats.get(f"{statname}death", 0) + else: + statname = "generalpve_" + self.deaths = stats.get(f"{statname}death", 0) + self.penetration_kills = stats.get(f"{statname}penetrationkills", 0) + self.matches_won = stats.get(f"{statname}matchwon", 0) + self.bullets_hit = stats.get(f"{statname}bullethit", 0) + self.melee_kills = stats.get(f"{statname}meleekills", 0) + self.bullets_fired = stats.get(f"{statname}bulletfired", 0) + self.matches_played = stats.get(f"{statname}matchplayed", 0) + self.kill_assists = stats.get(f"{statname}killassists", 0) + self.time_played = stats.get(f"{statname}timeplayed", 0) + self.revives = stats.get(f"{statname}revive", 0) + self.kills = stats.get(f"{statname}kills", 0) + self.headshots = stats.get(f"{statname}headshot", 0) + self.matches_lost = stats.get(f"{statname}matchlost", 0) + self.dbno_assists = stats.get(f"{statname}dbnoassists", 0) + self.suicides = stats.get(f"{statname}suicide", 0) + self.barricades_deployed = stats.get(f"{statname}barricadedeployed", 0) + self.reinforcements_deployed = stats.get(f"{statname}reinforcementdeploy", 0) + self.total_xp = stats.get(f"{statname}totalxp", 0) + self.rappel_breaches = stats.get(f"{statname}rappelbreach", 0) + self.distance_travelled = stats.get(f"{statname}distancetravelled", 0) + self.revives_denied = stats.get(f"{statname}revivedenied", 0) + self.dbnos = stats.get(f"{statname}dbno", 0) + self.gadgets_destroyed = stats.get(f"{statname}gadgetdestroy", 0) + self.areas_secured = stats.get(f"{statname}servershacked", 0) + self.areas_defended = stats.get(f"{statname}serverdefender", 0) + self.areas_contested = stats.get(f"{statname}serveraggression", 0) + self.hostages_rescued = stats.get(f"{statname}hostagerescue", 0) + self.hostages_defended = stats.get(f"{statname}hostagedefense", 0) + self.blind_kills = stats.get(f"{statname}blindkills", 0) def get_dict(self) -> dict[str: int]: return vars(self) From c9db81a61663351d43c7907c33b6fbca05078507 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 21:42:17 +0100 Subject: [PATCH 15/61] rename basically everything --- siegeapi/player.py | 79 ++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index b42b613..c7e5151 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -125,7 +125,7 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.name: str = data.get("nameOnPlatform") self.xp: int = 0 self.level: int = 0 - self.lootbox_probability: int = 0 + self.alpha_pack: int = 0 self.deaths: int = 0 self.penetration_kills: int = 0 self.matches_won: int = 0 @@ -167,41 +167,13 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.trends: Trends | None = None - async def is_currently_online(self) -> dict[str: bool | str]: - """Checks if the user is currently in game and if the user is 'online' / 'away' / 'dnd'""" - data = await self.auth.get(self.url_builder.create_online_status_url()) - statuses = data["onlineStatuses"][0] + async def load_weapons(self) -> Weapons: + self.weapons = Weapons(await self.auth.get(self.url_builder.create_weapons_url())) + return self.weapons - for connection in statuses["connections"]: - if connection["applicationId"] in SIEGE_APP_IDS: - return {"in_game": True, "status": statuses["onlineStatus"]} - return {"in_game": False, "status": statuses["onlineStatus"]} - - async def load_trends(self, block_duration: TrendBlockDuration = TrendBlockDuration.WEEKLY) -> Trends: - self.trends = Trends(await self.auth.get(self.url_builder.create_trends_url(block_duration))) - return self.trends + async def _fetch_statistics(self, statistics: list) -> dict[str: str | int | float]: - async def load_only_level(self) -> int: - data = await self.auth.get(self.url_builder.create_level_only_url()) - self.level = data["stats"]["PClearanceLevel"]["value"] - return self.level - - async def load_playtime(self) -> dict[str: int]: - data = await self.auth.get(self.url_builder.create_playtime_url(PLAYTIME_URL_STATS)) - self.pvp_time_played = data['profiles'][0]['stats']["PPvPTimePlayed"]["value"] - self.pve_time_played = data['profiles'][0]['stats']["PPvETimePlayed"]["value"] - self.time_played = data['profiles'][0]['stats']["PTotalTimePlayed"]["value"] - stats = { - "PVPTimePlayed": self.pvp_time_played, - "PVETimePlayed": self.pve_time_played, - "TotalTimePlayed": self.time_played, - } - return stats - - async def _fetch_statistics(self, statistics: list, data=None) -> dict[str: str | int | float]: - - if not data: - data = await self.auth.get(self.url_builder.fetch_statistic_url(statistics)) + data = await self.auth.get(self.url_builder.fetch_statistic_url(statistics)) if "results" not in data or self.id not in data["results"]: raise InvalidRequest(f"Missing results key in returned JSON object {str(data)}") @@ -215,6 +187,16 @@ async def _fetch_statistics(self, statistics: list, data=None) -> dict[str: str stats[statistic] = data[x] return stats + async def is_currently_online(self) -> dict[str: bool | str]: + """Checks if the user is currently in game and if the user is 'online' / 'away' / 'dnd'""" + data = await self.auth.get(self.url_builder.create_online_status_url()) + statuses = data["onlineStatuses"][0] + + for connection in statuses["connections"]: + if connection["applicationId"] in SIEGE_APP_IDS: + return {"in_game": True, "status": statuses["onlineStatus"]} + return {"in_game": False, "status": statuses["onlineStatus"]} + async def load_general(self) -> None: """ Loads players' general stats """ @@ -246,19 +228,32 @@ async def load_general(self) -> None: self.gadgets_destroyed = stats.get(f"{statname}gadgetdestroy", 0) self.blind_kills = stats.get(f"{statname}blindkills") - async def load_level(self, data=None) -> None: - """ Load the players' XP, level & alpha pack % """ + async def load_trends(self, block_duration: TrendBlockDuration = TrendBlockDuration.WEEKLY) -> Trends: + self.trends = Trends(await self.auth.get(self.url_builder.create_trends_url(block_duration))) + return self.trends - if not data: - data = await self.auth.get(self.url_builder.create_level_url()) + async def load_level(self) -> None: + data = await self.auth.get(self.url_builder.create_level_only_url()) + self.level = data["stats"]["PClearanceLevel"]["value"] + return self.level + + async def load_playtime(self) -> dict[str: int]: + data = await self.auth.get(self.url_builder.create_playtime_url(PLAYTIME_URL_STATS)) + self.pvp_time_played = data['profiles'][0]['stats']["PPvPTimePlayed"]["value"] + self.pve_time_played = data['profiles'][0]['stats']["PPvETimePlayed"]["value"] + self.time_played = data['profiles'][0]['stats']["PTotalTimePlayed"]["value"] + return self.pvp_time_played, self.pve_time_played, self.time_played + + async def load_alpha_pack(self) -> float: + data = await self.auth.get(self.url_builder.create_level_url()) if "player_profiles" in data and len(data["player_profiles"]) > 0: - # self.xp = data["player_profiles"][0].get("xp", 0) - self.level = data["player_profiles"][0].get("level", 0) - self.lootbox_probability = data["player_profiles"][0].get("lootbox_probability", 0) + self.alpha_pack = data["player_profiles"][0].get("lootbox_probability", 0) else: raise InvalidRequest(f"Missing key player_profiles in returned JSON object {str(data)}") + return self.alpha_pack + async def load_casual(self, region='emea', season=-1, data=None) -> Rank: """ Loads the players' rank for this region and season """ @@ -315,7 +310,7 @@ async def load_weapon_types(self, data=None) -> None: data = data["results"][self.id] self.weapons = [WeaponType(i, data) for i in range(1, 8)] - async def load_all_operators(self) -> dict[str: Operator]: + async def load_operators(self) -> dict[str: Operator]: # ask the api for all the basic stat names WITHOUT a postfix to ask for all (I assume) statistics = list(OPERATOR_URL_STATS) From eb897bbc3adf68827277d4268e0086a8e72edc1c Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 15 Feb 2022 21:43:11 +0100 Subject: [PATCH 16/61] should now work --- siegeapi/weapons.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 7ba9f1d..a0ebbe5 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -2,7 +2,7 @@ class Weapon: - def __init__(self, data): + def __init__(self, data: dict): self.name: str = data.get("weaponName") self.kills: int = data.get("kills") self.headshots: int = data.get("headshots") @@ -17,10 +17,28 @@ def __init__(self, data): self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" self.type: str = weapon.get("type") + def __repr__(self) -> str: + return str(vars(self)) -class WeaponSlots: - ... + +class WeaponsGameMode: + def __init__(self, data: dict): + self.primary: list = self._get_weapons_list(data.get("teamRoles").get("all").get("weaponSlots").get("primaryWeapons").get("weaponTypes")) + self.secondary: list = self._get_weapons_list(data.get("teamRoles").get("all").get("weaponSlots").get("secondaryWeapons").get("weaponTypes")) + + def _get_weapons_list(self, data: list[dict]) -> list[Weapon]: + return [Weapon(weapon) for weaponType in data for weapon in weaponType.get("weapons")] + + def __repr__(self) -> str: + return str(vars(self)) class Weapons: - ... + def __init__(self, data: dict): + self.all: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("all")) + self.casual: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("casual")) + self.ranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("ranked")) + self.unranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("unranked")) + + def __repr__(self) -> str: + return str(vars(self)) From eca6b3821ea840591d553c6814c1c12ea9acecce Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:00:57 +0100 Subject: [PATCH 17/61] rename get_players to be internal --- siegeapi/auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/auth.py b/siegeapi/auth.py index ec3486e..3d39797 100644 --- a/siegeapi/auth.py +++ b/siegeapi/auth.py @@ -167,7 +167,7 @@ async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict else: return await resp.text() - async def get_players(self, name=None, platform=None, uid=None) -> list[Player]: + async def _get_players(self, name=None, platform=None, uid=None) -> list[Player]: """ Get a list of players matching the search term on a given platform """ if name is None and uid is None: @@ -197,7 +197,7 @@ async def get_players(self, name=None, platform=None, uid=None) -> list[Player]: async def get_player(self, name=None, platform=None, uid=None) -> Player: """ Calls get_players and returns the first element """ - results = await self.get_players(name=name, platform=platform, uid=uid) + results = await self._get_players(name=name, platform=platform, uid=uid) return results[0] async def get_player_batch(self, platform, names=None, uids=None) -> PlayerBatch: From 06384f4e2aadf0002f4ab002911624057a5625d1 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:25:03 +0100 Subject: [PATCH 18/61] fix 146x146 profile pic url --- siegeapi/player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index c7e5151..fad7ab6 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -117,7 +117,7 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.spaceid: str = self.auth.spaceids[self.platform] self.url_builder: UrlBuilder = UrlBuilder(self.spaceid, self.platform_url, self.id) - self.profile_pic_url_146: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" + self.profile_pic_url_146: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_146_146.png" self.profile_pic_url_256: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" self.profile_pic_url_500: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_tall.png" self.profile_pic_url: str = self.profile_pic_url_256 From 9aad56ad416f4bd0ad83f45349dae5797b6cc3ca Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:29:53 +0100 Subject: [PATCH 19/61] remove unused var --- siegeapi/player.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index fad7ab6..9fcf674 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -123,7 +123,6 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.profile_pic_url: str = self.profile_pic_url_256 self.name: str = data.get("nameOnPlatform") - self.xp: int = 0 self.level: int = 0 self.alpha_pack: int = 0 self.deaths: int = 0 From c4dfc943d7f31ad7b410da93446fb75377131d0a Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:40:42 +0100 Subject: [PATCH 20/61] removed unsupported stat --- siegeapi/player.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 9fcf674..0085e8e 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -130,7 +130,6 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.matches_won: int = 0 self.bullets_hit: int = 0 self.melee_kills: int = 0 - self.bullets_fired: int = 0 self.matches_played: int = 0 self.kill_assists: int = 0 self.time_played: int = 0 From f573bd8301df274c1b37e91942e1e4c805fc1758 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:43:35 +0100 Subject: [PATCH 21/61] rename not updated time played to internal --- siegeapi/player.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 0085e8e..eef4a24 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -135,7 +135,7 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.time_played: int = 0 self.pvp_time_played: int = 0 self.pve_time_played: int = 0 - self.not_updated_time_played: int = 0 + self._not_updated_time_played: int = 0 self.revives: int = 0 self.kills: int = 0 self.headshots: int = 0 @@ -209,7 +209,7 @@ async def load_general(self) -> None: self.bullets_fired = stats.get(f"{statname}bulletfired", 0) self.matches_played = stats.get(f"{statname}matchplayed", 0) self.kill_assists = stats.get(f"{statname}killassists", 0) - self.not_updated_time_played = stats.get(f"{statname}timeplayed", 0) + self._not_updated_time_played = stats.get(f"{statname}timeplayed", 0) self.revives = stats.get(f"{statname}revive", 0) self.kills = stats.get(f"{statname}kills", 0) self.headshots = stats.get(f"{statname}headshot", 0) From ee4f373e6a38580f943e54efb14de283b2392800 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:47:02 +0100 Subject: [PATCH 22/61] why was this still here --- siegeapi/player.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index eef4a24..e70e5dc 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -155,7 +155,6 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.ranks: dict = {} self.casuals: dict = {} self.operators: dict = {} - self.gamemodes: dict = {} self.weapon_types: list = [] self.weapons: Weapons | None = None From 4ae3df45a1a5683c2bd509deb0fed189bf6bd091 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:54:22 +0100 Subject: [PATCH 23/61] - unused import --- siegeapi/player.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index e70e5dc..cd4841c 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -9,7 +9,6 @@ from .constants import * import aiohttp -import datetime class UrlBuilder: From b5f9f13da8e448c5fea8eb4ee126cc0211511cbe Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 14:59:18 +0100 Subject: [PATCH 24/61] forgot to remove this here --- siegeapi/player.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index cd4841c..8d8c4e9 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -204,7 +204,6 @@ async def load_general(self) -> None: self.matches_won = stats.get(f"{statname}matchwon", 0) self.bullets_hit = stats.get(f"{statname}bullethit", 0) self.melee_kills = stats.get(f"{statname}meleekills", 0) - self.bullets_fired = stats.get(f"{statname}bulletfired", 0) self.matches_played = stats.get(f"{statname}matchplayed", 0) self.kill_assists = stats.get(f"{statname}killassists", 0) self._not_updated_time_played = stats.get(f"{statname}timeplayed", 0) From 48b6f8fe6b15d84927d8b1caeb427976823baf9f Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 15:07:42 +0100 Subject: [PATCH 25/61] fix typehint for load_level() --- siegeapi/player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 8d8c4e9..2f3ac64 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -227,7 +227,7 @@ async def load_trends(self, block_duration: TrendBlockDuration = TrendBlockDurat self.trends = Trends(await self.auth.get(self.url_builder.create_trends_url(block_duration))) return self.trends - async def load_level(self) -> None: + async def load_level(self) -> int: data = await self.auth.get(self.url_builder.create_level_only_url()) self.level = data["stats"]["PClearanceLevel"]["value"] return self.level From 61f7f9d7c58f7ef8174b2897392298d6688bae1f Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 15:09:35 +0100 Subject: [PATCH 26/61] fix typehint for load_playtime --- siegeapi/player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 2f3ac64..c236522 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -232,7 +232,7 @@ async def load_level(self) -> int: self.level = data["stats"]["PClearanceLevel"]["value"] return self.level - async def load_playtime(self) -> dict[str: int]: + async def load_playtime(self) -> (int, int, int): data = await self.auth.get(self.url_builder.create_playtime_url(PLAYTIME_URL_STATS)) self.pvp_time_played = data['profiles'][0]['stats']["PPvPTimePlayed"]["value"] self.pve_time_played = data['profiles'][0]['stats']["PPvETimePlayed"]["value"] From 1f8b4bcb4871b71247bc05e425a81fa56b7f2562 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 15:14:36 +0100 Subject: [PATCH 27/61] fix yet another typehint, now alpha_pack --- siegeapi/player.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index c236522..21d5cdc 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -239,7 +239,7 @@ async def load_playtime(self) -> (int, int, int): self.time_played = data['profiles'][0]['stats']["PTotalTimePlayed"]["value"] return self.pvp_time_played, self.pve_time_played, self.time_played - async def load_alpha_pack(self) -> float: + async def load_alpha_pack(self) -> int: data = await self.auth.get(self.url_builder.create_level_url()) if "player_profiles" in data and len(data["player_profiles"]) > 0: From 7571e4093fb42ff3d324937fbdd19ec30ea0cb01 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 15:23:12 +0100 Subject: [PATCH 28/61] fix load_weapon_types() overwriting weapons data --- siegeapi/player.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 21d5cdc..a7c6be4 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -293,7 +293,7 @@ async def load_gamemodes(self) -> (Gamemode, Gamemode, Gamemode): self.thunt = Gamemode("terrohunt", stats) return self.ranked, self.casual, self.thunt - async def load_weapon_types(self, data=None) -> None: + async def load_weapon_types(self, data=None) -> list[WeaponType]: """ Load the players' weapon type stats """ if not data: @@ -303,7 +303,8 @@ async def load_weapon_types(self, data=None) -> None: raise InvalidRequest(f"Missing key results in returned JSON object {str(data)}") data = data["results"][self.id] - self.weapons = [WeaponType(i, data) for i in range(1, 8)] + self.weapon_types = [WeaponType(i, data) for i in range(1, 8)] + return self.weapon_types async def load_operators(self) -> dict[str: Operator]: # ask the api for all the basic stat names WITHOUT a postfix to ask for all (I assume) From 5e14eb5782124ae3e570435a7605c1e90c2487c8 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 19:34:03 +0100 Subject: [PATCH 29/61] rename internal function to be internal --- siegeapi/operators.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/siegeapi/operators.py b/siegeapi/operators.py index c61a28a..8fc2277 100644 --- a/siegeapi/operators.py +++ b/siegeapi/operators.py @@ -1,14 +1,14 @@ from .constants import operator_dict -def get_from_operators_const(name: str, what: str) -> str: +def _get_from_operators_const(name: str, what: str) -> str: return operator_dict[name][what] class Operator: def __init__(self, name, stats=None, unique_stats=None): self.name = name.lower() - self.readable = get_from_operators_const(self.name, 'name') + self.readable = _get_from_operators_const(self.name, 'name') stats = stats or {} self.wins = stats.get("roundwon", 0) @@ -20,8 +20,8 @@ def __init__(self, name, stats=None, unique_stats=None): self.dbnos = stats.get("dbno", 0) self.xp = stats.get("totalxp", 0) self.time_played = stats.get("timeplayed", 0) - self.atkdef = get_from_operators_const(self.name, 'side') - self.icon = get_from_operators_const(self.name, 'icon_url') + self.atkdef = _get_from_operators_const(self.name, 'side') + self.icon = _get_from_operators_const(self.name, 'icon_url') if unique_stats is not None: self.unique_stats = unique_stats From e61b248aa2625a3e63fa191826d05027336a5654 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 20:01:37 +0100 Subject: [PATCH 30/61] update example --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6b90e3b..927d875 100644 --- a/README.md +++ b/README.md @@ -46,23 +46,24 @@ async def sample(): print(f"Profile pic URL: {player.profile_pic_url}") await player.load_level() + await player.load_alpha_pack() + print(f"Level: {player.level}") - print(f"Alpha pack %: {player.lootbox_probability}") + print(f"Alpha pack %: {player.alpha_pack}") await auth.close() asyncio.get_event_loop().run_until_complete(sample()) +# Or `asyncio.run(sample())` ``` ### Output ```text Name: CNDRD Profile pic URL: https://ubisoft-avatars.akamaized.net/7e0f63df-a39b-44c5-8de0-d39a05926e77/default_256_256.png Level: 256 -Alpha pack %: 2050 +Level: 3250 ``` -> **_NOTE:_** `player.lootbox_probability` is 3 or 4-digits long E.g.: `player.lootbox_probability = 500` 👉 5.00% - --- ## Docs From 3e79cf22ce9f8eb658f6d7d7b5640ff627bf8f90 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Feb 2022 22:27:21 +0100 Subject: [PATCH 31/61] add missing gun --- siegeapi/constants/weapons.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/siegeapi/constants/weapons.py b/siegeapi/constants/weapons.py index 7835f56..bd4e0fc 100644 --- a/siegeapi/constants/weapons.py +++ b/siegeapi/constants/weapons.py @@ -101,6 +101,10 @@ "type": "Submachine Gun", "icon_url": "3a4dgTWGdiJqALhtRp4pKy/f2568d3de3cfe7e4b53179e8653cd2a2/MP7.png", }, + "MP5SD": { + "type": "Submachine Gun", + "icon_url": "6de3aa9aaa17458e7f6186ba59b8deff/MP5SD.png" + }, "T-5 SMG": { "type": "Submachine Gun", "icon_url": "1Ne8bvX8BdCALevWKMllQN/4baa3e79d323de134dd182e0272b9c3b/T-5_SMG.png", From 8d6e15db007e29c609151dfe40ef49b284230d8d Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 01:02:33 +0100 Subject: [PATCH 32/61] add missing weapons (yeah haha) ubi doesnt return any data if you havent played the gun since Oct 19. 2021 so until i rework how i get the data ill have to add every single gun :alien: --- siegeapi/constants/weapons.py | 90 +++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/siegeapi/constants/weapons.py b/siegeapi/constants/weapons.py index bd4e0fc..48e265a 100644 --- a/siegeapi/constants/weapons.py +++ b/siegeapi/constants/weapons.py @@ -63,6 +63,42 @@ "type": "Assault Rifle", "icon_url": "4P9dpUph5w3MSsLNnW6be/04baba24990fcb75a9c0bcfd01b7d190/Commando_9.png", }, + "AUG A2": { + "type": "Assault Rifle", + "icon_url": "1eO39zRe8XxJXH1KZiIWhM/02049ced0fbfa630833e8b0d3c03de07/AUG_A2.png", + }, + "F2": { + "type": "Assault Rifle", + "icon_url": "5HTvw1cJInVAGxOLXR0war/2f142437f5c0944fdcfcce8a03c37676/F2.png", + }, + "C8-SFW": { + "type": "Assault Rifle", + "icon_url": "1itXpz2GnvdwwRyhX1SYa2/b58ff71048fa3bb5ed09d5d935dc90f4/C8-SFW.png", + }, + "R4-C": { + "type": "Assault Rifle", + "icon_url": "dQbqK9VxczuiscwBDSkT8/777a062f6095dde0371eab5200dcb451/R4-C.png", + }, + "C7E": { + "type": "Assault Rifle", + "icon_url": "63vTDjkXeKq7rOoSBhoJD4/08603e6603d564e0fa38af9ec86b7c1f/C7E.png", + }, + "MK17 CQB": { + "type": "Assault Rifle", + "icon_url": "4LytczDQmu0M63gO2WtCCm/331ef3b1938352ae71d7c0bd23de3596/Mk17_CQB.png", + }, + "552 COMMANDO": { + "type": "Assault Rifle", + "icon_url": "1LT0N89YaOHvRwn3Pphr8K/02d4a3da9cda132d8201fd134f24fede/552_Commando.png", + }, + "ARX200": { + "type": "Assault Rifle", + "icon_url": "6VgkPBsr1WApI3rWc9kcM0/b18b8e25f3e951e8e722213f2ee59eb0/ARX200.png", + }, + "F90": { + "type": "Assault Rifle", + "icon_url": "62tE3th2ThcGHlrcqWkmEX/d69c9de199542e25fa55f6d293f15671/r6-operator-weapon-ar-f90.png", + }, # Submachine Guns "9mm C1": { @@ -89,6 +125,18 @@ "type": "Submachine Gun", "icon_url": "4yYCuRnduMq35CTHfq6wwU/b7d49cdbcb05917e014c99efeaadd33b/PDW9.png", }, + "UMP45": { + "type": "Submachine Gun", + "icon_url": "6X2EZPq2s8UKrP67uxz5FI/f0df4c57d5890c79311e4eb62d4470e7/UMP45.png", + }, + "SCORPION EVO 3 A1": { + "type": "Submachine Gun", + "icon_url": "6OdwaLWxcnFvhlVwWbP2Du/4f7e94bdb6d34d5c0aa7b7b147b4092e/Scorpion_EVO_3_A1.png", + }, + "P10 RONI": { + "type": "Submachine Gun", + "icon_url": "7K86OBjL3zmYWt0ZvUcCLj/16a947334e39f27da177d787773593e4/r6-operator-weapon-smg-p10roni.png", + }, "MP5": { "type": "Submachine Gun", "icon_url": "60YbOvSBQt6ZUlu8YDXoZm/51ef3857b2986de700262432e8433714/MP5.png", @@ -147,6 +195,14 @@ "type": "Marksman Rifle", "icon_url": "6KIMqp5dA95z1RI3PrG9jv/eb939638169811a3fa858a44e6e5d97e/Mk_14_EBR.png", }, + "OTs-03": { + "type": "Marksman Rifle", + "icon_url": "4fXznwDtLt61VCF8QIF4N3/34e2e6d6c33d4c504c945bdd13c322f6/OTs-03.png", + }, + "CSRX 300": { + "type": "Marksman Rifle", + "icon_url": "7tUB9ZNXJhdN6ejAkCEeFQ/99691bcc19f641cf872925905d08a539/CSRX_300.png", + }, # Shotguns "ACS12": { @@ -178,6 +234,10 @@ "type": "Shotgun", "icon_url": "2v6MwsHwjOZ5Muid53lyfN/e5f1c4997db93abfe3ac356fce23376c/SIX12.png", }, + "SIX12 SD": { + "type": "Shotgun", + "icon_url": "1GTua079Xbtkpjhx96sRsW/079ed1a71a0d12b5e48e1b0d40b87110/SIX12_SD.png", + }, "M1014": { "type": "Shotgun", "icon_url": "2pUiVbwNnQnDTesmWXktqW/f27c1fab9a354bb89cbe309a688f5e02/M1014.png", @@ -186,6 +246,10 @@ "type": "Shotgun", "icon_url": "5JoL3b36Fsztt9Q2XYmrbJ/dacec96948d3f8fe92914a69b9aac593/SG-CQB.png", }, + "SPAS-15": { + "type": "Shotgun", + "icon_url": "CyofBgipHq4RTafvPFWd4/bc3d0ecc871b70e57735855f852efacf/SPAS-15.png", + }, # Light Machine Guns "G8A1": { @@ -200,10 +264,26 @@ "type": "Light Machine Gun", "icon_url": "3p0oG7GsLIoHaRullf7xsF/e2a9e135af63e8897355023cd34538c4/M249_SAW.png", }, + "M249": { + "type": "Light Machine Gun", + "icon_url": "7z8UpVPS3P14OC1oL9dDIn/39c0c657f154218003fd4b2a9250b92f/M249.png", + }, "ALDA 5.56": { "type": "Light Machine Gun", "icon_url": "39yB6TFl9ph6Rb4bDV4lqK/7f9b3abf8dff19bacc026a7212849ca4/ALDA_5.56.png", }, + "6P41": { + "type": "Light Machine Gun", + "icon_url": "1wxS2HOCvoPAfnJEDFWjfw/7feddb98582ec37b500243d3f3e19eca/6P41.png", + }, + "DP28": { + "type": "Light Machine Gun", + "icon_url": "7LoT7yAe0LK7bDOeq6MZZM/33995bc704667674af1b73fe962d4c7c/Primary_gun_DP27.png", + }, + "T-95 LSW": { + "type": "Light Machine Gun", + "icon_url": "23HCxaNTRUHBlFAvCTMZQm/fe319cc164fac034a29e9b114ae7d5cb/T-95_LSW.png", + }, # Gadget "CCE SHIELD": { @@ -264,6 +344,10 @@ "type": "Pistol", "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", }, + "MK1 9mm": { + "type": "Pistol", + "icon_url": "3tWoNeF3jQYs3w4EOydQYs/434409c96693df1fd3e969d778e70795/Mk1_9mm_BI.png", + }, "GSH-18": { "type": "Pistol", "icon_url": "5s5Q33j3MNcXf9lwfxfd7m/4eb3a6af1d431481b6ddcec44fbc7602/GSh-18.png", @@ -337,4 +421,10 @@ "icon_url": "6W3Jz0YcQzbZ6BOPr7VVel/4c67f342964132a652f7d5821e887050/.44_Mag_Semi-Auto.png", }, + # Hand Cannon + "GONNE-6": { + "type": "Hand Cannon", + "icon_url": "23AlSVw8MwI1y3ZakEfqgW/c4561ae6e8da8db2627a146b8b55ee6c/GONNE-6_HUD_Icon__1_.png", + }, + } From f660d0ac752efc5d62fd3bfe73358b99dfc5a910 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 01:06:49 +0100 Subject: [PATCH 33/61] handle when user hasnt played a certain gamemode --- siegeapi/weapons.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index a0ebbe5..7944420 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -23,8 +23,8 @@ def __repr__(self) -> str: class WeaponsGameMode: def __init__(self, data: dict): - self.primary: list = self._get_weapons_list(data.get("teamRoles").get("all").get("weaponSlots").get("primaryWeapons").get("weaponTypes")) - self.secondary: list = self._get_weapons_list(data.get("teamRoles").get("all").get("weaponSlots").get("secondaryWeapons").get("weaponTypes")) + self.primary: list = self._get_weapons_list(data.get("teamRoles", {}).get("all", {}).get("weaponSlots", {}).get("primaryWeapons", {}).get("weaponTypes", {})) + self.secondary: list = self._get_weapons_list(data.get("teamRoles", {}).get("all", {}).get("weaponSlots", {}).get("secondaryWeapons", {}).get("weaponTypes", {})) def _get_weapons_list(self, data: list[dict]) -> list[Weapon]: return [Weapon(weapon) for weaponType in data for weapon in weaponType.get("weapons")] @@ -35,10 +35,10 @@ def __repr__(self) -> str: class Weapons: def __init__(self, data: dict): - self.all: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("all")) - self.casual: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("casual")) - self.ranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("ranked")) - self.unranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("unranked")) + self.all: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("all", {})) + self.casual: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("casual", {})) + self.ranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("ranked", {})) + self.unranked: WeaponsGameMode = WeaponsGameMode(data.get("platforms").get("PC").get("gameModes").get("unranked", {})) def __repr__(self) -> str: return str(vars(self)) From b42626403e4e4c9c2a7a3bc2d5d5b5cb56268a85 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 02:17:21 +0100 Subject: [PATCH 34/61] removed _last_data since i have no idea why it exists, it must not be useful lmao --- siegeapi/player.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index a7c6be4..d5f1994 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -90,9 +90,6 @@ async def _proxy(*args, **kwargs): root_result = await root_method(*args, **kwargs) results[root_player.id] = root_result - data = root_player._last_data - kwargs["data"] = data - for player_id in self.players: if player_id != root_player.id: results[player_id] = await getattr(self.players[player_id], name)(*args, **kwargs) From 8a7cd9645741a9dea6a126d893ccc88cbf6328ad Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 15:27:47 +0100 Subject: [PATCH 35/61] add probably all weapons --- siegeapi/constants/weapons.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/siegeapi/constants/weapons.py b/siegeapi/constants/weapons.py index 48e265a..14c6b3b 100644 --- a/siegeapi/constants/weapons.py +++ b/siegeapi/constants/weapons.py @@ -101,6 +101,10 @@ }, # Submachine Guns + "P90": { + "type": "Submachine Gun", + "icon_url": "4nGrNspOvII2oS3lEMkg5x/2398a493c298bc654f97c58767aa40f3/P90.png", + }, "9mm C1": { "type": "Submachine Gun", "icon_url": "60sbThKtOpNOwKu3OP0oGV/672fd9263f7786402a0d855273473a6f/9mm_C1.png", @@ -250,6 +254,26 @@ "type": "Shotgun", "icon_url": "CyofBgipHq4RTafvPFWd4/bc3d0ecc871b70e57735855f852efacf/SPAS-15.png", }, + "SPAS-12": { + "type": "Shotgun", + "icon_url": "7Hp6Fbss6uI59OT4nZNB6e/a4d09954803cb2580353cfa03e8c778b/SPAS-12.png", + }, + "SASG-12": { + "type": "Shotgun", + "icon_url": "2Q6mL4CbifmIgifV2yV3Hi/2bb2b323f055b03a2c1ba516c262c24e/SASG-12.png", + }, + "Supernova": { + "type": "Shotgun", + "icon_url": "2tpjCRFLcc3hogjJGbKDsi/5ad0ab63b7245022aca5c1c1fb42d473/SuperNova.png", + }, + "ITA12L": { + "type": "Shotgun", + "icon_url": "4Y6ziRzm9RiPii83fm8BV1/1f472744d2c2dec8d9206f4d8733d92c/ITA12L.png", + }, + "BOSG.12.2": { + "type": "Shotgun", + "icon_url": "2ZjVndetsX8WEn5ZfyUQa0/e3a781be7eab22876d25f748e8fd0f5a/BOSG.12.2.png", + }, # Light Machine Guns "G8A1": { @@ -280,6 +304,10 @@ "type": "Light Machine Gun", "icon_url": "7LoT7yAe0LK7bDOeq6MZZM/33995bc704667674af1b73fe962d4c7c/Primary_gun_DP27.png", }, + "DP27": { + "type": "Light Machine Gun", + "icon_url": "7LoT7yAe0LK7bDOeq6MZZM/33995bc704667674af1b73fe962d4c7c/Primary_gun_DP27.png", + }, "T-95 LSW": { "type": "Light Machine Gun", "icon_url": "23HCxaNTRUHBlFAvCTMZQm/fe319cc164fac034a29e9b114ae7d5cb/T-95_LSW.png", @@ -344,6 +372,10 @@ "type": "Pistol", "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", }, + "USP40": { + "type": "Pistol", + "icon_url": "7FxemzWRtlpAhK9MyKp1Gp/817cc25b6b7c3575dc1ba53a6a8170a9/USP40.png", + }, "MK1 9mm": { "type": "Pistol", "icon_url": "3tWoNeF3jQYs3w4EOydQYs/434409c96693df1fd3e969d778e70795/Mk1_9mm_BI.png", From 2c579b8fecd89f18d658549f60148da19be21ad5 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 15:28:10 +0100 Subject: [PATCH 36/61] handle when gun is missing from my constants list --- siegeapi/weapons.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 7944420..66b7741 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -13,9 +13,12 @@ def __init__(self, data: dict): self.rounds_with_kill: float = data.get("roundsWithAKill") self.rounds_with_multi_kill: float = data.get("roundsWithMultiKill") - weapon = WEAPONS_DICT.get(self.name) - self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" - self.type: str = weapon.get("type") + if weapon := WEAPONS_DICT.get(self.name): + self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" + self.type: str = weapon.get("type") + else: + self.image_url: str = "Missing Asset" + self.type: str = "Missing Asset" def __repr__(self) -> str: return str(vars(self)) From f3f1bcc540481ec701c3a79d4fe3f30c35b0e2fe Mon Sep 17 00:00:00 2001 From: CNDRD Date: Fri, 18 Feb 2022 15:28:18 +0100 Subject: [PATCH 37/61] make method static --- siegeapi/weapons.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 66b7741..7bd8aa6 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -29,7 +29,8 @@ def __init__(self, data: dict): self.primary: list = self._get_weapons_list(data.get("teamRoles", {}).get("all", {}).get("weaponSlots", {}).get("primaryWeapons", {}).get("weaponTypes", {})) self.secondary: list = self._get_weapons_list(data.get("teamRoles", {}).get("all", {}).get("weaponSlots", {}).get("secondaryWeapons", {}).get("weaponTypes", {})) - def _get_weapons_list(self, data: list[dict]) -> list[Weapon]: + @staticmethod + def _get_weapons_list(data: list[dict]) -> list[Weapon]: return [Weapon(weapon) for weaponType in data for weapon in weaponType.get("weapons")] def __repr__(self) -> str: From bb6e1439a379effc3f2a56eee0c0ca7856f521bd Mon Sep 17 00:00:00 2001 From: CNDRD Date: Sat, 19 Feb 2022 18:01:31 +0100 Subject: [PATCH 38/61] add imgur url for every gun --- siegeapi/constants/weapons.py | 124 +++++++++++++++++++++++++++++++--- siegeapi/weapons.py | 2 + 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/siegeapi/constants/weapons.py b/siegeapi/constants/weapons.py index 14c6b3b..9c566b1 100644 --- a/siegeapi/constants/weapons.py +++ b/siegeapi/constants/weapons.py @@ -6,332 +6,411 @@ "AK-12": { "type": "Assault Rifle", "icon_url": "7KAZZgnpqD07y47jVVXEuh/e0d7e67101f8f966aa6e1c59e835454f/AK-12.png", + "imgur_url": "https://i.imgur.com/XkqUvyS.png", }, "SC3000K": { "type": "Assault Rifle", "icon_url": "7x7eDTm2NNpfGiFMrfQqEX/9898e74c780537be3ca6d88db32ea21e/F2000.png", + "imgur_url": "https://i.imgur.com/93Vx6y4.png", }, "V308": { "type": "Assault Rifle", "icon_url": "5YBZe76NUDO32eF66wW90g/488c315743d59230962a4d67618223d6/V308.png", + "imgur_url": "https://i.imgur.com/xoxtQFf.png", }, "416-C CARBINE": { "type": "Assault Rifle", "icon_url": "2I86r2a2QD8EHTZVZnxcxy/2913450ba952a16c29fac1f5ce58ba1a/416-C_Carbine.png", + "imgur_url": "https://i.imgur.com/18j266k.png", }, "556XI": { "type": "Assault Rifle", "icon_url": "2dgpAeAWb3SkZV7rxDbVdQ/fa32323256b7c6f8a1977d3f71e7d4b2/556xi.png", + "imgur_url": "https://i.imgur.com/l3Z9O2Q.png", }, "M762": { "type": "Assault Rifle", "icon_url": "4oWAgi7tgQP1Tq0HooRtye/9109a74921ee17610d4bd85a61582823/M762.png", + "imgur_url": "https://i.imgur.com/bJqHwKt.png", }, "TYPE-89": { "type": "Assault Rifle", "icon_url": "7wLf325q9amF8bnVP1QGr0/2faff1a197f90dcded4472852a317d6b/Type-89.png", + "imgur_url": "https://i.imgur.com/hGDt4zV.png", }, "M4": { "type": "Assault Rifle", "icon_url": "3jhi90ycmuc8mAiuSXFoCi/bcf354459e7becd6ede52ee97917c832/M4.png", + "imgur_url": "https://i.imgur.com/lKDElT7.png", }, "PARA-308": { "type": "Assault Rifle", "icon_url": "6ub8y2Cs5EYhVPfDWuVVkW/82ca131a41ee4ba2e0b75f2dc52ed9e3/PARA-308.png", + "imgur_url": "https://i.imgur.com/246krdt.png", }, "SPEAR .308": { "type": "Assault Rifle", "icon_url": "29LjYuJ4s6yA8k9Uv2u28C/89ec812559e7d74b7c269279f4c46d92/Spear_.308.png", + "imgur_url": "https://i.imgur.com/PNyKa6N.png", }, "AK-74M": { "type": "Assault Rifle", "icon_url": "1j5HiQP8aFphTe65fqDdg0/23eecb5c603c5ba9f59fc6cbc5e4a531/AK-74M.png", + "imgur_url": "https://i.imgur.com/bOB4yay.png", }, "AR33": { "type": "Assault Rifle", "icon_url": "16U6xEvX8I5xQd9duveBLN/45d22960872cfa3fb6be9eb47fa0be4e/AR33.png", + "imgur_url": "https://i.imgur.com/fSUxgbS.png", }, "L85A2": { "type": "Assault Rifle", "icon_url": "5vYQpoyk36foDzDq49jBd0/1479a2d7189e545555ceccecf6bd7cc3/L85A2.png", + "imgur_url": "https://i.imgur.com/dFG30nS.png", }, "G36C": { "type": "Assault Rifle", "icon_url": "2SZoqSXKoNPvZFIJsFsDE5/cb109885bf19c8697abf832f10cfd9a6/G36C.png", + "imgur_url": "https://i.imgur.com/YuXb3x9.png", }, "COMMANDO 9": { "type": "Assault Rifle", "icon_url": "4P9dpUph5w3MSsLNnW6be/04baba24990fcb75a9c0bcfd01b7d190/Commando_9.png", + "imgur_url": "https://i.imgur.com/Jo2DJHb.png", }, "AUG A2": { "type": "Assault Rifle", "icon_url": "1eO39zRe8XxJXH1KZiIWhM/02049ced0fbfa630833e8b0d3c03de07/AUG_A2.png", + "imgur_url": "https://i.imgur.com/SG0dmYt.png", }, "F2": { "type": "Assault Rifle", "icon_url": "5HTvw1cJInVAGxOLXR0war/2f142437f5c0944fdcfcce8a03c37676/F2.png", + "imgur_url": "https://i.imgur.com/B9oWguM.png", }, "C8-SFW": { "type": "Assault Rifle", "icon_url": "1itXpz2GnvdwwRyhX1SYa2/b58ff71048fa3bb5ed09d5d935dc90f4/C8-SFW.png", + "imgur_url": "https://i.imgur.com/kxqQRY5.png", }, "R4-C": { "type": "Assault Rifle", "icon_url": "dQbqK9VxczuiscwBDSkT8/777a062f6095dde0371eab5200dcb451/R4-C.png", + "imgur_url": "https://i.imgur.com/pBxDdF5.png", }, "C7E": { "type": "Assault Rifle", "icon_url": "63vTDjkXeKq7rOoSBhoJD4/08603e6603d564e0fa38af9ec86b7c1f/C7E.png", + "imgur_url": "https://i.imgur.com/m0vBz74.png", }, "MK17 CQB": { "type": "Assault Rifle", "icon_url": "4LytczDQmu0M63gO2WtCCm/331ef3b1938352ae71d7c0bd23de3596/Mk17_CQB.png", + "imgur_url": "https://i.imgur.com/qFieFCz.png", }, "552 COMMANDO": { "type": "Assault Rifle", "icon_url": "1LT0N89YaOHvRwn3Pphr8K/02d4a3da9cda132d8201fd134f24fede/552_Commando.png", + "imgur_url": "https://i.imgur.com/iyeigKx.png", }, "ARX200": { "type": "Assault Rifle", "icon_url": "6VgkPBsr1WApI3rWc9kcM0/b18b8e25f3e951e8e722213f2ee59eb0/ARX200.png", + "imgur_url": "https://i.imgur.com/pjJNhg0.png", }, "F90": { "type": "Assault Rifle", "icon_url": "62tE3th2ThcGHlrcqWkmEX/d69c9de199542e25fa55f6d293f15671/r6-operator-weapon-ar-f90.png", + "imgur_url": "https://i.imgur.com/ltvoR5e.png", }, # Submachine Guns "P90": { "type": "Submachine Gun", "icon_url": "4nGrNspOvII2oS3lEMkg5x/2398a493c298bc654f97c58767aa40f3/P90.png", + "imgur_url": "https://i.imgur.com/JioXAPs.png", }, "9mm C1": { "type": "Submachine Gun", "icon_url": "60sbThKtOpNOwKu3OP0oGV/672fd9263f7786402a0d855273473a6f/9mm_C1.png", + "imgur_url": "https://i.imgur.com/CSicnOY.png", }, "AUG A3": { "type": "Submachine Gun", "icon_url": "3W9XJdMOgpHSw55HfwRSAv/cf8f220678d503e6c3e535c00b2e636a/AUG_A3.png", + "imgur_url": "https://i.imgur.com/EwhrsYo.png", }, "VECTOR .45 ACP": { "type": "Submachine Gun", "icon_url": "7D1cDf13FqUhoLihzvuPln/068aa7e507155598449c58c0a49a90d6/Vector_.45_ACP.png", + "imgur_url": "https://i.imgur.com/nYqNJVY.png", }, "M12": { "type": "Submachine Gun", "icon_url": "4FxqA5pa8JY9QQ7FEcjwPw/ffc779fcde5b970e7b95db6653637dab/M12.png", + "imgur_url": "https://i.imgur.com/xnjqNAP.png", }, "FMG-9": { "type": "Submachine Gun", "icon_url": "0oneJNsBR06QjuowxwtHG/bd3b391c6eec2bd615f2ed83197a13ac/FMG-9.png", + "imgur_url": "https://i.imgur.com/Sv4LCCi.png", }, "PDW9": { "type": "Submachine Gun", "icon_url": "4yYCuRnduMq35CTHfq6wwU/b7d49cdbcb05917e014c99efeaadd33b/PDW9.png", + "imgur_url": "https://i.imgur.com/SfD33PY.png", }, "UMP45": { "type": "Submachine Gun", "icon_url": "6X2EZPq2s8UKrP67uxz5FI/f0df4c57d5890c79311e4eb62d4470e7/UMP45.png", + "imgur_url": "https://i.imgur.com/DXCAI3x.png", }, "SCORPION EVO 3 A1": { "type": "Submachine Gun", "icon_url": "6OdwaLWxcnFvhlVwWbP2Du/4f7e94bdb6d34d5c0aa7b7b147b4092e/Scorpion_EVO_3_A1.png", + "imgur_url": "https://i.imgur.com/Xf4RkeF.png", }, "P10 RONI": { "type": "Submachine Gun", "icon_url": "7K86OBjL3zmYWt0ZvUcCLj/16a947334e39f27da177d787773593e4/r6-operator-weapon-smg-p10roni.png", + "imgur_url": "https://i.imgur.com/am0iQln.png", }, "MP5": { "type": "Submachine Gun", "icon_url": "60YbOvSBQt6ZUlu8YDXoZm/51ef3857b2986de700262432e8433714/MP5.png", + "imgur_url": "https://i.imgur.com/PUJ9el4.png", }, "MPX": { "type": "Submachine Gun", "icon_url": "5HFewpAJ8npDDCKFnEadhL/d398bb477d6b56fe41bfdb5862ed31c0/MPX.png", + "imgur_url": "https://i.imgur.com/0lGbMaK.png", }, "MP7": { "type": "Submachine Gun", "icon_url": "3a4dgTWGdiJqALhtRp4pKy/f2568d3de3cfe7e4b53179e8653cd2a2/MP7.png", + "imgur_url": "https://i.imgur.com/nTLMXY7.png", }, "MP5SD": { "type": "Submachine Gun", - "icon_url": "6de3aa9aaa17458e7f6186ba59b8deff/MP5SD.png" + "icon_url": "5HaMldwFltBwiiyDDfkPpD/6de3aa9aaa17458e7f6186ba59b8deff/MP5SD.png", + "imgur_url": "https://i.imgur.com/l5UoMyK.png", }, "T-5 SMG": { "type": "Submachine Gun", "icon_url": "1Ne8bvX8BdCALevWKMllQN/4baa3e79d323de134dd182e0272b9c3b/T-5_SMG.png", + "imgur_url": "https://i.imgur.com/aJD4n8e.png", }, "K1A": { "type": "Submachine Gun", "icon_url": "5mUa2p8WXbiyD71qUI8sGk/ed753b6f0ae30ab5737486dfcf32ee9f/K1A.png", + "imgur_url": "https://i.imgur.com/ASxXNFF.png", }, "Mx4 Storm": { "type": "Submachine Gun", "icon_url": "4qRh1frGkQZxNyeKA4D6n1/20f89cd1d9953f06207b7340ea77fb17/Mx4_Storm.png", + "imgur_url": "https://i.imgur.com/0KjOTla.png", }, "UZK50GI": { "type": "Submachine Gun", "icon_url": "5WMIsPUWTXprZnAwctPsTt/f1c652b681e7e9ba6ba66bcd29e12a76/uzk50gi.png", + "imgur_url": "https://i.imgur.com/EjnVX3B.png", }, "9x19VSN": { "type": "Submachine Gun", "icon_url": "42gH96xTTYaTZsfXI3c0wL/a7edbf11af97091ee884b68e59fe6a4f/9x19VSN.png", + "imgur_url": "https://i.imgur.com/YM28ZXk.png", }, "MP5K": { "type": "Submachine Gun", "icon_url": "1pk8nOI7ybQjYOSI4fuzOm/fcd78df0f729be545e75c09aae85c360/MP5K.png", + "imgur_url": "https://i.imgur.com/cJnZz6l.png", }, # Marksman Rifles "SR-25": { "type": "Marksman Rifle", "icon_url": "3H3sICdj6BK8LhtQPRd2aJ/26826ebba73e0e5fd503256d069f3256/SR-25.png", + "imgur_url": "https://i.imgur.com/GAwCFpP.png", }, "AR-15.50": { "type": "Marksman Rifle", "icon_url": "4lGGEGZLkbldz114Wl5hCo/78a04c46654f80fae03e730bd79f3563/AR-15.50.png", + "imgur_url": "https://i.imgur.com/k4RWCgE.png", }, "417": { "type": "Marksman Rifle", "icon_url": "5djkS4YtAtOF0vBmg0T60x/ea2b1ff7e5367e66c99bc7ad7e95bfe3/417.png", + "imgur_url": "https://i.imgur.com/XM1aYZ0.png", }, "Mk 14 EBR": { "type": "Marksman Rifle", "icon_url": "6KIMqp5dA95z1RI3PrG9jv/eb939638169811a3fa858a44e6e5d97e/Mk_14_EBR.png", + "imgur_url": "https://i.imgur.com/a7tnoMB.png", }, "OTs-03": { "type": "Marksman Rifle", "icon_url": "4fXznwDtLt61VCF8QIF4N3/34e2e6d6c33d4c504c945bdd13c322f6/OTs-03.png", + "imgur_url": "https://i.imgur.com/SvaWAHY.png", }, "CSRX 300": { "type": "Marksman Rifle", "icon_url": "7tUB9ZNXJhdN6ejAkCEeFQ/99691bcc19f641cf872925905d08a539/CSRX_300.png", + "imgur_url": "https://i.imgur.com/QIpmJkI.png", }, # Shotguns "ACS12": { "type": "Shotgun", "icon_url": "13z63kT1NLzn1U99o7WC4T/8655d3200f24b87246c36f2622603457/ACS12_PB.png", + "imgur_url": "https://i.imgur.com/oWkeNV1.png", }, "M590A1": { "type": "Shotgun", "icon_url": "2zRHmgqENNiZqXQxC9Rsbj/e6542407c642f9b7c5a4546afb6db30a/M590A1.png", + "imgur_url": "https://i.imgur.com/1hKRvhC.png", }, "M870": { "type": "Shotgun", "icon_url": "2rkU6g4Rlg0e0U4rczWGTV/a51589a54c43f476d8eb984c0ea881e9/M870.png", + "imgur_url": "https://i.imgur.com/2DulKY2.png", }, "TCSG12": { "type": "Shotgun", "icon_url": "2NDbY7BTBJ9R09LUilTlRf/3728337cd3ba14ed6ab9de0c22e879af/TCSG12.png", + "imgur_url": "https://i.imgur.com/jxNiaOx.png", }, # Yep, twice, because Ubi doesn't know how their own guns are named :) "FO-12": { "type": "Shotgun", "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + "imgur_url": "https://i.imgur.com/9mWXMtL.png", }, "F0-12": { "type": "Shotgun", "icon_url": "4TDWnhbgvLkc6HBWDJp2ST/f50cbd83d6d295ab59f17f7e21d713bc/FO-12.png", + "imgur_url": "https://i.imgur.com/9mWXMtL.png", }, "SIX12": { "type": "Shotgun", "icon_url": "2v6MwsHwjOZ5Muid53lyfN/e5f1c4997db93abfe3ac356fce23376c/SIX12.png", + "imgur_url": "https://i.imgur.com/XMdA44M.png", }, "SIX12 SD": { "type": "Shotgun", "icon_url": "1GTua079Xbtkpjhx96sRsW/079ed1a71a0d12b5e48e1b0d40b87110/SIX12_SD.png", + "imgur_url": "https://i.imgur.com/yco3bh7.png", }, "M1014": { "type": "Shotgun", "icon_url": "2pUiVbwNnQnDTesmWXktqW/f27c1fab9a354bb89cbe309a688f5e02/M1014.png", + "imgur_url": "https://i.imgur.com/QoKV2HB.png", }, "SG-CQB": { "type": "Shotgun", "icon_url": "5JoL3b36Fsztt9Q2XYmrbJ/dacec96948d3f8fe92914a69b9aac593/SG-CQB.png", + "imgur_url": "https://i.imgur.com/878GOhH.png", }, "SPAS-15": { "type": "Shotgun", "icon_url": "CyofBgipHq4RTafvPFWd4/bc3d0ecc871b70e57735855f852efacf/SPAS-15.png", + "imgur_url": "https://i.imgur.com/ptUqPpu.png", }, "SPAS-12": { "type": "Shotgun", "icon_url": "7Hp6Fbss6uI59OT4nZNB6e/a4d09954803cb2580353cfa03e8c778b/SPAS-12.png", + "imgur_url": "https://i.imgur.com/wMvRHWE.png", }, "SASG-12": { "type": "Shotgun", "icon_url": "2Q6mL4CbifmIgifV2yV3Hi/2bb2b323f055b03a2c1ba516c262c24e/SASG-12.png", + "imgur_url": "https://i.imgur.com/TASWBEp.png", }, "Supernova": { "type": "Shotgun", "icon_url": "2tpjCRFLcc3hogjJGbKDsi/5ad0ab63b7245022aca5c1c1fb42d473/SuperNova.png", + "imgur_url": "https://i.imgur.com/gshdPvF.png", }, "ITA12L": { "type": "Shotgun", "icon_url": "4Y6ziRzm9RiPii83fm8BV1/1f472744d2c2dec8d9206f4d8733d92c/ITA12L.png", + "imgur_url": "https://i.imgur.com/ldY0IlZ.png", }, "BOSG.12.2": { "type": "Shotgun", "icon_url": "2ZjVndetsX8WEn5ZfyUQa0/e3a781be7eab22876d25f748e8fd0f5a/BOSG.12.2.png", + "imgur_url": "https://i.imgur.com/90I2Sb8.png", }, # Light Machine Guns "G8A1": { "type": "Light Machine Gun", "icon_url": "4TIb7oeJesaROOOfTlCBaZ/ffd6a802f9a779a0d39b2122c49b3254/G8A1.png", + "imgur_url": "https://i.imgur.com/Wy6HdZW.png", }, "LMG-E": { "type": "Light Machine Gun", "icon_url": "7JVJIew6t3iKwgByvrFXyi/7ba44dfda28b525506633e453104a604/LMG-E.png", + "imgur_url": "https://i.imgur.com/UWXTqIL.png", }, "M249 SAW": { "type": "Light Machine Gun", "icon_url": "3p0oG7GsLIoHaRullf7xsF/e2a9e135af63e8897355023cd34538c4/M249_SAW.png", + "imgur_url": "https://i.imgur.com/dWLYeNw.png", }, "M249": { "type": "Light Machine Gun", "icon_url": "7z8UpVPS3P14OC1oL9dDIn/39c0c657f154218003fd4b2a9250b92f/M249.png", + "imgur_url": "https://i.imgur.com/gQOhuzN.png", }, "ALDA 5.56": { "type": "Light Machine Gun", "icon_url": "39yB6TFl9ph6Rb4bDV4lqK/7f9b3abf8dff19bacc026a7212849ca4/ALDA_5.56.png", + "imgur_url": "https://i.imgur.com/uNiNSiM.png", }, "6P41": { - "type": "Light Machine Gun", - "icon_url": "1wxS2HOCvoPAfnJEDFWjfw/7feddb98582ec37b500243d3f3e19eca/6P41.png", + "type": "Light Machine Gun", + "icon_url": "1wxS2HOCvoPAfnJEDFWjfw/7feddb98582ec37b500243d3f3e19eca/6P41.png", + "imgur_url": "https://i.imgur.com/nv4v9Q4.png", }, "DP28": { "type": "Light Machine Gun", "icon_url": "7LoT7yAe0LK7bDOeq6MZZM/33995bc704667674af1b73fe962d4c7c/Primary_gun_DP27.png", + "imgur_url": "https://i.imgur.com/EuXUXJt.png", }, "DP27": { "type": "Light Machine Gun", "icon_url": "7LoT7yAe0LK7bDOeq6MZZM/33995bc704667674af1b73fe962d4c7c/Primary_gun_DP27.png", + "imgur_url": "https://i.imgur.com/EuXUXJt.png", }, "T-95 LSW": { - "type": "Light Machine Gun", - "icon_url": "23HCxaNTRUHBlFAvCTMZQm/fe319cc164fac034a29e9b114ae7d5cb/T-95_LSW.png", + "type": "Light Machine Gun", + "icon_url": "23HCxaNTRUHBlFAvCTMZQm/fe319cc164fac034a29e9b114ae7d5cb/T-95_LSW.png", + "imgur_url": "https://i.imgur.com/6QCVGPg.png", }, # Gadget "CCE SHIELD": { "type": "Gadget", "icon_url": "5mmGgrYdJJHw2moBIEW9An/64e9727d959d7afdbb4fb06e2f75574a/CCE_Shield.png", + "imgur_url": "https://i.imgur.com/3CmDzwG.png", }, # Shield "Le Roc": { "type": "Shield", - "icon_url": "1bmXJOakdA6SOrGxBKA70T/1e489e366d6db287f475963df2040d3d/Extendable-Shield.png" + "icon_url": "1bmXJOakdA6SOrGxBKA70T/1e489e366d6db287f475963df2040d3d/Extendable-Shield.png", + "imgur_url": "https://i.imgur.com/pTB9tOm.png", }, # Ops ability "FLASH SHIELD": { "type": "Ops ability", - "icon_url": "7qmWjGZayvK4t6E80Gvu7g/8b789d6d639744dce100c2cfb9709e6a/G52-Tactical_Shield.png" + "icon_url": "7qmWjGZayvK4t6E80Gvu7g/8b789d6d639744dce100c2cfb9709e6a/G52-Tactical_Shield.png", + "imgur_url": "https://i.imgur.com/OFeah3y.png", }, # None "None": { "type": "None", - "icon_url": "yeah_lmao.png" + "icon_url": "yeah_lmao.png", + "imgur_url": "https://i.imgur.com/yeah_lmao.png", }, # Secondary Weapons @@ -339,124 +418,153 @@ "SUPER SHORTY": { "type": "Shotgun", "icon_url": "7Dq8LDmIxAveRqXM17orUW/cbd96b47cd8ca74a7827b16ef73fe7cf/r6-operator-weapon-sa-supershorty.png", + "imgur_url": "https://i.imgur.com/ceMDeDV.png", }, "ITA12S": { "type": "Shotgun", "icon_url": "5G4DroaSdqHzJWCe7qqbHZ/5dd2e03f853182c78a1e7fcbc642f0cf/ITA12S.png", + "imgur_url": "https://i.imgur.com/gKRXgpZ.png", }, # Machine Pistols "SMG-11": { "type": "Machine Pistol", "icon_url": "3WExw7Kepz9uAiWAbWW457/875fc631a3cf9fcc2849d9db2989cbcd/SMG-11.png", + "imgur_url": "https://i.imgur.com/HVuD3gD.png", }, "SMG-12": { "type": "Machine Pistol", "icon_url": "EwJgB7KdgOb6dDm7ro33u/b73f0890f992c1a365210f08efcc6db5/SMG-12.png", + "imgur_url": "https://i.imgur.com/1fC7KAS.png", }, "BEARING 9": { "type": "Machine Pistol", "icon_url": "4mdftEOh5Vu9KhhpgKLKrT/abedcc75868774018295ec2a08a7b3de/Bearing_9.png", + "imgur_url": "https://i.imgur.com/wT1qVsk.png", }, "C75 Auto": { "type": "Machine Pistol", "icon_url": "3wUuefwPjU705mZkTdJ9UH/8ccb11884cfa34c176ac5500af139177/C75_Auto.png", + "imgur_url": "https://i.imgur.com/VA1Y1FG.png", }, "SPSMG9": { "type": "Machine Pistol", "icon_url": "5EtwSgylXckBNg4n6gDR9J/bc6fc6c5c12ae11da59aee95828ebd76/SPSMG9.png", + "imgur_url": "https://i.imgur.com/owfOEEn.png", }, # Pistols "M45 MEUSOC": { "type": "Pistol", "icon_url": "3u5cecgWYl3WuJK50mKEGd/a4a0eb15c710edfc0d29e98c2ee7ea33/M45_MEUSOC.png", + "imgur_url": "https://i.imgur.com/eZqecY4.png", }, "USP40": { "type": "Pistol", "icon_url": "7FxemzWRtlpAhK9MyKp1Gp/817cc25b6b7c3575dc1ba53a6a8170a9/USP40.png", + "imgur_url": "https://i.imgur.com/HF6a0qj.png", }, "MK1 9mm": { "type": "Pistol", "icon_url": "3tWoNeF3jQYs3w4EOydQYs/434409c96693df1fd3e969d778e70795/Mk1_9mm_BI.png", + "imgur_url": "https://i.imgur.com/ntKax3y.png", }, "GSH-18": { "type": "Pistol", "icon_url": "5s5Q33j3MNcXf9lwfxfd7m/4eb3a6af1d431481b6ddcec44fbc7602/GSh-18.png", + "imgur_url": "https://i.imgur.com/bAcjOI1.png", }, "5.7 USG": { "type": "Pistol", "icon_url": "tkYcSAJSe5yGkeUhzZqBO/e81feb86df4a7eb6951052bec26b6ed7/5.7_USG.png", + "imgur_url": "https://i.imgur.com/fP7E1N6.png", }, "KERATOS .357": { "type": "Pistol", "icon_url": "15caVAsSCr8Rsb5Hid36uc/59632c4f90727931041ced62a620018b/Keratos_.357.png", + "imgur_url": "https://i.imgur.com/wpVBOFb.png", }, "P9": { "type": "Pistol", "icon_url": "6Fd1cl17KA0CtgodEiiY6v/d0f145ea72f2aacbd04260ba7d8f1c74/P9.png", + "imgur_url": "https://i.imgur.com/Nkuo7a8.png", }, "P229": { "type": "Pistol", "icon_url": "76ja0RxqzHW9PpvWgpG7Sk/cb753b50b20fe67deaef54d8b2a46b54/P229.png", + "imgur_url": "https://i.imgur.com/jw6hygP.png", }, "Q-929": { "type": "Pistol", "icon_url": "2fRVszR5yGDHbV0AL8muso/0838dac90b66aa810daa49d36382fb64/Q-929.png", + "imgur_url": "https://i.imgur.com/y4nQMpu.png", }, "P12": { "type": "Pistol", "icon_url": "2mpM7rah7rwEW0bViIirUC/ed9caa4db58421519fa4db390b1aa164/P12.png", + "imgur_url": "https://i.imgur.com/bh4W2aL.png", }, "PMM": { "type": "Pistol", "icon_url": "3y4LIwwm8YNQHAv8oOkWCK/a2375901cee34e68fa39c976d85de8aa/PMM.png", + "imgur_url": "https://i.imgur.com/tdz4YMY.png", }, "1911 TACOPS": { "type": "Pistol", "icon_url": "189UukZ6fVnvQR6LJtLYry/6eec29603d5b7b0ca8cab6ac0ef083ac/1911_TACOPS.png", + "imgur_url": "https://i.imgur.com/QOQ6kpd.png", }, "LFP586": { "type": "Pistol", "icon_url": "1zc7UtdBfCZakwbiYqBvSz/1fd3f1584de38ca7c9315d498f094276/LFP586.png", + "imgur_url": "https://i.imgur.com/2Qc7IPt.png", }, "PRB92": { "type": "Pistol", "icon_url": "dl28J1HsE7mzhj66pmd5D/b8d8fc48d2dde13154047de94abbd8ca/PRB92.png", + "imgur_url": "https://i.imgur.com/Gr4wE7G.png", }, "Bailiff 410": { "type": "Pistol", "icon_url": "N8FLbo4fsNyBe8msKgRhT/8f403dc0b58087bcafab786dd95ba33f/Bailiff_410.png", + "imgur_url": "https://i.imgur.com/Bl7MOeM.png", }, "D-50": { "type": "Pistol", "icon_url": "6mMQRDsrComRFa7bC6cNkG/8cd17e545e3d28dcc11a040d000cfa16/D-50.png", + "imgur_url": "https://i.imgur.com/XTWaD0k.png", }, "P-10C": { "type": "Pistol", "icon_url": "2l4qwB50zSFhFZVYRLNwqg/20df8114f69f96f2adc54779ccc5bbaa/P-10C.png", + "imgur_url": "https://i.imgur.com/WZ2m9XI.png", }, "P226 MK 25": { "type": "Pistol", "icon_url": "RTQvPQcywlRwUS1FjIKCX/6fc72fee2191c2e723276bc10ae4114e/P226_Mk_25.png", + "imgur_url": "https://i.imgur.com/kp8NHDn.png", }, "SDP 9mm": { "type": "Pistol", "icon_url": "Tgsdyz3XEqmgUYi9aZZgb/6755f4da7af7a7179ffab92acf8d477e/SDP_9mm.png", + "imgur_url": "https://i.imgur.com/J13BH6U.png", }, "RG15": { "type": "Pistol", "icon_url": "2LNSsp7B7wUnnPUweir7Jm/9f66d53be7a63a17a55253a0bea6eec1/RG15.png", + "imgur_url": "https://i.imgur.com/91Lo842.png", }, ".44 Mag Semi-Auto": { "type": "Pistol", "icon_url": "6W3Jz0YcQzbZ6BOPr7VVel/4c67f342964132a652f7d5821e887050/.44_Mag_Semi-Auto.png", + "imgur_url": "https://i.imgur.com/4QUGA4Z.png", }, # Hand Cannon "GONNE-6": { "type": "Hand Cannon", "icon_url": "23AlSVw8MwI1y3ZakEfqgW/c4561ae6e8da8db2627a146b8b55ee6c/GONNE-6_HUD_Icon__1_.png", + "imgur_url": "https://i.imgur.com/lc3eGIo.png", }, } diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 7bd8aa6..d8e3113 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -15,9 +15,11 @@ def __init__(self, data: dict): if weapon := WEAPONS_DICT.get(self.name): self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" + self.imgur_url: str = weapon.get("imgur_url") self.type: str = weapon.get("type") else: self.image_url: str = "Missing Asset" + self.imgur_url: str = "Missing Asset" self.type: str = "Missing Asset" def __repr__(self) -> str: From d1e8e3e386a85b341acc17ff2e64ef164c95940d Mon Sep 17 00:00:00 2001 From: Michal Mikulec <20823071+CNDRD@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:25:19 +0100 Subject: [PATCH 39/61] update Y7S1 stuff --- siegeapi/constants/operators.py | 2 +- siegeapi/constants/seasons.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/constants/operators.py b/siegeapi/constants/operators.py index 55ce2f1..26752c8 100644 --- a/siegeapi/constants/operators.py +++ b/siegeapi/constants/operators.py @@ -7,7 +7,7 @@ "armor": 2, "unit": "UNAFFILIATED", "country_code": "JP", - "roles": [], + "roles": ["Area Denial"], "side": "defender", "id": "", "icon_url": "", diff --git a/siegeapi/constants/seasons.py b/siegeapi/constants/seasons.py index 16692a1..8ffd9db 100644 --- a/siegeapi/constants/seasons.py +++ b/siegeapi/constants/seasons.py @@ -169,7 +169,7 @@ 25: { "name": "Demon Veil", - "hex": "#010101", + "hex": "#ffb52c", "code": "Y7S1", "start_date": "2022-03-08" }, From 032680e003e305d96f4d69dc36d97bb38f21b9b4 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Tue, 1 Mar 2022 21:08:01 +0100 Subject: [PATCH 40/61] fix typings for python 3.8 & 3.9 ( #1 ) --- siegeapi/auth.py | 5 ++- siegeapi/operators.py | 2 ++ siegeapi/player.py | 13 ++++--- siegeapi/ranks.py | 7 ++-- siegeapi/trends.py | 74 +++++++++++++++++++++------------------- siegeapi/weapon_types.py | 1 + siegeapi/weapons.py | 4 ++- 7 files changed, 61 insertions(+), 45 deletions(-) diff --git a/siegeapi/auth.py b/siegeapi/auth.py index 3d39797..3ad2d47 100644 --- a/siegeapi/auth.py +++ b/siegeapi/auth.py @@ -1,3 +1,6 @@ +from __future__ import annotations +from typing import List + import aiohttp import time import json @@ -167,7 +170,7 @@ async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict else: return await resp.text() - async def _get_players(self, name=None, platform=None, uid=None) -> list[Player]: + async def _get_players(self, name=None, platform=None, uid=None) -> List[Player]: """ Get a list of players matching the search term on a given platform """ if name is None and uid is None: diff --git a/siegeapi/operators.py b/siegeapi/operators.py index 8fc2277..977140b 100644 --- a/siegeapi/operators.py +++ b/siegeapi/operators.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .constants import operator_dict diff --git a/siegeapi/player.py b/siegeapi/player.py index d5f1994..c6ae847 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -1,3 +1,6 @@ +from __future__ import annotations +from typing import List + from .platforms import PlatformURLNames from .exceptions import InvalidRequest from .ranks import Rank, _get_rank_constants @@ -15,7 +18,7 @@ class UrlBuilder: def __init__(self, spaceid, platform_url, player_ids): self.spaceid: str = spaceid self.platform_url: str = platform_url - self.player_ids: list[str] = player_ids + self.player_ids: List[str] = player_ids def fetch_statistic_url(self, statistics: list) -> str: return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ @@ -290,7 +293,7 @@ async def load_gamemodes(self) -> (Gamemode, Gamemode, Gamemode): self.thunt = Gamemode("terrohunt", stats) return self.ranked, self.casual, self.thunt - async def load_weapon_types(self, data=None) -> list[WeaponType]: + async def load_weapon_types(self, data=None) -> List[WeaponType]: """ Load the players' weapon type stats """ if not data: @@ -330,7 +333,7 @@ async def load_operators(self) -> dict[str: Operator]: return self.operators @staticmethod - def _process_data(data: dict[str: int], op_dict: dict[str: dict[str: str | int | list[str] | list[dict[str: str]]]]) -> dict[str: int]: + def _process_data(data: dict[str: int], op_dict: dict[str: dict[str: str | int | List[str] | List[dict[str: str]]]]) -> dict[str: int]: processed_data = {} for opd in op_dict: op = operator_dict[opd] @@ -342,7 +345,7 @@ def _process_data(data: dict[str: int], op_dict: dict[str: dict[str: str | int | return processed_data @staticmethod - def _process_basic_data(data: dict[str: int], operator: dict[str: str | int | list[str] | list[dict[str: str]]]) -> dict[str: int]: + def _process_basic_data(data: dict[str: int], operator: dict[str: str | int | List[str] | List[dict[str: str]]]) -> dict[str: int]: basic_data = {} for stat in data: if stat.startswith(operator["safename"]): @@ -350,7 +353,7 @@ def _process_basic_data(data: dict[str: int], operator: dict[str: str | int | li return basic_data @staticmethod - def _process_unique_data(data: dict[str: int], operator: dict[str: str | int | list[str] | list[dict[str: str]]]) -> dict[str: int]: + def _process_unique_data(data: dict[str: int], operator: dict[str: str | int | List[str] | List[dict[str: str]]]) -> dict[str: int]: unique_data = {} for ability in operator["unique_stats"]: diff --git a/siegeapi/ranks.py b/siegeapi/ranks.py index 26ae404..4aa5b99 100644 --- a/siegeapi/ranks.py +++ b/siegeapi/ranks.py @@ -1,8 +1,11 @@ +from __future__ import annotations +from typing import Tuple, List + from .constants.ranks import * from .constants.seasons import seasons -def _get_rank_constants(season_number: int = -1) -> list[dict[str: str | int]]: +def _get_rank_constants(season_number: int = -1) -> List[dict[str: str | int]]: if 1 <= season_number <= 3: return ranks_v1 if 4 == season_number: @@ -16,7 +19,7 @@ def _get_rank_constants(season_number: int = -1) -> list[dict[str: str | int]]: return ranks_v5 -def _get_rank_from_mmr(mmr: int | float, season: int = -1) -> tuple[str, int, int, int]: +def _get_rank_from_mmr(mmr: int | float, season: int = -1) -> Tuple[str, int, int, int]: for rank_id, r in enumerate(_get_rank_constants(season)): if r["min_mmr"] <= int(mmr) <= r["max_mmr"]: return r["name"], r["min_mmr"], r["max_mmr"]+1, rank_id diff --git a/siegeapi/trends.py b/siegeapi/trends.py index 4f8c6c9..757bfb5 100644 --- a/siegeapi/trends.py +++ b/siegeapi/trends.py @@ -1,3 +1,5 @@ +from typing import List + class TrendBlockDuration: MONTHLY = "months" @@ -7,42 +9,42 @@ class TrendBlockDuration: class TrendBlocks: def __init__(self, data: dict): - self.stats_period: list[str] = data.get("statsPeriod", []) - self.matches_played: list[int] = data.get("matchesPlayed", []) - self.rounds_played: list[int] = data.get("roundsPlayed", []) - self.minutes_played: list[int] = data.get("minutesPlayed", []) - self.matches_won: list[int] = data.get("matchesWon", []) - self.matches_lost: list[int] = data.get("matchesLost", []) - self.rounds_won: list[int] = data.get("roundsWon", []) - self.rounds_lost: list[int] = data.get("roundsLost", []) - self.kills: list[int] = data.get("kills", []) - self.assists: list[int] = data.get("assists", []) - self.death: list[int] = data.get("death", []) - self.headshots: list[int] = data.get("headshots", []) - self.melee_kills: list[int] = data.get("meleeKills", []) - self.team_kills: list[int] = data.get("teamKills", []) - self.opening_kills: list[int] = data.get("openingKills", []) - self.opening_deaths: list[int] = data.get("openingDeaths", []) - self.trades: list[int] = data.get("trades", []) - self.opening_kill_trades: list[int] = data.get("openingKillTrades", []) - self.opening_death_trades: list[int] = data.get("openingDeathTrades", []) - self.revives: list[int] = data.get("revives", []) - self.distance_travelled: list[int] = data.get("distanceTravelled", []) - self.win_loss_ratio: list[float] = data.get("winLossRatio", []) - self.kill_death_ratio: list[float] = data.get("killDeathRatio", []) - self.headshot_accuracy: list[float] = data.get("headshotAccuracy", []) - self.kills_per_round: list[float] = data.get("killsPerRound", []) - self.rounds_with_kill: list[float] = data.get("roundsWithAKill", []) - self.rounds_with_multi_kill: list[float] = data.get("roundsWithMultiKill", []) - self.rounds_with_opening_kill: list[float] = data.get("roundsWithOpeningKill", []) - self.rounds_with_opening_death: list[float] = data.get("roundsWithOpeningDeath", []) - self.rounds_with_kost: list[float] = data.get("roundsWithKOST", []) - self.rounds_survived: list[float] = data.get("roundsSurvived", []) - self.rounds_with_ace: list[float] = data.get("roundsWithAnAce", []) - self.rounds_with_clutch: list[float] = data.get("roundsWithClutch", []) - self.time_alive_per_match: list[float] = data.get("timeAlivePerMatch", []) - self.time_dead_per_match: list[float] = data.get("timeDeadPerMatch", []) - self.distance_per_round: list[float] = data.get("distancePerRound", []) + self.stats_period: List[str] = data.get("statsPeriod", []) + self.matches_played: List[int] = data.get("matchesPlayed", []) + self.rounds_played: List[int] = data.get("roundsPlayed", []) + self.minutes_played: List[int] = data.get("minutesPlayed", []) + self.matches_won: List[int] = data.get("matchesWon", []) + self.matches_lost: List[int] = data.get("matchesLost", []) + self.rounds_won: List[int] = data.get("roundsWon", []) + self.rounds_lost: List[int] = data.get("roundsLost", []) + self.kills: List[int] = data.get("kills", []) + self.assists: List[int] = data.get("assists", []) + self.death: List[int] = data.get("death", []) + self.headshots: List[int] = data.get("headshots", []) + self.melee_kills: List[int] = data.get("meleeKills", []) + self.team_kills: List[int] = data.get("teamKills", []) + self.opening_kills: List[int] = data.get("openingKills", []) + self.opening_deaths: List[int] = data.get("openingDeaths", []) + self.trades: List[int] = data.get("trades", []) + self.opening_kill_trades: List[int] = data.get("openingKillTrades", []) + self.opening_death_trades: List[int] = data.get("openingDeathTrades", []) + self.revives: List[int] = data.get("revives", []) + self.distance_travelled: List[int] = data.get("distanceTravelled", []) + self.win_loss_ratio: List[float] = data.get("winLossRatio", []) + self.kill_death_ratio: List[float] = data.get("killDeathRatio", []) + self.headshot_accuracy: List[float] = data.get("headshotAccuracy", []) + self.kills_per_round: List[float] = data.get("killsPerRound", []) + self.rounds_with_kill: List[float] = data.get("roundsWithAKill", []) + self.rounds_with_multi_kill: List[float] = data.get("roundsWithMultiKill", []) + self.rounds_with_opening_kill: List[float] = data.get("roundsWithOpeningKill", []) + self.rounds_with_opening_death: List[float] = data.get("roundsWithOpeningDeath", []) + self.rounds_with_kost: List[float] = data.get("roundsWithKOST", []) + self.rounds_survived: List[float] = data.get("roundsSurvived", []) + self.rounds_with_ace: List[float] = data.get("roundsWithAnAce", []) + self.rounds_with_clutch: List[float] = data.get("roundsWithClutch", []) + self.time_alive_per_match: List[float] = data.get("timeAlivePerMatch", []) + self.time_dead_per_match: List[float] = data.get("timeDeadPerMatch", []) + self.distance_per_round: List[float] = data.get("distancePerRound", []) def __repr__(self) -> str: return str(vars(self)) diff --git a/siegeapi/weapon_types.py b/siegeapi/weapon_types.py index 17cffc1..1b31d2d 100644 --- a/siegeapi/weapon_types.py +++ b/siegeapi/weapon_types.py @@ -1,3 +1,4 @@ +from __future__ import annotations from typing import Callable diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index d8e3113..1efff05 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -1,3 +1,5 @@ +from typing import List + from .constants import WEAPONS_DICT @@ -32,7 +34,7 @@ def __init__(self, data: dict): self.secondary: list = self._get_weapons_list(data.get("teamRoles", {}).get("all", {}).get("weaponSlots", {}).get("secondaryWeapons", {}).get("weaponTypes", {})) @staticmethod - def _get_weapons_list(data: list[dict]) -> list[Weapon]: + def _get_weapons_list(data: List[dict]) -> List[Weapon]: return [Weapon(weapon) for weaponType in data for weapon in weaponType.get("weapons")] def __repr__(self) -> str: From 0a40102ee148fa2eea4138f7e4cee4a756c09deb Mon Sep 17 00:00:00 2001 From: CNDRD Date: Sat, 12 Mar 2022 18:49:45 +0100 Subject: [PATCH 41/61] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 927d875..0325f5f 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ asyncio.get_event_loop().run_until_complete(sample()) Name: CNDRD Profile pic URL: https://ubisoft-avatars.akamaized.net/7e0f63df-a39b-44c5-8de0-d39a05926e77/default_256_256.png Level: 256 -Level: 3250 +Alpha pack %: 3250 ``` --- From 690721cf202b887c0af51787479a4ba666b61d0d Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:29:04 +0100 Subject: [PATCH 42/61] rename internal method; reorganize --- siegeapi/auth.py | 94 ++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/siegeapi/auth.py b/siegeapi/auth.py index 3ad2d47..0ac21da 100644 --- a/siegeapi/auth.py +++ b/siegeapi/auth.py @@ -1,15 +1,14 @@ from __future__ import annotations -from typing import List +from urllib import parse +import datetime import aiohttp +import base64 import time import json -import base64 -from urllib import parse -import datetime from .exceptions import FailedToConnect, InvalidRequest -from .player import Player, PlayerBatch +from .player import Player class Auth: @@ -39,7 +38,7 @@ def __init__( self.sessionid: str = "" self.key: str = "" self.uncertain_spaceid: str = "" - self.spaceids: dict[str:str] = { + self.spaceids: dict[str: str] = { "uplay": "5172a557-50b5-4665-b7db-e3f2e8c5041d", "psn": "05bfb3f7-6c21-4c42-be1f-97a33fb5cf66", "xbl": "98a601e5-ca91-4440-b1c5-753f601a2c90" @@ -53,9 +52,41 @@ def __init__( self._login_cooldown: int = 0 self._session_start: float = time.time() - async def close(self) -> None: - """ Closes the session associated with the auth object """ - await self.session.close() + async def _find_players(self, name: str = None, platform: str = None, uid: str = None) -> list[Player]: + """ Get a list of players matching the search term on a given platform """ + + if name is None and uid is None: + raise TypeError("'name' and 'uid' are both None, exactly one must be given") + + if name is not None and uid is not None: + raise TypeError("Cannot search by 'uid' and 'name' at the same time, please give one or the other") + + if platform is None: + raise TypeError("platform cannot be None") + + if platform not in ("uplay", "xbl", "psn"): + raise TypeError(f"'platform' has to be one of the following: 'uplay' / 'xbl' / 'psn'; Not {platform}") + + if name: + data = await self.get(f"https://public-ubiservices.ubi.com/v3/profiles?" + f"nameOnPlatform={parse.quote(name)}&platformType={parse.quote(platform)}") + else: + data = await self.get(f"https://public-ubiservices.ubi.com/v3/users/{uid}/profiles?" + f"platformType={parse.quote(platform)}") + + if "profiles" in data: + results = [Player(self, x) for x in data["profiles"] if x.get("platformType", "") == platform] + if len(results) == 0: + raise InvalidRequest("No results") + return results + else: + raise InvalidRequest(f"Missing key profiles in returned JSON object {str(data)}") + + async def _ensure_session_valid(self) -> None: + if not self.session: + await self.refresh_session() + elif 0 <= self.refresh_session_period <= (time.time() - self._session_start): + await self.refresh_session() async def refresh_session(self) -> None: """ Closes the current session and opens a new one """ @@ -68,12 +99,6 @@ async def refresh_session(self) -> None: self.session = aiohttp.ClientSession() self._session_start = time.time() - async def _ensure_session_valid(self) -> None: - if not self.session: - await self.refresh_session() - elif 0 <= self.refresh_session_period <= (time.time() - self._session_start): - await self.refresh_session() - async def get_session(self) -> aiohttp.ClientSession(): """ Retrieves the current session, ensuring it's valid first """ await self._ensure_session_valid() @@ -107,7 +132,11 @@ async def connect(self) -> None: message = str(data["httpCode"]) raise FailedToConnect(message) - async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict | str: + async def close(self) -> None: + """ Closes the session associated with the auth object """ + await self.session.close() + + async def get(self, *args, retries: int = 0, referer: str = None, json_: bool = True, **kwargs) -> dict | str: if not self.key: last_error = None for _ in range(self.max_connect_retries): @@ -131,7 +160,7 @@ async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict kwargs["headers"]["Ubi-AppId"] = self.appid kwargs["headers"]["Ubi-SessionId"] = self.sessionid kwargs["headers"]["Connection"] = "keep-alive" - kwargs["headers"]["expiration"] = f"{(datetime.datetime.utcnow()+datetime.timedelta(hours=2.0)).isoformat()}Z" + kwargs["headers"]["expiration"] = f"{(datetime.datetime.utcnow() + datetime.timedelta(hours=2.0)).isoformat()}Z" kwargs["headers"]["Ubi-LocaleCode"] = "x" if referer is not None: @@ -142,7 +171,7 @@ async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict session = await self.get_session() resp = await session.get(*args, **kwargs) - if json: + if json_: try: data = await resp.json() except: @@ -170,37 +199,10 @@ async def get(self, *args, retries=0, referer=None, json=True, **kwargs) -> dict else: return await resp.text() - async def _get_players(self, name=None, platform=None, uid=None) -> List[Player]: - """ Get a list of players matching the search term on a given platform """ - - if name is None and uid is None: - raise TypeError("name and uid are both None, exactly one must be given") - - if name is not None and uid is not None: - raise TypeError("cannot search by uid and name at the same time, please give one or the other") - - if platform is None: - raise TypeError("platform cannot be None") - - if name: - data = await self.get(f"https://public-ubiservices.ubi.com/v3/profiles?" - f"nameOnPlatform={parse.quote(name)}&platformType={parse.quote(platform)}") - else: - data = await self.get(f"https://public-ubiservices.ubi.com/v3/users/{uid}/profiles?" - f"platformType={parse.quote(platform)}") - - if "profiles" in data: - results = [Player(self, x) for x in data["profiles"] if x.get("platformType", "") == platform] - if len(results) == 0: - raise InvalidRequest("No results") - return results - else: - raise InvalidRequest(f"Missing key profiles in returned JSON object {str(data)}") - async def get_player(self, name=None, platform=None, uid=None) -> Player: """ Calls get_players and returns the first element """ - results = await self._get_players(name=name, platform=platform, uid=uid) + results = await self._find_players(name=name, platform=platform, uid=uid) return results[0] async def get_player_batch(self, platform, names=None, uids=None) -> PlayerBatch: From 6b30bd978a5444309abde6866b4185b01a85181a Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:29:24 +0100 Subject: [PATCH 43/61] change return value of get_player_batch() --- siegeapi/auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/auth.py b/siegeapi/auth.py index 0ac21da..b8db562 100644 --- a/siegeapi/auth.py +++ b/siegeapi/auth.py @@ -205,7 +205,7 @@ async def get_player(self, name=None, platform=None, uid=None) -> Player: results = await self._find_players(name=name, platform=platform, uid=uid) return results[0] - async def get_player_batch(self, platform, names=None, uids=None) -> PlayerBatch: + async def get_player_batch(self, platform, names=None, uids=None) -> dict[str: Player]: players = {} if names is not None: for name in names: @@ -216,4 +216,4 @@ async def get_player_batch(self, platform, names=None, uids=None) -> PlayerBatch for uid in uids: player = await self.get_player(uid=uid, platform=platform) players[player.id] = player - return PlayerBatch(players) + return players From 712b576bc7d5d6e5f9202c6a0df2e4bfd6e98914 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:29:46 +0100 Subject: [PATCH 44/61] rename image_url to ubi_url --- siegeapi/weapons.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/siegeapi/weapons.py b/siegeapi/weapons.py index 1efff05..e2c20bf 100644 --- a/siegeapi/weapons.py +++ b/siegeapi/weapons.py @@ -16,11 +16,11 @@ def __init__(self, data: dict): self.rounds_with_multi_kill: float = data.get("roundsWithMultiKill") if weapon := WEAPONS_DICT.get(self.name): - self.image_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" + self.ubi_url: str = f"https://staticctf.akamaized.net/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/{weapon.get('icon_url')}" self.imgur_url: str = weapon.get("imgur_url") self.type: str = weapon.get("type") else: - self.image_url: str = "Missing Asset" + self.ubi_url: str = "Missing Asset" self.imgur_url: str = "Missing Asset" self.type: str = "Missing Asset" From 59f5033cd207c728d498ddab7eea30593861e1eb Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:30:09 +0100 Subject: [PATCH 45/61] add Azami icon url --- siegeapi/constants/operators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/constants/operators.py b/siegeapi/constants/operators.py index 26752c8..3937a59 100644 --- a/siegeapi/constants/operators.py +++ b/siegeapi/constants/operators.py @@ -10,7 +10,7 @@ "roles": ["Area Denial"], "side": "defender", "id": "", - "icon_url": "", + "icon_url": "https://i.imgur.com/AmyLoc5.png", "unique_stats": [ { "id": "operatorpvp_azami_something", From f3d3286f2934dbe5c535bcbd9bf8eaeb49399e0d Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:30:33 +0100 Subject: [PATCH 46/61] fix Demon Veil release date --- siegeapi/constants/seasons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siegeapi/constants/seasons.py b/siegeapi/constants/seasons.py index 8ffd9db..0e5aeeb 100644 --- a/siegeapi/constants/seasons.py +++ b/siegeapi/constants/seasons.py @@ -171,6 +171,6 @@ "name": "Demon Veil", "hex": "#ffb52c", "code": "Y7S1", - "start_date": "2022-03-08" + "start_date": "2022-03-15" }, } From 508bfce636ec5aa6283b819fa9601284cc096288 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:30:51 +0100 Subject: [PATCH 47/61] fix quotes --- siegeapi/constants/ranks.py | 226 ++++++++++++++++++------------------ 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/siegeapi/constants/ranks.py b/siegeapi/constants/ranks.py index c284507..540a644 100644 --- a/siegeapi/constants/ranks.py +++ b/siegeapi/constants/ranks.py @@ -1,133 +1,133 @@ # Until Y1S3 (#3) ranks_v1 = [ - {"name": 'Unranked', "min_mmr": 0, "max_mmr": 0}, - {"name": 'Copper 1', "min_mmr": 1, "max_mmr": 2199}, - {"name": 'Copper 2', "min_mmr": 2200, "max_mmr": 2399}, - {"name": 'Copper 3', "min_mmr": 2400, "max_mmr": 2549}, - {"name": 'Copper 4', "min_mmr": 2550, "max_mmr": 2699}, - {"name": 'Bronze 1', "min_mmr": 2700, "max_mmr": 2799}, - {"name": 'Bronze 2', "min_mmr": 2800, "max_mmr": 2899}, - {"name": 'Bronze 3', "min_mmr": 2900, "max_mmr": 3049}, - {"name": 'Bronze 4', "min_mmr": 3050, "max_mmr": 3199}, - {"name": 'Silver 1', "min_mmr": 3200, "max_mmr": 3349}, - {"name": 'Silver 2', "min_mmr": 3350, "max_mmr": 3519}, - {"name": 'Silver 3', "min_mmr": 3520, "max_mmr": 3699}, - {"name": 'Silver 4', "min_mmr": 3700, "max_mmr": 3929}, - {"name": 'Gold 1', "min_mmr": 3930, "max_mmr": 4159}, - {"name": 'Gold 2', "min_mmr": 4160, "max_mmr": 4399}, - {"name": 'Gold 3', "min_mmr": 4400, "max_mmr": 4639}, - {"name": 'Gold 4', "min_mmr": 4640, "max_mmr": 4899}, - {"name": 'Platinum 1', "min_mmr": 4900, "max_mmr": 5159}, - {"name": 'Platinum 2', "min_mmr": 5160, "max_mmr": 5449}, - {"name": 'Platinum 3', "min_mmr": 5450, "max_mmr": 5999}, - {"name": 'Diamond', "min_mmr": 6000, "max_mmr": 999999} + {"name": "Unranked", "min_mmr": 0, "max_mmr": 0}, + {"name": "Copper 1", "min_mmr": 1, "max_mmr": 2199}, + {"name": "Copper 2", "min_mmr": 2200, "max_mmr": 2399}, + {"name": "Copper 3", "min_mmr": 2400, "max_mmr": 2549}, + {"name": "Copper 4", "min_mmr": 2550, "max_mmr": 2699}, + {"name": "Bronze 1", "min_mmr": 2700, "max_mmr": 2799}, + {"name": "Bronze 2", "min_mmr": 2800, "max_mmr": 2899}, + {"name": "Bronze 3", "min_mmr": 2900, "max_mmr": 3049}, + {"name": "Bronze 4", "min_mmr": 3050, "max_mmr": 3199}, + {"name": "Silver 1", "min_mmr": 3200, "max_mmr": 3349}, + {"name": "Silver 2", "min_mmr": 3350, "max_mmr": 3519}, + {"name": "Silver 3", "min_mmr": 3520, "max_mmr": 3699}, + {"name": "Silver 4", "min_mmr": 3700, "max_mmr": 3929}, + {"name": "Gold 1", "min_mmr": 3930, "max_mmr": 4159}, + {"name": "Gold 2", "min_mmr": 4160, "max_mmr": 4399}, + {"name": "Gold 3", "min_mmr": 4400, "max_mmr": 4639}, + {"name": "Gold 4", "min_mmr": 4640, "max_mmr": 4899}, + {"name": "Platinum 1", "min_mmr": 4900, "max_mmr": 5159}, + {"name": "Platinum 2", "min_mmr": 5160, "max_mmr": 5449}, + {"name": "Platinum 3", "min_mmr": 5450, "max_mmr": 5999}, + {"name": "Diamond", "min_mmr": 6000, "max_mmr": 999999} ] # Y1S4 (#4) ranks_v2 = [ - {"name": 'Unranked', "min_mmr": 0, "max_mmr": 0}, - {"name": 'Copper 1', "min_mmr": 1, "max_mmr": 1399}, - {"name": 'Copper 2', "min_mmr": 1400, "max_mmr": 1499}, - {"name": 'Copper 3', "min_mmr": 1500, "max_mmr": 1599}, - {"name": 'Copper 4', "min_mmr": 1600, "max_mmr": 1699}, - {"name": 'Bronze 1', "min_mmr": 1700, "max_mmr": 1799}, - {"name": 'Bronze 2', "min_mmr": 1800, "max_mmr": 1899}, - {"name": 'Bronze 3', "min_mmr": 1900, "max_mmr": 1999}, - {"name": 'Bronze 4', "min_mmr": 2000, "max_mmr": 2099}, - {"name": 'Silver 1', "min_mmr": 2100, "max_mmr": 2199}, - {"name": 'Silver 2', "min_mmr": 2200, "max_mmr": 2299}, - {"name": 'Silver 3', "min_mmr": 2300, "max_mmr": 2399}, - {"name": 'Silver 4', "min_mmr": 2400, "max_mmr": 2499}, - {"name": 'Gold 1', "min_mmr": 2500, "max_mmr": 2599}, - {"name": 'Gold 2', "min_mmr": 2600, "max_mmr": 2699}, - {"name": 'Gold 3', "min_mmr": 2700, "max_mmr": 2700}, - {"name": 'Gold 4', "min_mmr": 2800, "max_mmr": 2999}, - {"name": 'Platinum 1', "min_mmr": 3000, "max_mmr": 3199}, - {"name": 'Platinum 2', "min_mmr": 3200, "max_mmr": 3399}, - {"name": 'Platinum 3', "min_mmr": 3400, "max_mmr": 3699}, - {"name": 'Diamond', "min_mmr": 3700, "max_mmr": 999999} + {"name": "Unranked", "min_mmr": 0, "max_mmr": 0}, + {"name": "Copper 1", "min_mmr": 1, "max_mmr": 1399}, + {"name": "Copper 2", "min_mmr": 1400, "max_mmr": 1499}, + {"name": "Copper 3", "min_mmr": 1500, "max_mmr": 1599}, + {"name": "Copper 4", "min_mmr": 1600, "max_mmr": 1699}, + {"name": "Bronze 1", "min_mmr": 1700, "max_mmr": 1799}, + {"name": "Bronze 2", "min_mmr": 1800, "max_mmr": 1899}, + {"name": "Bronze 3", "min_mmr": 1900, "max_mmr": 1999}, + {"name": "Bronze 4", "min_mmr": 2000, "max_mmr": 2099}, + {"name": "Silver 1", "min_mmr": 2100, "max_mmr": 2199}, + {"name": "Silver 2", "min_mmr": 2200, "max_mmr": 2299}, + {"name": "Silver 3", "min_mmr": 2300, "max_mmr": 2399}, + {"name": "Silver 4", "min_mmr": 2400, "max_mmr": 2499}, + {"name": "Gold 1", "min_mmr": 2500, "max_mmr": 2599}, + {"name": "Gold 2", "min_mmr": 2600, "max_mmr": 2699}, + {"name": "Gold 3", "min_mmr": 2700, "max_mmr": 2700}, + {"name": "Gold 4", "min_mmr": 2800, "max_mmr": 2999}, + {"name": "Platinum 1", "min_mmr": 3000, "max_mmr": 3199}, + {"name": "Platinum 2", "min_mmr": 3200, "max_mmr": 3399}, + {"name": "Platinum 3", "min_mmr": 3400, "max_mmr": 3699}, + {"name": "Diamond", "min_mmr": 3700, "max_mmr": 999999} ] # Y2S1 - Y4S2 (#5 - #14) ranks_v3 = [ - {"name": 'Unranked', "min_mmr": 0, "max_mmr": 0}, - {"name": 'Copper 4', "min_mmr": 1, "max_mmr": 1399}, - {"name": 'Copper 3', "min_mmr": 1400, "max_mmr": 1499}, - {"name": 'Copper 2', "min_mmr": 1500, "max_mmr": 1599}, - {"name": 'Copper 1', "min_mmr": 1600, "max_mmr": 1699}, - {"name": 'Bronze 4', "min_mmr": 1700, "max_mmr": 1799}, - {"name": 'Bronze 3', "min_mmr": 1800, "max_mmr": 1899}, - {"name": 'Bronze 2', "min_mmr": 1900, "max_mmr": 1999}, - {"name": 'Bronze 1', "min_mmr": 2000, "max_mmr": 2099}, - {"name": 'Silver 4', "min_mmr": 2100, "max_mmr": 2199}, - {"name": 'Silver 3', "min_mmr": 2200, "max_mmr": 2299}, - {"name": 'Silver 2', "min_mmr": 2300, "max_mmr": 2399}, - {"name": 'Silver 1', "min_mmr": 2400, "max_mmr": 2499}, - {"name": 'Gold 4', "min_mmr": 2500, "max_mmr": 2699}, - {"name": 'Gold 3', "min_mmr": 2700, "max_mmr": 2899}, - {"name": 'Gold 2', "min_mmr": 2900, "max_mmr": 3099}, - {"name": 'Gold 1', "min_mmr": 3100, "max_mmr": 3299}, - {"name": 'Platinum 3', "min_mmr": 3300, "max_mmr": 3699}, - {"name": 'Platinum 2', "min_mmr": 3700, "max_mmr": 4099}, - {"name": 'Platinum 1', "min_mmr": 4100, "max_mmr": 4499}, - {"name": 'Diamond', "min_mmr": 4500, "max_mmr": 999999} + {"name": "Unranked", "min_mmr": 0, "max_mmr": 0}, + {"name": "Copper 4", "min_mmr": 1, "max_mmr": 1399}, + {"name": "Copper 3", "min_mmr": 1400, "max_mmr": 1499}, + {"name": "Copper 2", "min_mmr": 1500, "max_mmr": 1599}, + {"name": "Copper 1", "min_mmr": 1600, "max_mmr": 1699}, + {"name": "Bronze 4", "min_mmr": 1700, "max_mmr": 1799}, + {"name": "Bronze 3", "min_mmr": 1800, "max_mmr": 1899}, + {"name": "Bronze 2", "min_mmr": 1900, "max_mmr": 1999}, + {"name": "Bronze 1", "min_mmr": 2000, "max_mmr": 2099}, + {"name": "Silver 4", "min_mmr": 2100, "max_mmr": 2199}, + {"name": "Silver 3", "min_mmr": 2200, "max_mmr": 2299}, + {"name": "Silver 2", "min_mmr": 2300, "max_mmr": 2399}, + {"name": "Silver 1", "min_mmr": 2400, "max_mmr": 2499}, + {"name": "Gold 4", "min_mmr": 2500, "max_mmr": 2699}, + {"name": "Gold 3", "min_mmr": 2700, "max_mmr": 2899}, + {"name": "Gold 2", "min_mmr": 2900, "max_mmr": 3099}, + {"name": "Gold 1", "min_mmr": 3100, "max_mmr": 3299}, + {"name": "Platinum 3", "min_mmr": 3300, "max_mmr": 3699}, + {"name": "Platinum 2", "min_mmr": 3700, "max_mmr": 4099}, + {"name": "Platinum 1", "min_mmr": 4100, "max_mmr": 4499}, + {"name": "Diamond", "min_mmr": 4500, "max_mmr": 999999} ] # Y4S3 - Y6S2 (#15 - #22) ranks_v4 = [ - {"name": 'Unranked', "min_mmr": 0, "max_mmr": 0}, - {"name": 'Copper 5', "min_mmr": 1, "max_mmr": 1199}, - {"name": 'Copper 4', "min_mmr": 1200, "max_mmr": 1299}, - {"name": 'Copper 3', "min_mmr": 1300, "max_mmr": 1399}, - {"name": 'Copper 2', "min_mmr": 1400, "max_mmr": 1499}, - {"name": 'Copper 1', "min_mmr": 1500, "max_mmr": 1599}, - {"name": 'Bronze 5', "min_mmr": 1600, "max_mmr": 1699}, - {"name": 'Bronze 4', "min_mmr": 1700, "max_mmr": 1799}, - {"name": 'Bronze 3', "min_mmr": 1800, "max_mmr": 1899}, - {"name": 'Bronze 2', "min_mmr": 1900, "max_mmr": 1999}, - {"name": 'Bronze 1', "min_mmr": 2000, "max_mmr": 2099}, - {"name": 'Silver 5', "min_mmr": 2100, "max_mmr": 2199}, - {"name": 'Silver 4', "min_mmr": 2200, "max_mmr": 2299}, - {"name": 'Silver 3', "min_mmr": 2300, "max_mmr": 2399}, - {"name": 'Silver 2', "min_mmr": 2400, "max_mmr": 2499}, - {"name": 'Silver 1', "min_mmr": 2500, "max_mmr": 2599}, - {"name": 'Gold 3', "min_mmr": 2600, "max_mmr": 2799}, - {"name": 'Gold 2', "min_mmr": 2800, "max_mmr": 2999}, - {"name": 'Gold 1', "min_mmr": 3000, "max_mmr": 3199}, - {"name": 'Platinum 3', "min_mmr": 3200, "max_mmr": 3599}, - {"name": 'Platinum 2', "min_mmr": 3600, "max_mmr": 3999}, - {"name": 'Platinum 1', "min_mmr": 4000, "max_mmr": 4399}, - {"name": 'Diamond', "min_mmr": 4400, "max_mmr": 4999}, - {"name": 'Champion', "min_mmr": 5000, "max_mmr": 999999} + {"name": "Unranked", "min_mmr": 0, "max_mmr": 0}, + {"name": "Copper 5", "min_mmr": 1, "max_mmr": 1199}, + {"name": "Copper 4", "min_mmr": 1200, "max_mmr": 1299}, + {"name": "Copper 3", "min_mmr": 1300, "max_mmr": 1399}, + {"name": "Copper 2", "min_mmr": 1400, "max_mmr": 1499}, + {"name": "Copper 1", "min_mmr": 1500, "max_mmr": 1599}, + {"name": "Bronze 5", "min_mmr": 1600, "max_mmr": 1699}, + {"name": "Bronze 4", "min_mmr": 1700, "max_mmr": 1799}, + {"name": "Bronze 3", "min_mmr": 1800, "max_mmr": 1899}, + {"name": "Bronze 2", "min_mmr": 1900, "max_mmr": 1999}, + {"name": "Bronze 1", "min_mmr": 2000, "max_mmr": 2099}, + {"name": "Silver 5", "min_mmr": 2100, "max_mmr": 2199}, + {"name": "Silver 4", "min_mmr": 2200, "max_mmr": 2299}, + {"name": "Silver 3", "min_mmr": 2300, "max_mmr": 2399}, + {"name": "Silver 2", "min_mmr": 2400, "max_mmr": 2499}, + {"name": "Silver 1", "min_mmr": 2500, "max_mmr": 2599}, + {"name": "Gold 3", "min_mmr": 2600, "max_mmr": 2799}, + {"name": "Gold 2", "min_mmr": 2800, "max_mmr": 2999}, + {"name": "Gold 1", "min_mmr": 3000, "max_mmr": 3199}, + {"name": "Platinum 3", "min_mmr": 3200, "max_mmr": 3599}, + {"name": "Platinum 2", "min_mmr": 3600, "max_mmr": 3999}, + {"name": "Platinum 1", "min_mmr": 4000, "max_mmr": 4399}, + {"name": "Diamond", "min_mmr": 4400, "max_mmr": 4999}, + {"name": "Champion", "min_mmr": 5000, "max_mmr": 999999} ] # Y6S3+ (#23+) ranks_v5 = [ - {"name": 'Unranked', "min_mmr": 0, "max_mmr": 0}, - {"name": 'Copper 5', "min_mmr": 1, "max_mmr": 1199}, - {"name": 'Copper 4', "min_mmr": 1200, "max_mmr": 1299}, - {"name": 'Copper 3', "min_mmr": 1300, "max_mmr": 1399}, - {"name": 'Copper 2', "min_mmr": 1400, "max_mmr": 1499}, - {"name": 'Copper 1', "min_mmr": 1500, "max_mmr": 1599}, - {"name": 'Bronze 5', "min_mmr": 1600, "max_mmr": 1699}, - {"name": 'Bronze 4', "min_mmr": 1700, "max_mmr": 1799}, - {"name": 'Bronze 3', "min_mmr": 1800, "max_mmr": 1899}, - {"name": 'Bronze 2', "min_mmr": 1900, "max_mmr": 1999}, - {"name": 'Bronze 1', "min_mmr": 2000, "max_mmr": 2099}, - {"name": 'Silver 5', "min_mmr": 2100, "max_mmr": 2199}, - {"name": 'Silver 4', "min_mmr": 2200, "max_mmr": 2299}, - {"name": 'Silver 3', "min_mmr": 2300, "max_mmr": 2399}, - {"name": 'Silver 2', "min_mmr": 2400, "max_mmr": 2499}, - {"name": 'Silver 1', "min_mmr": 2500, "max_mmr": 2599}, - {"name": 'Gold 3', "min_mmr": 2600, "max_mmr": 2799}, - {"name": 'Gold 2', "min_mmr": 2800, "max_mmr": 2999}, - {"name": 'Gold 1', "min_mmr": 3000, "max_mmr": 3199}, - {"name": 'Platinum 3', "min_mmr": 3200, "max_mmr": 3499}, - {"name": 'Platinum 2', "min_mmr": 3500, "max_mmr": 3799}, - {"name": 'Platinum 1', "min_mmr": 3800, "max_mmr": 4099}, - {"name": 'Diamond 3', "min_mmr": 4100, "max_mmr": 4399}, - {"name": 'Diamond 2', "min_mmr": 4400, "max_mmr": 4699}, - {"name": 'Diamond 1', "min_mmr": 4700, "max_mmr": 4999}, - {"name": 'Champions', "min_mmr": 5000, "max_mmr": 999999} + {"name": "Unranked", "min_mmr": 0, "max_mmr": 0}, + {"name": "Copper 5", "min_mmr": 1, "max_mmr": 1199}, + {"name": "Copper 4", "min_mmr": 1200, "max_mmr": 1299}, + {"name": "Copper 3", "min_mmr": 1300, "max_mmr": 1399}, + {"name": "Copper 2", "min_mmr": 1400, "max_mmr": 1499}, + {"name": "Copper 1", "min_mmr": 1500, "max_mmr": 1599}, + {"name": "Bronze 5", "min_mmr": 1600, "max_mmr": 1699}, + {"name": "Bronze 4", "min_mmr": 1700, "max_mmr": 1799}, + {"name": "Bronze 3", "min_mmr": 1800, "max_mmr": 1899}, + {"name": "Bronze 2", "min_mmr": 1900, "max_mmr": 1999}, + {"name": "Bronze 1", "min_mmr": 2000, "max_mmr": 2099}, + {"name": "Silver 5", "min_mmr": 2100, "max_mmr": 2199}, + {"name": "Silver 4", "min_mmr": 2200, "max_mmr": 2299}, + {"name": "Silver 3", "min_mmr": 2300, "max_mmr": 2399}, + {"name": "Silver 2", "min_mmr": 2400, "max_mmr": 2499}, + {"name": "Silver 1", "min_mmr": 2500, "max_mmr": 2599}, + {"name": "Gold 3", "min_mmr": 2600, "max_mmr": 2799}, + {"name": "Gold 2", "min_mmr": 2800, "max_mmr": 2999}, + {"name": "Gold 1", "min_mmr": 3000, "max_mmr": 3199}, + {"name": "Platinum 3", "min_mmr": 3200, "max_mmr": 3499}, + {"name": "Platinum 2", "min_mmr": 3500, "max_mmr": 3799}, + {"name": "Platinum 1", "min_mmr": 3800, "max_mmr": 4099}, + {"name": "Diamond 3", "min_mmr": 4100, "max_mmr": 4399}, + {"name": "Diamond 2", "min_mmr": 4400, "max_mmr": 4699}, + {"name": "Diamond 1", "min_mmr": 4700, "max_mmr": 4999}, + {"name": "Champions", "min_mmr": 5000, "max_mmr": 999999} ] From 6bb35fb4926b5046ea37a0ff97b2cb1bf3b4a89e Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:31:24 +0100 Subject: [PATCH 48/61] move PlatformURLNames --- siegeapi/platforms.py | 6 ------ siegeapi/player.py | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/siegeapi/platforms.py b/siegeapi/platforms.py index 9097888..5daeef7 100644 --- a/siegeapi/platforms.py +++ b/siegeapi/platforms.py @@ -4,9 +4,3 @@ class Platforms: XBOX = "xbl" PLAYSTATION = "psn" - -PlatformURLNames = { - "uplay": "OSBOR_PC_LNCH_A", - "psn": "OSBOR_PS4_LNCH_A", - "xbl": "OSBOR_XBOXONE_LNCH_A" -} diff --git a/siegeapi/player.py b/siegeapi/player.py index c6ae847..9b00a81 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -13,6 +13,12 @@ from .constants import * import aiohttp +PlatformURLNames = { + "uplay": "OSBOR_PC_LNCH_A", + "psn": "OSBOR_PS4_LNCH_A", + "xbl": "OSBOR_XBOXONE_LNCH_A" +} + class UrlBuilder: def __init__(self, spaceid, platform_url, player_ids): From e0fae746c716f5d025947a3a36c954c461ff49a2 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:32:25 +0100 Subject: [PATCH 49/61] update typings --- siegeapi/player.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 9b00a81..d68d3a2 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -1,5 +1,4 @@ from __future__ import annotations -from typing import List from .platforms import PlatformURLNames from .exceptions import InvalidRequest @@ -21,7 +20,7 @@ class UrlBuilder: - def __init__(self, spaceid, platform_url, player_ids): + def __init__(self, spaceid: str, platform_url: str, player_id: str): self.spaceid: str = spaceid self.platform_url: str = platform_url self.player_ids: List[str] = player_ids From 78f26c18c95b15b170e3dc5e36d4d46141c8a63d Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:32:59 +0100 Subject: [PATCH 50/61] remove unnecessary argument --- siegeapi/ranks.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/siegeapi/ranks.py b/siegeapi/ranks.py index 4aa5b99..43e03c9 100644 --- a/siegeapi/ranks.py +++ b/siegeapi/ranks.py @@ -27,7 +27,7 @@ def _get_rank_from_mmr(mmr: int | float, season: int = -1) -> Tuple[str, int, in class Rank: - def __init__(self, data, rank_definitions): + def __init__(self, data): self.kills: int = data.get("kills", 0) self.deaths: int = data.get("deaths", 0) self.last_mmr_change: int = int(data.get("last_match_mmr_change", 0)) @@ -39,9 +39,10 @@ def __init__(self, data, rank_definitions): self.losses: int = data.get("losses", 0) self.rank_id: int = data.get("rank") self.season: int = data.get("season", -1) - self.rank: str = rank_definitions[self.rank_id]["name"] + _rank_definitions = _get_rank_constants(self.season) + self.rank: str = _rank_definitions[self.rank_id]["name"] self.max_rank_id: int = data.get("max_rank") - self.max_rank: str = rank_definitions[self.max_rank_id]["name"] + self.max_rank: str = _rank_definitions[self.max_rank_id]["name"] self.region: str = data.get("region") self.abandons: int = data.get("abandons", 0) self.skill_mean: float = data.get("skill_mean", 0) From 8274aa6f3973c408c0ef182f948c6959901bcba6 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:33:16 +0100 Subject: [PATCH 51/61] remove weapon types --- siegeapi/weapon_types.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 siegeapi/weapon_types.py diff --git a/siegeapi/weapon_types.py b/siegeapi/weapon_types.py deleted file mode 100644 index 1b31d2d..0000000 --- a/siegeapi/weapon_types.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import annotations -from typing import Callable - - -class WeaponTypes: - """ Weapon Types """ - ASSAULT_RIFLE: int = 1 - SUBMACHINE_GUN: int = 2 - LIGHT_MACHINE_GUN: int = 3 - MARKSMAN_RIFLE: int = 4 - HANDGUN: int = 5 - SHOTGUN: int = 6 - MACHINE_PISTOL: int = 7 - - -WeaponNames = { - 1: "Assault Rifle", - 2: "Submachine Gun", - 3: "Light Machine Gun", - 4: "Marksman Rifle", - 5: "Handgun", - 6: "Shotgun", - 7: "Machine Pistol" -} - - -class WeaponType: - def __init__(self, weapon_type, stats=None): - self.type = weapon_type - self.name = WeaponNames.get(self.type, "Unknown") - - stat_name: Callable[[str], str] = lambda name: f"weapontypepvp_{name}:{self.type}:infinite" - stats = stats or {} - self.kills = stats.get(stat_name("kills"), 0) - self.headshots = stats.get(stat_name("headshot"), 0) - self.hits = stats.get(stat_name("bullethit"), 0) - self.shots = stats.get(stat_name("bulletfired"), 0) - - def get_dict(self) -> dict[str: str | int]: - return vars(self) From e76e4fa026413dccefd2dd5d9241e506711aa50b Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:33:23 +0100 Subject: [PATCH 52/61] remove platforms --- siegeapi/platforms.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 siegeapi/platforms.py diff --git a/siegeapi/platforms.py b/siegeapi/platforms.py deleted file mode 100644 index 5daeef7..0000000 --- a/siegeapi/platforms.py +++ /dev/null @@ -1,6 +0,0 @@ - -class Platforms: - UPLAY = "uplay" - XBOX = "xbl" - PLAYSTATION = "psn" - From da986701b47e705e4df588eca788bba518bec548 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:33:49 +0100 Subject: [PATCH 53/61] remove stat names & app ids --- siegeapi/constants/__init__.py | 2 - siegeapi/constants/app_ids.py | 10 ---- siegeapi/constants/stat_names.py | 97 -------------------------------- 3 files changed, 109 deletions(-) delete mode 100644 siegeapi/constants/app_ids.py delete mode 100644 siegeapi/constants/stat_names.py diff --git a/siegeapi/constants/__init__.py b/siegeapi/constants/__init__.py index 3e2b2a9..9cd787c 100644 --- a/siegeapi/constants/__init__.py +++ b/siegeapi/constants/__init__.py @@ -1,5 +1,3 @@ -from .stat_names import * from .seasons import seasons from .operators import operator_dict -from .app_ids import SIEGE_APP_IDS from .weapons import WEAPONS_DICT diff --git a/siegeapi/constants/app_ids.py b/siegeapi/constants/app_ids.py deleted file mode 100644 index 6624c9e..0000000 --- a/siegeapi/constants/app_ids.py +++ /dev/null @@ -1,10 +0,0 @@ -SIEGE_APP_IDS = [ - "8956241d-236d-4dbd-9e1e-bf6ed133773a", # PC (China) - "e3d5ea9e-50bd-43b7-88bf-39794f4e3d40", # PC - "a427a342-56bb-437b-b835-fa695c75893b", # PC TS - "fb4cc4c9-2063-461d-a1e8-84a7d36525fc", # PS4 - "6e3c99c9-6c3f-43f4-b4f6-f1a3143f2764", # PS5 - "e0aa997a-1626-4e5b-8215-b5f586b59fa2", # Stadia - "76f580d5-7f50-47cc-bbc1-152d000bfe59", # XBOX Series X - "4008612d-3baf-49e4-957a-33066726a7bc", # XBOX One -] diff --git a/siegeapi/constants/stat_names.py b/siegeapi/constants/stat_names.py deleted file mode 100644 index 9dd78fd..0000000 --- a/siegeapi/constants/stat_names.py +++ /dev/null @@ -1,97 +0,0 @@ -GENERAL_URL_STATS = [ - "generalpvp_timeplayed", - "generalpvp_matchplayed", - "generalpvp_matchwon", - "generalpvp_matchlost", - "generalpvp_kills", - "generalpvp_death", - "generalpvp_bullethit", - "generalpvp_bulletfired", - "generalpvp_killassists", - "generalpvp_revive", - "generalpvp_headshot", - "generalpvp_penetrationkills", - "generalpvp_meleekills", - "generalpvp_dbnoassists", - "generalpvp_suicide", - "generalpvp_barricadedeployed", - "generalpvp_reinforcementdeploy", - "generalpvp_totalxp", - "generalpvp_rappelbreach", - "generalpvp_distancetravelled", - "generalpvp_revivedenied", - "generalpvp_dbno", - "generalpvp_gadgetdestroy", - "generalpvp_blindkills" -] - -RANKED_CASUAL_THUNT_URL_STATS = [ - "casualpvp_matchwon", - "casualpvp_matchlost", - "casualpvp_timeplayed", - "casualpvp_matchplayed", - "casualpvp_kills", - "casualpvp_death", - "rankedpvp_matchwon", - "rankedpvp_matchlost", - "rankedpvp_timeplayed", - "rankedpvp_matchplayed", - "rankedpvp_kills", - "rankedpvp_death", - - "generalpve_dbnoassists", - "generalpve_death", - "generalpve_revive", - "generalpve_matchwon", - "generalpve_suicide", - "generalpve_servershacked", - "generalpve_serverdefender", - "generalpve_barricadedeployed", - "generalpve_reinforcementdeploy", - "generalpve_kills", - "generalpve_hostagedefense", - "generalpve_bulletfired", - "generalpve_matchlost", - "generalpve_killassists", - "generalpve_totalxp", - "generalpve_hostagerescue", - "generalpve_penetrationkills", - "generalpve_meleekills", - "generalpve_rappelbreach", - "generalpve_distancetravelled", - "generalpve_matchplayed", - "generalpve_serveraggression", - "generalpve_timeplayed", - "generalpve_revivedenied", - "generalpve_dbno", - "generalpve_bullethit", - "generalpve_blindkills", - "generalpve_headshot", - "generalpve_gadgetdestroy", - "generalpve_accuracy" -] - -OPERATOR_URL_STATS = [ - "operatorpvp_kills", - "operatorpvp_death", - "operatorpvp_roundwon", - "operatorpvp_roundlost", - "operatorpvp_meleekills", - "operatorpvp_totalxp", - "operatorpvp_headshot", - "operatorpvp_timeplayed", - "operatorpvp_dbno" -] - -PLAYTIME_URL_STATS = [ - "PPvPTimePlayed", - "PPvETimePlayed", - "PTotalTimePlayed" -] - -WEAPON_TYPE_STATS = [ - "weapontypepvp_kills", - "weapontypepvp_headshot", - "weapontypepvp_bulletfired", - "weapontypepvp_bullethit" -] From 2f3d822c327ca15ea9c6789345925dcb0687cd9a Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:34:33 +0100 Subject: [PATCH 54/61] update gamemode for new endpoint --- siegeapi/gamemode.py | 95 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/siegeapi/gamemode.py b/siegeapi/gamemode.py index 94790f2..5ff6482 100644 --- a/siegeapi/gamemode.py +++ b/siegeapi/gamemode.py @@ -1,50 +1,55 @@ +from __future__ import annotations + class Gamemode: - """ Contains information about a specific game queue """ - def __init__(self, name, stats=None): - self.name = name + def __init__(self, data: dict): + data = data.get("teamRoles", {}).get("all", [])[0] + self.matches_played: int = data.get("matchesPlayed") + self.rounds_played: int = data.get("roundsPlayed") + self.minutes_played: int = data.get("minutesPlayed") + self.matches_won: int = data.get("matchesWon") + self.matches_lost: int = data.get("matchesLost") + self.rounds_won: int = data.get("roundsWon") + self.rounds_lost: int = data.get("roundsLost") + self.kills: int = data.get("kills") + self.assists: int = data.get("assists") + self.death: int = data.get("death") + self.headshots: int = data.get("headshots") + self.melee_kills: int = data.get("meleeKills") + self.team_kills: int = data.get("teamKills") + self.opening_kills: int = data.get("openingKills") + self.opening_deaths: int = data.get("openingDeaths") + self.trades: int = data.get("trades") + self.opening_kill_trades: int = data.get("openingKillTrades") + self.opening_death_trades: int = data.get("openingDeathTrades") + self.revives: int = data.get("revives") + self.distance_travelled: int = data.get("distanceTravelled") + self.win_loss_ratio: float = data.get("winLossRatio") + self.kill_death_ratio: float = round((data.get("killDeathRatio").get("value") * 100), 2) + self.headshot_accuracy: float = round((data.get("headshotAccuracy").get("value") * 100), 2) + self.kills_per_round: float = round((data.get("killsPerRound").get("value") * 100), 2) + self.rounds_with_a_kill: float = round((data.get("roundsWithAKill").get("value") * 100), 2) + self.rounds_with_multi_kill: float = round((data.get("roundsWithMultiKill").get("value") * 100), 2) + self.rounds_with_opening_kill: float = round((data.get("roundsWithOpeningKill").get("value") * 100), 2) + self.rounds_with_opening_death: float = round((data.get("roundsWithOpeningDeath").get("value") * 100), 2) + self.rounds_with_kost: float = round((data.get("roundsWithKOST").get("value") * 100), 2) + self.rounds_survived: float = round((data.get("roundsSurvived").get("value") * 100), 2) + self.rounds_with_an_ace: float = round((data.get("roundsWithAnAce").get("value") * 100), 2) + self.rounds_with_clutch: float = round((data.get("roundsWithClutch").get("value") * 100), 2) + self.time_alive_per_match: float = data.get("timeAlivePerMatch") + self.time_dead_per_match: float = data.get("timeDeadPerMatch") + self.distance_per_round: float = data.get("distancePerRound") + + def __repr__(self) -> str: + return str(vars(self)) - if name == "ranked" or name == "casual": - statname = f"{name}pvp_" - stats = stats or {} - self.won = stats.get(f"{statname}matchwon", 0) - self.lost = stats.get(f"{statname}matchlost", 0) - self.time_played = stats.get(f"{statname}timeplayed", 0) - self.played = stats.get(f"{statname}matchplayed", 0) - self.kills = stats.get(f"{statname}kills", 0) - self.deaths = stats.get(f"{statname}death", 0) - else: - statname = "generalpve_" - self.deaths = stats.get(f"{statname}death", 0) - self.penetration_kills = stats.get(f"{statname}penetrationkills", 0) - self.matches_won = stats.get(f"{statname}matchwon", 0) - self.bullets_hit = stats.get(f"{statname}bullethit", 0) - self.melee_kills = stats.get(f"{statname}meleekills", 0) - self.bullets_fired = stats.get(f"{statname}bulletfired", 0) - self.matches_played = stats.get(f"{statname}matchplayed", 0) - self.kill_assists = stats.get(f"{statname}killassists", 0) - self.time_played = stats.get(f"{statname}timeplayed", 0) - self.revives = stats.get(f"{statname}revive", 0) - self.kills = stats.get(f"{statname}kills", 0) - self.headshots = stats.get(f"{statname}headshot", 0) - self.matches_lost = stats.get(f"{statname}matchlost", 0) - self.dbno_assists = stats.get(f"{statname}dbnoassists", 0) - self.suicides = stats.get(f"{statname}suicide", 0) - self.barricades_deployed = stats.get(f"{statname}barricadedeployed", 0) - self.reinforcements_deployed = stats.get(f"{statname}reinforcementdeploy", 0) - self.total_xp = stats.get(f"{statname}totalxp", 0) - self.rappel_breaches = stats.get(f"{statname}rappelbreach", 0) - self.distance_travelled = stats.get(f"{statname}distancetravelled", 0) - self.revives_denied = stats.get(f"{statname}revivedenied", 0) - self.dbnos = stats.get(f"{statname}dbno", 0) - self.gadgets_destroyed = stats.get(f"{statname}gadgetdestroy", 0) - self.areas_secured = stats.get(f"{statname}servershacked", 0) - self.areas_defended = stats.get(f"{statname}serverdefender", 0) - self.areas_contested = stats.get(f"{statname}serveraggression", 0) - self.hostages_rescued = stats.get(f"{statname}hostagerescue", 0) - self.hostages_defended = stats.get(f"{statname}hostagedefense", 0) - self.blind_kills = stats.get(f"{statname}blindkills", 0) +class Gamemodes: + def __init__(self, data: dict): + self.all: Gamemode = Gamemode(data.get("platforms").get("PC").get("gameModes").get("all", {})) + self.casual: Gamemode = Gamemode(data.get("platforms").get("PC").get("gameModes").get("casual", {})) + self.ranked: Gamemode = Gamemode(data.get("platforms").get("PC").get("gameModes").get("ranked", {})) + self.unranked: Gamemode = Gamemode(data.get("platforms").get("PC").get("gameModes").get("unranked", {})) - def get_dict(self) -> dict[str: int]: - return vars(self) + def __repr__(self) -> str: + return str(vars(self)) From 29c16989ccc47dfd594600fcb96c611114590a4b Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:34:45 +0100 Subject: [PATCH 55/61] update operators for the new endpoint --- siegeapi/operators.py | 96 +++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 27 deletions(-) diff --git a/siegeapi/operators.py b/siegeapi/operators.py index 977140b..f9e912f 100644 --- a/siegeapi/operators.py +++ b/siegeapi/operators.py @@ -3,32 +3,74 @@ from .constants import operator_dict -def _get_from_operators_const(name: str, what: str) -> str: - return operator_dict[name][what] +class Operator: + def __init__(self, data: dict): + self.name: str = data.get("statsDetail") + self.matches_played: int = data.get("matchesPlayed") + self.rounds_played: int = data.get("roundsPlayed") + self.minutes_played: int = data.get("minutesPlayed") + self.matches_won: int = data.get("matchesWon") + self.matches_lost: int = data.get("matchesLost") + self.rounds_won: int = data.get("roundsWon") + self.rounds_lost: int = data.get("roundsLost") + self.kills: int = data.get("kills") + self.assists: int = data.get("assists") + self.death: int = data.get("death") + self.headshots: int = data.get("headshots") + self.melee_kills: int = data.get("meleeKills") + self.team_kills: int = data.get("teamKills") + self.opening_kills: int = data.get("openingKills") + self.opening_deaths: int = data.get("openingDeaths") + self.trades: int = data.get("trades") + self.opening_kill_trades: int = data.get("openingKillTrades") + self.opening_death_trades: int = data.get("openingDeathTrades") + self.revives: int = data.get("revives") + self.distance_travelled: int = data.get("distanceTravelled") + self.win_loss_ratio: float = data.get("winLossRatio") + self.kill_death_ratio: float = round((data.get("killDeathRatio").get("value") * 100), 2) + self.headshot_accuracy: float = round((data.get("headshotAccuracy").get("value") * 100), 2) + self.kills_per_round: float = round((data.get("killsPerRound").get("value") * 100), 2) + self.rounds_with_a_kill: float = round((data.get("roundsWithAKill").get("value") * 100), 2) + self.rounds_with_multi_kill: float = round((data.get("roundsWithMultiKill").get("value") * 100), 2) + self.rounds_with_opening_kill: float = round((data.get("roundsWithOpeningKill").get("value") * 100), 2) + self.rounds_with_opening_death: float = round((data.get("roundsWithOpeningDeath").get("value") * 100), 2) + self.rounds_with_kost: float = round((data.get("roundsWithKOST").get("value") * 100), 2) + self.rounds_survived: float = round((data.get("roundsSurvived").get("value") * 100), 2) + self.rounds_with_an_ace: float = round((data.get("roundsWithAnAce").get("value") * 100), 2) + self.rounds_with_clutch: float = round((data.get("roundsWithClutch").get("value") * 100), 2) + self.time_alive_per_match: float = data.get("timeAlivePerMatch") + self.time_dead_per_match: float = data.get("timeDeadPerMatch") + self.distance_per_round: float = data.get("distancePerRound") + self.health: int = self._get_from_operators_const("health") + self.armor: int = self._get_from_operators_const("armor") + self.unit: int = self._get_from_operators_const("unit") + self.country_code: int = self._get_from_operators_const("country_code") + self.year_introduced: int = self._get_from_operators_const("year") + self.icon_url: int = self._get_from_operators_const("icon_url") -class Operator: - def __init__(self, name, stats=None, unique_stats=None): - self.name = name.lower() - self.readable = _get_from_operators_const(self.name, 'name') - - stats = stats or {} - self.wins = stats.get("roundwon", 0) - self.losses = stats.get("roundlost", 0) - self.kills = stats.get("kills", 0) - self.deaths = stats.get("death", 0) - self.headshots = stats.get("headshot", 0) - self.melees = stats.get("meleekills", 0) - self.dbnos = stats.get("dbno", 0) - self.xp = stats.get("totalxp", 0) - self.time_played = stats.get("timeplayed", 0) - self.atkdef = _get_from_operators_const(self.name, 'side') - self.icon = _get_from_operators_const(self.name, 'icon_url') - - if unique_stats is not None: - self.unique_stats = unique_stats - else: - self.unique_stats = {} - - def get_dict(self) -> dict[str: int | str]: - return vars(self) + def _get_from_operators_const(self, what: str) -> str | int | list: + return operator_dict.get(self.name.lower(), None).get(what, "Missing Data") + + def __repr__(self) -> str: + return str(vars(self)) + + +class OperatorsGameMode: + def __init__(self, data: dict): + self.attacker: list = [Operator(operator) for operator in data.get("teamRoles", {}).get("attacker", {})] + self.defender: list = [Operator(operator) for operator in data.get("teamRoles", {}).get("defender", {})] + + def __repr__(self) -> str: + return str(vars(self)) + + +class Operators: + def __init__(self, data: dict): + self.all: OperatorsGameMode = OperatorsGameMode(data.get("platforms").get("PC").get("gameModes").get("all", {})) + self.casual: OperatorsGameMode = OperatorsGameMode(data.get("platforms").get("PC").get("gameModes").get("casual", {})) + self.ranked: OperatorsGameMode = OperatorsGameMode(data.get("platforms").get("PC").get("gameModes").get("ranked", {})) + self.unranked: OperatorsGameMode = OperatorsGameMode(data.get("platforms").get("PC").get("gameModes").get("unranked", {})) + + def __repr__(self) -> str: + return str(vars(self)) From 1ecdc7b350a0743836868c69dd1cb5dba9122796 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:34:56 +0100 Subject: [PATCH 56/61] remove platforms --- siegeapi/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/siegeapi/__init__.py b/siegeapi/__init__.py index c9cae22..1f7240c 100644 --- a/siegeapi/__init__.py +++ b/siegeapi/__init__.py @@ -1,2 +1 @@ from .auth import Auth -from .platforms import Platforms From cd7c2d8cdee5ec148fdd3f6e3d976fc4b3964991 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:35:05 +0100 Subject: [PATCH 57/61] add maps --- siegeapi/maps.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 siegeapi/maps.py diff --git a/siegeapi/maps.py b/siegeapi/maps.py new file mode 100644 index 0000000..bfc6729 --- /dev/null +++ b/siegeapi/maps.py @@ -0,0 +1,62 @@ +from __future__ import annotations + + +class Map: + def __init__(self, data: dict): + self.map_name: str = data.get("statsDetail") + self.matches_played: int = data.get("matchesPlayed") + self.rounds_played: int = data.get("roundsPlayed") + self.minutes_played: int = data.get("minutesPlayed") + self.matches_won: int = data.get("matchesWon") + self.matches_lost: int = data.get("matchesLost") + self.rounds_won: int = data.get("roundsWon") + self.rounds_lost: int = data.get("roundsLost") + self.kills: int = data.get("kills") + self.assists: int = data.get("assists") + self.death: int = data.get("death") + self.headshots: int = data.get("headshots") + self.melee_kills: int = data.get("meleeKills") + self.team_kills: int = data.get("teamKills") + self.opening_kills: int = data.get("openingKills") + self.opening_deaths: int = data.get("openingDeaths") + self.trades: int = data.get("trades") + self.opening_kill_trades: int = data.get("openingKillTrades") + self.opening_death_trades: int = data.get("openingDeathTrades") + self.revives: int = data.get("revives") + self.distance_travelled: int = data.get("distanceTravelled") + self.win_loss_ratio: float = data.get("winLossRatio") + self.kill_death_ratio: float = round((data.get("killDeathRatio").get("value") * 100), 2) + self.headshot_accuracy: float = round((data.get("headshotAccuracy").get("value") * 100), 2) + self.kills_per_round: float = round((data.get("killsPerRound").get("value") * 100), 2) + self.rounds_with_a_kill: float = round((data.get("roundsWithAKill").get("value") * 100), 2) + self.rounds_with_multi_kill: float = round((data.get("roundsWithMultiKill").get("value") * 100), 2) + self.rounds_with_opening_kill: float = round((data.get("roundsWithOpeningKill").get("value") * 100), 2) + self.rounds_with_opening_death: float = round((data.get("roundsWithOpeningDeath").get("value") * 100), 2) + self.rounds_with_kost: float = round((data.get("roundsWithKOST").get("value") * 100), 2) + self.rounds_survived: float = round((data.get("roundsSurvived").get("value") * 100), 2) + self.rounds_with_an_ace: float = round((data.get("roundsWithAnAce").get("value") * 100), 2) + self.rounds_with_clutch: float = round((data.get("roundsWithClutch").get("value") * 100), 2) + self.time_alive_per_match: float = data.get("timeAlivePerMatch") + self.time_dead_per_match: float = data.get("timeDeadPerMatch") + self.distance_per_round: float = data.get("distancePerRound") + + def __repr__(self) -> str: + return str(vars(self)) + + +class MapRoles: + def __init__(self, data: dict): + self.all: list = [Map(map_) for map_ in data.get("teamRoles", {}).get("all", [])] + self.attacker: list = [Map(map_) for map_ in data.get("teamRoles", {}).get("attacker", [])] + self.defender: list = [Map(map_) for map_ in data.get("teamRoles", {}).get("defender", [])] + + +class Maps: + def __init__(self, data: dict): + self.all: MapRoles = MapRoles(data.get("platforms").get("PC").get("gameModes").get("all", {})) + self.casual: MapRoles = MapRoles(data.get("platforms").get("PC").get("gameModes").get("casual", {})) + self.ranked: MapRoles = MapRoles(data.get("platforms").get("PC").get("gameModes").get("ranked", {})) + self.unranked: MapRoles = MapRoles(data.get("platforms").get("PC").get("gameModes").get("unranked", {})) + + def __repr__(self) -> str: + return str(vars(self)) From aa24754852af9c113d9af1f920b80b10ae3c5c43 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:35:21 +0100 Subject: [PATCH 58/61] rework basically everything --- siegeapi/player.py | 444 +++++++++++++-------------------------------- 1 file changed, 128 insertions(+), 316 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index d68d3a2..2611036 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -1,15 +1,14 @@ from __future__ import annotations -from .platforms import PlatformURLNames from .exceptions import InvalidRequest -from .ranks import Rank, _get_rank_constants -from .gamemode import Gamemode -from .weapon_types import WeaponType -from .operators import Operator +from .ranks import Rank +from .gamemode import Gamemodes +from .operators import Operators from .trends import Trends, TrendBlockDuration from .weapons import Weapons +from .maps import Maps -from .constants import * +from datetime import date import aiohttp PlatformURLNames = { @@ -23,103 +22,78 @@ class UrlBuilder: def __init__(self, spaceid: str, platform_url: str, player_id: str): self.spaceid: str = spaceid self.platform_url: str = platform_url - self.player_ids: List[str] = player_ids + self.player_id: str = player_id + self.siege_release: str = "20151201" + self.today: str = date.today().strftime("%Y%m%d") - def fetch_statistic_url(self, statistics: list) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ - f"populations={self.player_ids}&statistics={','.join(statistics)}" - - def create_level_url(self) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/r6playerprofile/" \ - f"playerprofile/progressions?profile_ids={self.player_ids}" - - def create_rank_url(self, region, season) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/r6karma/players?" \ - f"board_id=pvp_ranked&profile_ids={self.player_ids}®ion_id={region}&season_id={season}" - - def create_casual_url(self, region, season) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/r6karma/players?" \ - f"board_id=pvp_casual&profile_ids={self.player_ids}®ion_id={region}&season_id={season}" - - def create_operator_url(self, statistics: list) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ - f"populations={self.player_ids}&statistics={','.join(statistics)}" - - def create_weapon_type_url(self, statistics: list) -> str: - return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/playerstats2/statistics?" \ - f"populations={self.player_ids}&statistics={','.join(statistics)}" - - def create_playtime_url(self, statistics) -> str: + def playtime(self) -> str: return f"https://public-ubiservices.ubi.com/v1/profiles/stats?" \ - f"profileIds={self.player_ids}&spaceId={self.spaceid}&statNames={','.join(statistics)}" - - def create_level_only_url(self) -> str: - return f"https://public-ubiservices.ubi.com/v1/profiles/{self.player_ids}/stats/PClearanceLevel?spaceId={self.spaceid}" - - def create_trends_url(self, block_duration: TrendBlockDuration) -> str: - return f"https://r6s-stats.ubisoft.com/v1/current/trend/{self.player_ids}?" \ - f"gameMode=all,ranked,casual,unranked&teamRole=all,attacker,defender&trendType={block_duration}" - - def create_online_status_url(self) -> str: - return f"https://public-ubiservices.ubi.com/v1/users/onlineStatuses?UserIds={self.player_ids}" - - def create_weapons_url(self) -> str: - return f"https://r6s-stats.ubisoft.com/v1/current/weapons/{self.player_ids}?" \ - f"gameMode=all,ranked,casual,unranked&platform=PC&teamRole=all" - - -class PlayerBatch: - """ Accumulates requests for multiple players' stats in to a single request, saving time """ - - def __init__(self, players): - self.players = players - self.player_ids = [player_id for player_id in players] - self._player_objs = [players[player_id] for player_id in players] + f"profileIds={self.player_id}" \ + f"&spaceId={self.spaceid}" \ + f"&statNames=PPvPTimePlayed,PPvETimePlayed,PTotalTimePlayed" - if len(players) == 0: - raise ValueError("batch must contain at least one player") - - def __iter__(self): - return iter(self._player_objs) - - def __getitem__(self, name): - return self.players[name] - - def __getattr__(self, name): - root_player = self.players[self.player_ids[0]] - root_method = getattr(root_player, name) - - async def _proxy(*args, **kwargs): - results = {} - - # temporarily override url builder so we get data for all players - root_player.url_builder.player_ids = ",".join(self.player_ids) - - root_result = await root_method(*args, **kwargs) - results[root_player.id] = root_result - - for player_id in self.players: - if player_id != root_player.id: - results[player_id] = await getattr(self.players[player_id], name)(*args, **kwargs) - - # reset root player url builder to default state - root_player.url_builder.player_ids = root_player.id - - return results - - return _proxy + def level_xp_alphapack(self) -> str: + return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/sandboxes/{self.platform_url}/r6playerprofile/" \ + f"playerprofile/progressions?profile_ids={self.player_id}" + + def boards(self, season: int, board_id: str, region: str) -> str: + return f"https://public-ubiservices.ubi.com/v1/spaces/{self.spaceid}/" \ + f"sandboxes/{self.platform_url}/r6karma/players?" \ + f"board_id=pvp_{board_id}" \ + f"&profile_ids={self.player_id}" \ + f"®ion_id={region}" \ + f"&season_id={season}" + + def trends(self, block_duration: TrendBlockDuration = TrendBlockDuration.WEEKLY, start_date: str = None, end_date: str = None) -> str: + return f"https://r6s-stats.ubisoft.com/v1/current/trend/{self.player_id}?" \ + f"gameMode=all,ranked,casual,unranked" \ + f"&teamRole=all,attacker,defender" \ + f"&trendType={block_duration}" \ + f"&startDate={start_date or self.siege_release}" \ + f"&endDate={end_date or self.today}" + + def weapons(self, start_date: str = None, end_date: str = None) -> str: + return f"https://r6s-stats.ubisoft.com/v1/current/weapons/{self.player_id}?" \ + f"gameMode=all,ranked,casual,unranked" \ + f"&platform=PC" \ + f"&teamRole=all" \ + f"&startDate={start_date or self.siege_release}" \ + f"&endDate={end_date or self.today}" + + def operators(self, start_date: str = None, end_date: str = None): + return f"https://r6s-stats.ubisoft.com/v1/current/operators/{self.player_id}?" \ + f"gameMode=all,ranked,casual,unranked" \ + f"&platform=PC" \ + f"&teamRole=attacker,defender" \ + f"&startDate={start_date or self.siege_release}" \ + f"&endDate={end_date or self.today}" + + def gamemodes(self, start_date: str = None, end_date: str = None): + return f"https://r6s-stats.ubisoft.com/v1/current/summary/{self.player_id}?" \ + f"gameMode=all,ranked,unranked,casual" \ + f"&platform=PC" \ + f"&startDate={start_date or self.siege_release}" \ + f"&endDate={end_date or self.today}" + + def maps(self, start_date: str = None, end_date: str = None): + return f"https://r6s-stats.ubisoft.com/v1/current/maps/{self.player_id}?" \ + f"gameMode=all,ranked,casual,unranked" \ + f"&platform=PC" \ + f"&teamRole=all,attacker,defender" \ + f"&startDate={start_date or self.siege_release}" \ + f"&endDate={end_date or self.today}" class Player: def __init__(self, auth: aiohttp.ClientSession(), data: dict): - self.auth: aiohttp.ClientSession() = auth self.id: str = data.get("profileId") - self.userid: str = data.get("userId") - self.platform: str = data.get("platformType") - self.platform_url: str = PlatformURLNames[self.platform] - self.spaceid: str = self.auth.spaceids[self.platform] - self.url_builder: UrlBuilder = UrlBuilder(self.spaceid, self.platform_url, self.id) + + self._auth: aiohttp.ClientSession() = auth + self._platform: str = data.get("platformType") + self._platform_url: str = PlatformURLNames[self._platform] + self._spaceid: str = self._auth.spaceids[self._platform] + self._url_builder: UrlBuilder = UrlBuilder(self._spaceid, self._platform_url, self.id) self.profile_pic_url_146: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_146_146.png" self.profile_pic_url_256: str = f"https://ubisoft-avatars.akamaized.net/{self.id}/default_256_256.png" @@ -128,249 +102,87 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.name: str = data.get("nameOnPlatform") self.level: int = 0 - self.alpha_pack: int = 0 - self.deaths: int = 0 - self.penetration_kills: int = 0 - self.matches_won: int = 0 - self.bullets_hit: int = 0 - self.melee_kills: int = 0 - self.matches_played: int = 0 - self.kill_assists: int = 0 - self.time_played: int = 0 + self.alpha_pack: float = 0 + self.xp: int = 0 + + self.total_time_played: int = 0 self.pvp_time_played: int = 0 self.pve_time_played: int = 0 - self._not_updated_time_played: int = 0 - self.revives: int = 0 - self.kills: int = 0 - self.headshots: int = 0 - self.matches_lost: int = 0 - self.dbno_assists: int = 0 - self.suicides: int = 0 - self.barricades_deployed: int = 0 - self.reinforcements_deployed: int = 0 - self.total_xp: int = 0 - self.rappel_breaches: int = 0 - self.distance_travelled: int = 0 - self.revives_denied: int = 0 - self.dbnos: int = 0 - self.gadgets_destroyed: int = 0 - self.blind_kills: int = 0 self.ranks: dict = {} self.casuals: dict = {} - self.operators: dict = {} - self.weapon_types: list = [] - self.weapons: Weapons | None = None - - self.casual: Gamemode | None = None - self.ranked: Gamemode | None = None - self.thunt: Gamemode | None = None + self.newcomers: dict = {} + self.events: dict = {} + self.weapons: Weapons | None = None self.trends: Trends | None = None + self.operators: Operators | None = None + self.gamemodes: Gamemodes | None = None + self.maps: Maps | None = None - async def load_weapons(self) -> Weapons: - self.weapons = Weapons(await self.auth.get(self.url_builder.create_weapons_url())) - return self.weapons - - async def _fetch_statistics(self, statistics: list) -> dict[str: str | int | float]: - - data = await self.auth.get(self.url_builder.fetch_statistic_url(statistics)) - - if "results" not in data or self.id not in data["results"]: - raise InvalidRequest(f"Missing results key in returned JSON object {str(data)}") - - data = data["results"][self.id] - stats = {} - - for x in data: - statistic = x.split(":")[0] - if statistic in statistics: - stats[statistic] = data[x] - return stats - - async def is_currently_online(self) -> dict[str: bool | str]: - """Checks if the user is currently in game and if the user is 'online' / 'away' / 'dnd'""" - data = await self.auth.get(self.url_builder.create_online_status_url()) - statuses = data["onlineStatuses"][0] - - for connection in statuses["connections"]: - if connection["applicationId"] in SIEGE_APP_IDS: - return {"in_game": True, "status": statuses["onlineStatus"]} - return {"in_game": False, "status": statuses["onlineStatus"]} - - async def load_general(self) -> None: - """ Loads players' general stats """ - - stats = await self._fetch_statistics(GENERAL_URL_STATS) - - statname: str = "generalpvp_" - self.deaths = stats.get(f"{statname}death", 0) - self.penetration_kills = stats.get(f"{statname}penetrationkills", 0) - self.matches_won = stats.get(f"{statname}matchwon", 0) - self.bullets_hit = stats.get(f"{statname}bullethit", 0) - self.melee_kills = stats.get(f"{statname}meleekills", 0) - self.matches_played = stats.get(f"{statname}matchplayed", 0) - self.kill_assists = stats.get(f"{statname}killassists", 0) - self._not_updated_time_played = stats.get(f"{statname}timeplayed", 0) - self.revives = stats.get(f"{statname}revive", 0) - self.kills = stats.get(f"{statname}kills", 0) - self.headshots = stats.get(f"{statname}headshot", 0) - self.matches_lost = stats.get(f"{statname}matchlost", 0) - self.dbno_assists = stats.get(f"{statname}dbnoassists", 0) - self.suicides = stats.get(f"{statname}suicide", 0) - self.barricades_deployed = stats.get(f"{statname}barricadedeployed", 0) - self.reinforcements_deployed = stats.get(f"{statname}reinforcementdeploy", 0) - self.total_xp = stats.get(f"{statname}totalxp", 0) - self.rappel_breaches = stats.get(f"{statname}rappelbreach", 0) - self.distance_travelled = stats.get(f"{statname}distancetravelled", 0) - self.revives_denied = stats.get(f"{statname}revivedenied", 0) - self.dbnos = stats.get(f"{statname}dbno", 0) - self.gadgets_destroyed = stats.get(f"{statname}gadgetdestroy", 0) - self.blind_kills = stats.get(f"{statname}blindkills") - - async def load_trends(self, block_duration: TrendBlockDuration = TrendBlockDuration.WEEKLY) -> Trends: - self.trends = Trends(await self.auth.get(self.url_builder.create_trends_url(block_duration))) - return self.trends - - async def load_level(self) -> int: - data = await self.auth.get(self.url_builder.create_level_only_url()) - self.level = data["stats"]["PClearanceLevel"]["value"] - return self.level - - async def load_playtime(self) -> (int, int, int): - data = await self.auth.get(self.url_builder.create_playtime_url(PLAYTIME_URL_STATS)) - self.pvp_time_played = data['profiles'][0]['stats']["PPvPTimePlayed"]["value"] - self.pve_time_played = data['profiles'][0]['stats']["PPvETimePlayed"]["value"] - self.time_played = data['profiles'][0]['stats']["PTotalTimePlayed"]["value"] - return self.pvp_time_played, self.pve_time_played, self.time_played - - async def load_alpha_pack(self) -> int: - data = await self.auth.get(self.url_builder.create_level_url()) - - if "player_profiles" in data and len(data["player_profiles"]) > 0: - self.alpha_pack = data["player_profiles"][0].get("lootbox_probability", 0) - else: - raise InvalidRequest(f"Missing key player_profiles in returned JSON object {str(data)}") - - return self.alpha_pack - - async def load_casual(self, region='emea', season=-1, data=None) -> Rank: - """ Loads the players' rank for this region and season """ + async def load_playtime(self) -> None: + data = await self._auth.get(self._url_builder.playtime()) + stats = data.get("profiles", [])[0].get("stats", {}) - if not data: - data = await self.auth.get(self.url_builder.create_casual_url(region, season)) + self.pvp_time_played = int(stats.get("PPvPTimePlayed", {}).get("value", 0)) + self.pve_time_played = int(stats.get("PPvETimePlayed", {}).get("value", 0)) + self.total_time_played = int(stats.get("PTotalTimePlayed", {}).get("value", 0)) - if season < 0: - season = len(seasons) + season + async def load_progress(self) -> None: + data = await self._auth.get(self._url_builder.level_xp_alphapack()) - rank_definitions = _get_rank_constants(season) + self.xp = int(data.get("player_profiles", [])[0].get("xp", 0)) + self.alpha_pack = int(data.get("player_profiles", [])[0].get("lootbox_probability", 0)) / 100 + self.level = int(data.get("player_profiles", [])[0].get("level", 0)) - if "players" in data and self.id in data["players"]: - regionkey = f"{region}:{season}" - self.casuals[regionkey] = Rank(data["players"][self.id], rank_definitions) - return self.casuals[regionkey] - else: - raise InvalidRequest(f"Missing players key in returned JSON object {str(data)}") + async def load_ranked(self, season: int = -1, region: str = "emea") -> Rank: + data = await self._auth.get(self._url_builder.boards(season, "ranked", region)) + if data["players"] == {}: + raise InvalidRequest(f"There is no such data for the given combination of season ({season}) and region ({region})") - async def load_rank(self, region='emea', season=-1, data=None) -> Rank: - """ Loads the players rank for the given and season """ + self.ranks[f"{region}:{season}"] = Rank(data["players"][self.id]) + return self.ranks[f"{region}:{season}"] - if not data: - data = await self.auth.get(self.url_builder.create_rank_url(region, season)) + async def load_casual(self, season: int = -1, region: str = "emea") -> Rank: + data = await self._auth.get(self._url_builder.boards(season, "casual", region)) + if data["players"] == {}: + raise InvalidRequest(f"There is no such data for the given combination of season ({season}) and region ({region})") - if season < 0: - season = len(seasons) + season + self.casuals[f"{region}:{season}"] = Rank(data["players"][self.id]) + return self.casuals[f"{region}:{season}"] - rank_definitions = _get_rank_constants(season) + async def load_newcomer(self, season: int = -1, region: str = "emea") -> Rank: + data = await self._auth.get(self._url_builder.boards(season, "newcomer", region)) + if data["players"] == {}: + raise InvalidRequest(f"There is no such data for the given combination of season ({season}) and region ({region})") - if "players" in data and self.id in data["players"]: - regionkey = f"{region}:{season}" - self.ranks[regionkey] = Rank(data["players"][self.id], rank_definitions) - return self.ranks[regionkey] - else: - raise InvalidRequest(f"Missing players key in returned JSON object {str(data)}") + self.newcomers[f"{region}:{season}"] = Rank(data["players"][self.id]) + return self.newcomers[f"{region}:{season}"] - async def load_gamemodes(self) -> (Gamemode, Gamemode, Gamemode): - """ Loads the totals for players' ranked, casual and thunt gamemodes """ - stats = await self._fetch_statistics(RANKED_CASUAL_THUNT_URL_STATS) - self.ranked = Gamemode("ranked", stats) - self.casual = Gamemode("casual", stats) - self.thunt = Gamemode("terrohunt", stats) - return self.ranked, self.casual, self.thunt + async def load_events(self, season: int = -1, region: str = "emea") -> Rank: + data = await self._auth.get(self._url_builder.boards(season, "event", region)) + if data["players"] == {}: + raise InvalidRequest(f"There is no such data for the given combination of season ({season}) and region ({region})") - async def load_weapon_types(self, data=None) -> List[WeaponType]: - """ Load the players' weapon type stats """ + self.events[f"{region}:{season}"] = Rank(data["players"][self.id]) + return self.events[f"{region}:{season}"] - if not data: - data = await self.auth.get(self.url_builder.create_weapon_type_url(WEAPON_TYPE_STATS)) - - if "results" not in data or self.id not in data["results"]: - raise InvalidRequest(f"Missing key results in returned JSON object {str(data)}") - - data = data["results"][self.id] - self.weapon_types = [WeaponType(i, data) for i in range(1, 8)] - return self.weapon_types - - async def load_operators(self) -> dict[str: Operator]: - # ask the api for all the basic stat names WITHOUT a postfix to ask for all (I assume) - statistics = list(OPERATOR_URL_STATS) - - # also add in all the unique - for op in operator_dict: - for ability in operator_dict[op]["unique_stats"]: - statistics.append(f"{ability['id']}:{operator_dict[op]['id']}:infinite") - - data = await self.auth.get(self.url_builder.create_operator_url(statistics)) - - if "results" not in data or self.id not in data["results"]: - raise InvalidRequest(f"Missing results key in returned JSON object {str(data)}") - - data = data["results"][self.id] - - processed_data = self._process_data(data, operator_dict) + async def load_trends(self, block_duration: TrendBlockDuration = TrendBlockDuration.WEEKLY) -> Trends: + self.trends = Trends(await self._auth.get(self._url_builder.trends(block_duration))) + return self.trends - for operator_name in operator_dict: - op = operator_dict[operator_name] - base_data = self._process_basic_data(processed_data, op) - unique_data = self._process_unique_data(data, op) - self.operators[operator_name] = Operator(op["safename"], base_data, unique_data) + async def load_weapons(self) -> Weapons: + self.weapons = Weapons(await self._auth.get(self._url_builder.weapons())) + return self.weapons + async def load_operators(self) -> Operators: + self.operators = Operators(await self._auth.get(self._url_builder.operators())) return self.operators - @staticmethod - def _process_data(data: dict[str: int], op_dict: dict[str: dict[str: str | int | List[str] | List[dict[str: str]]]]) -> dict[str: int]: - processed_data = {} - for opd in op_dict: - op = operator_dict[opd] - for stat in data: - stat_ed = stat.replace(":infinite", "") - if stat_ed.endswith(op["id"]): - # .replace() cuz Ubi throws in a rogue ':' once in a while.. - processed_data[f"{opd}_{stat_ed[12:-4]}".replace(':', '')] = data[stat] - return processed_data - - @staticmethod - def _process_basic_data(data: dict[str: int], operator: dict[str: str | int | List[str] | List[dict[str: str]]]) -> dict[str: int]: - basic_data = {} - for stat in data: - if stat.startswith(operator["safename"]): - basic_data[f"{stat[len(operator['safename']) + 1:]}"] = data[stat] - return basic_data - - @staticmethod - def _process_unique_data(data: dict[str: int], operator: dict[str: str | int | List[str] | List[dict[str: str]]]) -> dict[str: int]: - unique_data = {} - - for ability in operator["unique_stats"]: - # Currently hard-coded to only return PVP stats - match = f"{ability['id']}:{operator['id']}:infinite" - ab_name = ability["id"].replace("operatorpvp_", "") - - if match in data: - unique_data[ab_name] = {"value": data[match]} - else: - # the stupid API just doesn't return anything if we have zero of that stat - unique_data[ab_name] = {"value": 0} - unique_data[ab_name]["name"] = ability["name"] - - return unique_data + async def load_gamemodes(self) -> Gamemodes: + self.gamemodes = Gamemodes(await self._auth.get(self._url_builder.gamemodes())) + return self.gamemodes + + async def load_maps(self) -> Maps: + self.maps = Maps(await self._auth.get(self._url_builder.maps())) + return self.maps From 7f6c9d4f89cbcb9f49c16789510d56d1572a9b24 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 03:35:41 +0100 Subject: [PATCH 59/61] update example --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0325f5f..aeccb93 100644 --- a/README.md +++ b/README.md @@ -35,21 +35,23 @@ pip install siegeapi ## Quick example ```python -from siegeapi import Auth, Platforms +from siegeapi import Auth import asyncio async def sample(): auth = Auth("UBI_EMAIL", "UBI_PASSWORD") - player = await auth.get_player(uid="7e0f63df-a39b-44c5-8de0-d39a05926e77", platform=Platforms.UPLAY) + player = await auth.get_player(uid="7e0f63df-a39b-44c5-8de0-d39a05926e77") print(f"Name: {player.name}") print(f"Profile pic URL: {player.profile_pic_url}") - await player.load_level() - await player.load_alpha_pack() + await player.load_playtime() + print(f"Total Time Played: {player.total_time_played}") + await player.load_progress() print(f"Level: {player.level}") print(f"Alpha pack %: {player.alpha_pack}") + print(f"XP: {player.xp}") await auth.close() @@ -60,8 +62,9 @@ asyncio.get_event_loop().run_until_complete(sample()) ```text Name: CNDRD Profile pic URL: https://ubisoft-avatars.akamaized.net/7e0f63df-a39b-44c5-8de0-d39a05926e77/default_256_256.png -Level: 256 +Level: 261 Alpha pack %: 3250 +XP: 118420 ``` --- From a5336db827e31d361f9eb1676734be51afca6c5d Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 21:25:58 +0100 Subject: [PATCH 60/61] save a few lines --- siegeapi/player.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/siegeapi/player.py b/siegeapi/player.py index 2611036..3b8298d 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -11,11 +11,7 @@ from datetime import date import aiohttp -PlatformURLNames = { - "uplay": "OSBOR_PC_LNCH_A", - "psn": "OSBOR_PS4_LNCH_A", - "xbl": "OSBOR_XBOXONE_LNCH_A" -} +PlatformURLNames = {"uplay": "OSBOR_PC_LNCH_A", "psn": "OSBOR_PS4_LNCH_A", "xbl": "OSBOR_XBOXONE_LNCH_A"} class UrlBuilder: From de2a7372b12488e882001fa96d28de4addc584a1 Mon Sep 17 00:00:00 2001 From: CNDRD Date: Thu, 17 Mar 2022 21:26:55 +0100 Subject: [PATCH 61/61] add total_xp & xp_to_level_up --- siegeapi/player.py | 3 +++ siegeapi/utils.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 siegeapi/utils.py diff --git a/siegeapi/player.py b/siegeapi/player.py index 3b8298d..ba8b77f 100644 --- a/siegeapi/player.py +++ b/siegeapi/player.py @@ -1,6 +1,7 @@ from __future__ import annotations from .exceptions import InvalidRequest +from .utils import get_total_xp, get_xp_to_next_lvl from .ranks import Rank from .gamemode import Gamemodes from .operators import Operators @@ -100,6 +101,8 @@ def __init__(self, auth: aiohttp.ClientSession(), data: dict): self.level: int = 0 self.alpha_pack: float = 0 self.xp: int = 0 + self.total_xp: int = get_total_xp(self.level, self.xp) + self.xp_to_level_up: int = get_xp_to_next_lvl(self.level) - self.xp self.total_time_played: int = 0 self.pvp_time_played: int = 0 diff --git a/siegeapi/utils.py b/siegeapi/utils.py new file mode 100644 index 0000000..dcb3aff --- /dev/null +++ b/siegeapi/utils.py @@ -0,0 +1,39 @@ +def get_xp_to_next_lvl(lvl: int): + if lvl == 0: + return 500 + if lvl == 1: + return 1_500 + if lvl in (2, 3): + return 3_500 + if lvl in (4, 5): + return 4_000 + if lvl in (6, 7, 8): + return 4_500 + if lvl in (9, 10): + return 5_500 + if lvl in (11, 12, 13): + return 6_000 + if lvl in (14, 15, 16): + return 6_500 + if lvl in (17, 18, 19): + return 7_000 + if lvl in (20, 21, 22): + return 7_500 + if lvl in (23, 24, 25): + return 8_000 + if lvl in (26, 27, 28): + return 8_500 + if lvl in (29, 30, 31): + return 9_000 + if lvl in (32, 33, 34): + return 9_500 + if lvl in (35, 36, 37): + return 10_000 + return (lvl - 18) * 500 + + +def get_total_xp(lvl: int, current_xp: int): + total = 0 + for level in range(1, lvl): + total += _get_xp_to_next_lvl(level) + return total + current_xp