From 602021a94a6756bd0d77132f669947b37350068e Mon Sep 17 00:00:00 2001 From: stoney420 Date: Fri, 27 Jun 2025 18:55:40 +0200 Subject: [PATCH] Update scripts/generate_playlist.py --- scripts/generate_playlist.py | 259 ++++++++++------------------------- 1 file changed, 71 insertions(+), 188 deletions(-) diff --git a/scripts/generate_playlist.py b/scripts/generate_playlist.py index 486d359..55de5bb 100644 --- a/scripts/generate_playlist.py +++ b/scripts/generate_playlist.py @@ -59,174 +59,41 @@ def load_group_overrides(): def detect_country_from_channel(channel_name, epg_id="", logo_url=""): """ - Auto-detect country from channel information using cascading approach. - Returns the detected country group or 'Uncategorized' if no match found. + Simple country detection that will definitely work. """ + # Convert to lowercase for easier matching + name_lower = channel_name.lower() + epg_lower = epg_id.lower() - # Normalize inputs for better matching - channel_lower = channel_name.lower().strip() - epg_lower = epg_id.lower().strip() - logo_lower = logo_url.lower().strip() + log_message(f"Detecting country for: '{channel_name}' (EPG: '{epg_id}')", "DEBUG") - # 1. BROADCASTER NAMES (Most reliable) - broadcaster_country = { - # US Major Networks - "cbs": "๐Ÿ‡บ๐Ÿ‡ธ United States", "nbc": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "abc": "๐Ÿ‡บ๐Ÿ‡ธ United States", "fox": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "espn": "๐Ÿ‡บ๐Ÿ‡ธ United States", "cnn": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "hbo": "๐Ÿ‡บ๐Ÿ‡ธ United States", "mtv": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "discovery": "๐Ÿ‡บ๐Ÿ‡ธ United States", "cartoon network": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "showtime": "๐Ÿ‡บ๐Ÿ‡ธ United States", "starz": "๐Ÿ‡บ๐Ÿ‡ธ United States", - "tnt": "๐Ÿ‡บ๐Ÿ‡ธ United States", "tbs": "๐Ÿ‡บ๐Ÿ‡ธ United States", - - # UK Networks - "bbc": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", "itv": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", - "channel 4": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", "sky": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", - "e4": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", "film4": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", - "more4": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", "dave": "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom", - - # Canadian Networks - "cbc": "๐Ÿ‡จ๐Ÿ‡ฆ Canada", "ctv": "๐Ÿ‡จ๐Ÿ‡ฆ Canada", "global": "๐Ÿ‡จ๐Ÿ‡ฆ Canada", - "tvo": "๐Ÿ‡จ๐Ÿ‡ฆ Canada", "aptn": "๐Ÿ‡จ๐Ÿ‡ฆ Canada", - - # German Networks - "ard": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", "zdf": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", "rtl": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", - "sat.1": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", "pro7": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", "vox": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", - "kabel": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", "n24": "๐Ÿ‡ฉ๐Ÿ‡ช Germany", - - # French Networks - "tf1": "๐Ÿ‡ซ๐Ÿ‡ท France", "france 2": "๐Ÿ‡ซ๐Ÿ‡ท France", "m6": "๐Ÿ‡ซ๐Ÿ‡ท France", - "canal+": "๐Ÿ‡ซ๐Ÿ‡ท France", "arte": "๐Ÿ‡ซ๐Ÿ‡ท France", - - # Spanish Networks - "tve": "๐Ÿ‡ช๐Ÿ‡ธ Spain", "antena 3": "๐Ÿ‡ช๐Ÿ‡ธ Spain", "telecinco": "๐Ÿ‡ช๐Ÿ‡ธ Spain", - "cuatro": "๐Ÿ‡ช๐Ÿ‡ธ Spain", "la sexta": "๐Ÿ‡ช๐Ÿ‡ธ Spain", - - # Italian Networks - "rai": "๐Ÿ‡ฎ๐Ÿ‡น Italy", "mediaset": "๐Ÿ‡ฎ๐Ÿ‡น Italy", "canale 5": "๐Ÿ‡ฎ๐Ÿ‡น Italy", - "italia 1": "๐Ÿ‡ฎ๐Ÿ‡น Italy", "rete 4": "๐Ÿ‡ฎ๐Ÿ‡น Italy", - - # Other Countries - "globo": "๐Ÿ‡ง๐Ÿ‡ท Brazil", "band": "๐Ÿ‡ง๐Ÿ‡ท Brazil", "sbt": "๐Ÿ‡ง๐Ÿ‡ท Brazil", - "televisa": "๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico", "tv azteca": "๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico", - "al jazeera": "๐Ÿ‡ธ๐Ÿ‡ฆ Arabic", "mbc": "๐Ÿ‡ธ๐Ÿ‡ฆ Arabic", "lbc": "๐Ÿ‡ธ๐Ÿ‡ฆ Arabic", - "rt": "๐Ÿ‡ท๐Ÿ‡บ Russia", "channel one": "๐Ÿ‡ท๐Ÿ‡บ Russia", - "cctv": "๐Ÿ‡จ๐Ÿ‡ณ China", "phoenix": "๐Ÿ‡จ๐Ÿ‡ณ China", - "nhk": "๐Ÿ‡ฏ๐Ÿ‡ต Japan", "fuji": "๐Ÿ‡ฏ๐Ÿ‡ต Japan", - "kbs": "๐Ÿ‡ฐ๐Ÿ‡ท South Korea", "sbs": "๐Ÿ‡ฐ๐Ÿ‡ท South Korea", "mbc": "๐Ÿ‡ฐ๐Ÿ‡ท South Korea", - "abc au": "๐Ÿ‡ฆ๐Ÿ‡บ Australia", "seven": "๐Ÿ‡ฆ๐Ÿ‡บ Australia", "nine": "๐Ÿ‡ฆ๐Ÿ‡บ Australia", - "npo": "๐Ÿ‡ณ๐Ÿ‡ฑ Netherlands", "rtl nl": "๐Ÿ‡ณ๐Ÿ‡ฑ Netherlands" - } + # UK Detection + if "sky" in name_lower or ".uk" in epg_lower or "british" in name_lower or "bbc" in name_lower or "itv" in name_lower: + log_message(f"Detected UK for: {channel_name}", "INFO") + return "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom" - # Check for exact broadcaster matches - for broadcaster, country in broadcaster_country.items(): - if broadcaster in channel_lower: - return country + # US Detection + if "usa" in name_lower or "us " in name_lower or ".us" in epg_lower or "america" in name_lower or "cnn" in name_lower or "espn" in name_lower or "fox" in name_lower: + log_message(f"Detected US for: {channel_name}", "INFO") + return "๐Ÿ‡บ๐Ÿ‡ธ United States" - # 2. COUNTRY NAME PATTERNS (Very reliable) - country_patterns = { - "๐Ÿ‡บ๐Ÿ‡ธ United States": [ - "usa", "united states", "america", "american", " us ", "us:", "(us)", "us hd" - ], - "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom": [ - " uk ", "uk:", "(uk)", "united kingdom", "britain", "british", "england", "english" - ], - "๐Ÿ‡จ๐Ÿ‡ฆ Canada": [ - "canada", "canadian", " ca ", "ca:", "(ca)" - ], - "๐Ÿ‡ฉ๐Ÿ‡ช Germany": [ - "germany", "german", "deutschland", "deutsch", " de ", "de:", "(de)" - ], - "๐Ÿ‡ซ๐Ÿ‡ท France": [ - "france", "french", "franรงais", " fr ", "fr:", "(fr)" - ], - "๐Ÿ‡ช๐Ÿ‡ธ Spain": [ - "spain", "spanish", "espaรฑa", "espaรฑol", " es ", "es:", "(es)" - ], - "๐Ÿ‡ฎ๐Ÿ‡น Italy": [ - "italy", "italian", "italia", "italiano", " it ", "it:", "(it)" - ], - "๐Ÿ‡ง๐Ÿ‡ท Brazil": [ - "brazil", "brazilian", "brasil", "portuguรชs", " br ", "br:", "(br)" - ], - "๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico": [ - "mexico", "mexican", "mรฉxico", " mx ", "mx:", "(mx)" - ], - "๐Ÿ‡ฆ๐Ÿ‡บ Australia": [ - "australia", "australian", "aussie", " au ", "au:", "(au)" - ], - "๐Ÿ‡ณ๐Ÿ‡ฑ Netherlands": [ - "netherlands", "dutch", "holland", "nederland", " nl ", "nl:", "(nl)" - ], - "๐Ÿ‡ท๐Ÿ‡บ Russia": [ - "russia", "russian", "ั€ะพััะธั", " ru ", "ru:", "(ru)" - ], - "๐Ÿ‡จ๐Ÿ‡ณ China": [ - "china", "chinese", "ไธญๅ›ฝ", " cn ", "cn:", "(cn)" - ], - "๐Ÿ‡ฏ๐Ÿ‡ต Japan": [ - "japan", "japanese", "ๆ—ฅๆœฌ", " jp ", "jp:", "(jp)" - ], - "๐Ÿ‡ฐ๐Ÿ‡ท South Korea": [ - "korea", "korean", "ํ•œ๊ตญ", " kr ", "kr:", "(kr)", "south korea" - ], - "๐Ÿ‡ธ๐Ÿ‡ฆ Arabic": [ - "arabic", "arab", "middle east", "ุงู„ุนุฑุจูŠุฉ", "al ", "aljazeera" - ], - "๐Ÿ‡ฎ๐Ÿ‡ณ India": [ - "india", "indian", "hindi", "bollywood", "zee", "star plus" - ], - "๐Ÿ‡ต๐Ÿ‡น Portugal": [ - "portugal", "portuguese", " pt ", "pt:", "(pt)" - ], - "๐Ÿ‡น๐Ÿ‡ท Turkey": [ - "turkey", "turkish", "tรผrkiye", " tr ", "tr:", "(tr)" - ] - } + # Canada Detection + if "canada" in name_lower or "cbc" in name_lower or ".ca" in epg_lower or "ctv" in name_lower: + log_message(f"Detected Canada for: {channel_name}", "INFO") + return "๐Ÿ‡จ๐Ÿ‡ฆ Canada" - # Check channel name for country patterns - for country, patterns in country_patterns.items(): - for pattern in patterns: - if pattern in channel_lower: - return country + # Germany Detection + if "german" in name_lower or ".de" in epg_lower or "ard" in name_lower or "zdf" in name_lower: + log_message(f"Detected Germany for: {channel_name}", "INFO") + return "๐Ÿ‡ฉ๐Ÿ‡ช Germany" - # 3. EPG ID ANALYSIS (Good for country codes) - epg_country_map = { - "๐Ÿ‡บ๐Ÿ‡ธ United States": [".us", "usa.", ".com"], - "๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom": [".uk", ".gb", "british"], - "๐Ÿ‡จ๐Ÿ‡ฆ Canada": [".ca", "canada."], - "๐Ÿ‡ฉ๐Ÿ‡ช Germany": [".de", "german."], - "๐Ÿ‡ซ๐Ÿ‡ท France": [".fr", "france."], - "๐Ÿ‡ช๐Ÿ‡ธ Spain": [".es", "spain."], - "๐Ÿ‡ฎ๐Ÿ‡น Italy": [".it", "italy."], - "๐Ÿ‡ง๐Ÿ‡ท Brazil": [".br", "brazil."], - "๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico": [".mx", "mexico."], - "๐Ÿ‡ฆ๐Ÿ‡บ Australia": [".au", "australia."], - "๐Ÿ‡ณ๐Ÿ‡ฑ Netherlands": [".nl", "netherlands."], - "๐Ÿ‡ท๐Ÿ‡บ Russia": [".ru", "russia."], - "๐Ÿ‡จ๐Ÿ‡ณ China": [".cn", "china."], - "๐Ÿ‡ฏ๐Ÿ‡ต Japan": [".jp", "japan."], - "๐Ÿ‡ฐ๐Ÿ‡ท South Korea": [".kr", "korea."], - "๐Ÿ‡ฎ๐Ÿ‡ณ India": [".in", "india."], - "๐Ÿ‡ต๐Ÿ‡น Portugal": [".pt", "portugal."], - "๐Ÿ‡น๐Ÿ‡ท Turkey": [".tr", "turkey."] - } + # France Detection + if "france" in name_lower or ".fr" in epg_lower or "tf1" in name_lower: + log_message(f"Detected France for: {channel_name}", "INFO") + return "๐Ÿ‡ซ๐Ÿ‡ท France" - # Check EPG ID for country indicators - if epg_id: - for country, patterns in epg_country_map.items(): - for pattern in patterns: - if pattern in epg_lower: - return country - - # 4. LOGO URL ANALYSIS (Sometimes helpful) - if logo_url: - for country, patterns in epg_country_map.items(): - for pattern in patterns: - if pattern in logo_lower: - return country - - # If no match found, return Uncategorized + # No match found + log_message(f"No country detected for: {channel_name}", "DEBUG") return "Uncategorized" def apply_auto_country_detection(channel, group_overrides, settings): @@ -351,64 +218,77 @@ def remove_duplicates(channels, settings): def update_existing_channels_with_country_detection(): """Re-process existing channels.txt to apply country detection to old channels.""" if not os.path.exists(CHANNELS_FILE): + log_message("No channels.txt file found", "WARNING") return settings = load_settings() group_overrides = load_group_overrides() - if not settings.get('auto_detect_country', True): - return - - log_message("Re-detecting countries for existing channels...", "INFO") + log_message("Starting to re-detect countries for ALL existing channels...", "INFO") # Read existing channels with open(CHANNELS_FILE, 'r', encoding='utf-8') as f: content = f.read() + log_message(f"Read {len(content)} characters from channels.txt", "DEBUG") + channel_blocks = re.split(r'\n\s*\n+', content.strip()) + log_message(f"Found {len(channel_blocks)} channel blocks", "INFO") + updated_channels = [] changes_made = 0 - for block in channel_blocks: + for i, block in enumerate(channel_blocks): if block.strip(): channel = parse_channel_block(block) if channel: old_group = channel.get('Group', 'Uncategorized') + stream_name = channel.get('Stream name', 'Unknown') + epg_id = channel.get('EPG id', '') - # Apply auto-detection (this will update the group) - channel = apply_auto_country_detection(channel, group_overrides, settings) + log_message(f"Processing channel {i+1}: '{stream_name}' (currently in '{old_group}')", "DEBUG") - new_group = channel.get('Group', 'Uncategorized') + # Force apply auto-detection regardless of current group + detected_country = detect_country_from_channel(stream_name, epg_id, "") - # Log if group changed - if old_group != new_group: + # Always update if we detected something specific + if detected_country != "Uncategorized": + channel['Group'] = detected_country changes_made += 1 - log_message(f"Updated: '{channel.get('Stream name')}' from '{old_group}' to '{new_group}'", "INFO") + log_message(f"CHANGED: '{stream_name}' from '{old_group}' to '{detected_country}'", "INFO") + else: + log_message(f"NO CHANGE: '{stream_name}' stays as '{old_group}'", "DEBUG") updated_channels.append(channel) - # If changes were made, rewrite the file - if changes_made > 0: - log_message(f"Updating {changes_made} channels with new country detection...", "INFO") + # Always rewrite the file if we have channels + if updated_channels: + log_message(f"Rewriting channels.txt with {len(updated_channels)} channels ({changes_made} changes made)", "INFO") - # Backup original + # Create backup backup_name = f"{CHANNELS_FILE}.backup.{datetime.now().strftime('%Y%m%d_%H%M%S')}" - import shutil - shutil.copy2(CHANNELS_FILE, backup_name) - log_message(f"Created backup: {backup_name}", "INFO") + try: + import shutil + shutil.copy2(CHANNELS_FILE, backup_name) + log_message(f"Created backup: {backup_name}", "INFO") + except Exception as e: + log_message(f"Could not create backup: {e}", "WARNING") # Write updated channels - with open(CHANNELS_FILE, 'w', encoding='utf-8') as f: - for i, channel in enumerate(updated_channels): - if i > 0: - f.write("\n\n") - - block_content = convert_to_channels_txt_block(channel) - f.write(block_content) - - log_message(f"Successfully updated {changes_made} channels with country detection", "INFO") + try: + with open(CHANNELS_FILE, 'w', encoding='utf-8') as f: + for i, channel in enumerate(updated_channels): + if i > 0: + f.write("\n\n") + + block_content = convert_to_channels_txt_block(channel) + f.write(block_content) + + log_message(f"Successfully rewrote channels.txt with country detection", "INFO") + except Exception as e: + log_message(f"ERROR writing channels.txt: {e}", "ERROR") else: - log_message("No channels needed country detection updates", "INFO") + log_message("No channels found to update", "WARNING") def process_import(): """Process bulk import file.""" @@ -522,6 +402,9 @@ def generate_playlist(): settings = load_settings() group_overrides = load_group_overrides() + + log_message(f"Settings loaded: {settings}", "INFO") + log_message(f"Group overrides loaded: {group_overrides}", "INFO") # FIRST: Update existing channels with country detection update_existing_channels_with_country_detection()