Files
LEDMatrix/test/check_soccer_logos.py
2025-09-16 14:31:31 -04:00

316 lines
9.8 KiB
Python

#!/usr/bin/env python3
"""
Soccer Logo Checker and Downloader
This script checks for missing logos of major teams from supported soccer leagues
and downloads them from ESPN API if missing.
Supported Leagues:
- Premier League (eng.1)
- La Liga (esp.1)
- Bundesliga (ger.1)
- Serie A (ita.1)
- Ligue 1 (fra.1)
- Liga Portugal (por.1)
- Champions League (uefa.champions)
- Europa League (uefa.europa)
- MLS (usa.1)
"""
import os
import sys
import logging
from pathlib import Path
from typing import Dict, List, Tuple
# Add src directory to path for imports
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'src'))
from logo_downloader import download_missing_logo, get_soccer_league_key, LogoDownloader
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# Major teams for each league (with their ESPN abbreviations)
MAJOR_TEAMS = {
'eng.1': { # Premier League
'ARS': 'Arsenal',
'AVL': 'Aston Villa',
'BHA': 'Brighton & Hove Albion',
'BOU': 'AFC Bournemouth',
'BRE': 'Brentford',
'BUR': 'Burnley',
'CHE': 'Chelsea',
'CRY': 'Crystal Palace',
'EVE': 'Everton',
'FUL': 'Fulham',
'LIV': 'Liverpool',
'LUT': 'Luton Town',
'MCI': 'Manchester City',
'MUN': 'Manchester United',
'NEW': 'Newcastle United',
'NFO': 'Nottingham Forest',
'SHU': 'Sheffield United',
'TOT': 'Tottenham Hotspur',
'WHU': 'West Ham United',
'WOL': 'Wolverhampton Wanderers'
},
'esp.1': { # La Liga
'ALA': 'Alavés',
'ATH': 'Athletic Bilbao',
'ATM': 'Atlético Madrid',
'BAR': 'Barcelona',
'BET': 'Real Betis',
'CEL': 'Celta Vigo',
'ESP': 'Espanyol',
'GET': 'Getafe',
'GIR': 'Girona',
'LEG': 'Leganés',
'RAY': 'Rayo Vallecano',
'RMA': 'Real Madrid',
'SEV': 'Sevilla',
'VAL': 'Valencia',
'VLD': 'Valladolid'
},
'ger.1': { # Bundesliga
'BOC': 'VfL Bochum',
'DOR': 'Borussia Dortmund',
'FCA': 'FC Augsburg',
'FCB': 'Bayern Munich',
'FCU': 'FC Union Berlin',
'KOL': '1. FC Köln',
'LEV': 'Bayer Leverkusen',
'M05': 'Mainz 05',
'RBL': 'RB Leipzig',
'SCF': 'SC Freiburg',
'SGE': 'Eintracht Frankfurt',
'STU': 'VfB Stuttgart',
'SVW': 'Werder Bremen',
'TSG': 'TSG Hoffenheim',
'WOB': 'VfL Wolfsburg'
},
'ita.1': { # Serie A
'ATA': 'Atalanta',
'CAG': 'Cagliari',
'EMP': 'Empoli',
'FIO': 'Fiorentina',
'INT': 'Inter Milan',
'JUV': 'Juventus',
'LAZ': 'Lazio',
'MIL': 'AC Milan',
'MON': 'Monza',
'NAP': 'Napoli',
'ROM': 'Roma',
'TOR': 'Torino',
'UDI': 'Udinese',
'VER': 'Hellas Verona'
},
'fra.1': { # Ligue 1
'LIL': 'Lille',
'LYON': 'Lyon',
'MAR': 'Marseille',
'MON': 'Monaco',
'NAN': 'Nantes',
'NICE': 'Nice',
'OL': 'Olympique Lyonnais',
'OM': 'Olympique de Marseille',
'PAR': 'Paris Saint-Germain',
'PSG': 'Paris Saint-Germain',
'REN': 'Rennes',
'STR': 'Strasbourg'
},
'por.1': { # Liga Portugal
'ARO': 'Arouca',
'BEN': 'SL Benfica',
'BRA': 'SC Braga',
'CHA': 'Chaves',
'EST': 'Estoril Praia',
'FAM': 'Famalicão',
'GIL': 'Gil Vicente',
'MOR': 'Moreirense',
'POR': 'FC Porto',
'PTM': 'Portimonense',
'RIO': 'Rio Ave',
'SR': 'Sporting CP',
'SCP': 'Sporting CP', # Alternative abbreviation
'VGU': 'Vitória de Guimarães',
'VSC': 'Vitória de Setúbal'
},
'uefa.champions': { # Champions League (major teams)
'AJX': 'Ajax',
'ATM': 'Atlético Madrid',
'BAR': 'Barcelona',
'BAY': 'Bayern Munich',
'CHE': 'Chelsea',
'INT': 'Inter Milan',
'JUV': 'Juventus',
'LIV': 'Liverpool',
'MCI': 'Manchester City',
'MUN': 'Manchester United',
'PSG': 'Paris Saint-Germain',
'RMA': 'Real Madrid',
'TOT': 'Tottenham Hotspur'
},
'uefa.europa': { # Europa League (major teams)
'ARS': 'Arsenal',
'ATM': 'Atlético Madrid',
'BAR': 'Barcelona',
'CHE': 'Chelsea',
'INT': 'Inter Milan',
'JUV': 'Juventus',
'LIV': 'Liverpool',
'MUN': 'Manchester United',
'NAP': 'Napoli',
'ROM': 'Roma',
'SEV': 'Sevilla'
},
'usa.1': { # MLS
'ATL': 'Atlanta United',
'AUS': 'Austin FC',
'CHI': 'Chicago Fire',
'CIN': 'FC Cincinnati',
'CLB': 'Columbus Crew',
'DAL': 'FC Dallas',
'DC': 'D.C. United',
'HOU': 'Houston Dynamo',
'LA': 'LA Galaxy',
'LAFC': 'Los Angeles FC',
'MIA': 'Inter Miami',
'MIN': 'Minnesota United',
'MTL': 'CF Montréal',
'NSC': 'Nashville SC',
'NYC': 'New York City FC',
'NYR': 'New York Red Bulls',
'ORL': 'Orlando City',
'PHI': 'Philadelphia Union',
'POR': 'Portland Timbers',
'RSL': 'Real Salt Lake',
'SEA': 'Seattle Sounders',
'SJ': 'San Jose Earthquakes',
'SKC': 'Sporting Kansas City',
'TOR': 'Toronto FC',
'VAN': 'Vancouver Whitecaps'
}
}
def check_logo_exists(team_abbr: str, logo_dir: str) -> bool:
"""Check if a logo file exists for the given team abbreviation."""
logo_path = os.path.join(logo_dir, f"{team_abbr}.png")
return os.path.exists(logo_path)
def download_team_logo(team_abbr: str, team_name: str, league_code: str) -> bool:
"""Download a team logo from ESPN API."""
try:
soccer_league_key = get_soccer_league_key(league_code)
logger.info(f"Downloading {team_abbr} ({team_name}) from {league_code}")
success = download_missing_logo(team_abbr, soccer_league_key, team_name)
if success:
logger.info(f"✅ Successfully downloaded {team_abbr} ({team_name})")
return True
else:
logger.warning(f"❌ Failed to download {team_abbr} ({team_name})")
return False
except Exception as e:
logger.error(f"❌ Error downloading {team_abbr} ({team_name}): {e}")
return False
def check_league_logos(league_code: str, teams: Dict[str, str], logo_dir: str) -> Tuple[int, int]:
"""Check and download missing logos for a specific league."""
logger.info(f"\n🔍 Checking {league_code} ({LEAGUE_NAMES.get(league_code, league_code)})")
missing_logos = []
existing_logos = []
# Check which logos are missing
for team_abbr, team_name in teams.items():
if check_logo_exists(team_abbr, logo_dir):
existing_logos.append(team_abbr)
else:
missing_logos.append((team_abbr, team_name))
logger.info(f"📊 Found {len(existing_logos)} existing logos, {len(missing_logos)} missing")
if existing_logos:
logger.info(f"✅ Existing: {', '.join(existing_logos)}")
if missing_logos:
logger.info(f"❌ Missing: {', '.join([f'{abbr} ({name})' for abbr, name in missing_logos])}")
# Download missing logos
downloaded_count = 0
failed_count = 0
for team_abbr, team_name in missing_logos:
if download_team_logo(team_abbr, team_name, league_code):
downloaded_count += 1
else:
failed_count += 1
return downloaded_count, failed_count
def main():
"""Main function to check and download all soccer logos."""
logger.info("⚽ Soccer Logo Checker and Downloader")
logger.info("=" * 50)
# Ensure logo directory exists
logo_dir = "assets/sports/soccer_logos"
os.makedirs(logo_dir, exist_ok=True)
logger.info(f"📁 Logo directory: {logo_dir}")
# League names for display
global LEAGUE_NAMES
LEAGUE_NAMES = {
'eng.1': 'Premier League',
'esp.1': 'La Liga',
'ger.1': 'Bundesliga',
'ita.1': 'Serie A',
'fra.1': 'Ligue 1',
'por.1': 'Liga Portugal',
'uefa.champions': 'Champions League',
'uefa.europa': 'Europa League',
'usa.1': 'MLS'
}
total_downloaded = 0
total_failed = 0
total_existing = 0
# Check each league
for league_code, teams in MAJOR_TEAMS.items():
downloaded, failed = check_league_logos(league_code, teams, logo_dir)
total_downloaded += downloaded
total_failed += failed
total_existing += len(teams) - downloaded - failed
# Summary
logger.info("\n" + "=" * 50)
logger.info("📈 SUMMARY")
logger.info("=" * 50)
logger.info(f"✅ Existing logos: {total_existing}")
logger.info(f"⬇️ Downloaded: {total_downloaded}")
logger.info(f"❌ Failed downloads: {total_failed}")
logger.info(f"📊 Total teams checked: {total_existing + total_downloaded + total_failed}")
if total_failed > 0:
logger.warning(f"\n⚠️ {total_failed} logos failed to download. This might be due to:")
logger.warning(" - Network connectivity issues")
logger.warning(" - ESPN API rate limiting")
logger.warning(" - Team abbreviations not matching ESPN's format")
logger.warning(" - Teams not currently in the league")
if total_downloaded > 0:
logger.info(f"\n🎉 Successfully downloaded {total_downloaded} new logos!")
logger.info(" These logos are now available for use in the LEDMatrix display.")
logger.info(f"\n📁 All logos are stored in: {os.path.abspath(logo_dir)}")
if __name__ == "__main__":
main()