diff --git a/lib/models/livetv_channel.dart b/lib/models/livetv_channel.dart index c54e7183..872f40f8 100644 --- a/lib/models/livetv_channel.dart +++ b/lib/models/livetv_channel.dart @@ -34,13 +34,13 @@ class LiveTvChannel { factory LiveTvChannel.fromJson(Map json) { return LiveTvChannel( - key: json['key'] as String? ?? json['ratingKey'] as String? ?? json['identifier'] as String? ?? json['channelIdentifier'] as String? ?? '', - identifier: json['identifier'] as String? ?? json['channelIdentifier'] as String?, + key: json['key'] as String? ?? json['ratingKey'] as String? ?? json['identifier'] as String? ?? json['id'] as String? ?? json['channelIdentifier'] as String? ?? '', + identifier: json['identifier'] as String? ?? json['id'] as String? ?? json['channelIdentifier'] as String?, callSign: json['callSign'] as String?, title: json['title'] as String? ?? json['callSign'] as String?, thumb: json['thumb'] as String?, art: json['art'] as String?, - number: json['number'] as String? ?? json['channelNumber'] as String? ?? json['channelVcn']?.toString(), + number: json['number'] as String? ?? json['channelNumber'] as String? ?? json['channelVcn']?.toString() ?? json['vcn']?.toString(), hd: json['hd'] == true || json['hd'] == 1, lineup: json['lineup'] as String?, slug: json['slug'] as String?, diff --git a/lib/services/plex_client.dart b/lib/services/plex_client.dart index 582fd0c5..e4b5e41d 100644 --- a/lib/services/plex_client.dart +++ b/lib/services/plex_client.dart @@ -2210,14 +2210,9 @@ class PlexClient { return dvrs.isNotEmpty; } - /// Get EPG channels for a specific lineup + /// Get EPG channels using provider lineup endpoints (matches official Plex web client) Future> getEpgChannels({String? lineup}) async { - final queryParams = {}; - if (lineup != null) queryParams['lineup'] = lineup; - - return _wrapListApiCall(() => _dio.get('/livetv/epg/channels', queryParameters: queryParams), ( - response, - ) { + List parseChannels(Response response) { final container = _getMediaContainer(response); if (container != null && container['Channel'] is List && (container['Channel'] as List).isNotEmpty) { appLogger.d('EPG channel sample: ${(container['Channel'] as List).first}'); @@ -2232,7 +2227,6 @@ class PlexClient { .where((ch) => ch.key.isNotEmpty) .toList(); } - // Also check for Metadata key (some endpoints return channels there) if (container != null && container['Metadata'] != null) { return (container['Metadata'] as List) .map( @@ -2245,7 +2239,18 @@ class PlexClient { } appLogger.d('EPG channels: container keys=${container?.keys.toList()}, size=${container?['size']}'); return []; - }, 'Failed to get EPG channels'); + } + + final allChannels = []; + for (final provider in _providerEpg) { + try { + final response = await _dio.get('/${provider.identifier}/lineups/dvr/channels'); + allChannels.addAll(parseChannels(response)); + } catch (e) { + appLogger.e('Failed to get EPG channels from ${provider.identifier}', error: e); + } + } + return allChannels; } /// Return EPG providers (already parsed from /media/providers during initialization)