added more missing soccer logos

This commit is contained in:
Chuck
2025-09-16 14:31:31 -04:00
parent 854c236a60
commit 764d80e818
31 changed files with 411 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

View File

@@ -0,0 +1,96 @@
# Soccer Logo Checker and Downloader
## Overview
The `check_soccer_logos.py` script automatically 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) - 20 teams
- **La Liga** (esp.1) - 15 teams
- **Bundesliga** (ger.1) - 15 teams
- **Serie A** (ita.1) - 14 teams
- **Ligue 1** (fra.1) - 12 teams
- **Liga Portugal** (por.1) - 15 teams
- **Champions League** (uefa.champions) - 13 major teams
- **Europa League** (uefa.europa) - 11 major teams
- **MLS** (usa.1) - 25 teams
**Total: 140 major teams across 9 leagues**
## Usage
```bash
cd test
python check_soccer_logos.py
```
## What It Does
1. **Checks Existing Logos**: Scans `assets/sports/soccer_logos/` for existing logo files
2. **Identifies Missing Logos**: Compares against the list of major teams
3. **Downloads from ESPN**: Automatically fetches missing logos from ESPN API
4. **Creates Placeholders**: If download fails, creates colored placeholder logos
5. **Provides Summary**: Shows detailed statistics of the process
## Output
The script provides detailed logging showing:
- ✅ Existing logos found
- ⬇️ Successfully downloaded logos
- ❌ Failed downloads (with placeholders created)
- 📊 Summary statistics
## Example Output
```
🔍 Checking por.1 (Liga Portugal)
📊 Found 2 existing logos, 13 missing
✅ Existing: BEN, POR
❌ Missing: ARO (Arouca), BRA (SC Braga), CHA (Chaves), ...
Downloading ARO (Arouca) from por.1
✅ Successfully downloaded ARO (Arouca)
...
📈 SUMMARY
✅ Existing logos: 25
⬇️ Downloaded: 115
❌ Failed downloads: 0
📊 Total teams checked: 140
```
## Logo Storage
All logos are stored in: `assets/sports/soccer_logos/`
Format: `{TEAM_ABBREVIATION}.png` (e.g., `BEN.png`, `POR.png`, `LIV.png`)
## Integration with LEDMatrix
These logos are automatically used by the soccer manager when displaying:
- Live games
- Recent games
- Upcoming games
- Odds ticker
- Leaderboards
The system will automatically download missing logos on-demand during normal operation, but this script ensures all major teams have logos available upfront.
## Notes
- **Real Logos**: Downloaded from ESPN's official API
- **Placeholders**: Created for teams not found in ESPN data
- **Caching**: Logos are cached locally to avoid repeated downloads
- **Format**: All logos converted to RGBA PNG format for LEDMatrix compatibility
- **Size**: Logos are optimized for LED matrix display (typically 36x36 pixels)
## Troubleshooting
If downloads fail:
1. Check internet connectivity
2. Verify ESPN API is accessible
3. Some teams may not be in current league rosters
4. Placeholder logos will be created as fallback
The script is designed to be robust and will always provide some form of logo for every team.

315
test/check_soccer_logos.py Normal file
View File

@@ -0,0 +1,315 @@
#!/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()