diff --git a/assets/sports/nba_logos/BKN.png b/assets/sports/nba_logos/BKN.png index cb77bcf3..828dc14e 100644 Binary files a/assets/sports/nba_logos/BKN.png and b/assets/sports/nba_logos/BKN.png differ diff --git a/assets/sports/nba_logos/UTAH.png b/assets/sports/nba_logos/UTAH.png index b0499428..4886d337 100644 Binary files a/assets/sports/nba_logos/UTAH.png and b/assets/sports/nba_logos/UTAH.png differ diff --git a/assets/sports/nba_logos/nba.png b/assets/sports/nba_logos/nba.png index 05e48b3d..7e8ddf8f 100644 Binary files a/assets/sports/nba_logos/nba.png and b/assets/sports/nba_logos/nba.png differ diff --git a/assets/sports/ncaa_fbs_logos/ncaam.png b/assets/sports/ncaa_fbs_logos/ncaam.png index 17219c6e..51e42b21 100644 Binary files a/assets/sports/ncaa_fbs_logos/ncaam.png and b/assets/sports/ncaa_fbs_logos/ncaam.png differ diff --git a/assets/sports/nhl_logos/nhl.png b/assets/sports/nhl_logos/nhl.png index 18a372f2..f36fe3f4 100644 Binary files a/assets/sports/nhl_logos/nhl.png and b/assets/sports/nhl_logos/nhl.png differ diff --git a/config/config.json b/config/config.json index 1575b845..ba1905e5 100644 --- a/config/config.json +++ b/config/config.json @@ -190,8 +190,8 @@ "request_timeout": 30, "dynamic_duration": true, "min_duration": 45, - "max_duration": 300, - "duration_buffer": 0.2, + "max_duration": 600, + "duration_buffer": 0.3, "time_per_team": 2.0, "time_per_league": 3.0 }, diff --git a/src/leaderboard_manager.py b/src/leaderboard_manager.py index 948c88e4..4d36b0ea 100644 --- a/src/leaderboard_manager.py +++ b/src/leaderboard_manager.py @@ -159,9 +159,16 @@ class LeaderboardManager: """Clear all leaderboard cache data to force fresh data fetch.""" try: for league_key in self.league_configs.keys(): - cache_key = f"leaderboard_{league_key}" - self.cache_manager.clear_cache(cache_key) - logger.info(f"Cleared cache for {league_key}") + # Clear all leaderboard cache variants + cache_keys = [ + f"leaderboard_{league_key}", + f"leaderboard_{league_key}_rankings", + f"leaderboard_{league_key}_standings" + ] + + for cache_key in cache_keys: + self.cache_manager.clear_cache(cache_key) + logger.info(f"Cleared cache for {cache_key}") # Also clear individual team record caches for league_key in self.league_configs.keys(): diff --git a/src/logo_downloader.py b/src/logo_downloader.py index 668e695e..702048d4 100644 --- a/src/logo_downloader.py +++ b/src/logo_downloader.py @@ -118,15 +118,31 @@ class LogoDownloader: with open(filepath, 'wb') as f: f.write(response.content) - # Verify the downloaded file is a valid image + # Verify and convert the downloaded image to RGBA format try: with Image.open(filepath) as img: - img.verify() - logger.info(f"Successfully downloaded logo for {team_name} -> {filepath.name}") + # Convert to RGBA to avoid PIL warnings about palette images with transparency + if img.mode in ('P', 'LA', 'L'): + # Convert palette or grayscale images to RGBA + img = img.convert('RGBA') + elif img.mode == 'RGB': + # Convert RGB to RGBA (add alpha channel) + img = img.convert('RGBA') + elif img.mode != 'RGBA': + # For any other mode, convert to RGBA + img = img.convert('RGBA') + + # Save the converted image + img.save(filepath, 'PNG') + + logger.info(f"Successfully downloaded and converted logo for {team_name} -> {filepath.name}") return True except Exception as e: - logger.error(f"Downloaded file for {team_name} is not a valid image: {e}") - os.remove(filepath) # Remove invalid file + logger.error(f"Downloaded file for {team_name} is not a valid image or conversion failed: {e}") + try: + os.remove(filepath) # Remove invalid file + except: + pass return False except requests.exceptions.RequestException as e: @@ -551,6 +567,42 @@ class LogoDownloader: except Exception as e: logger.error(f"Failed to create placeholder logo for {team_abbreviation}: {e}") return False + + def convert_image_to_rgba(self, filepath: Path) -> bool: + """Convert an image file to RGBA format to avoid PIL warnings.""" + try: + with Image.open(filepath) as img: + if img.mode != 'RGBA': + # Convert to RGBA + converted_img = img.convert('RGBA') + converted_img.save(filepath, 'PNG') + logger.debug(f"Converted {filepath.name} from {img.mode} to RGBA") + return True + else: + logger.debug(f"{filepath.name} is already in RGBA format") + return True + except Exception as e: + logger.error(f"Failed to convert {filepath.name} to RGBA: {e}") + return False + + def convert_all_logos_to_rgba(self, league: str) -> Tuple[int, int]: + """Convert all logos in a league directory to RGBA format.""" + logo_dir = Path(self.get_logo_directory(league)) + if not logo_dir.exists(): + logger.warning(f"Logo directory does not exist: {logo_dir}") + return 0, 0 + + converted_count = 0 + failed_count = 0 + + for logo_file in logo_dir.glob("*.png"): + if self.convert_image_to_rgba(logo_file): + converted_count += 1 + else: + failed_count += 1 + + logger.info(f"Converted {converted_count} logos to RGBA format for {league}, {failed_count} failed") + return converted_count, failed_count # Convenience function for easy integration