first commit
No files matched your search
@@ -0,0 +1,60 @@
|
||||
# Node
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnp/
|
||||
.pnp.js
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
coverage/
|
||||
|
||||
# pnpm (keep pnpm-lock.yaml)
|
||||
pnpm-debug.log*
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
venv/
|
||||
.venv/
|
||||
env/
|
||||
pip-wheel-metadata/
|
||||
*.egg-info/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# Secrets and keys
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
secrets.*
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
ehthumbs.db
|
||||
|
||||
# Misc caches
|
||||
.cache/
|
||||
.parcel-cache/
|
||||
@@ -0,0 +1,106 @@
|
||||
ALL EXCLUSIVE AND OG ITEMS THAT ARE SUPPOSED TO BE LABELED MYTHIC IN THE SKIN CHECK!
|
||||
Season 1 exclusives
|
||||
Season 2 Battle Pass exclusives
|
||||
Promotional exclusives (Samsung, Nintendo, PlayStation, Xbox, Twitch Prime, Intel, NVIDIA, etc.)
|
||||
Founder exclusives
|
||||
Tournament exclusives
|
||||
Creator/Search for Survivors exclusives
|
||||
Limited-time challenge exclusives
|
||||
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
OG Skins
|
||||
Renegade Raider
|
||||
Aerial Assault Trooper
|
||||
Black Knight
|
||||
Blue Squire
|
||||
Royale Knight
|
||||
Sparkle Specialist
|
||||
The Reaper
|
||||
Elite Agent
|
||||
Omega (fully upgraded)
|
||||
Purple Skull Trooper
|
||||
Pink Ghoul Trooper
|
||||
Exclusive Skins
|
||||
Galaxy
|
||||
IKONIK
|
||||
Glow
|
||||
Wonder
|
||||
Honor Guard
|
||||
Eon
|
||||
Dark Vertex
|
||||
Double Helix
|
||||
Neo Versa
|
||||
Royale Bomber
|
||||
Wildcat
|
||||
Stealth Reflex
|
||||
Reflex (original)
|
||||
Rogue Spider Knight
|
||||
Huntmaster Saber
|
||||
Surf Strider
|
||||
Blue Team Leader
|
||||
Blue Striker
|
||||
Carbon Commando
|
||||
Prodigy
|
||||
Cloud Striker
|
||||
Fixer
|
||||
Point Patroller
|
||||
Trailblazer
|
||||
OG Pickaxes
|
||||
Raider's Revenge
|
||||
Aerial Assault One
|
||||
AC/DC
|
||||
Trusty No. 2
|
||||
Party Animal
|
||||
OG / Exclusive Emotes
|
||||
Fresh
|
||||
Rambunctious
|
||||
Tidy
|
||||
Floss
|
||||
Take the L
|
||||
Orange Justice
|
||||
Ride the Pony
|
||||
Pony Up
|
||||
Scenario
|
||||
Evasive Maneuvers
|
||||
Widow's Pirouette
|
||||
Hot Marat
|
||||
Kiss the Cup
|
||||
Rare Banners
|
||||
Battle Bus Banner
|
||||
Alpha Tester Banner
|
||||
Founder's Banners
|
||||
Frostnite 128 Banner
|
||||
FNCS Champion Banners
|
||||
World Cup Finalist Banners
|
||||
Fall Skirmish Banner
|
||||
Summer Skirmish Banner
|
||||
Galaxy Banner
|
||||
IKONIK Banner
|
||||
Glow Banner
|
||||
Wonder Banner
|
||||
Honor Guard Banner
|
||||
EON Banner
|
||||
Dark Vertex Banner
|
||||
Double Helix Banner
|
||||
Neo Versa Banner
|
||||
Wildcat Banner
|
||||
Search for Survivors Creator Banners
|
||||
PewDiePie Banner
|
||||
VanossGaming Banner
|
||||
Muselk Banner
|
||||
Jesse Cox Banner
|
||||
Dhalucard Banner
|
||||
Folagor03 Banner
|
||||
Ionix_TV Banner
|
||||
JesusAVGN Banner
|
||||
OrkPod Banner
|
||||
Rare Emoticons
|
||||
Founder Emoticons
|
||||
Galaxy Emoticon
|
||||
IKONIK Emoticon
|
||||
Glow Emoticon
|
||||
Wonder Emoticon
|
||||
Honor Guard Emoticon
|
||||
Twitch Prime Emoticons
|
||||
Early Battle Pass Emoticons
|
||||
@@ -0,0 +1,178 @@
|
||||
FORTNITE OG / EXCLUSIVE / PROMOTIONAL / STW / CREATOR BANNER MASTER LIST
|
||||
|
||||
======================== YOUTUBER / CREATOR BANNERS
|
||||
======================== - PewDiePie Banner - VanossGaming Banner -
|
||||
Muselk Banner - Jesse Cox Banner - Dhalucard Banner - Folagor03 Banner -
|
||||
Ionix_TV Banner - JesusAVGN Banner - OrkPod Banner
|
||||
|
||||
======================== SAVE THE WORLD EXCLUSIVE BANNERS
|
||||
======================== - Founder’s Banner - Ultimate Founder’s
|
||||
Banner - Challenge the Horde Banner - Horde Bash Banner - Frostnite
|
||||
Banner - Frostnite 128 Banner - Hit the Road Banner - Endurance Banner -
|
||||
Mythic Storm King Banner - Survive the Storm Banner - Canny Valley
|
||||
Endurance Banner - Plankerton Endurance Banner - Stonewood Endurance
|
||||
Banner - Twine Peaks Endurance Banner
|
||||
|
||||
======================== OG SKINS ======================== - Renegade
|
||||
Raider - Aerial Assault Trooper - Black Knight - Blue Squire - Royale
|
||||
Knight - Sparkle Specialist - The Reaper - Elite Agent - Omega (Max
|
||||
Lights) - Carbide (Max Lights) - Purple Skull Trooper - Pink Ghoul
|
||||
Trooper
|
||||
|
||||
======================== EXCLUSIVE SKINS ======================== -
|
||||
Galaxy - IKONIK - Glow - Honor Guard - Wonder - EON - Dark Vertex -
|
||||
Double Helix - Neo Versa - Royale Bomber - Wildcat - Reflex - Stealth
|
||||
Reflex - Rogue Spider Knight - Huntmaster Saber - Blue Team Leader -
|
||||
Blue Striker - Carbon Commando - Prodigy - Cloud Striker - Fixer - Point
|
||||
Patroller - Trailblazer - Havoc - Rose Team Leader - Warpaint
|
||||
|
||||
======================== EXCLUSIVE PICKAXES ======================== -
|
||||
Raider’s Revenge - Aerial Assault One - Merry Mint Axe - Stellar Axe -
|
||||
Resonator - Razor Edge - Pinpoint - Angular Axe - Tenderizer - AC/DC -
|
||||
Trusty No. 2 - Party Animal
|
||||
|
||||
======================== EXCLUSIVE EMOTES ======================== -
|
||||
Scenario - Levitate - Pony Up - Ride The Pony - Fresh - Rambunctious -
|
||||
Tidy - Floss - Take The L - Orange Justice - Evasive Maneuvers - Widow’s
|
||||
Pirouette - Hot Marat - Kiss The Cup
|
||||
|
||||
======================== SAMSUNG GALAXY BUNDLE
|
||||
======================== - Galaxy - Galactic Disc - Stellar Axe -
|
||||
Discovery
|
||||
|
||||
======================== IKONIK BUNDLE ======================== -
|
||||
IKONIK - Scenario
|
||||
|
||||
======================== GLOW BUNDLE ======================== - Glow -
|
||||
Levitate
|
||||
|
||||
======================== EON BUNDLE ======================== - EON -
|
||||
Resonator - Aurora
|
||||
|
||||
======================== DARK VERTEX BUNDLE ======================== -
|
||||
Dark Vertex - Dark Deflector - Razor Edge - Dark Forerunner
|
||||
|
||||
======================== DOUBLE HELIX BUNDLE ======================== -
|
||||
Double Helix - Telemetry - Pinpoint - Rotor
|
||||
|
||||
======================== NEO VERSA BUNDLE ======================== - Neo
|
||||
Versa - Neo Phrenzy
|
||||
|
||||
======================== ROYALE BOMBER BUNDLE ======================== -
|
||||
Royale Bomber - Royale Air
|
||||
|
||||
======================== REFLEX BUNDLE ======================== -
|
||||
Reflex - Response Unit - Angular Axe - Pivot
|
||||
|
||||
======================== STEALTH REFLEX BUNDLE
|
||||
======================== - Stealth Reflex - Stealth Response Unit
|
||||
|
||||
======================== WILDCAT BUNDLE ======================== -
|
||||
Wildcat - Sleek Strike
|
||||
|
||||
======================== ROGUE SPIDER KNIGHT BUNDLE
|
||||
======================== - Rogue Spider Knight - Time Keeper
|
||||
|
||||
======================== FOUNDER EXCLUSIVES ======================== -
|
||||
Rose Team Leader - Warpaint - Pony Up - Founder’s Umbrella - Founder’s
|
||||
Gliders - Founder’s Pickaxes - Founder’s Banners
|
||||
|
||||
======================== RARE BANNERS ======================== - Alpha
|
||||
Tester Banner - Battle Bus Banner - Founder’s Banner - FNCS Champion
|
||||
Banner - World Cup Banner - Fall Skirmish Banner - Summer Skirmish
|
||||
Banner - Galaxy Banner - IKONIK Banner - Glow Banner - Wonder Banner -
|
||||
Honor Guard Banner - EON Banner - Dark Vertex Banner - Double Helix
|
||||
Banner - Neo Versa Banner - Wildcat Banner
|
||||
|
||||
|
||||
extra stuff IGNORE THAT IT SAYS MISSING JUST ADD THEM TO EITHER OG OR EXCLUSIVE LIST
|
||||
|
||||
|
||||
Missing Exclusive Skins
|
||||
Honor Guard
|
||||
Wonder
|
||||
Surf Strider
|
||||
Gildedguy
|
||||
Tart Tycoon
|
||||
Various FNCS reward skins/styles
|
||||
Platform-exclusive reskins
|
||||
Crew Pack exclusive legacy styles
|
||||
Missing Pickaxes
|
||||
Crowbar (High Stakes)
|
||||
Instigator
|
||||
Founder-exclusive pickaxes
|
||||
STW event pickaxes
|
||||
Galaxy Cup pickaxes
|
||||
Tournament reward pickaxes
|
||||
Missing Gliders
|
||||
Snowflake Umbrella
|
||||
Mako
|
||||
Founder's Gliders
|
||||
Exclusive bundle gliders
|
||||
Tournament gliders
|
||||
Missing Banners
|
||||
Many Search for Survivors creator banners
|
||||
Alpha Tester variants
|
||||
Early STW event banners
|
||||
Dungeon banners
|
||||
Ventures banners
|
||||
Holiday event banners
|
||||
Tournament placement banners
|
||||
Missing Emoticons
|
||||
Founder emoticons
|
||||
Samsung emoticons
|
||||
Wonder emoticons
|
||||
Honor Guard emoticons
|
||||
Twitch Prime emoticons
|
||||
Early Battle Pass emoticons
|
||||
Missing Wraps
|
||||
Stealth Black
|
||||
Magma
|
||||
Star Scout
|
||||
Competitive reward wraps
|
||||
Platform-exclusive wraps
|
||||
Missing Sprays
|
||||
Tournament sprays
|
||||
World Cup sprays
|
||||
FNCS sprays
|
||||
STW sprays
|
||||
Missing Loading Screens
|
||||
Galaxy loading screens
|
||||
Wildcat loading screens
|
||||
Tournament loading screens
|
||||
STW exclusive loading screens
|
||||
Missing Back Blings
|
||||
|
||||
There are dozens of exclusive back blings tied to:
|
||||
|
||||
Samsung bundles
|
||||
Xbox bundles
|
||||
Nintendo bundles
|
||||
PlayStation bundles
|
||||
Founder packs
|
||||
Twitch Prime packs
|
||||
Intel/NVIDIA promotions
|
||||
Missing OG Progression Items
|
||||
Max Omega Lights
|
||||
Max Carbide Lights
|
||||
Corrupted Scratch levels
|
||||
Golden Peely
|
||||
Fully Enlightened Chapter 2 skins
|
||||
Holo Foil Marvel skins
|
||||
Rainbow Foil Marvel skins
|
||||
Gold Agent styles
|
||||
Missing STW Exclusives
|
||||
|
||||
This is a huge category:
|
||||
|
||||
Founder heroes
|
||||
Founder schematics
|
||||
Founder banners
|
||||
Event banners
|
||||
Challenge the Horde rewards
|
||||
Survive the Storm rewards
|
||||
Frostnite rewards
|
||||
Endurance rewards
|
||||
Mythic Storm King rewards
|
||||
|
||||
If your goal is a checker that's com
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -0,0 +1,27 @@
|
||||

|
||||
|
||||
Provably-Safe Telegram Fortnite Skin Checker Bot
|
||||
- single handedly developed by @xhexago on telegram and discord
|
||||
|
||||
Setup Guide(Windows):
|
||||
- install Python 3.11.4 from https://www.python.org/ftp/python/3.11.4/python-3.11.4-amd64.exe
|
||||
- make sure python is installed with the option "Add to "PATh";
|
||||
- python -m pip install --upgrade pip
|
||||
|
||||
- pip install Pillow==11.0.0
|
||||
- pip install telebot
|
||||
- pip install asyncio
|
||||
- pip install aiohttp
|
||||
|
||||
Setup Guide(Linux):
|
||||
- sudo apt update
|
||||
- sudo apt upgrade
|
||||
- sudo apt install -y python3
|
||||
- sudo apt install -y python3-pip
|
||||
- pip install Pillow==11.0.0
|
||||
- pip install telebot
|
||||
- pip install asyncio
|
||||
- pip install aiohttp
|
||||
|
||||
- Make .env file with variables for:
|
||||
- TELEGRAM_API_TOKEN
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,24 @@
|
||||
class FortniteCosmetic:
|
||||
def __init__(self):
|
||||
self.cosmetic_id = ""
|
||||
self.name = ""
|
||||
self.backend_value = "AthenaCharacter"
|
||||
self.rarity_value = "common"
|
||||
self.small_icon = ""
|
||||
self.is_banner = False
|
||||
self.unlocked_styles = {}
|
||||
self.is_exclusive = False
|
||||
self.is_popular = False
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"cosmetic_id": self.cosmetic_id,
|
||||
"name": self.name,
|
||||
"backend_value": self.backend_value,
|
||||
"rarity_value": self.rarity_value,
|
||||
"small_icon": self.small_icon,
|
||||
"is_banner": self.is_banner,
|
||||
"unlocked_styles": self.unlocked_styles,
|
||||
"is_exclusive": self.is_exclusive,
|
||||
"is_popular": self.is_popular,
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,690 @@
|
||||
import aiohttp
|
||||
import requests
|
||||
import asyncio
|
||||
import os
|
||||
import platform
|
||||
import json
|
||||
import math
|
||||
from typing import Optional
|
||||
from datetime import datetime, timezone
|
||||
from cosmetic import FortniteCosmetic
|
||||
from utils import bool_to_emoji
|
||||
|
||||
# these tokens are used to authorize in epic games's API and let us do the skincheck without getting errors
|
||||
EPIC_API_SWITCH_TOKEN = "OThmN2U0MmMyZTNhNGY4NmE3NGViNDNmYmI0MWVkMzk6MGEyNDQ5YTItMDAxYS00NTFlLWFmZWMtM2U4MTI5MDFjNGQ3"
|
||||
# keep in mind, sometimes epic games block the client ids, so then you have to generate new ios token for it to start working again
|
||||
EPIC_API_IOS_CLIENT_TOKEN = "M2Y2OWU1NmM3NjQ5NDkyYzhjYzI5ZjFhZjA4YThhMTI6YjUxZWU5Y2IxMjIzNGY1MGE2OWVmYTY3ZWY1MzgxMmU="
|
||||
|
||||
class EpicEndpoints:
|
||||
endpoint_oauth_token = "https://account-public-service-prod.ol.epicgames.com/account/api/oauth/token"
|
||||
endpoint_prod03_oauth_token = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/token"
|
||||
endpoint_redirect_url = "https://www.epicgames.com/id/login?redirectUrl=https%3A//www.epicgames.com/id/login%3FredirectUrl%3Dhttps%253A%252F%252Fwww.epicgames.com%252Fid%252Fapi%252Fredirect%253FclientId%253Dec684b8c687f479fadea3cb2ad83f5c6%2526responseType%253Dcode"
|
||||
endpoint_oauth_exchange = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/exchange"
|
||||
endpoint_device_auth = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/deviceAuthorization"
|
||||
|
||||
# locker categories we render
|
||||
locker_categories = ['AthenaCharacter', 'AthenaBackpack', 'AthenaPickaxe', 'AthenaDance', 'AthenaGlider', 'AthenaPopular', 'AthenaExclusive']
|
||||
|
||||
class EpicUser:
|
||||
def __init__(self, data: dict = {}):
|
||||
self.raw = data
|
||||
|
||||
# api response for login link generation
|
||||
self.access_token = data.get("access_token", "")
|
||||
self.expires_in = data.get("expires_in", 0)
|
||||
self.expires_at = data.get("expires_at", "")
|
||||
self.token_type = data.get("token_type", "")
|
||||
self.client_id = data.get("client_id", "")
|
||||
self.internal_client = data.get("internal_client", False)
|
||||
self.client_service = data.get("client_service", "")
|
||||
self.product_id = data.get("product_id", "")
|
||||
self.application_id = data.get("application_id", "")
|
||||
|
||||
# api response for account metadata
|
||||
self.refresh_token = data.get("refresh_token", "")
|
||||
self.refresh_expires = data.get("refresh_expires", "")
|
||||
self.refresh_expires_at = data.get("refresh_expires_at", "")
|
||||
self.account_id = data.get("account_id", "")
|
||||
self.display_name = data.get("displayName", "")
|
||||
self.app = data.get("app", "")
|
||||
self.in_app_id = data.get("in_app_id", "")
|
||||
self.acr = data.get("acr", "")
|
||||
self.auth_time = data.get("auth_time", "")
|
||||
|
||||
class LockerData:
|
||||
def __init__(self):
|
||||
self.cosmetic_categories = {}
|
||||
self.cosmetic_array = {}
|
||||
self.unlocked_styles = {}
|
||||
self.homebase_banners = {}
|
||||
self.last_match = ''
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"cosmetic_categories": self.cosmetic_categories,
|
||||
"cosmetic_array": self.cosmetic_array,
|
||||
"unlocked_styles": self.unlocked_styles,
|
||||
"homebase_banners": self.homebase_banners,
|
||||
}
|
||||
|
||||
def add_missing_array2(arr, arr2, category, idclean):
|
||||
# i hate hardcoding stuff, so ill make helper funcs instead
|
||||
if category not in arr:
|
||||
arr[category] = []
|
||||
arr2[category] = []
|
||||
|
||||
arr[category].append(idclean)
|
||||
|
||||
def add_missing_array(arr, arr2, category):
|
||||
# i hate hardcoding stuff, so ill make helper funcs instead
|
||||
if category not in arr:
|
||||
arr[category] = []
|
||||
arr2[category] = []
|
||||
|
||||
async def get_cosmetic_data(cosmetic_lowercase_id):
|
||||
try:
|
||||
response = requests.get(
|
||||
f'https://fortnite-api.com/v2/cosmetics/br/search/ids?language=en{cosmetic_lowercase_id}'
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
return response.json().get('data', [])
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error getting cosmetic info for cosmetic with ID: {cosmetic_lowercase_id}\n> Exception: {e}")
|
||||
return []
|
||||
|
||||
class EpicGenerator:
|
||||
def __init__(self) -> None:
|
||||
# init the generator
|
||||
self.http: aiohttp.ClientSession
|
||||
self.user_agent = f"DeviceAuthGenerator/{platform.system()}/{platform.version()}"
|
||||
self.access_token = ""
|
||||
|
||||
async def start(self) -> None:
|
||||
self.http = aiohttp.ClientSession(headers={"User-Agent": self.user_agent})
|
||||
self.access_token = await self.get_access_token()
|
||||
|
||||
async def kill(self) -> None:
|
||||
await self.http.close()
|
||||
|
||||
async def get_access_token(self) -> str:
|
||||
# getting the access token from epic's api(REQUIRES usage of EPIC_API_SWITCH_TOKEN as Authorization in headers for it to work)
|
||||
# if it's not getting any data, it means the EPIC_API_SWITCH_TOKEN is expired, you must find new one :D
|
||||
async with self.http.request(
|
||||
method="POST",
|
||||
url=EpicEndpoints.endpoint_oauth_token,
|
||||
headers={
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Authorization": f"basic {EPIC_API_SWITCH_TOKEN}"
|
||||
},
|
||||
data={ "grant_type": "client_credentials" },
|
||||
) as response:
|
||||
data = await response.json()
|
||||
return data["access_token"]
|
||||
|
||||
async def create_device_code(self) -> tuple:
|
||||
# devide code is used on the link the checker bot sends u "active?userCode=SOMETHING" something like this
|
||||
# REQUIRES usage of self.access_token, which we got from get_access_token function, as Authorization in headers
|
||||
# returns the device code, used in the link we generate for the user to login
|
||||
async with self.http.request(
|
||||
method="POST",
|
||||
url=EpicEndpoints.endpoint_device_auth,
|
||||
headers={
|
||||
"Authorization": f"bearer {self.access_token}",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
) as response:
|
||||
data = await response.json()
|
||||
return data
|
||||
|
||||
async def create_exchange_code(self, user: EpicUser) -> str:
|
||||
# creates exchange code for the api requests & returns it
|
||||
# REQUIRES usage of user.access_token, which we got from get_access_token function, as Authorization in headers
|
||||
async with self.http.request(
|
||||
method="GET",
|
||||
url=EpicEndpoints.endpoint_oauth_exchange,
|
||||
headers={"Authorization": f"bearer {user.access_token}"},
|
||||
) as response:
|
||||
data = await response.json()
|
||||
return data["code"]
|
||||
|
||||
async def wait_for_device_code_completion(self, bot, message, code: str) -> Optional[EpicUser]:
|
||||
while True:
|
||||
try:
|
||||
async with self.http.request(
|
||||
method="POST",
|
||||
url=EpicEndpoints.endpoint_prod03_oauth_token,
|
||||
headers={
|
||||
"Authorization": f"basic {EPIC_API_SWITCH_TOKEN}",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data={"grant_type": "device_code", "device_code": code},
|
||||
timeout=10
|
||||
) as request:
|
||||
token_data = await request.json()
|
||||
|
||||
if request.status == 200 and "access_token" in token_data:
|
||||
break
|
||||
|
||||
# Handle specific API errors
|
||||
error_code = token_data.get("errorCode")
|
||||
if error_code == "errors.com.epicgames.account.oauth.authorization_pending":
|
||||
pass
|
||||
|
||||
elif error_code == "g":
|
||||
pass
|
||||
|
||||
elif error_code == "errors.com.epicgames.not_found":
|
||||
bot.send_message(message.chat.id, f'❌ Login link expired, please use /login again.')
|
||||
return None
|
||||
else:
|
||||
bot.send_message(message.chat.id, f'❌ Error occurred: {token_data.get("errorMessage", "Unknown error")}')
|
||||
return None
|
||||
|
||||
await asyncio.sleep(10)
|
||||
except ValueError as ve:
|
||||
print(f"Error with waiting for device code: {ve}")
|
||||
bot.send_message(message.chat.id, f'❌ An unexpected error occurred, please try again later.')
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Unhandled exception: {e}")
|
||||
bot.send_message(message.chat.id, f'❌ An error occurred, please contact support.')
|
||||
return None
|
||||
|
||||
try:
|
||||
async with self.http.request(
|
||||
method="GET",
|
||||
url=EpicEndpoints.endpoint_oauth_exchange,
|
||||
headers={"Authorization": f"bearer {token_data['access_token']}"},
|
||||
) as request:
|
||||
if request.status != 200:
|
||||
bot.send_message(message.chat.id, f'❌ Failed to retrieve exchange code. Please try again.')
|
||||
return None
|
||||
|
||||
exchange_data = await request.json()
|
||||
|
||||
async with self.http.request(
|
||||
method="POST",
|
||||
url=EpicEndpoints.endpoint_prod03_oauth_token,
|
||||
headers={
|
||||
"Authorization": f"basic {EPIC_API_IOS_CLIENT_TOKEN}",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
data={
|
||||
"grant_type": "exchange_code",
|
||||
"exchange_code": exchange_data["code"]
|
||||
},
|
||||
) as request:
|
||||
if request.status != 200:
|
||||
bot.send_message(message.chat.id, f'❌ Failed to authenticate using exchange code. Please try again.')
|
||||
return None
|
||||
|
||||
auth_data = await request.json()
|
||||
|
||||
return EpicUser(data=auth_data)
|
||||
|
||||
except KeyError as ke:
|
||||
bot.send_message(message.chat.id, f'❌ Unexpected response format from server.')
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Unhandled exception during token exchange: {e}")
|
||||
bot.send_message(message.chat.id, f'❌ An error occurred while completing authentication.')
|
||||
return None
|
||||
|
||||
async def create_device_auths(self, user: EpicUser) -> dict:
|
||||
# creates device auth
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
async with self.http.request(
|
||||
method="POST",
|
||||
url=f"https://account-public-service-prod.ol.epicgames.com/account/api/public/account/{user.account_id}/deviceAuth",
|
||||
headers={
|
||||
"Authorization": f"bearer {user.access_token}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
) as request:
|
||||
data = await request.json()
|
||||
|
||||
return {
|
||||
"device_id": data["deviceId"],
|
||||
"account_id": data["accountId"],
|
||||
"secret": data["secret"],
|
||||
"user_agent": data["userAgent"],
|
||||
"created": {
|
||||
"location": data["created"]["location"],
|
||||
"ip_address": data["created"]["ipAddress"],
|
||||
"datetime": data["created"]["dateTime"],
|
||||
},
|
||||
}
|
||||
|
||||
async def get_account_metadata(self, user: EpicUser) -> json:
|
||||
# grabs account's metadata(basic information) from the api
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
|
||||
url = f'https://account-public-service-prod03.ol.epicgames.com/account/api/public/account/displayName/{user.display_name}'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
async with self.http.get(url, headers=headers) as response:
|
||||
metadata = await response.json()
|
||||
|
||||
return metadata
|
||||
|
||||
async def get_external_connections(self, user: EpicUser) -> dict:
|
||||
# returns external connected accounts info
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
async with self.http.request(
|
||||
method="GET",
|
||||
url=f"https://account-public-service-prod03.ol.epicgames.com/account/api/public/account/{user.account_id}/externalAuths",
|
||||
headers={"Authorization": f"bearer {user.access_token}"}
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return []
|
||||
|
||||
external_auths = await resp.json()
|
||||
|
||||
return external_auths
|
||||
|
||||
async def get_public_account_info(self, user: EpicUser) -> dict:
|
||||
# returns basic public info about the account
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
url = f'https://account-public-service-prod03.ol.epicgames.com/account/api/public/account/{user.account_id}'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}"
|
||||
}
|
||||
|
||||
async with self.http.get(url, headers=headers) as response:
|
||||
account_data = await response.json()
|
||||
|
||||
account_info = {} # creating json for only stuff we are interested into
|
||||
creation_date = account_data.get("created", "?")
|
||||
if creation_date != "?":
|
||||
creation_date = datetime.strptime(creation_date, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%d/%m/%Y")
|
||||
|
||||
account_info['creation_date'] = creation_date
|
||||
account_info['externalAuths'] = await self.get_external_connections(user)
|
||||
return account_info
|
||||
|
||||
async def get_common_profile(self, user: EpicUser) -> json:
|
||||
# gets the common profile, containing vbucks, receipts amount, vbucks purchases history, banners list
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
|
||||
url = f'https://fortnite-public-service-prod11.ol.epicgames.com/fortnite/api/game/v2/profile/{user.account_id}/client/QueryProfile?profileId=common_core&rvn=-1'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
profile_data = requests.post(url, headers=headers, json={}).json()
|
||||
return profile_data
|
||||
|
||||
async def get_friend_codes(self, user: EpicUser, platform: str) -> json:
|
||||
# https://fngw-mcp-gc-livefn.ol.epicgames.com/fortnite/api/v2/game/friendcodes/<accountID>/<platform>
|
||||
# gets the save the world redeem codes based on the platform you've entered
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
# this always returns an error saying page isn't found, im not sure why.
|
||||
url = f'https://fngw-mcp-gc-livefn.ol.epicgames.com/fortnite/api/v2/game/friendcodes/{user.account_id}/{platform}'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}"
|
||||
}
|
||||
|
||||
async with self.http.get(url, headers=headers) as response:
|
||||
codes_data = await response.json()
|
||||
|
||||
return codes_data
|
||||
|
||||
async def get_homebase_profile(self, user: EpicUser) -> json:
|
||||
# gets the save the world profile data
|
||||
# REQUIRES usage of user.access_token as Authorization in headers
|
||||
|
||||
url = f'https://fngw-mcp-gc-livefn.ol.epicgames.com/fortnite/api/game/v2/profile/{user.account_id}/client/QueryPublicProfile'
|
||||
querystring = { "profileId":"campaign", "rvn":"-1" }
|
||||
payload = {}
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"bearer {user.access_token}"
|
||||
}
|
||||
|
||||
profile_data = requests.request("POST", url, json=payload, headers=headers, params=querystring).json()
|
||||
|
||||
return profile_data
|
||||
|
||||
async def set_affiliate(self, user: EpicUser, affiliate_name: str):
|
||||
url = f'https://fortnite-public-service-prod11.ol.epicgames.com/fortnite/api/game/v2/profile/{user.account_id}/client/SetAffiliateName?profileId=common_core'
|
||||
payload = { "affiliateName": affiliate_name }
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"bearer {user.access_token}"
|
||||
}
|
||||
|
||||
affiliate_response = requests.request("POST", url, json=payload, headers=headers)
|
||||
|
||||
if affiliate_response.status != 200:
|
||||
print(f"Error setting affiliate name ({affiliate_response.status})")
|
||||
|
||||
async def get_locker_data(self, user: EpicUser) -> LockerData:
|
||||
# gets locker arrays
|
||||
# locker_categories - the locker categories we render
|
||||
url = f'https://fortnite-public-service-prod11.ol.epicgames.com/fortnite/api/game/v2/profile/{user.account_id}/client/QueryProfile?profileId=athena'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
athena_data = requests.post(url, headers=headers, json={}).json()
|
||||
|
||||
locker_data = LockerData()
|
||||
exclusive_cosmetics = []
|
||||
popular_cosmetics = []
|
||||
if "profileChanges" not in athena_data:
|
||||
return LockerData()
|
||||
|
||||
# activity
|
||||
account_level = athena_data.get("profileChanges", [{}])[0].get("profile", {}).get("stats", {}).get("attributes", {}).get("accountLevel", 1)
|
||||
last_match_end = athena_data.get("profileChanges", [{}])[0].get("profile", {}).get("stats", {}).get("attributes", {}).get("last_match_end_datetime", "")
|
||||
if last_match_end:
|
||||
last_match_end_date = datetime.fromisoformat(last_match_end.replace("Z", "+00:00"))
|
||||
days_since_last_match = (datetime.now(timezone.utc) - last_match_end_date).days
|
||||
last_match_date_str = last_match_end_date.strftime("%d.%m.%y")
|
||||
locker_data.last_match = f"{last_match_date_str} ({days_since_last_match} days ago)"
|
||||
else:
|
||||
locker_data.last_match = "800+ days ago"
|
||||
|
||||
# getting extra cosmetics
|
||||
try:
|
||||
with open('exclusive.txt', 'r', encoding='utf-8') as f:
|
||||
exclusive_cosmetics = [i.strip() for i in f.readlines()]
|
||||
|
||||
with open('most_wanted.txt', 'r', encoding='utf-8') as f:
|
||||
popular_cosmetics = [i.strip() for i in f.readlines()]
|
||||
except FileNotFoundError:
|
||||
print("Warning: exclusive.txt or most_wanted.txt not found.")
|
||||
|
||||
# getting owned items list
|
||||
for i in athena_data['profileChanges'][0]['profile']['items']:
|
||||
template_id = athena_data['profileChanges'][0]['profile']['items'][i]['templateId']
|
||||
if template_id.startswith('Athena'):
|
||||
cosmetic_category = template_id.split(':')[0]
|
||||
cosmetic_id = template_id.split(':')[1]
|
||||
locker_data.unlocked_styles[cosmetic_id] = []
|
||||
|
||||
# adding missing categories to the arrays
|
||||
if 'AthenaExclusive' not in locker_data.cosmetic_categories:
|
||||
locker_data.cosmetic_categories['AthenaExclusive'] = []
|
||||
locker_data.cosmetic_array['AthenaExclusive'] = []
|
||||
locker_data.cosmetic_categories['AthenaExclusive'].append(cosmetic_id)
|
||||
|
||||
if 'AthenaPopular' not in locker_data.cosmetic_categories:
|
||||
locker_data.cosmetic_categories['AthenaPopular'] = []
|
||||
locker_data.cosmetic_array['AthenaPopular'] = []
|
||||
locker_data.cosmetic_categories['AthenaPopular'].append(cosmetic_id)
|
||||
|
||||
if 'HomebaseBannerIcons' not in locker_data.cosmetic_categories:
|
||||
locker_data.cosmetic_categories['HomebaseBannerIcons'] = []
|
||||
locker_data.cosmetic_array['HomebaseBannerIcons'] = []
|
||||
locker_data.cosmetic_categories['HomebaseBannerIcons'].append(cosmetic_id)
|
||||
|
||||
if cosmetic_category not in locker_data.cosmetic_categories:
|
||||
locker_data.cosmetic_categories[cosmetic_category] = []
|
||||
locker_data.cosmetic_array[cosmetic_category] = []
|
||||
locker_data.cosmetic_categories[cosmetic_category].append(cosmetic_id)
|
||||
|
||||
# listing the owned unlocked styles for each cosmetic
|
||||
for item_id, item_data in athena_data['profileChanges'][0]['profile']['items'].items():
|
||||
template_id = item_data.get('templateId', '')
|
||||
|
||||
if template_id.startswith('Athena'):
|
||||
lowercase_cosmetic_id = template_id.split(':')[1]
|
||||
|
||||
# adding the cosmetic to the "unlocked styles"
|
||||
if lowercase_cosmetic_id not in locker_data.unlocked_styles:
|
||||
locker_data.unlocked_styles[lowercase_cosmetic_id] = []
|
||||
|
||||
attributes = item_data.get('attributes', {})
|
||||
variants = attributes.get('variants', [])
|
||||
|
||||
for variant in variants:
|
||||
# adding the cosmetic's owned styles
|
||||
locker_data.unlocked_styles[lowercase_cosmetic_id].extend(variant.get('owned', []))
|
||||
|
||||
# getting banners
|
||||
common_profile_data = await self.get_common_profile(user)
|
||||
if common_profile_data:
|
||||
# common profile found
|
||||
for profileChange in common_profile_data["profileChanges"]:
|
||||
profile_items = profileChange["profile"]["items"]
|
||||
|
||||
# checking every item
|
||||
for item_key, item_value in profile_items.items():
|
||||
cosmetic_template_id = item_value.get("templateId", "")
|
||||
if cosmetic_template_id:
|
||||
# the banner is found, so we adding it
|
||||
lowercase_banner_id = cosmetic_template_id.split(':')[1]
|
||||
if lowercase_banner_id not in locker_data.homebase_banners:
|
||||
locker_data.homebase_banners[lowercase_banner_id] = []
|
||||
|
||||
|
||||
for category in locker_categories:
|
||||
if category == "AthenaPopular" or category == 'AthenaExclusive':
|
||||
continue
|
||||
|
||||
try:
|
||||
list_of_cosmetic_ids = []
|
||||
# splitting the category's cosmetic ids to sublists
|
||||
for i in range(0, len(locker_data.cosmetic_categories[category]), 50):
|
||||
sublist = locker_data.cosmetic_categories[category][i:i+50]
|
||||
list_of_cosmetic_ids.append(sublist)
|
||||
|
||||
for cosmetic_id in list_of_cosmetic_ids:
|
||||
cosmetics_data = requests.get('https://fortnite-api.com/v2/cosmetics/br/search/ids?language=en&id={}'.format('&id='.join(cosmetic_id)))
|
||||
c_data = cosmetics_data.json().get("data", [])
|
||||
if not c_data:
|
||||
# cosmetics data not found
|
||||
continue
|
||||
|
||||
for cosmetic in c_data:
|
||||
if cosmetic['id'] == "CID_DefaultOutfit":
|
||||
# skipping default skin
|
||||
continue
|
||||
|
||||
if category == 'AthenaDance' and cosmetic['type']['value'] != 'emote' and cosmetic['id'] not in exclusive_cosmetics:
|
||||
# emote category, but isnt exclusive and isnt emote
|
||||
continue
|
||||
|
||||
make_mythic = False
|
||||
if cosmetic['id'] in exclusive_cosmetics:
|
||||
make_mythic = True
|
||||
# Pink Ghoul Trooper
|
||||
if cosmetic['id'].lower() == 'cid_029_athena_commando_f_halloween':
|
||||
make_mythic = False
|
||||
if 'Mat3' in locker_data.unlocked_styles.get('cid_029_athena_commando_f_halloween', []):
|
||||
make_mythic = True
|
||||
|
||||
# Purple Skull Trooper
|
||||
if cosmetic['id'].lower() == 'cid_030_athena_commando_m_halloween':
|
||||
make_mythic = False
|
||||
if 'Mat1' in locker_data.unlocked_styles.get('cid_030_athena_commando_m_halloween', []):
|
||||
make_mythic = True
|
||||
|
||||
# Aerial Assault Trooper
|
||||
if cosmetic['id'].lower() == 'cid_017_athena_commando_m':
|
||||
make_mythic = False
|
||||
if 'Stage2' in locker_data.unlocked_styles.get('cid_017_athena_commando_m', []):
|
||||
make_mythic = True
|
||||
|
||||
# Renegade Raider
|
||||
if cosmetic['id'].lower() == 'cid_028_athena_commando_f':
|
||||
make_mythic = False
|
||||
if 'Mat3' in locker_data.unlocked_styles.get('cid_028_athena_commando_f', []):
|
||||
make_mythic = True
|
||||
|
||||
# Raider's Revenge
|
||||
if cosmetic['id'].lower() == 'pickaxe_lockjaw':
|
||||
make_mythic = False
|
||||
if 'Stage2' in locker_data.unlocked_styles.get('pickaxe_lockjaw', []):
|
||||
make_mythic = True
|
||||
|
||||
# Aerial Assault One
|
||||
if cosmetic['id'].lower() == 'glider_id_001':
|
||||
make_mythic = False
|
||||
if 'Stage2' in locker_data.unlocked_styles.get('glider_id_001', []):
|
||||
make_mythic = True
|
||||
|
||||
# Stage 5 Omega Lights
|
||||
if cosmetic['id'].lower() == 'cid_116_athena_commando_m_carbideblack':
|
||||
make_mythic = False
|
||||
if 'Stage5' in locker_data.unlocked_styles.get('cid_116_athena_commando_m_carbideblack', []):
|
||||
make_mythic = True
|
||||
|
||||
# Gold Midas
|
||||
if cosmetic['id'].lower() == 'cid_694_athena_commando_m_catburglar':
|
||||
make_mythic = False
|
||||
if 'Stage4' in locker_data.unlocked_styles.get('cid_694_athena_commando_m_catburglar', []):
|
||||
make_mythic = True
|
||||
|
||||
# Gold Meowscles
|
||||
if cosmetic['id'].lower() == 'cid_693_athena_commando_m_buffcat':
|
||||
make_mythic = False
|
||||
if 'Stage4' in locker_data.unlocked_styles.get('cid_693_athena_commando_m_buffcat', []):
|
||||
make_mythic = True
|
||||
|
||||
# Gold TNtina
|
||||
if cosmetic['id'].lower() == 'cid_691_athena_commando_f_tntina':
|
||||
make_mythic = False
|
||||
if 'Stage7' in locker_data.unlocked_styles.get('cid_691_athena_commando_f_tntina', []):
|
||||
make_mythic = True
|
||||
|
||||
# Gold Skye
|
||||
if cosmetic['id'].lower() == 'cid_690_athena_commando_f_photographer':
|
||||
make_mythic = False
|
||||
if 'Stage4' in locker_data.unlocked_styles.get('cid_690_athena_commando_f_photographer', []):
|
||||
make_mythic = True
|
||||
|
||||
# Gold Agent Peely
|
||||
if cosmetic['id'].lower() == 'cid_701_athena_commando_m_bananaagent':
|
||||
make_mythic = False
|
||||
if 'Stage4' in locker_data.unlocked_styles.get('cid_701_athena_commando_m_bananaagent', []):
|
||||
make_mythic = True
|
||||
|
||||
# World Cup Fishtick
|
||||
if cosmetic['id'].lower() == 'cid_315_athena_commando_m_teriyakifish':
|
||||
make_mythic = False
|
||||
if 'Stage3' in locker_data.unlocked_styles.get('cid_315_athena_commando_m_teriyakifish', []):
|
||||
make_mythic = True
|
||||
|
||||
# Mate Black Masterchief
|
||||
if cosmetic['id'].lower() == 'cid_971_athena_commando_m_jupiter_s0z6m':
|
||||
make_mythic = False
|
||||
if 'Mat2' in locker_data.unlocked_styles.get('cid_971_athena_commando_m_jupiter_s0z6m', []):
|
||||
make_mythic = True
|
||||
|
||||
if make_mythic == True:
|
||||
cosmetic['rarity']['value'] = 'mythic'
|
||||
|
||||
cosmetic_info = FortniteCosmetic()
|
||||
cosmetic_info.cosmetic_id = cosmetic['id']
|
||||
cosmetic_info.name = cosmetic['name']
|
||||
cosmetic_info.small_icon = cosmetic['images']['smallIcon']
|
||||
cosmetic_info.backend_value = category
|
||||
cosmetic_info.rarity_value = cosmetic['rarity']['value']
|
||||
cosmetic_info.is_banner = False
|
||||
cosmetic_info.is_exclusive = make_mythic
|
||||
cosmetic_info.is_popular = cosmetic['id'] in popular_cosmetics
|
||||
cosmetic_info.unlocked_styles = locker_data.unlocked_styles[cosmetic['id'].lower()]
|
||||
|
||||
locker_data.cosmetic_array[category].append(cosmetic_info)
|
||||
|
||||
# now special ones
|
||||
if cosmetic_info.is_popular:
|
||||
locker_data.cosmetic_array['AthenaPopular'].append(cosmetic_info)
|
||||
|
||||
if make_mythic:
|
||||
locker_data.cosmetic_array['AthenaExclusive'].append(cosmetic_info)
|
||||
|
||||
except Exception as e:
|
||||
print(f'exception: {e}')
|
||||
continue
|
||||
|
||||
# handle banners
|
||||
banners_data = requests.get('https://fortnite-api.com/v1/banners')
|
||||
for fn_banner in banners_data.json()['data']:
|
||||
banner_lower_id = fn_banner['id'].lower()
|
||||
if banner_lower_id not in locker_data.homebase_banners:
|
||||
# banner isn't owned
|
||||
continue
|
||||
|
||||
make_mythic = False
|
||||
icon = fn_banner['images']['icon']
|
||||
rarity = 'uncommon'
|
||||
if fn_banner['id'] in exclusive_cosmetics:
|
||||
make_mythic = True
|
||||
rarity = 'mythic'
|
||||
|
||||
# for future
|
||||
cosmetic_info = FortniteCosmetic()
|
||||
cosmetic_info.cosmetic_id = fn_banner['id']
|
||||
cosmetic_info.name = fn_banner['devName']
|
||||
cosmetic_info.small_icon = fn_banner['images']['smallIcon']
|
||||
cosmetic_info.rarity_value = rarity
|
||||
cosmetic_info.backend_value = 'HomebaseBannerIcons'
|
||||
cosmetic_info.is_banner = True
|
||||
cosmetic_info.is_exclusive = make_mythic
|
||||
cosmetic_info.is_popular = fn_banner['id'] in popular_cosmetics
|
||||
|
||||
locker_data.cosmetic_array['HomebaseBannerIcons'].append(cosmetic_info)
|
||||
# now exclusive ones
|
||||
if make_mythic:
|
||||
locker_data.cosmetic_array['AthenaExclusive'].append(cosmetic_info)
|
||||
|
||||
# sorting exclusives category
|
||||
locker_data.cosmetic_array['AthenaExclusive'].sort(
|
||||
key=lambda cosmetic: exclusive_cosmetics.index(cosmetic.cosmetic_id)
|
||||
if cosmetic.cosmetic_id in exclusive_cosmetics
|
||||
else float('inf')
|
||||
)
|
||||
|
||||
# returning back the locker data
|
||||
return locker_data
|
||||
|
||||
async def get_seasons_message(self, user: EpicUser) -> str:
|
||||
url = f'https://fortnite-public-service-prod11.ol.epicgames.com/fortnite/api/game/v2/profile/{user.account_id}/client/QueryProfile?profileId=athena'
|
||||
headers = {
|
||||
"Authorization": f"bearer {user.access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
athena_data = requests.post(url, headers=headers, json={}).json()
|
||||
|
||||
past_seasons = {}
|
||||
seasons_info = []
|
||||
|
||||
# seasons infos
|
||||
past_seasons = athena_data.get("profileChanges", [{}])[0].get("profile", {}).get("stats", {}).get("attributes", {}).get("past_seasons", [])
|
||||
total_wins = sum(season.get("numWins", 0) for season in past_seasons)
|
||||
total_matches = sum(
|
||||
season.get("numHighBracket", 0) + season.get("numLowBracket", 0) +
|
||||
season.get("numHighBracket_LTM", 0) + season.get("numLowBracket_LTM", 0) +
|
||||
season.get("numHighBracket_Ar", 0) + season.get("numLowBracket_Ar", 0)
|
||||
for season in past_seasons
|
||||
)
|
||||
|
||||
curses = athena_data.get("profileChanges", [{}])[0].get("profile", {}).get("stats", {}).get("attributes", {})
|
||||
cursesinfo = {
|
||||
'level': curses.get('level', 1),
|
||||
'book_level': curses.get('book_level', 1)
|
||||
}
|
||||
|
||||
for season in past_seasons:
|
||||
seasons_info.append(f"""
|
||||
#️⃣Season {season.get('seasonNumber', 1)}
|
||||
› Level: {season.get('seasonLevel', '1')}
|
||||
› Battle Pass: {bool_to_emoji(season.get('purchasedVIP', False))}
|
||||
› Wins: {season.get('numWins', 0)}
|
||||
""")
|
||||
|
||||
seasons_info_embeds = seasons_info
|
||||
seasons_info_message = "Previous Seasons History:\n" + "\n".join(seasons_info_embeds)
|
||||
seasons_info_message += f"\nCurrent Season:\n› Level: {cursesinfo['level']}\n› Battle Pass Level: {cursesinfo['book_level']}"
|
||||
return seasons_info_message
|
||||
@@ -0,0 +1,415 @@
|
||||
Pickaxe_Lockjaw
|
||||
CID_028_Athena_Commando_F
|
||||
CID_029_Athena_Commando_F_Halloween
|
||||
CID_017_Athena_Commando_M
|
||||
CID_030_Athena_Commando_M_Halloween
|
||||
Glider_ID_001
|
||||
Pickaxe_ID_376_FNCS
|
||||
Pickaxe_FNCS_S32
|
||||
CID_035_Athena_Commando_M_Medieval
|
||||
CID_039_Athena_Commando_F_Disco
|
||||
|
||||
CID_660_Athena_Commando_F_BandageNinjaBlue
|
||||
CID_619_Athena_Commando_F_TechLlama
|
||||
CID_434_Athena_Commando_F_StealthHonor
|
||||
CID_757_Athena_Commando_F_WildCat
|
||||
CID_175_Athena_Commando_M_Celestial
|
||||
CID_342_Athena_Commando_M_StreetRacerMetallic
|
||||
CID_313_Athena_Commando_M_KpopFashion
|
||||
CID_386_Athena_Commando_M_StreetOpsStealth
|
||||
CID_259_Athena_Commando_M_StreetOps
|
||||
CID_174_Athena_Commando_F_CarbideWhite
|
||||
Character_MasterKeyOrder
|
||||
CID_371_Athena_Commando_M_SpeedyMidnight
|
||||
CID_753_Athena_Commando_F_Hostile
|
||||
CID_183_Athena_Commando_M_ModernMilitaryRed
|
||||
CID_479_Athena_Commando_F_Davinci
|
||||
CID_516_Athena_Commando_M_BlackWidowRogue
|
||||
CID_441_Athena_Commando_F_CyberScavengerBlue
|
||||
CID_783_Athena_Commando_M_AquaJacket
|
||||
CID_850_Athena_Commando_F_SkullBriteCube
|
||||
CID_113_Athena_Commando_M_BlueAce
|
||||
CID_515_Athena_Commando_M_BarbequeLarry
|
||||
CID_971_Athena_Commando_M_Jupiter_S0Z6M
|
||||
|
||||
|
||||
CID_033_Athena_Commando_F_Medieval
|
||||
CID_032_Athena_Commando_M_Medieval
|
||||
|
||||
|
||||
CID_084_Athena_Commando_M_Assassin
|
||||
CID_083_Athena_Commando_F_Tactical
|
||||
CID_090_Athena_Commando_M_Tactical
|
||||
|
||||
CID_116_Athena_Commando_M_CarbideBlack
|
||||
|
||||
|
||||
CID_703_Athena_Commando_M_Cyclone
|
||||
CID_761_Athena_Commando_M_CycloneSpace
|
||||
CID_478_Athena_Commando_F_WorldCup
|
||||
CID_964_Athena_Commando_M_Historian_869BC
|
||||
CID_315_Athena_Commando_M_TeriyakiFish
|
||||
|
||||
CID_085_Athena_Commando_M_Twitch
|
||||
CID_089_Athena_Commando_M_RetroGrey
|
||||
CID_114_Athena_Commando_F_TacticalWoodland
|
||||
|
||||
|
||||
CID_096_Athena_Commando_F_Founder
|
||||
CID_095_Athena_Commando_M_Founder
|
||||
|
||||
|
||||
Character_SnowNinjaDark
|
||||
CID_052_Athena_Commando_F_PSBlue
|
||||
CID_138_Athena_Commando_M_PSBurnout
|
||||
CID_296_Athena_Commando_M_Math
|
||||
CID_360_Athena_Commando_M_TechOpsBlue
|
||||
CID_A_101_Athena_Commando_M_TacticalWoodlandBlue
|
||||
CID_A_421_Athena_Commando_F_BlizzardBomber
|
||||
CID_657_Athena_Commando_F_TechOpsBlue
|
||||
CID_711_Athena_Commando_M_LongShorts
|
||||
Character_BlueJet
|
||||
CID_926_Athena_Commando_F_StreetFashionDiamond
|
||||
Character_RetroWheels
|
||||
|
||||
|
||||
CID_701_Athena_Commando_M_BananaAgent
|
||||
CID_690_Athena_Commando_F_Photographer
|
||||
CID_691_Athena_Commando_F_TNTina
|
||||
CID_693_Athena_Commando_M_BuffCat
|
||||
CID_694_Athena_Commando_M_CatBurglar
|
||||
|
||||
|
||||
Character_TubaGummi
|
||||
|
||||
|
||||
BID_004_BlackKnight
|
||||
BID_415_TechLlama
|
||||
BID_138_Celestial
|
||||
BID_521_WildCat
|
||||
BID_249_StreetOpsStealth
|
||||
BID_234_SpeedyMidnight
|
||||
BID_604_SkullBritecube
|
||||
BID_114_ModernMilitaryRed
|
||||
BID_346_BlackWidowRogue
|
||||
PetCarrier_013_BbqLarry
|
||||
|
||||
BID_002_RoyaleKnight
|
||||
BID_001_BlueSquire
|
||||
|
||||
|
||||
Backpack_SnowNinjaDark
|
||||
BID_A_019_BlizzardBomberFemale
|
||||
BID_169_MathMale
|
||||
BID_224_TechOpsBlue
|
||||
Backpack_BlueJet
|
||||
Backpack_SnowSoldierFashion
|
||||
|
||||
|
||||
BID_027_Scavenger
|
||||
BID_468_Cyclone
|
||||
BID_520_CycloneUniverse
|
||||
|
||||
|
||||
Backpack_FNCSShield_S32
|
||||
|
||||
|
||||
Pickaxe_ID_116_Celestial
|
||||
Pickaxe_ID_398_WildCatFemale
|
||||
Pickaxe_ID_077_CarbideWhite
|
||||
Pickaxe_ID_099_ModernMilitaryRed
|
||||
Pickaxe_ID_461_SkullBriteCube
|
||||
Pickaxe_ID_189_StreetOpsStealth
|
||||
Pickaxe_ID_178_SpeedyMidnight
|
||||
|
||||
|
||||
Pickaxe_ID_294_CandyCane
|
||||
Pickaxe_ID_508_HistorianMale_6BQSW
|
||||
|
||||
|
||||
Pickaxe_ID_013_Teslacoil
|
||||
Pickaxe_ID_011_Medieval
|
||||
Pickaxe_ID_028_Space
|
||||
Pickaxe_ID_092_Bling
|
||||
|
||||
|
||||
Pickaxe_ID_039_TacticalBlack
|
||||
Pickaxe_ID_044_TacticalUrbanHammer
|
||||
|
||||
|
||||
Pickaxe_ID_265_BarbequeLarry1H
|
||||
|
||||
|
||||
Pickaxe_ID_STW006_Tier_7
|
||||
Pickaxe_ID_153_RoseLeader
|
||||
|
||||
|
||||
Pickaxe_SnowNinjaDark
|
||||
BID_055_PSBurnout
|
||||
Pickaxe_ID_088_PSBurnout
|
||||
Pickaxe_ID_256_TechOpsBlue
|
||||
Pickaxe_ID_464_LongShortsMale
|
||||
Pickaxe_ID_717_NetworkFemale
|
||||
Pickaxe_SnowSoldierFashion
|
||||
Pickaxe_RetroWheels
|
||||
|
||||
|
||||
Pickaxe_ID_STW005_Tier_6
|
||||
Pickaxe_ID_STW004_Tier_5
|
||||
Pickaxe_ID_STW003_Tier_4
|
||||
Pickaxe_ID_STW002_Tier_3
|
||||
Pickaxe_ID_STW007_Basic
|
||||
Pickaxe_ID_STW001_Tier_1
|
||||
|
||||
|
||||
Pickaxe_SpookyNeonRed
|
||||
Pickaxe_SpookyNeonBlue
|
||||
Pickaxe_ID_359_CycloneMale
|
||||
|
||||
|
||||
EID_KPopDance03
|
||||
EID_Davinci
|
||||
|
||||
|
||||
EID_Fresh
|
||||
EID_Floss
|
||||
EID_Worm
|
||||
EID_RideThePonyTwo
|
||||
EID_TakeTheL
|
||||
EID_HipHop01
|
||||
EID_GoodVibes
|
||||
EID_IceKing
|
||||
EID_RichFam
|
||||
EID_PlayerEleven
|
||||
EID_RigorMortis
|
||||
EID_Gleam
|
||||
EID_Downward_8GZUA
|
||||
EID_CycloneHeadBang
|
||||
EID_SandwichBop
|
||||
EID_JulyBooks
|
||||
EID_Laugh
|
||||
EID_Textile_3O8QG
|
||||
EID_Uproar_496SC
|
||||
EID_Tidy
|
||||
EID_Zippy
|
||||
|
||||
|
||||
EID_Avian
|
||||
|
||||
|
||||
Emoji_S22_Showdown_Mae
|
||||
Emoji_S22_Showdown_Zet
|
||||
|
||||
|
||||
Spray_Showdown_Mae
|
||||
Spray_Showdown_Zet
|
||||
Spray_Showdown_Pi
|
||||
SPID_066_Llamalaxy
|
||||
SPID_065_DiscoBaller
|
||||
SPID_043_Flairspray
|
||||
SPID_274_Alt_3
|
||||
SPID_022_SoloShowdown
|
||||
|
||||
|
||||
Glider_Warthog
|
||||
Glider_ID_003_District
|
||||
|
||||
Glider_ID_211_WildCatBlue
|
||||
Glider_ID_090_Celestial
|
||||
Glider_ID_056_CarbideWhite
|
||||
Glider_ID_075_ModernMilitaryRed
|
||||
Glider_ID_137_StreetOpsStealth
|
||||
Glider_ID_131_SpeedyMidnight
|
||||
|
||||
|
||||
Glider_ID_002_Medieval
|
||||
Glider_ID_015_Brite
|
||||
|
||||
|
||||
Glider_ID_161_RoseLeader
|
||||
FounderGlider
|
||||
Glider_Military
|
||||
|
||||
|
||||
Glider_ID_013_PSBlue
|
||||
Glider_ID_067_PSBurnout
|
||||
Glider_ID_150_TechOpsBlue
|
||||
Glider_ID_309_TacticalWoodlandBlue
|
||||
Glider_ID_389_BlizzardBomberFemale
|
||||
Glider_SnowSoldierFashion
|
||||
|
||||
Glider_ID_196_CycloneMale
|
||||
Glider_ID_347_PeachMale
|
||||
|
||||
|
||||
FounderUmbrella
|
||||
Umbrella_Snowflake
|
||||
Umbrella_PaperParasol
|
||||
Umbrella_AssassinSuit
|
||||
Umbrella_Lettuce
|
||||
Umbrella_Vendetta
|
||||
|
||||
|
||||
Wrap_SnowNinjaDark
|
||||
Wrap_333_StealthWoodland
|
||||
Wrap_UnknownNetwork
|
||||
Wrap_DyedBurst
|
||||
Wrap_210_Thermal
|
||||
Wrap_303_GasCloud
|
||||
|
||||
|
||||
Trails_ID_059_Sony2
|
||||
Trails_ID_123_TacticalWoodlandBlue
|
||||
Trails_ID_150_Avalanche
|
||||
|
||||
|
||||
OT11Banner
|
||||
OT10Banner
|
||||
OT9Banner
|
||||
OT8Banner
|
||||
OT7Banner
|
||||
OT6Banner
|
||||
OT5Banner
|
||||
OT4Banner
|
||||
OT3Banner
|
||||
OT2Banner
|
||||
OT1Banner
|
||||
OtherBanner51
|
||||
BRSeason01
|
||||
NewsletterBanner
|
||||
Winter2018Krampus
|
||||
Winter2018BearTrapFoot
|
||||
Winter2018Cooker
|
||||
Winter2018SnowmanBuried
|
||||
Winter2018CrownFlame
|
||||
Winter2018IcicleCluster
|
||||
Winter2018Tower
|
||||
Winter2018Wave30Complete
|
||||
Winter2018GingerbreadMan
|
||||
StarlightBanner6
|
||||
StarlightBanner5
|
||||
StarlightBanner4
|
||||
StarlightBanner3
|
||||
StarlightBanner2
|
||||
StarlightBanner1
|
||||
EnduranceWave30Theater04
|
||||
EnduranceWave30Theater03
|
||||
EnduranceWave30Theater02
|
||||
EnduranceWave30Theater01
|
||||
WargamesTprifts
|
||||
WargamesTiki
|
||||
WargamesPods
|
||||
SurvivalBannerStorm2018Med
|
||||
HordeBanner2018TwinePeaks
|
||||
SurvivalBannerStorm2018Stonewood
|
||||
WargamesAnomaly
|
||||
WargamesMeteor
|
||||
WargamesTornado
|
||||
AchievementUnspeakableHorrors
|
||||
AchievementWorldExplorer
|
||||
AchievementGuardianAngel
|
||||
AchievementPlaysWellWithOthers
|
||||
AchievementTalentedBuilder
|
||||
AchievementGoGnome
|
||||
AchievementLootLegend
|
||||
SurvivalBannerPlankertonComplete
|
||||
SurvivalBannerCannyValleyComplete
|
||||
SurvivalBannerStonewoodComplete
|
||||
InfluencerBanner1
|
||||
InfluencerBanner2
|
||||
InfluencerBanner3
|
||||
InfluencerBanner4
|
||||
InfluencerBanner5
|
||||
InfluencerBanner6
|
||||
InfluencerBanner7
|
||||
InfluencerBanner8
|
||||
InfluencerBanner9
|
||||
InfluencerBanner10
|
||||
InfluencerBanner11
|
||||
InfluencerBanner12
|
||||
InfluencerBanner13
|
||||
InfluencerBanner14
|
||||
InfluencerBanner15
|
||||
InfluencerBanner16
|
||||
InfluencerBanner17
|
||||
InfluencerBanner18
|
||||
InfluencerBanner19
|
||||
InfluencerBanner20
|
||||
InfluencerBanner21
|
||||
InfluencerBanner22
|
||||
InfluencerBanner23
|
||||
InfluencerBanner24
|
||||
InfluencerBanner25
|
||||
InfluencerBanner26
|
||||
InfluencerBanner27
|
||||
InfluencerBanner28
|
||||
InfluencerBanner29
|
||||
InfluencerBanner30
|
||||
InfluencerBanner31
|
||||
InfluencerBanner32
|
||||
InfluencerBanner33
|
||||
InfluencerBanner34
|
||||
InfluencerBanner35
|
||||
InfluencerBanner36
|
||||
InfluencerBanner37
|
||||
InfluencerBanner38
|
||||
InfluencerBanner39
|
||||
InfluencerBanner40
|
||||
InfluencerBanner41
|
||||
InfluencerBanner42
|
||||
InfluencerBanner43
|
||||
InfluencerBanner44
|
||||
InfluencerBanner45
|
||||
InfluencerBanner46
|
||||
InfluencerBanner47
|
||||
InfluencerBanner48
|
||||
InfluencerBanner49
|
||||
InfluencerBanner50
|
||||
InfluencerBanner51
|
||||
InfluencerBanner52
|
||||
InfluencerBanner53
|
||||
InfluencerBanner54
|
||||
InfluencerBanner55
|
||||
InfluencerBanner56
|
||||
InfluencerBanner57
|
||||
InfluencerBanner58
|
||||
BRS22_Showdown_Mae
|
||||
FounderTier5Banner1
|
||||
FounderTier5Banner2
|
||||
FounderTier5Banner3
|
||||
FounderTier5Banner4
|
||||
FounderTier5Banner5
|
||||
FounderTier4Banner1
|
||||
FounderTier4Banner2
|
||||
FounderTier4Banner3
|
||||
FounderTier4Banner4
|
||||
FounderTier4Banner5
|
||||
FounderTier3Banner1
|
||||
FounderTier3Banner2
|
||||
FounderTier3Banner3
|
||||
FounderTier3Banner4
|
||||
FounderTier3Banner5
|
||||
FounderTier2Banner1
|
||||
FounderTier2Banner2
|
||||
FounderTier2Banner3
|
||||
FounderTier2Banner4
|
||||
FounderTier2Banner5
|
||||
FounderTier1Banner1
|
||||
FounderTier1Banner2
|
||||
FounderTier1Banner3
|
||||
FounderTier1Banner4
|
||||
FounderTier1Banner5
|
||||
SurvivalBannerHolidayHard
|
||||
SurvivalBannerHolidayMed
|
||||
SurvivalBannerHolidayEasy
|
||||
SurvivalBannerStorm2018Hard
|
||||
SurvivalBannerStorm2018Med
|
||||
SurvivalBannerStorm2018Easy
|
||||
BRS10Level100
|
||||
BRS9Lvl100
|
||||
BRS8Level100
|
||||
NewsletterBanne
|
||||
BRWorldCup2019
|
||||
BRS23_FNCS_Drops
|
||||
BRS9Doggus
|
||||
BRS9Cattus
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
@@ -0,0 +1,148 @@
|
||||
Pickaxe_ID_376_FNCS
|
||||
Pickaxe_FNCS_S32
|
||||
CID_017_Athena_Commando_M
|
||||
CID_028_Athena_Commando_F
|
||||
Pickaxe_Lockjaw
|
||||
Glider_ID_001
|
||||
|
||||
|
||||
CID_619_Athena_Commando_F_TechLlama
|
||||
CID_035_Athena_Commando_M_Medieval
|
||||
CID_039_Athena_Commando_F_Disco
|
||||
CID_434_Athena_Commando_F_StealthHonor
|
||||
CID_757_Athena_Commando_F_WildCat
|
||||
CID_175_Athena_Commando_M_Celestial
|
||||
CID_703_Athena_Commando_M_Cyclone
|
||||
CID_761_Athena_Commando_M_CycloneSpace
|
||||
CID_515_Athena_Commando_M_BarbequeLarry
|
||||
CID_259_Athena_Commando_M_StreetOps
|
||||
|
||||
|
||||
CID_A_215_Athena_Commando_F_SunriseCastle_48TIZ
|
||||
CID_A_381_Athena_Commando_F_CactusRocker_3HTBV
|
||||
Character_TigerRootFame
|
||||
Character_Hitman_Dark
|
||||
Character_VoltaicHuntress
|
||||
Character_FallValleyBlink
|
||||
Character_FallValleyCharge
|
||||
Character_UpbeatIguana_D
|
||||
Character_UpbeatIguana
|
||||
CID_993_Athena_Commando_M_TyphoonRobot_2YRGV
|
||||
Character_StallionAviator
|
||||
CID_530_Athena_Commando_F_BlackMonday_1BV6J
|
||||
CID_A_138_Athena_Commando_F_Foray_YQPB0
|
||||
CID_A_205_Athena_Commando_F_TextileRam_GMRJ0
|
||||
CID_A_206_Athena_Commando_F_TextileSparkle_V8YSA
|
||||
CID_A_207_Athena_Commando_M_TextileKnight_9TE8L
|
||||
CID_A_208_Athena_Commando_M_TextilePup_C85OD
|
||||
CID_424_Athena_Commando_M_Vigilante
|
||||
CID_423_Athena_Commando_F_Painter
|
||||
CID_A_266_Athena_Commando_F_Grandeur_9CO1M
|
||||
CID_A_265_Athena_Commando_M_Grandeur_TBC0O
|
||||
Character_Hitman_Dark
|
||||
Character_BlueMystery_Dark
|
||||
Character_PinkTrooperDark
|
||||
Character_DarkVogue
|
||||
CID_A_256_Athena_Commando_F_UproarBraids_8IOZW
|
||||
CID_A_329_Athena_Commando_F_Uproar_I5N5Z
|
||||
CID_A_385_Athena_Commando_F_Rumble
|
||||
CID_A_162_Athena_Commando_F_Quarrel_E5D63
|
||||
CID_A_161_Athena_Commando_M_Quarrel_SLXQG
|
||||
CID_A_384_Athena_Commando_M_Rumble
|
||||
CID_A_024_Athena_Commando_F_Skirmish_QW2BQ
|
||||
CID_A_023_Athena_Commando_M_Skirmish_W1N7H
|
||||
CID_478_Athena_Commando_F_WorldCup
|
||||
Character_SpeedDialBattle
|
||||
CID_704_Athena_Commando_F_LollipopTrickster
|
||||
CID_715_Athena_Commando_F_TwinDark
|
||||
CID_A_047_Athena_Commando_F_Windwalker
|
||||
CID_805_Athena_Commando_F_PunkDevilSummer
|
||||
CID_801_Athena_Commando_F_GolfSummer
|
||||
CID_650_Athena_Commando_F_HolidayPJ_B
|
||||
Character_FauxVenom
|
||||
CID_365_Athena_Commando_M_LuckyRider
|
||||
CID_512_Athena_Commando_F_CubePaintRedKnight
|
||||
CID_653_Athena_Commando_F_UglySweaterFrozen
|
||||
Character_BrightIon
|
||||
CID_216_Athena_Commando_F_Medic
|
||||
CID_A_338_Athena_Commando_F_Galactic_HN9D
|
||||
Character_RedOasisPomegranate
|
||||
Character_RedOasisApricot
|
||||
CID_819_Athena_Commando_F_NeonTightSuit_B
|
||||
Character_SuperNovaTaro
|
||||
CID_A_096_Athena_Commando_F_TaxiUpgradedMulticolor
|
||||
CID_A_388_Athena_Commando_F_Lyrical
|
||||
CID_A_387_Athena_Commando_M_Lyrical
|
||||
CID_861_Athena_Commando_F_Elastic_B
|
||||
CID_A_250_Athena_Commando_F_ZombieElastic_B
|
||||
CID_A_443_Athena_Commando_F_PennantSeasOne_C
|
||||
CID_A_444_Athena_Commando_F_PennantSeasOne_D
|
||||
CID_A_441_Athena_Commando_F_PennantSeasOne
|
||||
|
||||
|
||||
CID_065_Athena_Commando_F_SkiGirl_FRA
|
||||
CID_062_Athena_Commando_F_SkiGirl_USA
|
||||
CID_066_Athena_Commando_F_SkiGirl_GER
|
||||
CID_064_Athena_Commando_F_SkiGirl_GBR
|
||||
CID_063_Athena_Commando_F_SkiGirl_CAN
|
||||
CID_068_Athena_Commando_F_SkiGirl_KOR
|
||||
|
||||
|
||||
Character_ReconExpert_FNCS
|
||||
Character_GarbageFNCS
|
||||
Character_TreasureHunterFashionsFNCS
|
||||
Character_LeatherKey
|
||||
CID_888_Athena_Commando_F_ChOneBanshee
|
||||
CID_889_Athena_Commando_F_ChOneWildcat
|
||||
CID_884_Athena_Commando_F_ChOneRamirez
|
||||
CID_885_Athena_Commando_M_ChOneHawk
|
||||
|
||||
|
||||
BID_138_Celestial
|
||||
BID_004_BlackKnight
|
||||
BID_229_LuckyRiderMale
|
||||
BID_468_Cyclone
|
||||
BID_273_AssassinSuitCoin
|
||||
|
||||
|
||||
Pickaxe_ID_294_CandyCane
|
||||
Pickaxe_ID_508_HistorianMale_6BQSW
|
||||
Pickaxe_ID_363_LollipopTricksterFemale
|
||||
HalloweenScythe
|
||||
Pickaxe_ID_015_HolidayCandyCane
|
||||
Pickaxe_ID_599_CavernFemale
|
||||
Pickaxe_ID_804_FNCSS20Male
|
||||
Pickaxe_ID_138_Gnome
|
||||
Pickaxe_SlowBurn
|
||||
Pickaxe_IronBlaze
|
||||
Pickaxe_ID_074_SharpDresser
|
||||
Pickaxe_ID_014_WinterCamo
|
||||
Pickaxe_ID_359_CycloneMale
|
||||
Pickaxe_ID_475_ChOnePickaxe
|
||||
|
||||
|
||||
EID_Fresh
|
||||
EID_Floss
|
||||
EID_TakeTheL
|
||||
EID_CycloneHeadBang
|
||||
EID_SpeedDial
|
||||
EID_JanuaryBop
|
||||
EID_Devotion
|
||||
EID_Laugh
|
||||
EID_Griddles
|
||||
EID_Coping
|
||||
EID_Cyclone
|
||||
EID_JanuaryBop
|
||||
EID_Punctual
|
||||
EID_Breakdance2
|
||||
EID_Jaywalking
|
||||
EID_PlayerEleven
|
||||
EID_HipHop01
|
||||
EID_GoodVibes
|
||||
EID_SandwichBop
|
||||
EID_LetsPlay
|
||||
|
||||
|
||||
Glider_ID_314_SpaceChimpMale
|
||||
Glider_Warthog
|
||||
Glider_ID_244_ChOneGlider
|
||||
@@ -0,0 +1 @@
|
||||
import os
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.7 KiB |