From d2fc5b8f43591fa93dc3b6dfa9b0deb30db3c6c8 Mon Sep 17 00:00:00 2001 From: Michal Vrba Date: Fri, 11 Sep 2026 12:00:26 +0200 Subject: [PATCH] changes --- .../Services/RadioLibraryService.cs | 135 +++++++++++++++++- src/AIRadioShowcase/wwwroot/favicon.ico | Bin 0 -> 4286 bytes src/AIRadioShowcase/wwwroot/favicon.svg | 43 ++++++ src/AIRadioShowcase/wwwroot/index.html | 4 +- src/AIRadioShowcase/wwwroot/web.config | 117 +++++++++++++++ 5 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 src/AIRadioShowcase/wwwroot/favicon.ico create mode 100644 src/AIRadioShowcase/wwwroot/favicon.svg create mode 100644 src/AIRadioShowcase/wwwroot/web.config diff --git a/src/AIRadioShowcase/Services/RadioLibraryService.cs b/src/AIRadioShowcase/Services/RadioLibraryService.cs index 9e55514..159ff0f 100644 --- a/src/AIRadioShowcase/Services/RadioLibraryService.cs +++ b/src/AIRadioShowcase/Services/RadioLibraryService.cs @@ -17,7 +17,7 @@ public class RadioLibraryService public async Task> LoadStationsAsync() { - var folders = AudioCatalog.Folders; + var folders = await DiscoverFoldersAsync(); var loaded = new List(); int index = 0; @@ -31,6 +31,129 @@ public class RadioLibraryService return _stations; } + private async Task> DiscoverFoldersAsync() + { + var folders = new HashSet(StringComparer.OrdinalIgnoreCase); + + // 1. Try querying IIS / server directory listing for audio/ + try + { + var response = await _http.GetAsync("audio/"); + if (response.IsSuccessStatusCode) + { + var html = await response.Content.ReadAsStringAsync(); + if (html.Contains("> DiscoverTracksAsync(string folder) + { + var tracks = new HashSet(StringComparer.OrdinalIgnoreCase); + + // 1. Try querying IIS / server directory listing for audio/{folder}/ + try + { + var response = await _http.GetAsync($"audio/{folder}/"); + if (response.IsSuccessStatusCode) + { + var html = await response.Content.ReadAsStringAsync(); + if (html.Contains(" Path.GetFileNameWithoutExtension(f), StringComparer.OrdinalIgnoreCase) + .Select(g => g.OrderBy(f => + { + var ext = Path.GetExtension(f).ToLowerInvariant(); + var idx = Array.IndexOf(audioExtOrder, ext); + return idx >= 0 ? idx : 99; + }).First()) + .OrderBy(t => t) + .ToList(); + } + + private List ParseDirectoryListing(string html) + { + var list = new List(); + var matches = System.Text.RegularExpressions.Regex.Matches(html, @"href\s*=\s*[""']([^""'#?]+)[""']", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + foreach (System.Text.RegularExpressions.Match m in matches) + { + var href = m.Groups[1].Value.Trim(); + href = href.TrimEnd('/'); + var name = Path.GetFileName(href); + if (string.IsNullOrWhiteSpace(name) || name.StartsWith(".") || name.Equals("audio", StringComparison.OrdinalIgnoreCase)) + continue; + + var ext = Path.GetExtension(name); + if (!string.IsNullOrEmpty(ext)) + continue; + + list.Add(name); + } + return list; + } + + private List ParseAudioFilesFromHtml(string html) + { + var list = new List(); + var validExts = new HashSet(StringComparer.OrdinalIgnoreCase) { ".mp3", ".wav", ".ogg", ".flac", ".m4a", ".aac" }; + var matches = System.Text.RegularExpressions.Regex.Matches(html, @"href\s*=\s*[""']([^""'#?]+)[""']", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + foreach (System.Text.RegularExpressions.Match m in matches) + { + var href = m.Groups[1].Value.Trim(); + var name = Path.GetFileName(href); + var ext = Path.GetExtension(name); + if (validExts.Contains(ext)) + { + list.Add(name); + } + } + return list; + } + private async Task LoadStationFromFolderAsync(string folder, int index) { var formattedName = FormatStationName(folder); @@ -61,13 +184,11 @@ public class RadioLibraryService } // Dynamically discovered tracks from audio folder - if (AudioCatalog.FolderTracks.TryGetValue(folder, out var fileNames) && fileNames != null && fileNames.Length > 0) + var tracks = await DiscoverTracksAsync(folder); + foreach (var fileName in tracks) { - foreach (var fileName in fileNames) - { - var track = BuildTrack(folder, fileName, station.DefaultCoverUrl); - station.Tracks.Add(track); - } + var track = BuildTrack(folder, fileName, station.DefaultCoverUrl); + station.Tracks.Add(track); } // If no tracks found, add a fallback track entry diff --git a/src/AIRadioShowcase/wwwroot/favicon.ico b/src/AIRadioShowcase/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..42b5ef88003b535967324ecadc4a67093ea10db3 GIT binary patch literal 4286 zcmeI0!3u*g42J)~P9DaPv9rg$!ft!Bz0MxWhu9lrO(hVdH3aJFA(fcgR=@U7TSefM zj%fm)@wozb0FPv;2(M&Zo>Qt@C;EbV+jtqMhsn5mu$g&O{*9hF9_+1rO*@)l#dpi`OK`DZYTMc{2Eu63s-#bm%T^y5buq@*4WAmgMH}VM*pnk#@dsZXzg3;Z}nl# z-r|?qddqms);+cPXWiGT{*e6POryizX$pJVYwe2Tcd(fo{Lnw55*Z?N&o-= literal 0 HcmV?d00001 diff --git a/src/AIRadioShowcase/wwwroot/favicon.svg b/src/AIRadioShowcase/wwwroot/favicon.svg new file mode 100644 index 0000000..f6bf0c7 --- /dev/null +++ b/src/AIRadioShowcase/wwwroot/favicon.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AIRadioShowcase/wwwroot/index.html b/src/AIRadioShowcase/wwwroot/index.html index 0df8873..6cd570c 100644 --- a/src/AIRadioShowcase/wwwroot/index.html +++ b/src/AIRadioShowcase/wwwroot/index.html @@ -12,7 +12,9 @@ - + + + diff --git a/src/AIRadioShowcase/wwwroot/web.config b/src/AIRadioShowcase/wwwroot/web.config new file mode 100644 index 0000000..14c889c --- /dev/null +++ b/src/AIRadioShowcase/wwwroot/web.config @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +