diff --git a/README.md b/README.md index f68e802..3dc5219 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Before installing or using this plugin, it is **highly recommended** that you cr * **Advanced Fuzzy Matching**: Automatically finds and assigns streams to channels using an advanced fuzzy-matching engine (`fuzzy_matcher.py`). * **Unlimited Stream Support**: Fetches and processes ALL available streams regardless of quantity (no 10,000 stream limit). * **Enhanced OTA Callsign Matching**: Uses a robust `*_channels.json` database for superior callsign extraction and matching for Over-The-Air broadcast channels. +* **Selectable Channel Databases** *(NEW v0.6.0)*: Enable or disable specific channel databases through the GUI settings. +* **Multi-Country Support** *(NEW v0.6.0)*: Support for multiple country databases with automatic country code prefix handling (e.g., `CA:`, `UK `). * **Multi-Stream Assignment**: Assigns **all** matching streams to each channel (e.g., 4K, FHD, HD versions), sorted by quality. * **Quality Prioritization**: Sorts matched streams by quality (4K → FHD → HD → (H) → (F) → (D) → SD → Slow). * **Channel Visibility Management**: Automatically enables/disables channels based on stream assignments and duplicate detection. @@ -44,11 +46,44 @@ Before installing or using this plugin, it is **highly recommended** that you cr Stream-Mapparr uses `*_channels.json` files to improve OTA (Over-The-Air) and cable channel matching. The plugin includes `US_channels.json` by default, but you can create additional database files for other countries or regions. +**NEW in v0.6.0**: Channel databases are now **selectable within the GUI**! You can enable or disable specific databases in the plugin settings. + ### Database File Format Channel database files follow the naming pattern: `[COUNTRY_CODE]_channels.json` (e.g., `US_channels.json`, `CA_channels.json`, `UK_channels.json`) -Each file contains a JSON array of channel objects with three required fields: +#### Recommended Format (v0.6.0+) + +The recommended format includes metadata at the top level: + +```json +{ + "country_code": "CA", + "country_name": "Canada", + "version": "2025-11-10", + "channels": [ + { + "channel_name": "CBC", + "category": "News", + "type": "National" + }, + { + "channel_name": "CTV", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Global", + "category": "Entertainment", + "type": "National" + } + ] +} +``` + +#### Legacy Format (Still Supported) + +The legacy format is still supported and uses a direct array: ```json [ @@ -61,17 +96,25 @@ Each file contains a JSON array of channel objects with three required fields: "channel_name": "CTV", "category": "Entertainment", "type": "National" - }, - { - "channel_name": "Global", - "category": "Entertainment", - "type": "National" } ] ``` +**Note**: If using the legacy format without metadata, the database will be displayed in settings using the filename. + ### Field Descriptions +#### Metadata Fields (Recommended Format Only) + +| Field | Required | Description | Examples | +|:---|:---|:---|:---| +| **country_code** | Recommended | Two-letter ISO country code | `US`, `CA`, `UK`, `AU`, `DE` | +| **country_name** | Recommended | Full country/region name | `United States`, `Canada`, `United Kingdom` | +| **version** | Optional | Database version or date | `2025-11-10`, `1.0`, `v2` | +| **channels** | Yes | Array of channel objects | See below | + +#### Channel Object Fields + | Field | Required | Description | Examples | |:---|:---|:---|:---| | **channel_name** | Yes | The channel name or callsign | `CBC`, `BBC One`, `WSBT`, `Sky Sports` | @@ -113,58 +156,97 @@ Each file contains a JSON array of channel objects with three required fields: ``` * The plugin will automatically detect and use all `*_channels.json` files in the directory -### Example: Creating UK_channels.json +### Example: Creating UK_channels.json (Recommended Format) ```json -[ - { - "channel_name": "BBC One", - "category": "Entertainment", - "type": "National" - }, - { - "channel_name": "BBC Two", - "category": "Entertainment", - "type": "National" - }, - { - "channel_name": "ITV", - "category": "Entertainment", - "type": "National" - }, - { - "channel_name": "Channel 4", - "category": "Entertainment", - "type": "National" - }, - { - "channel_name": "Sky Sports", - "category": "Sports", - "type": "National" - } -] +{ + "country_code": "UK", + "country_name": "United Kingdom", + "version": "2025-11-11", + "channels": [ + { + "channel_name": "BBC One", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "BBC Two", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "ITV", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Channel 4", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Sky Sports", + "category": "Sports", + "type": "National" + } + ] +} ``` +### Managing Channel Databases in the GUI + +**NEW in v0.6.0**: All channel databases are now manageable through the plugin settings! + +1. **Viewing Available Databases** + * Navigate to **Plugins** → **Stream-Mapparr** → **Settings** + * Scroll to the **"📚 Channel Databases"** section + * All detected `*_channels.json` files will be listed with checkboxes + +2. **Enabling/Disabling Databases** + * Check the box next to a database to enable it for matching + * Uncheck the box to disable it + * By default, only the **US** database is enabled + * If only one database exists, it will be enabled by default + +3. **Database Labels** + * Databases using the **recommended format** show: `Country Name (vVersion)` + * Example: `Canada (v2025-11-10)` + * Databases using the **legacy format** show: `Filename` + * Example: `UK_channels.json` + +4. **Country Code Prefix Handling** + * Stream names may be prefixed with country codes (e.g., `CA: CBC`, `UK BBC One`) + * The plugin automatically removes these prefixes during matching + * Supported formats: `CC:`, `CC `, `CCC:`, or `CCC ` (where C = letter) + ### Tips for Better Matching * Include all variations of channel names (e.g., `BBC 1`, `BBC One`, `BBC1`) * Add both full names and abbreviations (e.g., `The Sports Network`, `TSN`) * Include regional variants if applicable (e.g., `BBC One London`, `BBC One Scotland`) * Use the exact callsigns for OTA broadcast stations -* Test your database by running the plugin and checking the logs for matching activity +* Enable only the databases relevant to your region for better matching accuracy +* Use the recommended format with metadata for clearer identification in the GUI +* Test your database by enabling it in settings and checking the logs for matching activity ## Settings Reference | Setting | Type | Default | Description | |:---|:---|:---|:---| -| **Fuzzy Match Threshold** | `number` | 85 | Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches. | +| **Overwrite Existing Streams** | `boolean` | True | If enabled, removes all existing streams and replaces with matched streams | +| **Fuzzy Match Threshold** | `number` | 85 | Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches | | **Dispatcharr URL** | `string` | - | Full URL of your Dispatcharr instance (e.g., `http://192.168.1.10:9191`) | | **Dispatcharr Admin Username** | `string` | - | Username for API authentication | | **Dispatcharr Admin Password** | `password` | - | Password for API authentication | | **Profile Name** | `string` | - | Name of an existing Channel Profile to process (e.g., "Primary", "Sports") | | **Channel Groups** | `string` | - | Comma-separated group names to process, or leave empty for all groups | | **Ignore Tags** | `string` | - | Comma-separated tags to ignore during matching (e.g., `4K, [4K], [Dead]`) | +| **Ignore Quality Tags** | `boolean` | True | Remove quality-related patterns like [4K], HD, (SD) during matching | +| **Ignore Regional Tags** | `boolean` | True | Remove regional indicators like "East" during matching | +| **Ignore Geographic Tags** | `boolean` | True | Remove geographic prefixes like US:, CA:, UK: during matching | +| **Ignore Miscellaneous Tags** | `boolean` | True | Remove miscellaneous tags like (CX), (Backup) during matching | | **Visible Channel Limit** | `number` | 1 | Number of channels per matching group that will be visible and have streams added | +| **Enable [Database]** *(v0.6.0)* | `boolean` | US: True, Others: False | Enable or disable specific channel databases for matching | ## Usage Guide diff --git a/Stream-Mapparr/CA_channels.json b/Stream-Mapparr/CA_channels.json new file mode 100644 index 0000000..949169a --- /dev/null +++ b/Stream-Mapparr/CA_channels.json @@ -0,0 +1,107 @@ +{ + "country_code": "CA", + "country_name": "Canada", + "version": "2025-11-11", + "channels": [ + { + "channel_name": "CBC", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "CBC News Network", + "category": "News", + "type": "National" + }, + { + "channel_name": "CTV", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "CTV News Channel", + "category": "News", + "type": "National" + }, + { + "channel_name": "Global", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Citytv", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "TSN", + "category": "Sports", + "type": "National" + }, + { + "channel_name": "The Sports Network", + "category": "Sports", + "type": "National" + }, + { + "channel_name": "Sportsnet", + "category": "Sports", + "type": "National" + }, + { + "channel_name": "TVA", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Ici Radio-Canada", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "CTV Comedy Channel", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "CTV Drama Channel", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Discovery Channel", + "category": "Documentary", + "type": "National" + }, + { + "channel_name": "History", + "category": "Documentary", + "type": "National" + }, + { + "channel_name": "Food Network Canada", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "HGTV Canada", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "W Network", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Showcase", + "category": "Entertainment", + "type": "National" + }, + { + "channel_name": "Space", + "category": "Entertainment", + "type": "National" + } + ] +} diff --git a/Stream-Mapparr/fuzzy_matcher.py b/Stream-Mapparr/fuzzy_matcher.py index cd0d195..506e14e 100644 --- a/Stream-Mapparr/fuzzy_matcher.py +++ b/Stream-Mapparr/fuzzy_matcher.py @@ -44,11 +44,14 @@ REGIONAL_PATTERNS = [ r'\s[Ee][Aa][Ss][Tt]', ] -# Geographic prefix patterns: US:, USA:, etc. +# Geographic prefix patterns: US:, USA:, CA:, UK:, etc. GEOGRAPHIC_PATTERNS = [ - # Geographic prefixes - r'\bUSA?:\s', # "US:" or "USA:" - r'\bUS\s', # "US " at word boundary + # Geographic prefixes at start with colon: "US:", "CA:", "UK:", etc. (any 2-3 letter code followed by colon) + r'^[A-Z]{2,3}:\s*', + # Geographic prefixes at start with space: "US ", "CA ", "UK ", etc. (any 2-3 letter code followed by space) + r'^[A-Z]{2,3}\s+', + # Legacy USA pattern for backward compatibility + r'\bUSA?:\s', ] # Miscellaneous patterns: (CX), (Backup), single-letter tags, etc. diff --git a/Stream-Mapparr/plugin.py b/Stream-Mapparr/plugin.py index c58d841..4d3f3e1 100644 --- a/Stream-Mapparr/plugin.py +++ b/Stream-Mapparr/plugin.py @@ -29,108 +29,151 @@ LOGGER.setLevel(logging.INFO) class Plugin: """Dispatcharr Stream-Mapparr Plugin""" - + name = "Stream-Mapparr" - version = "0.5.0d" + version = "0.6.0" description = "🎯 Automatically add matching streams to channels based on name similarity and quality precedence with enhanced fuzzy matching" - - # Settings rendered by UI - fields = [ - { - "id": "overwrite_streams", - "label": "🔄 Overwrite Existing Streams", - "type": "boolean", - "default": True, - "help_text": "If enabled, all existing streams will be removed and replaced with matched streams. If disabled, only new streams will be added (existing streams preserved).", - }, - { - "id": "fuzzy_match_threshold", - "label": "🎯 Fuzzy Match Threshold", - "type": "number", - "default": 85, - "help_text": "Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches. Default: 85", - }, - { - "id": "dispatcharr_url", - "label": "🌐 Dispatcharr URL", - "type": "string", - "default": "", - "placeholder": "http://192.168.1.10:9191", - "help_text": "URL of your Dispatcharr instance (from your browser address bar). Example: http://127.0.0.1:9191", - }, - { - "id": "dispatcharr_username", - "label": "👤 Dispatcharr Admin Username", - "type": "string", - "help_text": "Your admin username for the Dispatcharr UI. Required for API access.", - }, - { - "id": "dispatcharr_password", - "label": "🔑 Dispatcharr Admin Password", - "type": "string", - "input_type": "password", - "help_text": "Your admin password for the Dispatcharr UI. Required for API access.", - }, - { - "id": "profile_name", - "label": "📋 Profile Name", - "type": "string", - "default": "", - "placeholder": "Sports, Movies, News", - "help_text": "*** Required Field *** - The name(s) of existing Channel Profile(s) to process channels from. Multiple profiles can be specified separated by commas.", - }, - { - "id": "selected_groups", - "label": "📁 Channel Groups (comma-separated)", - "type": "string", - "default": "", - "placeholder": "Sports, News, Entertainment", - "help_text": "Specific channel groups to process, or leave empty for all groups.", - }, - { - "id": "ignore_tags", - "label": "🏷️ Ignore Tags (comma-separated)", - "type": "string", - "default": "", - "placeholder": "4K, [4K], \" East\", \"[Dead]\"", - "help_text": "Tags to ignore when matching streams. Use quotes to preserve spaces/special chars (e.g., \" East\" for tags with leading space).", - }, - { - "id": "ignore_quality_tags", - "label": "🎬 Ignore Quality Tags", - "type": "boolean", - "default": True, - "help_text": "If enabled, hardcoded quality tags like [4K], [HD], (UHD), etc., will be ignored during matching.", - }, - { - "id": "ignore_regional_tags", - "label": "🌍 Ignore Regional Tags", - "type": "boolean", - "default": True, - "help_text": "If enabled, hardcoded regional tags like 'East' will be ignored during matching.", - }, - { - "id": "ignore_geographic_tags", - "label": "🗺️ Ignore Geographic Tags", - "type": "boolean", - "default": True, - "help_text": "If enabled, hardcoded geographic prefixes like 'US:', 'USA:' will be ignored during matching.", - }, - { - "id": "ignore_misc_tags", - "label": "🏷️ Ignore Miscellaneous Tags", - "type": "boolean", - "default": True, - "help_text": "If enabled, miscellaneous tags like (CX), (Backup), and single-letter tags will be ignored during matching.", - }, - { - "id": "visible_channel_limit", - "label": "👁️ Visible Channel Limit", - "type": "number", - "default": 1, - "help_text": "Number of channels that will be visible and have streams added. Channels are prioritized by quality tags, then by channel number.", - }, - ] + + @property + def fields(self): + """Dynamically generate settings fields including channel database selection.""" + # Static fields that are always present + static_fields = [ + { + "id": "overwrite_streams", + "label": "🔄 Overwrite Existing Streams", + "type": "boolean", + "default": True, + "help_text": "If enabled, all existing streams will be removed and replaced with matched streams. If disabled, only new streams will be added (existing streams preserved).", + }, + { + "id": "fuzzy_match_threshold", + "label": "🎯 Fuzzy Match Threshold", + "type": "number", + "default": 85, + "help_text": "Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches. Default: 85", + }, + { + "id": "dispatcharr_url", + "label": "🌐 Dispatcharr URL", + "type": "string", + "default": "", + "placeholder": "http://192.168.1.10:9191", + "help_text": "URL of your Dispatcharr instance (from your browser address bar). Example: http://127.0.0.1:9191", + }, + { + "id": "dispatcharr_username", + "label": "👤 Dispatcharr Admin Username", + "type": "string", + "help_text": "Your admin username for the Dispatcharr UI. Required for API access.", + }, + { + "id": "dispatcharr_password", + "label": "🔑 Dispatcharr Admin Password", + "type": "string", + "input_type": "password", + "help_text": "Your admin password for the Dispatcharr UI. Required for API access.", + }, + { + "id": "profile_name", + "label": "📋 Profile Name", + "type": "string", + "default": "", + "placeholder": "Sports, Movies, News", + "help_text": "*** Required Field *** - The name(s) of existing Channel Profile(s) to process channels from. Multiple profiles can be specified separated by commas.", + }, + { + "id": "selected_groups", + "label": "📁 Channel Groups (comma-separated)", + "type": "string", + "default": "", + "placeholder": "Sports, News, Entertainment", + "help_text": "Specific channel groups to process, or leave empty for all groups.", + }, + { + "id": "ignore_tags", + "label": "🏷️ Ignore Tags (comma-separated)", + "type": "string", + "default": "", + "placeholder": "4K, [4K], \" East\", \"[Dead]\"", + "help_text": "Tags to ignore when matching streams. Use quotes to preserve spaces/special chars (e.g., \" East\" for tags with leading space).", + }, + { + "id": "ignore_quality_tags", + "label": "🎬 Ignore Quality Tags", + "type": "boolean", + "default": True, + "help_text": "If enabled, hardcoded quality tags like [4K], [HD], (UHD), etc., will be ignored during matching.", + }, + { + "id": "ignore_regional_tags", + "label": "🌍 Ignore Regional Tags", + "type": "boolean", + "default": True, + "help_text": "If enabled, hardcoded regional tags like 'East' will be ignored during matching.", + }, + { + "id": "ignore_geographic_tags", + "label": "🗺️ Ignore Geographic Tags", + "type": "boolean", + "default": True, + "help_text": "If enabled, hardcoded geographic prefixes like 'US:', 'USA:' will be ignored during matching.", + }, + { + "id": "ignore_misc_tags", + "label": "🏷️ Ignore Miscellaneous Tags", + "type": "boolean", + "default": True, + "help_text": "If enabled, miscellaneous tags like (CX), (Backup), and single-letter tags will be ignored during matching.", + }, + { + "id": "visible_channel_limit", + "label": "👁️ Visible Channel Limit", + "type": "number", + "default": 1, + "help_text": "Number of channels that will be visible and have streams added. Channels are prioritized by quality tags, then by channel number.", + }, + ] + + # Add channel database section header + static_fields.append({ + "id": "channel_databases_header", + "type": "info", + "label": "📚 Channel Databases", + }) + + # Dynamically add channel database enable/disable fields + try: + databases = self._get_channel_databases() + + if databases: + for db_info in databases: + db_id = db_info['id'] + db_label = db_info['label'] + db_default = db_info['default'] + + static_fields.append({ + "id": f"db_enabled_{db_id}", + "type": "boolean", + "label": f"Enable {db_label}", + "help_text": f"Enable or disable the {db_label} channel database for matching.", + "default": db_default + }) + else: + static_fields.append({ + "id": "no_databases_found", + "type": "info", + "label": "⚠️ No channel databases found. Place XX_channels.json files in the plugin directory.", + }) + except Exception as e: + LOGGER.error(f"[Stream-Mapparr] Error loading channel databases for settings: {e}") + static_fields.append({ + "id": "database_error", + "type": "info", + "label": f"⚠️ Error loading channel databases: {e}", + }) + + return static_fields # Actions for Dispatcharr UI actions = [ @@ -201,9 +244,71 @@ class Plugin: self.loaded_streams = [] self.channel_stream_matches = [] self.fuzzy_matcher = None - + LOGGER.info(f"[Stream-Mapparr] {self.name} Plugin v{self.version} initialized") + def _get_channel_databases(self): + """ + Scan for channel database files and return metadata for each. + + Returns: + List of dicts with 'id', 'label', 'default', and 'file_path' keys + """ + plugin_dir = os.path.dirname(__file__) + databases = [] + + try: + from glob import glob + pattern = os.path.join(plugin_dir, '*_channels.json') + channel_files = sorted(glob(pattern)) + + for channel_file in channel_files: + try: + filename = os.path.basename(channel_file) + # Extract country code from filename (e.g., "US" from "US_channels.json") + country_code = filename.split('_')[0].upper() + + # Try to read the file and extract metadata + with open(channel_file, 'r', encoding='utf-8') as f: + file_data = json.load(f) + + # Check if it's the new format with metadata + if isinstance(file_data, dict) and 'country_code' in file_data: + country_name = file_data.get('country_name', filename) + version = file_data.get('version', '') + if version: + label = f"{country_name} (v{version})" + else: + label = country_name + else: + # Old format or missing metadata - use filename + label = filename + + # Determine default value: US enabled by default, or if only one database, enable it + # We'll check the count later + default = (country_code == 'US') + + databases.append({ + 'id': country_code, + 'label': label, + 'default': default, + 'file_path': channel_file, + 'filename': filename + }) + + except Exception as e: + LOGGER.warning(f"[Stream-Mapparr] Error reading database file {channel_file}: {e}") + continue + + # If only one database exists, enable it by default + if len(databases) == 1: + databases[0]['default'] = True + + except Exception as e: + LOGGER.error(f"[Stream-Mapparr] Error scanning for channel databases: {e}") + + return databases + def _initialize_fuzzy_matcher(self, match_threshold=85): """Initialize the fuzzy matcher with configured threshold.""" if self.fuzzy_matcher is None: @@ -545,33 +650,86 @@ class Plugin: return sorted(streams, key=get_quality_index) - def _load_channels_data(self, logger): - """Load channel data from *_channels.json files.""" + def _load_channels_data(self, logger, settings=None): + """ + Load channel data from enabled *_channels.json files. + + Args: + logger: Logger instance + settings: Plugin settings dict (optional, for filtering by enabled databases) + + Returns: + List of channel data from enabled databases + """ plugin_dir = os.path.dirname(__file__) channels_data = [] - + try: - # Find all *_channels.json files - from glob import glob - pattern = os.path.join(plugin_dir, '*_channels.json') - channel_files = glob(pattern) - - if channel_files: - for channel_file in channel_files: - try: - with open(channel_file, 'r', encoding='utf-8') as f: - file_data = json.load(f) - channels_data.extend(file_data) - logger.info(f"[Stream-Mapparr] Loaded {len(file_data)} channels from {os.path.basename(channel_file)}") - except Exception as e: - logger.error(f"[Stream-Mapparr] Error loading {channel_file}: {e}") - - logger.info(f"[Stream-Mapparr] Loaded total of {len(channels_data)} channels from {len(channel_files)} file(s)") - else: + # Get all available databases + databases = self._get_channel_databases() + + if not databases: logger.warning(f"[Stream-Mapparr] No *_channels.json files found in {plugin_dir}") + return channels_data + + # Filter to only enabled databases + enabled_databases = [] + for db_info in databases: + db_id = db_info['id'] + setting_key = f"db_enabled_{db_id}" + + # Check if this database is enabled in settings + if settings: + is_enabled = settings.get(setting_key, db_info['default']) + else: + # No settings provided, use default + is_enabled = db_info['default'] + + if is_enabled: + enabled_databases.append(db_info) + + if not enabled_databases: + logger.warning("[Stream-Mapparr] No channel databases are enabled. Please enable at least one database in settings.") + return channels_data + + # Load data from enabled databases + for db_info in enabled_databases: + channel_file = db_info['file_path'] + db_label = db_info['label'] + country_code = db_info['id'] + + try: + with open(channel_file, 'r', encoding='utf-8') as f: + file_data = json.load(f) + + # Handle both old and new format + if isinstance(file_data, dict) and 'channels' in file_data: + # New format with metadata + channels_list = file_data['channels'] + # Add country_code to each channel for prefix handling + for channel in channels_list: + channel['_country_code'] = country_code + elif isinstance(file_data, list): + # Old format - direct array + channels_list = file_data + # Add country_code to each channel for prefix handling + for channel in channels_list: + channel['_country_code'] = country_code + else: + logger.error(f"[Stream-Mapparr] Invalid format in {channel_file}") + continue + + channels_data.extend(channels_list) + logger.info(f"[Stream-Mapparr] Loaded {len(channels_list)} channels from {db_label}") + + except Exception as e: + logger.error(f"[Stream-Mapparr] Error loading {channel_file}: {e}") + + logger.info(f"[Stream-Mapparr] Loaded total of {len(channels_data)} channels from {len(enabled_databases)} enabled database(s)") + except Exception as e: logger.error(f"[Stream-Mapparr] Error loading channel data files: {e}") - + return channels_data def _is_ota_channel(self, channel_info): @@ -1313,7 +1471,7 @@ class Plugin: logger.info("[Stream-Mapparr] Settings validated successfully, proceeding with preview...") # Load channel data from channels.json - channels_data = self._load_channels_data(logger) + channels_data = self._load_channels_data(logger, settings) # Load processed data with open(self.processed_data_file, 'r') as f: @@ -1522,9 +1680,9 @@ class Plugin: token, error = self._get_api_token(settings, logger) if error: return {"status": "error", "message": error} - + # Load channel data from channels.json - channels_data = self._load_channels_data(logger) + channels_data = self._load_channels_data(logger, settings) # Load processed data with open(self.processed_data_file, 'r') as f: