using System; using System.Collections.Generic; using System.Threading.Tasks; using Newtonsoft.Json; using Tesses.WebServer; using System.Net; using YoutubeExplode.Videos; using System.Linq; using System.IO; using System.Text; using YoutubeExplode.Playlists; using YoutubeExplode.Channels; namespace Tesses.YouTubeDownloader.Server { internal class ApiV1Server : Tesses.WebServer.Server { IDownloader downloader1; public ApiV1Server(IDownloader dl) { downloader1=dl; } public override async Task GetAsync(ServerContext ctx) { string path=ctx.UrlAndQuery; if(path.StartsWith("/AddItemRes/")) { string id_res=path.Substring(12); string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries); if(id_res_split.Length ==2) { int num; if(int.TryParse(id_res_split[0],out num)) { if(num < 0) num=1; if(num > 3) num=1; await downloader1.AddItemAsync(id_res_split[1],(Resolution)num); } } // await ctx.SendTextAsync( // $"

You Will Be Redirected in 5 Sec

\n" //); await ctx.SendRedirectAsync("/"); } if(path.StartsWith("/AddItem/")) { //string id_res=path.Substring(12); //string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries); //if(id_res_split.Length ==2) //{ await downloader1.AddItemAsync(path.Substring(9),Resolution.PreMuxed); // } // await ctx.SendTextAsync( // $"

You Will Be Redirected in 5 Sec

\n" //); await ctx.SendRedirectAsync("/"); } } } internal class ApiStorage : Tesses.WebServer.Server { ITYTDBase baseCtl; public ApiStorage(ITYTDBase baseCtl) { this.baseCtl=baseCtl; } public static System.Net.Mime.ContentDisposition GetVideoContentDisposition(string name) { var cd = new System.Net.Mime.ContentDisposition(); string filename = GetVideoName(name); cd.FileName = filename; cd.DispositionType = System.Net.Mime.DispositionTypeNames.Inline; return cd; } public static string GetVideoName(string name) { string asAscii = Encoding.ASCII.GetString( Encoding.Convert( Encoding.UTF8, Encoding.GetEncoding( Encoding.ASCII.EncodingName, new EncoderReplacementFallback(string.Empty), new DecoderExceptionFallback() ), Encoding.UTF8.GetBytes(name) ) ); return asAscii; } public override async Task GetAsync(ServerContext ctx) { string path=ctx.UrlAndQuery; /*if(path.StartsWith("/File/NotConverted/")) { // redirect to new // /File/NotConverted/xxxxxxxxxxx.mp4 string idmp4=WebUtility.UrlDecode(path.Substring(19)); if(idmp4.Length == 15) { string id=Path.GetFileNameWithoutExtension(idmp4); string path2 = $"Info/{id}.json"; if(!await baseCtl.FileExistsAsync(path2)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } var data= await baseCtl.ReadAllTextAsync(path2); var data2=JsonConvert.DeserializeObject(data); var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.PreMuxed); if(!await baseCtl.FileExistsAsync(loc)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } using(var s = await baseCtl.OpenReadAsyncWithLength(loc)) { await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc)); } } } else if(path.StartsWith("/File/Converted/")) { // redirect to new // /File/NotConverted/xxxxxxxxxxx.mp4 string idmp4=WebUtility.UrlDecode(path.Substring(16)); if(idmp4.Length == 15) { string id=Path.GetFileNameWithoutExtension(idmp4); string path2 = $"Info/{id}.json"; if(!await baseCtl.FileExistsAsync(path2)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } var data= await baseCtl.ReadAllTextAsync(path2); var data2=JsonConvert.DeserializeObject(data); var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.Mux); if(!await baseCtl.FileExistsAsync(loc)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } using(var s = await baseCtl.OpenReadAsyncWithLength(loc)) { await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc)); } } } else if(path.StartsWith("/File/Audio/")) { // redirect to new // /File/NotConverted/xxxxxxxxxxx.mp4 string idmp4=WebUtility.UrlDecode(path.Substring(12)); if(idmp4.Length == 15) { string id=Path.GetFileNameWithoutExtension(idmp4); string path2 = $"Info/{id}.json"; if(!await baseCtl.FileExistsAsync(path2)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } var data= await baseCtl.ReadAllTextAsync(path2); var data2=JsonConvert.DeserializeObject(data); var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.AudioOnly); if(!await baseCtl.FileExistsAsync(loc)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } using(var s = await baseCtl.OpenReadAsyncWithLength(loc)) { await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc)); } } } else if(path.StartsWith("/File/Info/")) { string idjson=WebUtility.UrlDecode(path.Substring(11)); string path2 = $"Info/{idjson}"; if(!await baseCtl.FileExistsAsync(path2)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } var data= await baseCtl.ReadAllTextAsync(path2); var data2=JsonConvert.DeserializeObject(data); await ctx.SendJsonAsync(data2.ToLegacy()); } else*/ if(path.StartsWith("/File/")) { string file=WebUtility.UrlDecode(path.Substring(6)); if(!await baseCtl.FileExistsAsync(file)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } using(var s = await baseCtl.OpenReadAsync(file)) { await ctx.SendStreamAsync(s); } }/*else if(path.StartsWith("/File-v2/")) { string file=WebUtility.UrlDecode(path.Substring(9)); if(!await baseCtl.FileExistsAsync(file)) { await NotFoundServer.ServerNull.GetAsync(ctx); return; } using(var s = await baseCtl.OpenReadAsyncWithLength(file)) { await ctx.SendStreamAsync(s); } }*/ else if(path.StartsWith("/GetFiles/")) { await ctx.SendJsonAsync(baseCtl.EnumerateFiles( WebUtility.UrlDecode(path.Substring(10))).ToList()); }else if(path.StartsWith("/GetDirectories/")) { await ctx.SendJsonAsync(baseCtl.EnumerateDirectories( WebUtility.UrlDecode(path.Substring(16))).ToList()); }else if(path.StartsWith("/FileExists-v2/")) { await ctx.SendTextAsync(baseCtl.FileExists(WebUtility.UrlDecode(path.Substring(15))) ? "true" : "false","text/plain"); } else if(path.StartsWith("/FileExists/")) { await ctx.SendTextAsync(baseCtl.FileExists(WebUtility.UrlDecode(path.Substring(12))) ? "true" : "false","text/plain"); }else if(path.StartsWith("/DirectoryExists/")) { await ctx.SendTextAsync(baseCtl.DirectoryExists(WebUtility.UrlDecode(path.Substring(17))) ? "true" : "false","text/plain"); }else if(path.StartsWith("/Video/")) { string id=path.Substring(7); VideoId? id1=VideoId.TryParse(id); if(id1.HasValue){ if(baseCtl.FileExists($"Info/{id1.Value.Value}.json")) { //Console.WriteLine("Id exists"); SavedVideo v = await baseCtl.GetVideoInfoAsync(id1.Value); string path0= await BestStreams.GetPathResolution(baseCtl,v,Resolution.PreMuxed); if(!string.IsNullOrWhiteSpace(path0)) { //Console.WriteLine("F is not null"); string filename = $"{v.Title}-{Path.GetFileName(path0)}"; string header=GetVideoContentDisposition(filename).ToString(); ctx.ResponseHeaders.Add("Content-Disposition",header); using(var strm = await baseCtl.OpenReadAsync(path0)) { await ctx.SendStreamAsync(strm,HeyRed.Mime.MimeTypesMap.GetMimeType(filename)); } } } } }else if(path.StartsWith("/VideoRes/")) { string id_res=path.Substring(10); string[] id_res_split = id_res.Split(new char[] {'/'},2,StringSplitOptions.RemoveEmptyEntries); if(id_res_split.Length ==2) { int num; if(int.TryParse(id_res_split[0],out num)) { if(num < 0) num=1; if(num > 3) num=1; VideoId? id1=VideoId.TryParse(id_res_split[1]); if(id1.HasValue){ if(baseCtl.FileExists($"Info/{id1.Value.Value}.json")) { //Console.WriteLine("Id exists"); SavedVideo v = await baseCtl.GetVideoInfoAsync(id1.Value); string path0= await BestStreams.GetPathResolution(baseCtl,v,(Resolution)num); if(!string.IsNullOrWhiteSpace(path0)) { //Console.WriteLine("F is not null"); string filename = $"{v.Title}-{Path.GetFileName(path0)}"; string header=GetVideoContentDisposition(filename).ToString(); ctx.ResponseHeaders.Add("Content-Disposition",header); using(var strm = await baseCtl.OpenReadAsync(path0)) { await ctx.SendStreamAsync(strm,HeyRed.Mime.MimeTypesMap.GetMimeType(filename)); } } } } } } } else{ await NotFoundServer.ServerNull.GetAsync(ctx); } } } internal class ApiV2Server : RouteServer { IDownloader Downloader; public ApiV2Server(IDownloader downloader) { this.Downloader=downloader; AddBoth("/AddItem",AddItem); AddBoth("/AddChannel",AddChannel); AddBoth("/AddUser",AddUser); AddBoth("/AddPlaylist",AddPlaylist); AddBoth("/AddVideo",AddVideo); AddBoth("/Progress",ProgressFunc); AddBoth("/QueueList",QueueList); AddBoth("/subscribe",Subscribe); AddBoth("/resubscribe",Resubscribe); AddBoth("/unsubscribe",Unsubscribe); AddBoth("/subscriptions",Subscriptions); AddBoth("/Subscribe",Subscribe); AddBoth("/Resubscribe",Resubscribe); AddBoth("/Unsubscribe",Unsubscribe); AddBoth("/Subscriptions",Subscriptions); AddBoth("/AddToList",AddToList); AddBoth("/DeleteFromList",DeleteFromList); Add("/ReplaceList",ReplaceList,"POST"); AddBoth("/DeleteList",DeleteList); AddBoth("/SetResolutionInList",SetResolutionInList); /* public async Task AddToPersonalPlaylistAsync(string name, IEnumerable<(VideoId Id, Resolution Resolution)> items) { throw new NotImplementedException(); } public async Task ReplacePersonalPlaylistAsync(string name, IEnumerable<(VideoId Id, Resolution Resolution)> items) { throw new NotImplementedException(); } public async Task RemoveItemFromPersonalPlaylistAsync(string name, VideoId id) { throw new NotImplementedException(); } public async Task SetResolutionForItemInPersonalPlaylistAsync(string name, VideoId id, Resolution resolution) { throw new NotImplementedException(); }*/ } private void AddBoth(string url,HttpActionAsync action) { Add(url,action); Add(url,async(evt)=>{ evt.ParseBody(); await action(evt); },"POST"); } public async Task DeleteList(ServerContext ctx) { //this is for personal playlists string name; if(ctx.QueryParams.TryGetFirst("name",out name)){ Downloader.DeletePersonalPlaylist(name); //Downloader.AddToPersonalPlaylistAsync(name); } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task ReplaceList(ServerContext ctx) { //this is for personal playlists string name; if(ctx.QueryParams.TryGetFirst("name",out name)){ string jsonData; List itemList; if(ctx.QueryParams.TryGetFirst("data",out jsonData)) { itemList = JsonConvert.DeserializeObject>(jsonData); await Downloader.ReplacePersonalPlaylistAsync(name,itemList); } //Downloader.AddToPersonalPlaylistAsync(name); } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task AddToList(ServerContext ctx) { //this is for personal playlists string name; if(ctx.QueryParams.TryGetFirst("name",out name)){ string jsonData; List itemList; if(ctx.Method == "POST" && ctx.QueryParams.TryGetFirst("data",out jsonData)) { itemList = JsonConvert.DeserializeObject>(jsonData); }else{ itemList=new List(); string id; if(ctx.QueryParams.TryGetFirst("v",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } VideoId? id1=VideoId.TryParse(id); if(id1.HasValue) { itemList.Add(new ListContentItem(id1,resolution)); } } } await Downloader.AddToPersonalPlaylistAsync(name,itemList); //Downloader.AddToPersonalPlaylistAsync(name); } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task DeleteFromList(ServerContext ctx) { //this is for personal playlists string name; if(ctx.QueryParams.TryGetFirst("name",out name)){ string id; if(ctx.QueryParams.TryGetFirst("v",out id)) { VideoId? id1=VideoId.TryParse(id); if(id1.HasValue) { await Downloader.RemoveItemFromPersonalPlaylistAsync(name,id1.Value); } } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task SetResolutionInList(ServerContext ctx) { //this is for personal playlists string name; if(ctx.QueryParams.TryGetFirst("name",out name)){ string id; if(ctx.QueryParams.TryGetFirst("v",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } VideoId? id1=VideoId.TryParse(id); if(id1.HasValue) { await Downloader.SetResolutionForItemInPersonalPlaylistAsync(name,id1.Value,resolution); } } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task Subscriptions(ServerContext ctx) { IStorage storage = Downloader as IStorage; if(storage != null) { var sub=storage.GetLoadedSubscriptions(); await ctx.SendJsonAsync(sub); } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task Resubscribe(ServerContext ctx) { IStorage storage = Downloader as IStorage; if(storage != null) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { string confstr; ChannelBellInfo conf=ChannelBellInfo.NotifyAndDownload; if(ctx.QueryParams.TryGetFirst("conf",out confstr)) { if(!Enum.TryParse(confstr,out conf)) { conf = ChannelBellInfo.NotifyAndDownload; } } ChannelId? cid=ChannelId.TryParse(id); if(cid.HasValue) { await storage.ResubscribeAsync(cid.Value,conf); } } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task Unsubscribe(ServerContext ctx) { IStorage storage = Downloader as IStorage; if(storage != null) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { ChannelId? cid=ChannelId.TryParse(id); if(cid.HasValue) { storage.Unsubscribe(cid.Value); } } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task Subscribe(ServerContext ctx) { IStorage storage = Downloader as IStorage; if(storage != null) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { string getinfostr; bool getinfo=true; if(ctx.QueryParams.TryGetFirst("getinfo",out getinfostr)) { if(getinfostr == "false") { getinfo=false; } } string confstr; ChannelBellInfo conf=ChannelBellInfo.NotifyAndDownload; if(ctx.QueryParams.TryGetFirst("conf",out confstr)) { if(!Enum.TryParse(confstr,out conf)) { conf = ChannelBellInfo.NotifyAndDownload; } } ChannelId? cid=ChannelId.TryParse(id); if(cid.HasValue) { await storage.SubscribeAsync(cid.Value,getinfo,conf); }else{ UserName? uname=UserName.TryParse(id); await storage.SubscribeAsync(uname.Value,conf); } } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task QueueList(ServerContext ctx) { await ctx.SendJsonAsync(Downloader.GetQueueList()); } public async Task ProgressFunc(ServerContext ctx) { await ctx.SendJsonAsync(Downloader.GetProgress()); } public async Task AddVideo(ServerContext ctx) { string id; if(ctx.QueryParams.TryGetFirst("v",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } VideoId? id1=VideoId.TryParse(id); if(id1.HasValue) { await Downloader.AddVideoAsync(id1.Value,resolution); } } await ctx.SendTextAsync( $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" ); } public async Task AddItem(ServerContext ctx) { string id; if(ctx.QueryParams.TryGetFirst("v",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } await Downloader.AddItemAsync(id,resolution); } await ctx.SendTextAsync( $"

You Will Be Redirected in 5 Sec

\n" ); } public async Task AddUser(ServerContext ctx) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } UserName? id1=UserName.TryParse(id); if(id1.HasValue) { await Downloader.AddUserAsync(id1.Value,resolution); } } await ctx.SendTextAsync( $"

You Will Be Redirected in 5 Sec

\n" ); } public async Task AddChannel(ServerContext ctx) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } ChannelId? id1=ChannelId.TryParse(id); if(id1.HasValue) { await Downloader.AddChannelAsync(id1.Value,resolution); } } await ctx.SendTextAsync( $"

You Will Be Redirected in 5 Sec

\n" ); } public async Task AddPlaylist(ServerContext ctx) { string id; if(ctx.QueryParams.TryGetFirst("id",out id)) { Resolution resolution=Resolution.PreMuxed; string res; if(ctx.QueryParams.TryGetFirst("res",out res)) { if(!Enum.TryParse(res,out resolution)) { resolution=Resolution.PreMuxed; } } PlaylistId? id1=PlaylistId.TryParse(id); if(id1.HasValue) { await Downloader.AddPlaylistAsync(id1.Value,resolution); } } await ctx.SendTextAsync( $"

You Will Be Redirected in 5 Sec

\n" ); } } public class TYTDServer { /// /// Constructor /// /// TYTD context public TYTDServer(ITYTDBase baseCtl) { ExtensionsServer=new ChangeableServer(); RootServer=new ChangeableServer(); MountableServer mountableServer=new MountableServer(RootServer); IDownloader downloader=baseCtl as IDownloader; if(downloader != null) { mountableServer.Mount("/api/",new ApiV1Server(downloader)); mountableServer.Mount("/api/v2/",new ApiV2Server(downloader)); } mountableServer.Mount("/api/v2/Extensions/",ExtensionsServer); mountableServer.Mount("/api/Storage/",new ApiStorage(baseCtl)); InnerServer=mountableServer; } /// /// To provide to tesses.webserver /// public IServer InnerServer {get; private set;} /// /// Set by Nuget Package Tesses.YouTubeDownloader.ExtensionLoader /// public ChangeableServer ExtensionsServer {get; private set;} /// /// An optional static website (recomendeded) /// public ChangeableServer RootServer {get;private set;} } }