using System; using System.IO; using System.Linq; using System.Reactive; using System.Reactive.Subjects; using System.Threading.Tasks; using System.Collections.Generic; namespace TV_Player { public class ProgramsData { private readonly ReplaySubject> programsSubject = new ReplaySubject>(); private readonly ReplaySubject> groupsSubject = new ReplaySubject>(); private readonly ReplaySubject programGuideSubject = new ReplaySubject(); public IObservable> AllPrograms => programsSubject; public IObservable> GroupsInformation => groupsSubject; public IObservable ProgramGuideInfo => programGuideSubject; private readonly string _programName; public ProgramsData(string name,string playlistURL) { _programName = name; Task.Run(() => GetPrograms(name,playlistURL)); } private async Task GetPrograms(string name,string m3uLink) { System.Diagnostics.Debug.WriteLine($"[ProgramsData] Starting download of: {m3uLink}"); //string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u"; try { // if link is a well-formed absolute URI load from web, otherwise treat as a local file path // for relative paths try resolving against the application's base directory var result = (programList: new List(), programGuide: string.Empty); if (Uri.IsWellFormedUriString(m3uLink, UriKind.Absolute)) { System.Diagnostics.Debug.WriteLine("[ProgramsData] Detected URL, downloading from web"); result = await M3UParser.DownloadM3UFromWebAsync(m3uLink); } else { // try as provided path first var candidate = m3uLink; if (!Path.IsPathRooted(candidate)) { candidate = Path.Combine(AppContext.BaseDirectory ?? string.Empty, candidate); } if (File.Exists(candidate)) { System.Diagnostics.Debug.WriteLine($"[ProgramsData] Detected local file, loading from disk: {candidate}"); result = await M3UParser.DownloadM3UFromWebAsync(candidate); } else { throw new FileNotFoundException($"M3U file not found: {m3uLink}"); } } System.Diagnostics.Debug.WriteLine($"[ProgramsData] Downloaded {result.programList.Count} programs"); programsSubject.OnNext(result.programList); var groupping = result.programList.GroupBy(item => item.GroupTitle) .Select(group => new GroupInfo() { Name = group.Key, Count = group.Count() }) .OrderBy(g => g.Name) .ToList(); System.Diagnostics.Debug.WriteLine($"[ProgramsData] Publishing {groupping.Count} groups: {string.Join(", ", groupping.Select(g => $"{g.Name}({g.Count})"))}"); if (groupping.Count == 0) { System.Diagnostics.Debug.WriteLine("[ProgramsData] WARNING: No groups found! Check if programs have 'group-title' metadata."); } groupsSubject.OnNext(groupping); await Task.Run(() => GetProgramGuide(name, result.programGuide)); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"[ProgramsData] ERROR downloading programs: {ex.Message}"); throw; } } public Task GetGuideByProgram(string channelID) { return M3UParser.ParseEpg(_programName,channelID); } private async Task GetProgramGuide(string name, string guideLink) { //guideLink = "http://epg.da-tv.vip/107-light.xml"; await M3UParser.DownloadGuideFromWebAsync(name,guideLink); programGuideSubject.OnNext(Unit.Default); } } }