chore(cod_api_tool.py): remove whitespace & add try except for cleaning match_info and stats files
This commit is contained in:
parent
61b910ab45
commit
dfc647e500
325
cod_api_tool.py
325
cod_api_tool.py
@ -24,13 +24,13 @@ api = API()
|
||||
|
||||
class CodStatsManager:
|
||||
"""Main class to manage COD API interactions and data processing."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self._ensure_directories_exist()
|
||||
self.replacements = self._load_replacements()
|
||||
self.api_key = self._get_api_key()
|
||||
api.login(self.api_key)
|
||||
|
||||
|
||||
def _ensure_directories_exist(self):
|
||||
"""Ensure necessary directories exist."""
|
||||
if not os.path.exists(STATS_DIR):
|
||||
@ -38,7 +38,7 @@ class CodStatsManager:
|
||||
match_dir_path = os.path.join(STATS_DIR, MATCH_DIR)
|
||||
if not os.path.exists(match_dir_path):
|
||||
os.makedirs(match_dir_path)
|
||||
|
||||
|
||||
def _load_replacements(self):
|
||||
"""Load replacements from the JSON file."""
|
||||
# First, handle running as PyInstaller executable
|
||||
@ -49,13 +49,13 @@ class CodStatsManager:
|
||||
else:
|
||||
# If running as a normal Python script
|
||||
replacements_path = REPLACEMENTS_FILE
|
||||
|
||||
|
||||
if not os.path.exists(replacements_path):
|
||||
raise FileNotFoundError(f"{replacements_path} not found. Ensure it exists in the script's directory.")
|
||||
|
||||
|
||||
with open(replacements_path, 'r') as file:
|
||||
return json.load(file)
|
||||
|
||||
|
||||
def _get_api_key(self):
|
||||
"""Get API key from file or user input."""
|
||||
if os.path.exists(COOKIE_FILE):
|
||||
@ -66,13 +66,13 @@ class CodStatsManager:
|
||||
with open(COOKIE_FILE, 'w') as f:
|
||||
f.write(api_key)
|
||||
return api_key
|
||||
|
||||
|
||||
def _extract_player_name(self, full_name):
|
||||
"""Extract just the player name part before the # symbol."""
|
||||
if '#' in full_name:
|
||||
return full_name.split('#')[0]
|
||||
return full_name
|
||||
|
||||
|
||||
def save_to_file(self, data, filename, player_name=None):
|
||||
"""Save data to a JSON file with player name in the filename if provided."""
|
||||
if player_name:
|
||||
@ -81,68 +81,68 @@ class CodStatsManager:
|
||||
# Insert player name before the extension
|
||||
base, ext = os.path.splitext(filename)
|
||||
filename = f"{base}-{player_name_clean}{ext}"
|
||||
|
||||
|
||||
file_path = os.path.join(STATS_DIR, filename)
|
||||
|
||||
|
||||
# Ensure data is JSON serializable before saving
|
||||
serializable_data = self._ensure_json_serializable(data)
|
||||
|
||||
|
||||
with open(file_path, 'w') as json_file:
|
||||
json.dump(serializable_data, json_file, indent=4)
|
||||
print(f"Data saved to {file_path}")
|
||||
|
||||
|
||||
return file_path # Return the path for potential YAML conversion
|
||||
|
||||
|
||||
def get_player_name(self):
|
||||
"""Get player name from user input."""
|
||||
return input("Please enter the player's username (with #1234567): ")
|
||||
|
||||
|
||||
def fetch_data(self, player_name=None, convert_to_yaml=False, delete_json=False, **options):
|
||||
"""Fetch data based on specified options."""
|
||||
if not player_name:
|
||||
player_name = self.get_player_name()
|
||||
|
||||
|
||||
# If no specific option is selected, fetch basic stats
|
||||
if not any(options.values()):
|
||||
saved_files = self._fetch_basic_stats(player_name)
|
||||
if convert_to_yaml:
|
||||
self.convert_files_to_yaml(saved_files, delete_json)
|
||||
return
|
||||
|
||||
|
||||
# If all_stats option is selected, fetch everything
|
||||
if options.get('all_stats'):
|
||||
saved_files = self._fetch_all_stats(player_name)
|
||||
if convert_to_yaml:
|
||||
self.convert_files_to_yaml(saved_files, delete_json)
|
||||
return
|
||||
|
||||
|
||||
# Otherwise, fetch only requested data
|
||||
saved_files = self._fetch_specific_data(player_name, options)
|
||||
if convert_to_yaml:
|
||||
self.convert_files_to_yaml(saved_files, delete_json)
|
||||
|
||||
|
||||
def _fetch_basic_stats(self, player_name):
|
||||
"""Fetch basic player stats and match history."""
|
||||
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||
|
||||
|
||||
saved_files = []
|
||||
saved_files.append(self.save_to_file(player_stats, 'stats.json', player_name))
|
||||
saved_files.append(self.save_to_file(match_info, 'match_info.json', player_name))
|
||||
|
||||
|
||||
return saved_files
|
||||
|
||||
|
||||
def _fetch_all_stats(self, player_name):
|
||||
"""Fetch all available stats for a player."""
|
||||
# Basic stats
|
||||
player_stats = api.ModernWarfare.fullData(platforms.Activision, player_name)
|
||||
match_info = api.ModernWarfare.combatHistory(platforms.Activision, player_name)
|
||||
season_loot_data = api.ModernWarfare.seasonLoot(platforms.Activision, player_name)
|
||||
|
||||
|
||||
# Player-specific data
|
||||
identities_data = api.Me.loggedInIdentities()
|
||||
map_list = api.ModernWarfare.mapList(platforms.Activision)
|
||||
|
||||
|
||||
# Save basic data
|
||||
saved_files = []
|
||||
saved_files.append(self.save_to_file(player_stats, 'stats.json', player_name))
|
||||
@ -150,7 +150,7 @@ class CodStatsManager:
|
||||
saved_files.append(self.save_to_file(season_loot_data, 'season_loot.json'))
|
||||
saved_files.append(self.save_to_file(map_list, 'map_list.json'))
|
||||
saved_files.append(self.save_to_file(identities_data, 'identities.json'))
|
||||
|
||||
|
||||
# Check if userInfo.json exists to determine if we should fetch additional data
|
||||
user_info_file = os.path.join('userInfo.json')
|
||||
if os.path.exists(user_info_file):
|
||||
@ -169,9 +169,9 @@ class CodStatsManager:
|
||||
saved_files.append(self.save_to_file(cod_points, 'cp.json'))
|
||||
saved_files.append(self.save_to_file(connected_accounts, 'connectedAccounts.json'))
|
||||
saved_files.append(self.save_to_file(settings, 'settings.json'))
|
||||
|
||||
|
||||
return saved_files
|
||||
|
||||
|
||||
def _fetch_specific_data(self, player_name, options):
|
||||
"""Fetch specific data based on provided options."""
|
||||
endpoints = {
|
||||
@ -185,16 +185,16 @@ class CodStatsManager:
|
||||
'connected_accounts': (api.Me.connectedAccounts, [], 'connectedAccounts.json'),
|
||||
'settings': (api.Me.settings, [], 'settings.json')
|
||||
}
|
||||
|
||||
|
||||
saved_files = []
|
||||
for option, value in options.items():
|
||||
if value and option in endpoints:
|
||||
func, args, filename = endpoints[option]
|
||||
data = func(*args)
|
||||
saved_files.append(self.save_to_file(data, filename, player_name))
|
||||
|
||||
|
||||
return saved_files
|
||||
|
||||
|
||||
def convert_files_to_yaml(self, file_paths=None, delete_json=False):
|
||||
"""
|
||||
Convert specific JSON files to YAML format.
|
||||
@ -216,23 +216,23 @@ class CodStatsManager:
|
||||
if os.path.exists(json_path) and json_path.endswith(".json"):
|
||||
yaml_path = self._convert_json_file_to_yaml(json_path)
|
||||
converted_files.append((json_path, yaml_path))
|
||||
|
||||
|
||||
# Delete JSON files if requested
|
||||
if delete_json:
|
||||
for json_path, _ in converted_files:
|
||||
os.remove(json_path)
|
||||
print(f"Deleted: {json_path}")
|
||||
|
||||
|
||||
return converted_files
|
||||
|
||||
|
||||
def _convert_json_file_to_yaml(self, json_path):
|
||||
"""Convert a single JSON file to YAML format."""
|
||||
yaml_path = json_path.replace(".json", ".yaml")
|
||||
|
||||
|
||||
# Read JSON file
|
||||
with open(json_path, 'r') as json_file:
|
||||
data = json.load(json_file)
|
||||
|
||||
|
||||
# Write YAML file
|
||||
with open(yaml_path, 'w', encoding='utf-8') as yaml_file:
|
||||
yaml.dump(
|
||||
@ -248,75 +248,92 @@ class CodStatsManager:
|
||||
line_break="unix",
|
||||
indent=2
|
||||
)
|
||||
|
||||
|
||||
print(f"Converted: {json_path} --> {yaml_path}")
|
||||
return yaml_path
|
||||
|
||||
|
||||
def beautify_all_data(self, timezone='GMT', player_name=None):
|
||||
"""Beautify all data files."""
|
||||
self.beautify_stats_data(timezone, player_name)
|
||||
self.beautify_match_data(timezone, player_name)
|
||||
self.beautify_feed_data(timezone)
|
||||
self.clean_json_files('friendFeed.json', 'eventFeed.json')
|
||||
print("All data beautified successfully.")
|
||||
|
||||
print("Data beautified successfully.")
|
||||
|
||||
def beautify_stats_data(self, timezone='GMT', player_name=None):
|
||||
"""Beautify stats data."""
|
||||
if player_name:
|
||||
file_name = f'stats-{self._extract_player_name(player_name)}.json'
|
||||
else:
|
||||
file_name = 'stats.json'
|
||||
|
||||
file_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"File {file_path} not found. Skipping beautification.")
|
||||
return
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
# Convert times and durations
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
# Replace keys with more readable names
|
||||
data = self._recursive_key_replace(data)
|
||||
|
||||
# Sort data by relevant metrics
|
||||
data = self._sort_data(data)
|
||||
|
||||
# Save modified data
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
print(f"Keys sorted and replaced in {file_path}.")
|
||||
|
||||
if player_name is None:
|
||||
print("Please specify a Player Name to sort Stats")
|
||||
return 0
|
||||
try:
|
||||
if player_name:
|
||||
file_name = f'stats-{self._extract_player_name(player_name)}.json'
|
||||
# else:
|
||||
# file_name = 'stats.json'
|
||||
|
||||
file_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"File {file_path} not found. Skipping beautification.")
|
||||
return
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
# Convert times and durations
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
# Replace keys with more readable names
|
||||
data = self._recursive_key_replace(data)
|
||||
|
||||
# Sort data by relevant metrics
|
||||
data = self._sort_data(data)
|
||||
|
||||
# Save modified data
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
print(f"Keys sorted and replaced in {file_path}.")
|
||||
|
||||
except Exception as e:
|
||||
print("An error occurred while processing match data.")
|
||||
return 0
|
||||
|
||||
def beautify_match_data(self, timezone='GMT', player_name=None):
|
||||
"""Beautify match data."""
|
||||
if player_name:
|
||||
file_name = f'match_info-{self._extract_player_name(player_name)}.json'
|
||||
else:
|
||||
file_name = 'match_info.json'
|
||||
|
||||
file_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"File {file_path} not found. Skipping beautification.")
|
||||
return
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
# Convert times and durations
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
# Replace keys with more readable names
|
||||
data = self._recursive_key_replace(data)
|
||||
|
||||
# Save modified data
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
print(f"Keys replaced in {file_path}.")
|
||||
|
||||
if player_name is None:
|
||||
print("Please specify a Player Name to sort Match Info")
|
||||
return 0
|
||||
|
||||
try:
|
||||
if player_name:
|
||||
file_name = f'match_info-{self._extract_player_name(player_name)}.json'
|
||||
# else:
|
||||
# file_name = 'match_info.json'
|
||||
|
||||
file_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"File {file_path} not found. Skipping beautification.")
|
||||
return
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
# Convert times and durations
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
# Replace keys with more readable names
|
||||
data = self._recursive_key_replace(data)
|
||||
|
||||
# Save modified data
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
print(f"Keys replaced in {file_path}.")
|
||||
|
||||
except Exception as e:
|
||||
print("An error occurred while processing match data.")
|
||||
return 0
|
||||
|
||||
def beautify_feed_data(self, timezone='GMT', player_name=None):
|
||||
"""Beautify feed data files."""
|
||||
for feed_file_base in ['friendFeed.json', 'eventFeed.json']:
|
||||
@ -325,48 +342,48 @@ class CodStatsManager:
|
||||
file_name = f"{feed_file_base.replace('.json', '')}-{clean_name}.json"
|
||||
else:
|
||||
file_name = feed_file_base
|
||||
|
||||
|
||||
file_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"{file_name} does not exist, skipping.")
|
||||
continue
|
||||
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
|
||||
# Convert times and durations
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
|
||||
# Replace keys with more readable names
|
||||
data = self._recursive_key_replace(data)
|
||||
|
||||
|
||||
# Save modified data
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
|
||||
print(f"Keys sorted and replaced in {file_name}.")
|
||||
|
||||
|
||||
def split_matches_into_files(self, timezone='GMT', player_name=None):
|
||||
"""Split match data into separate files."""
|
||||
matches_dir = os.path.join(STATS_DIR, MATCH_DIR)
|
||||
if not os.path.exists(matches_dir):
|
||||
os.makedirs(matches_dir)
|
||||
|
||||
|
||||
file_name = f'match_info-{self._extract_player_name(player_name)}.json'
|
||||
|
||||
|
||||
match_info_path = os.path.join(STATS_DIR, file_name)
|
||||
if not os.path.exists(match_info_path):
|
||||
print(f"Match info file not found at {match_info_path}. Skipping split.")
|
||||
return
|
||||
|
||||
|
||||
with open(match_info_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
matches = data.get('data', {}).get('matches', [])
|
||||
|
||||
|
||||
if not matches:
|
||||
print("No matches found to split.")
|
||||
return
|
||||
|
||||
|
||||
# Check if time conversion is needed
|
||||
sample_match = matches[0]
|
||||
needs_time_conversion = (
|
||||
@ -374,62 +391,62 @@ class CodStatsManager:
|
||||
isinstance(sample_match.get("utcEndSeconds"), int) or
|
||||
isinstance(sample_match.get("duration"), int)
|
||||
)
|
||||
|
||||
|
||||
if needs_time_conversion:
|
||||
print("Converting match timestamps to human-readable format...")
|
||||
self._replace_time_and_duration_recursive(data, timezone)
|
||||
|
||||
|
||||
# Update the main match file
|
||||
with open(match_info_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
|
||||
|
||||
# Process each match
|
||||
for idx, match in enumerate(matches):
|
||||
# Create a copy to avoid modifying the original data
|
||||
match_copy = dict(match)
|
||||
|
||||
|
||||
# Remove large loadout data to keep files smaller
|
||||
if 'player' in match_copy:
|
||||
match_copy['player'].pop('loadouts', None)
|
||||
match_copy['player'].pop('loadout', None)
|
||||
|
||||
|
||||
# Save to individual file
|
||||
file_name = f"match_{idx + 1}.json"
|
||||
file_path = os.path.join(matches_dir, file_name)
|
||||
with open(file_path, 'w') as match_file:
|
||||
json.dump(match_copy, match_file, indent=4)
|
||||
|
||||
|
||||
print(f"Matches split into {len(matches)} separate files in {matches_dir}.")
|
||||
|
||||
|
||||
def clean_json_files(self, *filenames, player_name=None):
|
||||
"""Clean JSON files by removing HTML-like tags and entities."""
|
||||
regex_pattern = r'<span class="|</span>|">|mp-stat-items|kills-value|headshots-value|username|game-mode|kdr-value|accuracy-value|defends-value'
|
||||
replace = ''
|
||||
|
||||
|
||||
for base_filename in filenames:
|
||||
if player_name:
|
||||
clean_name = self._extract_player_name(player_name)
|
||||
filename = f"{base_filename.replace('.json', '')}-{clean_name}.json"
|
||||
else:
|
||||
filename = base_filename
|
||||
|
||||
|
||||
file_path = os.path.join(STATS_DIR, filename)
|
||||
if not os.path.exists(file_path):
|
||||
print(f"{filename} does not exist, skipping.")
|
||||
continue
|
||||
|
||||
|
||||
with open(file_path, 'r') as file:
|
||||
content = file.read()
|
||||
|
||||
|
||||
# Replace unwanted patterns
|
||||
modified_content = re.sub(regex_pattern, replace, content)
|
||||
|
||||
|
||||
# Save cleaned content
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(modified_content)
|
||||
|
||||
|
||||
print(f"Removed unreadable strings from {filename}.")
|
||||
|
||||
|
||||
def _recursive_key_replace(self, obj):
|
||||
"""Recursively replace keys and values with more readable versions."""
|
||||
if isinstance(obj, dict):
|
||||
@ -446,7 +463,7 @@ class CodStatsManager:
|
||||
return [self._recursive_key_replace(item) for item in obj]
|
||||
else:
|
||||
return self.replacements.get(obj, obj) if isinstance(obj, str) else obj
|
||||
|
||||
|
||||
def _sort_data(self, data):
|
||||
"""Sort data by meaningful metrics for better readability."""
|
||||
if isinstance(data, dict):
|
||||
@ -492,7 +509,7 @@ class CodStatsManager:
|
||||
# Recursively sort nested data
|
||||
data[key] = self._sort_data(value)
|
||||
return data
|
||||
|
||||
|
||||
def _replace_time_and_duration_recursive(self, data, timezone):
|
||||
"""Recursively replace epoch times with human-readable formats."""
|
||||
time_keys = [
|
||||
@ -500,12 +517,12 @@ class CodStatsManager:
|
||||
"avgLifeTime", "percentTimeMoving"
|
||||
]
|
||||
date_keys = ["date", "updated", "originalDate", "dateAdded"]
|
||||
|
||||
|
||||
if isinstance(data, list):
|
||||
# Sort lists containing items with dateAdded
|
||||
if data and isinstance(data[0], dict) and "dateAdded" in data[0]:
|
||||
data.sort(key=lambda x: x.get("dateAdded", 0), reverse=True)
|
||||
|
||||
|
||||
for item in data:
|
||||
self._replace_time_and_duration_recursive(item, timezone)
|
||||
elif isinstance(data, dict):
|
||||
@ -525,20 +542,20 @@ class CodStatsManager:
|
||||
data[key] = self._convert_duration_milliseconds(value)
|
||||
else:
|
||||
self._replace_time_and_duration_recursive(value, timezone)
|
||||
|
||||
|
||||
def _epoch_milli_to_human_readable(self, epoch_millis, timezone='GMT'):
|
||||
"""Convert epoch milliseconds to human-readable date string."""
|
||||
if isinstance(epoch_millis, str):
|
||||
return epoch_millis
|
||||
|
||||
|
||||
dt_object = datetime.datetime.utcfromtimestamp(epoch_millis / 1000.0)
|
||||
return self._format_datetime(dt_object, timezone)
|
||||
|
||||
|
||||
def _epoch_to_human_readable(self, epoch_timestamp, timezone='GMT'):
|
||||
"""Convert epoch seconds to human-readable date string."""
|
||||
if isinstance(epoch_timestamp, str):
|
||||
return epoch_timestamp
|
||||
|
||||
|
||||
dt_object = datetime.datetime.utcfromtimestamp(epoch_timestamp)
|
||||
return self._format_datetime(dt_object, timezone)
|
||||
|
||||
@ -550,39 +567,39 @@ class CodStatsManager:
|
||||
'CST': -6, # Updated for consistency
|
||||
'PST': -8
|
||||
}
|
||||
|
||||
|
||||
if timezone not in timezone_offsets:
|
||||
raise ValueError(f"Unsupported timezone: {timezone}")
|
||||
|
||||
|
||||
# Apply timezone offset
|
||||
dt_object = dt_object + datetime.timedelta(hours=timezone_offsets[timezone])
|
||||
|
||||
|
||||
# Format date string
|
||||
return f"{timezone}: {dt_object.strftime('%A, %B %d, %Y %I:%M:%S %p')}"
|
||||
|
||||
|
||||
def _convert_duration_milliseconds(self, milliseconds):
|
||||
"""Convert milliseconds to a human-readable duration string."""
|
||||
if isinstance(milliseconds, str) and "Minutes" in milliseconds:
|
||||
return milliseconds # Already converted
|
||||
|
||||
|
||||
seconds, milliseconds = divmod(milliseconds, 1000)
|
||||
minutes, seconds = divmod(seconds, 60)
|
||||
return f"{minutes} Minutes {seconds} Seconds {milliseconds} Milliseconds"
|
||||
|
||||
|
||||
def _convert_duration_seconds(self, seconds):
|
||||
"""Convert seconds to a human-readable duration string."""
|
||||
if isinstance(seconds, str):
|
||||
return seconds # Already converted
|
||||
|
||||
|
||||
days, seconds = divmod(seconds, 86400)
|
||||
hours, seconds = divmod(seconds, 3600)
|
||||
minutes, seconds = divmod(seconds, 60)
|
||||
|
||||
|
||||
days = int(days)
|
||||
hours = int(hours)
|
||||
minutes = int(minutes)
|
||||
seconds = int(seconds)
|
||||
|
||||
|
||||
return f"{days} Days {hours} Hours {minutes} Minutes {seconds} Seconds"
|
||||
|
||||
def _ensure_json_serializable(self, obj):
|
||||
@ -601,7 +618,7 @@ class CodStatsManager:
|
||||
|
||||
class CLI:
|
||||
"""Command Line Interface manager."""
|
||||
|
||||
|
||||
def __init__(self, stats_manager):
|
||||
self.stats_manager = stats_manager
|
||||
self.help_text = """
|
||||
@ -611,7 +628,7 @@ class CLI:
|
||||
- Once logged in, press F12 for your browsers developer tools. Then go to Application --> Storage --> Cookies --> https://www.callofduty.com and find ACT_SSO_COOKIE
|
||||
- Enter the value when prompted
|
||||
"""
|
||||
|
||||
|
||||
def display_menu(self):
|
||||
"""Display the main menu and get user choice."""
|
||||
print("\nBeautify Options:")
|
||||
@ -631,7 +648,7 @@ class CLI:
|
||||
print("\nOptions Not Requiring Player Name:")
|
||||
print("11) Get season loot")
|
||||
print("12) Get map list")
|
||||
|
||||
|
||||
print("\nYAML Conversion Options:")
|
||||
print("13) Convert all JSON files to YAML")
|
||||
print("14) Convert all JSON files to YAML and delete JSON files")
|
||||
@ -644,20 +661,20 @@ class CLI:
|
||||
except ValueError:
|
||||
print("Please enter a valid number.")
|
||||
return -1
|
||||
|
||||
|
||||
def handle_menu_choice(self, choice):
|
||||
"""Handle the user's menu choice."""
|
||||
if choice == 0:
|
||||
print("Exiting...")
|
||||
return False
|
||||
|
||||
|
||||
if choice in [3, 4, 5, 6, 7, 8, 9, 10, 11]:
|
||||
player_name = input("Please enter the player's username (with #1234567): ")
|
||||
# convert_to_yaml = input("Convert results to YAML? (y/n): ").lower() == 'y'
|
||||
# delete_json = False
|
||||
# if convert_to_yaml:
|
||||
# delete_json = input("Delete JSON files after conversion? (y/n): ").lower() == 'y'
|
||||
|
||||
|
||||
options = {
|
||||
3: {'all_stats': True},
|
||||
4: {'season_loot': True},
|
||||
@ -669,12 +686,12 @@ class CLI:
|
||||
10: {'connected_accounts': True},
|
||||
11: {'settings': True}
|
||||
}
|
||||
|
||||
|
||||
if choice in options:
|
||||
self.stats_manager.fetch_data(player_name=player_name, **options[choice])
|
||||
# self.stats_manager.fetch_data(player_name=player_name, convert_to_yaml=convert_to_yaml,
|
||||
# delete_json=delete_json, **options[choice])
|
||||
|
||||
|
||||
elif choice == 1:
|
||||
player_name = input("Enter player name for beautification (leave blank if not player-specific): ")
|
||||
self.stats_manager.beautify_all_data(player_name=player_name if player_name else None)
|
||||
@ -689,16 +706,16 @@ class CLI:
|
||||
else:
|
||||
print("Invalid choice. Please try again.")
|
||||
return True
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def run_interactive_mode(self):
|
||||
"""Run the interactive menu mode."""
|
||||
running = True
|
||||
while running:
|
||||
choice = self.display_menu()
|
||||
running = self.handle_menu_choice(choice)
|
||||
|
||||
|
||||
def setup_argument_parser(self):
|
||||
"""Set up command line argument parser."""
|
||||
parser = argparse.ArgumentParser(
|
||||
@ -706,13 +723,13 @@ class CLI:
|
||||
epilog=self.help_text,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
|
||||
|
||||
# Group arguments for better help display
|
||||
group_default = parser.add_argument_group("Default Options")
|
||||
group_data = parser.add_argument_group("Data Fetching Options")
|
||||
group_cleaning = parser.add_argument_group("Data Cleaning Options")
|
||||
group_yaml = parser.add_argument_group("YAML Conversion Options")
|
||||
|
||||
|
||||
# Default options
|
||||
group_default.add_argument(
|
||||
"-tz", "--timezone",
|
||||
@ -721,7 +738,7 @@ class CLI:
|
||||
choices=TIMEZONE_OPTIONS,
|
||||
help="Specify the timezone (GMT, EST, CST, PST)"
|
||||
)
|
||||
|
||||
|
||||
# Data fetching options
|
||||
group_data.add_argument("-p", "--player_name", type=str, help="Player's username (with #1234567)")
|
||||
group_data.add_argument("-a", "--all_stats", action="store_true", help="Fetch all the different types of stats data")
|
||||
@ -734,7 +751,7 @@ class CLI:
|
||||
group_data.add_argument("-cp", "--cod_points", action="store_true", help="Fetch only your COD Point balance")
|
||||
group_data.add_argument("-ca", "--connected_accounts", action="store_true", help="Fetch only connected accounts data")
|
||||
group_data.add_argument("-s", "--settings", action="store_true", help="Fetch only your account settings")
|
||||
|
||||
|
||||
# Data cleaning options
|
||||
group_cleaning.add_argument("-c", "--clean", action="store_true", help="Beautify all data")
|
||||
group_cleaning.add_argument("-sm", "--split_matches", action="store_true", help="Split matches into separate JSON files")
|
||||
@ -742,13 +759,13 @@ class CLI:
|
||||
group_cleaning.add_argument("-cmd", "--clean_match_data", action="store_true", help="Beautify match_info.json data")
|
||||
group_cleaning.add_argument("-cff", "--clean_friend_feed", action="store_true", help="Clean friend feed data")
|
||||
group_cleaning.add_argument("-cef", "--clean_event_feed", action="store_true", help="Clean event feed data")
|
||||
|
||||
|
||||
# YAML conversion options
|
||||
group_yaml.add_argument("-y", "--yaml", action="store_true", help="Convert JSON files to YAML")
|
||||
group_yaml.add_argument("-d", "--delete_json", action="store_true", help="Delete JSON files after YAML conversion")
|
||||
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def run_cli_mode(self, args):
|
||||
"""Run the command line mode with parsed arguments."""
|
||||
# Check if only YAML conversion is requested
|
||||
@ -761,7 +778,7 @@ class CLI:
|
||||
]):
|
||||
self.stats_manager.convert_files_to_yaml(delete_json=args.delete_json)
|
||||
return
|
||||
|
||||
|
||||
# Prioritize cleaning operations
|
||||
if args.clean:
|
||||
self.stats_manager.beautify_all_data(timezone=args.timezone, player_name=args.player_name)
|
||||
@ -800,7 +817,7 @@ def main():
|
||||
"""Main entry point for the application."""
|
||||
stats_manager = CodStatsManager()
|
||||
cli = CLI(stats_manager)
|
||||
|
||||
|
||||
# Parse command line arguments
|
||||
if len(sys.argv) > 1:
|
||||
parser = cli.setup_argument_parser()
|
||||
|
Loading…
x
Reference in New Issue
Block a user