added more missing soccer logos
BIN
assets/sports/soccer_logos/AJX.png
Normal file
|
After Width: | Height: | Size: 558 B |
BIN
assets/sports/soccer_logos/ARO.png
Normal file
|
After Width: | Height: | Size: 298 KiB |
BIN
assets/sports/soccer_logos/AUS.png
Normal file
|
After Width: | Height: | Size: 577 B |
BIN
assets/sports/soccer_logos/BAY.png
Normal file
|
After Width: | Height: | Size: 545 B |
BIN
assets/sports/soccer_logos/BRA.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
assets/sports/soccer_logos/BUR.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/sports/soccer_logos/CHA.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
assets/sports/soccer_logos/DOR.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
assets/sports/soccer_logos/EST.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
assets/sports/soccer_logos/FAM.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
assets/sports/soccer_logos/GIL.png
Normal file
|
After Width: | Height: | Size: 406 B |
BIN
assets/sports/soccer_logos/KOL.png
Normal file
|
After Width: | Height: | Size: 487 B |
BIN
assets/sports/soccer_logos/LEV.png
Normal file
|
After Width: | Height: | Size: 432 B |
BIN
assets/sports/soccer_logos/LUT.png
Normal file
|
After Width: | Height: | Size: 331 B |
BIN
assets/sports/soccer_logos/LYON.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
assets/sports/soccer_logos/MAR.png
Normal file
|
After Width: | Height: | Size: 581 B |
BIN
assets/sports/soccer_logos/MOR.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
assets/sports/soccer_logos/MTL.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
assets/sports/soccer_logos/NICE.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
assets/sports/soccer_logos/NSC.png
Normal file
|
After Width: | Height: | Size: 612 B |
BIN
assets/sports/soccer_logos/NYC.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
assets/sports/soccer_logos/NYR.png
Normal file
|
After Width: | Height: | Size: 495 B |
BIN
assets/sports/soccer_logos/PSG.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
assets/sports/soccer_logos/PTM.png
Normal file
|
After Width: | Height: | Size: 471 B |
BIN
assets/sports/soccer_logos/RIO.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
assets/sports/soccer_logos/SHU.png
Normal file
|
After Width: | Height: | Size: 468 B |
BIN
assets/sports/soccer_logos/STU.png
Normal file
|
After Width: | Height: | Size: 484 B |
BIN
assets/sports/soccer_logos/VGU.png
Normal file
|
After Width: | Height: | Size: 560 B |
BIN
assets/sports/soccer_logos/VSC.png
Normal file
|
After Width: | Height: | Size: 635 B |
96
test/README_soccer_logos.md
Normal 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
@@ -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()
|
||||||