First commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
using YoutubeExplode.Search;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Cryptography;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Tesses.YouTubeDownloader2025Companion;
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
|
||||
private static ReloadingScript log_page = new ReloadingScript("wwwroot/pages/log.sbnhtml");
|
||||
|
||||
public static async Task<string> LogAsync(ServerContext ctx)
|
||||
{
|
||||
var cfg = Program.Config ?? new AuthConfig();
|
||||
int page=1;
|
||||
if(!ctx.QueryParams.TryGetFirstInt32("page",out page))
|
||||
page = 1;
|
||||
|
||||
List<object> entries=new List<object>();
|
||||
|
||||
using(var db = new Database())
|
||||
{
|
||||
foreach(var vid in await db.GetLogEntriesAsync((page-1) * 20))
|
||||
{
|
||||
var time = vid.DateTime.DateTime;
|
||||
|
||||
if(vid.HasStrings)
|
||||
{
|
||||
entries.Add(new{
|
||||
Time = $"{time.ToShortDateString()} {time.ToShortTimeString()}",
|
||||
vid.Type,
|
||||
Videotitle = HttpUtility.HtmlEncode(vid.VideoTitle),
|
||||
Videourl = HttpUtility.HtmlAttributeEncode($"{cfg.TYTDUrl.TrimEnd('/')}/watch?v={HttpUtility.UrlEncode(vid.VideoId)}"),
|
||||
Channeltitle = HttpUtility.HtmlEncode(vid.ChannelTitle),
|
||||
Channelurl = HttpUtility.HtmlAttributeEncode($"{cfg.TYTDUrl.TrimEnd('/')}/channel?id={HttpUtility.UrlEncode(vid.ChannelId)}"),
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
entries.Add(new {
|
||||
Time = $"{time.ToShortDateString()} {time.ToShortTimeString()}",
|
||||
vid.Type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Components.Shell("Logs",log_page.Render(new{
|
||||
Entries=entries,
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/log?page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/log?page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
//using YouTubeMusicAPI.Models.Info;
|
||||
//using Acornima.Ast;
|
||||
//using YouTubeMusicAPI.Models;
|
||||
//using YouTubeMusicAPI.Models.Search;
|
||||
using Newtonsoft.Json;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class AlbumSongLink(int? songNumber,string name,string albumId, string songId, TimeSpan dur) {
|
||||
public string Songnumber => songNumber.HasValue ? songNumber.Value.ToString() : "-";
|
||||
public string Duration => dur.ToString("m\\:ss");
|
||||
public string Songname => HttpUtility.HtmlEncode(name);
|
||||
public string Songurl => HttpUtility.HtmlAttributeEncode($"/music/song?albumId={HttpUtility.UrlEncode(albumId)}&songId={HttpUtility.UrlEncode(songId)}");
|
||||
}
|
||||
public static partial class Pages {
|
||||
private static ReloadingScript album_info = new ReloadingScript("wwwroot/pages/music/albums/album-info.sbnhtml");
|
||||
|
||||
public static string AlbumInfo(string name, string id, List<AlbumSongLink> songLinks)
|
||||
{
|
||||
|
||||
return Components.Shell($"Album info", album_info.Render(new {
|
||||
Name = HttpUtility.HtmlEncode(name),
|
||||
Songs = songLinks,
|
||||
Addvals = HttpUtility.HtmlAttributeEncode(JsonConvert.SerializeObject(new{id}))
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class AlbumLink(string name, string id, string thumbnail) {
|
||||
public string Albumname => HttpUtility.HtmlEncode(name);
|
||||
public string Albumurl => HttpUtility.HtmlAttributeEncode($"/music/album?id={HttpUtility.UrlEncode(id)}");
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode(thumbnail);
|
||||
}
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript album_listing = new ReloadingScript("wwwroot/pages/music/albums/albums.sbnhtml");
|
||||
public static string AlbumListing(string query, List<AlbumLink> links,int page)
|
||||
{
|
||||
return Components.Shell($"Album search {query}", album_listing.Render(new {
|
||||
Albums = links,
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/albums?q={HttpUtility.UrlEncode(query)}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/albums?q={HttpUtility.UrlEncode(query)}&page={page + 1}")
|
||||
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
//using YouTubeMusicAPI.Models.Info;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class ArtistAlbumLink(string name, string id, string thumbnail) {
|
||||
public string Albumname => HttpUtility.HtmlEncode(name);
|
||||
public string Albumurl => HttpUtility.HtmlAttributeEncode($"/music/album?id={HttpUtility.UrlEncode(id)}");
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode(thumbnail);
|
||||
}
|
||||
public static partial class Pages {
|
||||
private static ReloadingScript artist_album_listing = new ReloadingScript("wwwroot/pages/music/artists/artist-album-list.sbnhtml");
|
||||
|
||||
public static string ArtistAlbumListing(Guid id, List<AlbumLink> albums, int page)
|
||||
{
|
||||
return Components.Shell("Albums", artist_album_listing.Render(new {
|
||||
Albums = albums,
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/artist?id={HttpUtility.UrlEncode(id.ToString())}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/artist?id={HttpUtility.UrlEncode(id.ToString())}&page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class ArtistLink(string name, string id, string thumbnail) {
|
||||
public string Artistname => HttpUtility.HtmlEncode(name);
|
||||
public string Artisturl => HttpUtility.HtmlAttributeEncode($"/music/artist?id={HttpUtility.UrlEncode(id)}");
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode(thumbnail);
|
||||
}
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript artist_listing = new ReloadingScript("wwwroot/pages/music/artists/artists.sbnhtml");
|
||||
public static string ArtistListing(string query, List<ArtistLink> links, int page)
|
||||
{
|
||||
return Components.Shell($"Artist search {query}", artist_listing.Render(new {
|
||||
Artists = links,
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/artists?q={HttpUtility.UrlEncode(query)}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/artists?q={HttpUtility.UrlEncode(query)}&page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
//using YouTubeMusicAPI.Models.Info;
|
||||
//using Acornima.Ast;
|
||||
//using YouTubeMusicAPI.Models;
|
||||
//using YouTubeMusicAPI.Models.Search;
|
||||
using Newtonsoft.Json;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class MyAlbumSongLink(int? songNumber,string name, string albumId, string songId, TimeSpan dur, string btn) {
|
||||
public string Songnumber => songNumber.HasValue ? songNumber.Value.ToString() : "-";
|
||||
public string Duration => dur.ToString(
|
||||
"m\\:ss"
|
||||
);
|
||||
public string Songname => HttpUtility.HtmlEncode(name);
|
||||
public string Songurl => HttpUtility.HtmlAttributeEncode($"/music/mysong?albumId={HttpUtility.UrlEncode(albumId)}&songId={HttpUtility.UrlEncode(songId)}");
|
||||
|
||||
public string Btn => btn;
|
||||
}
|
||||
public static partial class Pages {
|
||||
private static ReloadingScript myalbum_info = new ReloadingScript("wwwroot/pages/music/myalbums/album-info.sbnhtml");
|
||||
|
||||
public static string MyAlbumInfo(string name, string id, List<MyAlbumSongLink> songLinks, bool hasAny, string artists)
|
||||
{
|
||||
|
||||
return Components.Shell($"Album info", myalbum_info.Render(new {
|
||||
Name = HttpUtility.HtmlEncode(name),
|
||||
Songs = songLinks,
|
||||
Addvals = HttpUtility.HtmlAttributeEncode(JsonConvert.SerializeObject(new{id})),
|
||||
Hasanysongs = hasAny,
|
||||
Zipurl = HttpUtility.HtmlAttributeEncode($"/api/v1/album.zip?albumId={HttpUtility.UrlEncode(id)}"),
|
||||
Artists = artists
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript myalbum_listing = new ReloadingScript("wwwroot/pages/music/myalbums/albums.sbnhtml");
|
||||
public static string MyAlbumListing(string query, List<MyAlbumLink> links,int page)
|
||||
{
|
||||
return Components.Shell($"Album search {query}", myalbum_listing.Render(new {
|
||||
Albums = links,
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/myalbums?q={HttpUtility.UrlEncode(query)}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/myalbums?q={HttpUtility.UrlEncode(query)}&page={page + 1}")
|
||||
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
//using YouTubeMusicAPI.Models.Info;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class MyAlbumLink(string name, string id, string thumbnail) {
|
||||
public string Albumname => HttpUtility.HtmlEncode(name);
|
||||
public string Albumurl => HttpUtility.HtmlAttributeEncode($"/music/myalbum?id={HttpUtility.UrlEncode(id)}");
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode(thumbnail);
|
||||
}
|
||||
public static partial class Pages {
|
||||
private static ReloadingScript myartist_album_listing = new ReloadingScript("wwwroot/pages/music/myartists/artist-album-list.sbnhtml");
|
||||
|
||||
public static string MyArtistAlbumListing(Guid id,string query, List<MyAlbumLink> albums, int page)
|
||||
{
|
||||
return Components.Shell("Albums", myartist_album_listing.Render(new {
|
||||
Searchurl = $"/music/myartist?id={id.ToString()}",
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Albums = albums,
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/myartist?q={HttpUtility.UrlEncode(query)}&id={HttpUtility.UrlEncode(id.ToString())}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/myartist?q={HttpUtility.UrlEncode(query)}&id={HttpUtility.UrlEncode(id.ToString())}&page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class MyArtistLink(string name, string id, string thumbnail) {
|
||||
public string Artistname => HttpUtility.HtmlEncode(name);
|
||||
public string Artisturl => HttpUtility.HtmlAttributeEncode($"/music/myartist?id={HttpUtility.UrlEncode(id)}");
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode(thumbnail);
|
||||
}
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript myartist_listing = new ReloadingScript("wwwroot/pages/music/myartists/artists.sbnhtml");
|
||||
public static string MyArtistListing(string query, List<MyArtistLink> links, int page)
|
||||
{
|
||||
return Components.Shell($"Artist search {query}", myartist_listing.Render(new {
|
||||
Artists = links,
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/myartists?q={HttpUtility.UrlEncode(query)}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/myartists?q={HttpUtility.UrlEncode(query)}&page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
using System.Text;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript mysong = new ReloadingScript("wwwroot/pages/music/mysongs/song.sbnhtml");
|
||||
|
||||
private static ReloadingScript isnt_correct = new ReloadingScript("wwwroot/components/music/mysongs/isntcorrect.sbnhtml");
|
||||
public static string IsntCorrect(string songId, string albumId, string query)
|
||||
{
|
||||
|
||||
return isnt_correct.Render(new {
|
||||
Cancelurl = HttpUtility.HtmlAttributeEncode($"/music/mysong?songId={HttpUtility.UrlEncode(songId)}&albumId={HttpUtility.UrlEncode(albumId)}"),
|
||||
Albumid = HttpUtility.HtmlAttributeEncode(albumId),
|
||||
Songid = HttpUtility.HtmlAttributeEncode(songId),
|
||||
Searchurl = query == "" ? "" : HttpUtility.HtmlAttributeEncode($"/search_dialog?q={HttpUtility.UrlEncode(query)}")
|
||||
});
|
||||
}
|
||||
public static string MySong(Song song, Album album, SongVideo video, string tytdEndpoint,bool downloaded, int trackIndex, TimeSpan ts, List<Artist> contributingArtists)
|
||||
{
|
||||
StringBuilder builder=new StringBuilder();
|
||||
|
||||
for(int i = 0; i < contributingArtists.Count; i++)
|
||||
{
|
||||
string link = $"<a hx-target=\"body\" hx-push-url=\"true\" hx-get=\"{HttpUtility.HtmlAttributeEncode($"/music/myartist?id={HttpUtility.UrlEncode(contributingArtists[i].ArtistId)}")}\" href=\"{HttpUtility.HtmlAttributeEncode($"/music/myartist?id={HttpUtility.UrlEncode(contributingArtists[i].ArtistId)}")}\">{HttpUtility.HtmlEncode(contributingArtists[i].ArtistName)}</a>";
|
||||
if(i == 0)
|
||||
builder.Append(link);
|
||||
else if(i == 1)
|
||||
builder.Append($" feat {link}");
|
||||
else
|
||||
builder.Append($", {link}");
|
||||
}
|
||||
|
||||
|
||||
return Components.Shell("", mysong.Render(new {
|
||||
Songname = HttpUtility.HtmlEncode(song.SongName),
|
||||
Albumurl = HttpUtility.HtmlAttributeEncode($"/music/myalbum?id={HttpUtility.UrlEncode(album.AlbumId)}"),
|
||||
Albumname = HttpUtility.HtmlEncode(album.AlbumName),
|
||||
Trackindex = trackIndex.ToString("D2"),
|
||||
Duration = ts.ToString("m\\:ss"),
|
||||
Albumart = HttpUtility.HtmlAttributeEncode($"/api/v1/album-thumbnail?id={HttpUtility.UrlEncode(album.AlbumId)}"),
|
||||
Artists = builder.ToString(),
|
||||
Videothumbnail = HttpUtility.HtmlAttributeEncode($"/api/v1/video-thumbnail?v={HttpUtility.UrlEncode(video.VideoId)}"),
|
||||
Videotitle = HttpUtility.HtmlEncode($"{video.VideoTitle}-{video.VideoId}"),
|
||||
Incorrectsongurl = HttpUtility.HtmlAttributeEncode($"/music/fix-song?songId={HttpUtility.UrlEncode(song.SongId)}&albumId={HttpUtility.UrlEncode(album.AlbumId)}"),
|
||||
Tytdurl = HttpUtility.HtmlAttributeEncode($"{tytdEndpoint.TrimEnd('/')}/watch?v={HttpUtility.UrlEncode(video.VideoId)}"),
|
||||
Dlbtn = downloaded ? $"<a class=\"button\" href=\"/api/v1/song?albumId={HttpUtility.UrlEncode(album.AlbumId)}&songId={HttpUtility.UrlEncode(song.SongId)}\"><i>download</i> Download</a>" : string.IsNullOrEmpty(video.VideoId) ? "<span><i>file_download_off</i> Unavailable</span>" : "<span><i>downloading</i> Downloading</span>",
|
||||
Hasvideo = !string.IsNullOrEmpty(video.VideoId)
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
namespace Tesses.YouTubeDownloader2025Companion
|
||||
{
|
||||
public class MySongLink(string name, string id, string btn) {
|
||||
public string Name => HttpUtility.HtmlEncode(name);
|
||||
public string Songname => HttpUtility.HtmlEncode(name);
|
||||
public string Songurl => HttpUtility.HtmlAttributeEncode($"/music/mysong?songId={HttpUtility.UrlEncode(id)}");
|
||||
|
||||
public string Btn => btn;
|
||||
|
||||
}
|
||||
public static partial class Pages {
|
||||
|
||||
private static ReloadingScript mysongs_listing = new ReloadingScript("wwwroot/pages/music/mysongs/songs.sbnhtml");
|
||||
public static string MySongListing(string query, List<MySongLink> links, int page)
|
||||
{
|
||||
return Components.Shell($"Artist search {query}", mysongs_listing.Render(new {
|
||||
Songs = links,
|
||||
Q = HttpUtility.HtmlAttributeEncode(query),
|
||||
Prev = HttpUtility.HtmlAttributeEncode($"/music/mysongs?q={HttpUtility.UrlEncode(query)}&page={(page == 1 ? 1 : page - 1)}"),
|
||||
Current = page,
|
||||
Next = HttpUtility.HtmlAttributeEncode($"/music/mysongs?q={HttpUtility.UrlEncode(query)}&page={page + 1}")
|
||||
}),Program.DefaultLinks());
|
||||
}
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
using YoutubeExplode.Search;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Cryptography;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Tesses.YouTubeDownloader2025Companion;
|
||||
|
||||
public class SearchResultHandler : IEventable {
|
||||
private class SearchResultObj(IAsyncEnumerator<YoutubeExplode.Common.Batch<ISearchResult>> e,bool isDialog) {
|
||||
public long expires = Program.NowEpoch + (3600*6);
|
||||
|
||||
public IAsyncEnumerator<YoutubeExplode.Common.Batch<ISearchResult>> enumerator = e;
|
||||
|
||||
public bool isDialog = isDialog;
|
||||
}
|
||||
private ConcurrentDictionary<string,SearchResultObj> ents=new ConcurrentDictionary<string, SearchResultObj>();
|
||||
|
||||
public SearchResultHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private class SearchResult(string tytdUrl, string title, string id)
|
||||
{
|
||||
public string Url => HttpUtility.HtmlAttributeEncode($"{tytdUrl.TrimEnd('/')}/watch?v={id}");
|
||||
|
||||
public string Imgurl => HttpUtility.HtmlAttributeEncode($"/api/v1/video-thumbnail?v={id}");
|
||||
|
||||
public string Title => HttpUtility.HtmlEncode(title);
|
||||
|
||||
public string Dialogok => HttpUtility.HtmlAttributeEncode($"searchDialogSubmit('{HttpUtility.JavaScriptStringEncode(id)}')");
|
||||
|
||||
public string Addbtnjson => HttpUtility.HtmlAttributeEncode(JsonConvert.SerializeObject(new{type="add",value=id}));
|
||||
}
|
||||
public async Task<string> SearchAsync(string query,bool isDialog)
|
||||
{
|
||||
var obj = Program.YouTubeClient.Search.GetResultBatchesAsync(query, YoutubeExplode.Search.SearchFilter.Video);
|
||||
SearchResultObj ro = new SearchResultObj(obj.GetAsyncEnumerator(),isDialog);
|
||||
string id = RandomNumberGenerator.GetHexString(32);
|
||||
while(!ents.TryAdd(id,ro))
|
||||
{
|
||||
id = RandomNumberGenerator.GetHexString(32);
|
||||
}
|
||||
|
||||
|
||||
return await MoreAsync(id,ro);
|
||||
}
|
||||
|
||||
private static ReloadingScript results_component = new ReloadingScript("wwwroot/components/search-results.sbnhtml");
|
||||
private static ReloadingScript results_dialog_component = new ReloadingScript("wwwroot/components/search-results-dialog.sbnhtml");
|
||||
|
||||
private async Task<string> MoreAsync(string id,SearchResultObj o)
|
||||
{
|
||||
if(o.expires <= Program.NowEpoch)
|
||||
{
|
||||
return """<div class="row"><div class="max"></div><div class="min"><h1>The search has expired</h1></div><div class="max"></div></div>""";
|
||||
}
|
||||
if(await o.enumerator.MoveNextAsync())
|
||||
{
|
||||
|
||||
var tytd = Program.Config ?? new AuthConfig();
|
||||
List<SearchResult> results = new List<SearchResult>();
|
||||
foreach(var ent in o.enumerator.Current.Items)
|
||||
if(ent is VideoSearchResult item)
|
||||
results.Add(new SearchResult(tytd.TYTDUrl, item.Title, item.Id));
|
||||
|
||||
return o.isDialog ? results_dialog_component.Render(new{results, moreurl = HttpUtility.HtmlAttributeEncode($"/search_more?id={id}")}) : results_component.Render(new {
|
||||
results, moreurl = HttpUtility.HtmlAttributeEncode($"/search_more?id={id}")
|
||||
});
|
||||
}
|
||||
return """<div class="row"><div class="max"></div><div class="min"><h1>There are no more results</h1></div><div class="max"></div></div>""";
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> MoreAsync(string id)
|
||||
{
|
||||
if(ents.TryGetValue(id, out var v))
|
||||
{
|
||||
return await MoreAsync(id,v);
|
||||
}
|
||||
return """<div class="row"><div class="max"></div><div class="min"><h1>There are no more results</h1></div><div class="max"></div></div>""";
|
||||
}
|
||||
|
||||
public async Task EventAsync()
|
||||
{
|
||||
try {
|
||||
List<string> expired = new List<string>();
|
||||
var time = Program.NowEpoch;
|
||||
foreach(var item in ents)
|
||||
{
|
||||
if(item.Value.expires <= time)
|
||||
expired.Add(item.Key);
|
||||
}
|
||||
foreach(var expire in expired)
|
||||
ents.Remove(expire,out var e);
|
||||
}catch{
|
||||
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class Components {
|
||||
public static async Task<string> SearchMoreAsync(ServerContext ctx)
|
||||
{
|
||||
if(ctx.QueryParams.TryGetFirst("id",out var id))
|
||||
{
|
||||
return await Program.SearchResultHandler.MoreAsync(id);
|
||||
}
|
||||
return """<div class="row"><div class="max"></div><div class="min"><h1>No continuation id provided</h1></div><div class="max"></div></div>""";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
|
||||
private static ReloadingScript search_page = new ReloadingScript("wwwroot/pages/search.sbnhtml");
|
||||
|
||||
public static async Task<string> SearchAsync(ServerContext ctx)
|
||||
{
|
||||
string q="";
|
||||
string body = "";
|
||||
if(ctx.QueryParams.TryGetFirst("q",out q))
|
||||
{
|
||||
|
||||
body = await Program.SearchResultHandler.SearchAsync(q,false);
|
||||
}
|
||||
|
||||
return Components.Shell($"Search {q}",search_page.Render(new {body,q = HttpUtility.HtmlAttributeEncode(q)}),Program.DefaultLinks());
|
||||
}
|
||||
public static async Task<string> SearchDialogAsync(ServerContext ctx)
|
||||
{
|
||||
string q="";
|
||||
string body = "";
|
||||
if(ctx.QueryParams.TryGetFirst("q",out q))
|
||||
{
|
||||
|
||||
body = await Program.SearchResultHandler.SearchAsync(q,true);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Tesses.WebServer;
|
||||
using Scriban;
|
||||
using System.Web;
|
||||
using YoutubeExplode.Search;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Cryptography;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Tesses.YouTubeDownloader2025Companion;
|
||||
|
||||
public static partial class Pages {
|
||||
|
||||
|
||||
private static ReloadingScript settings_page = new ReloadingScript("wwwroot/pages/settings.sbnhtml");
|
||||
|
||||
public static string Settings(ServerContext ctx)
|
||||
{
|
||||
return Components.Shell("Settings",settings_page.Render(new{}),Program.DefaultLinks());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user