using System.Linq; using SimpleHttp; using System; using System.Collections.Generic; using System.IO; using System.IO.Pipes; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading; using TYTD.Server.Models; using Newtonsoft.Json; using System.Net; using System.Threading.Tasks; using TYTD.Server.Functions; using YoutubeExplode.Videos; using YoutubeExplode; using YoutubeExplode.Videos.Streams; using PlaylistsNET; using PlaylistsNET.Content; using PlaylistsNET.Models; using PlaylistsNET.Utils; using YoutubeExplode.Playlists; using Dasync.Collections; using YoutubeExplode.Search; using Hyperlinq; using System.Net.Sockets; using System.IO.Compression; namespace TYTD { static class Program { public static void RemoveRange(this List list,IEnumerable items) { foreach(var item in items) { list.Remove(item); } } static ApiHomePageInfo info; //static string webSitePath; static void Main(string[] arg) { foreach (var dir in new[] {"Info", "PersonalPlaylist", "NotConverted","Converted","Audio","Download","Channel","Playlist","WebSite","ClosedCaptions","config/apidll","config/apistore", "Thumbnails/120x90", "Thumbnails/168x94", "Thumbnails/196x110", "Thumbnails/320x180", "Thumbnails/360x202", "Thumbnails/480x360", "Thumbnails/900x900", "Thumbnails/1280x720", "Thumbnails/1920x1080", "Thumbnails/246x138", "Thumbnails/336x188", "Thumbnails/480x270", "Thumbnails/720x404" }) { Directory.CreateDirectory(dir); } info = new ApiHomePageInfo(); Directory.CreateDirectory(Path.Combine("config", "apidll")); Downloader.GetManifest = GetManifest; Thread t = new Thread(new ThreadStart(() => { Downloader.DL.DownloadThread().GetAwaiter().GetResult(); })); t.Start(); Thread t2 = new Thread(new ThreadStart(() => { Downloader.DL.ListenForQueueItem().GetAwaiter().GetResult(); })); t2.Start(); string file = Path.Combine("config","discover_info.json"); BroadcastSettings settings = new BroadcastSettings(); //http://+:3250/ if(File.Exists(file)) { settings=JsonConvert.DeserializeObject(file); } if(settings.broadcast) { ushort port = 3250; if(arg.Length > 0) { string url0 = arg[0]; Uri uri = new Uri(url0.Replace("+", "domain")); port = (ushort)uri.Port; } //UdpClient cl; Thread t3 = new Thread(() => { IPEndPoint end = new IPEndPoint(0, 0); ushort _port = port; UdpClient c = new UdpClient(new IPEndPoint(IPAddress.Any, 32501)); while (true) { var data= c.Receive(ref end); string text=Encoding.UTF8.GetString(data); if(text.Equals("TYTD_BROADCAST", StringComparison.Ordinal)) { byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Broadcast(_port,settings.name))); c.Send(json,json.Length, end); } } }); t3.Start(); } // we need to get our app name so that // we can create unique names for our mutex and our pipe //webSitePath = Downloader.DL.GetPath(true, "WebSite"); Directory.CreateDirectory("WebSite"); Route.Before += Route_Before; /* Generic */ Downloader.RouteAdd("/api/AddItems","Generic","Post JSON file with\n" + WebUtility.HtmlEncode("") + "\nJson structure is like: this", (HttpAction)AddItems, "POST"); Downloader.RouteAdd("/api/AddItem/{Id}", "Generic", "Add Item to downloader\nDownloader will auto detect media type\nIt will be SD (Premuxed Video)\nParams:\n{Id}: The Id or URL for the media",(HttpAction)AddItem); Downloader.RouteAdd("/api/AddItemRes/{R}/{Id}","Generic", "Add Item to downloader\nDownloader will auto detect media type\nParams:\n{R}:0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: The Id or URL for the media", (HttpAction)AddItemRes); Downloader.RouteAdd("/api/AddFile/{Url}", "Generic", "Add Normal HTTP(S) download\nParams:\n{Url}: url to file for download", (HttpAction)AddFile); Downloader.RouteAdd("/api/AddCaptions/{Id}", "Generic", "Download all subtitles for video\nParams:\n{Id}: video id to get subtitles from", (HttpAction)AddCaptions); /* Videos */ Downloader.RouteAdd("/api/AddVideoInfo/{Id}", "Videos", "Get Video Info only (Don't Download the video)\nParams:\n{Id}: Video Id to download Info and Thumbnails for",AddVideoInfo); Downloader.RouteAdd("/api/AddVideo/{Id}","Videos", "Add Video to downloader\nIt will be SD (Premuxed Video)\nParams:\n{Id}: The Id or URL for the video", (HttpAction)AddVideo); Downloader.RouteAdd("/api/AddVideoRes/{R}/{Id}","Videos", "Add Video to downloader\nParams:\n{R}:0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: The Id or URL for the video", (HttpAction)AddVideoRes); Downloader.RouteAdd("/api/Redownload","Videos","Resume all videos downloading (Ignores Complete) (SD, Premuxed Video)", (HttpAction)Redownload); Downloader.RouteAdd("/api/RedownloadRes/{R}","Videos", "Resume all videos downloading (Ignores Complete)\nParams:\n{R}: 0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only", (HttpAction)RedownloadRes); Downloader.RouteAdd("/api/Watch/{VideoId}","Videos", "Brings Up Watch Page, loads watch_page.thtml\nParams:\n{VideoId}: the video id, replaces value in thtml file", (HttpAction)Watch); Downloader.RouteAdd("/api/VideoInfo/{Id}","Videos","Brings up html Video Info\nParams:\n{Id}: Video Id or Url to get info from",(HttpAction)VideoInfo); /* Playlist */ Downloader.RouteAdd("/api/AddPlaylistOnly/{Id}","Playlist","Add playlist, dont download videos\nParams:\n{Id}: Playlist Id or Url to download", AddPlaylistOnly); Downloader.RouteAdd("/api/RedownloadPlaylist/{Id}", "Playlist", "Redownload Playlist Entries (Wont Update Playlist, use /api/AddPlaylist/ for that)\nThis will download playlist if not already done, or if playlist is empty\n(SD, Premuxed Video)\nParams:\n{Id}: Existing Playlist Id",(HttpAction)RedownloadPlaylist); Downloader.RouteAdd("/api/RedownloadPlaylistRes/{R}/{Id}", "Playlist", "Redownload Playlist Entries (Wont Update Playlist, use /api/AddPlaylist/ for that)\nThis will download playlist if not already done, or if playlist is empty\nParams:\n{Id}: Existing Playlist Id\n{R}: 0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only", (HttpAction)RedownloadPlaylistRes, "GET"); Downloader.RouteAdd("/api/AddPlaylist/{Id}","Playlist", "Add Playlist to downloader\nIt will be SD (Premuxed Video)\nParams:\n{Id}: The Id or URL for the Playlist", (HttpAction)AddPlaylist); Downloader.RouteAdd("/api/AddPlaylistRes/{R}/{Id}","Playlist", "Add Playlist to downloader\nParams:\n{R}:0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: The Id or URL for the playlist", (HttpAction)AddPlaylistRes); Downloader.RouteAdd("/api/PersonalPlaylist/{PlaylistName}","PersonalPlaylist","Create personal playlist with name",(HttpAction)PersonalPlaylist); Downloader.RouteAdd("/api/CreatePlaylist/{Ids}/playlist.{extension}","PersonalPlaylist","Create Playlist with Ids\nParams:\n{Ids}: Comma seperated VideoIds\n{extension}: m3u, m3u8, pls, wpl, zpl", (HttpAction)CreatePlaylist); Downloader.RouteAdd("/api/CreatePlaylistRes/{Ids}/playlist.{extension}","PersonalPlaylist","Create Playlist with Ids, Res\nParams:\n {Ids}: Comma seperated VideoIds,Res,VideoId,Res where Res is 0=HD, 1=SD, 2=Audio only\n{extension}: m3u, m3u8, pls, wpl, zpl", (HttpAction)CreatePlaylistRes); Downloader.RouteAdd("/api/PlaylistInfo/{Id}","Playlist", "Brings up html Playlist Info\nParams:\n{Id}: Playlist Id or Url to get info from", (HttpAction)PlaylistInfo); Downloader.RouteAdd("/api/ListPlaylists/","Playlist","List all playlists", (HttpAction)ListPlaylists); /* Search */ Downloader.RouteAdd("/api/SearchOnly/{text}","Search","Search youtube without downloading thumbnails, VideoInfos", (HttpAction)SearchOnly); Downloader.RouteAdd("/api/Search/{text}","Search","Search youtube", (HttpAction)Search); Downloader.RouteAdd("/api/SearchPage/","Search","Search youtube html", SearchPage); Downloader.RouteAdd("/api/SearchPage/{query}","Search","Search youtube html",SearchPage); Downloader.RouteAdd("/api/SearchPage/","Search","Search youtube html",SearchPage,"POST"); Downloader.RouteAdd("/api/SearchVideos/","Video", "Search existing videos", (HttpAction)SearchVideos,"POST"); Downloader.RouteAdd("/api/SearchVideos/{query}","Videos", "Search existing videos", (HttpAction)SearchVideos, "GET"); Downloader.RouteAdd("/api/SearchVideos/", "Videos", "Search existing videos", (HttpAction)SearchVideos, "GET"); /* Channel */ Downloader.RouteAdd("/api/AddChannelOnly/{Id}","Channel", "Add Channel, dont download videos\nParams:\n{Id}: Channel Id or Url to download", AddChannelOnly); Downloader.RouteAdd("/api/AddChannel/{Id}","Channel", "Add Channel to downloader\nIt will be SD (Premuxed Video)\nParams:\n{Id}: The Id or URL for the Channel", (HttpAction)AddChannel); Downloader.RouteAdd("/api/AddChannelRes/{R}/{Id}","Channel", "Add Channel to downloader\nParams:\n{R}:0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: The Id or URL for the Channel", (HttpAction)AddChannelRes); /* User */ Downloader.RouteAdd("/api/AddUserOnly/{Id}","User", "Add Channel By Username, dont download videos\nParams:\n{Id}: Username or UserUrl to download", AddUserOnly); Downloader.RouteAdd("/api/AddUser/{Id}","User", "Add Channel By Username to downloader\nIt will be SD (Premuxed Video)\nParams:\n{Id}: The Name or UserURL for the Channel", (HttpAction)AddUser); Downloader.RouteAdd("/api/AddUserRes/{R}/{Id}","User", "Add Channel By Username to downloader\nParams:\n{R}:0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: The Id or UserURL for the Channel", (HttpAction)AddUserRes); /* Queue and Progress */ Downloader.RouteAdd("/api/QueueList","Queue","QueueList as json", (HttpAction)QueueList); Downloader.RouteAdd("/api/QueueListPage/","Queue","QueueList as html", (HttpAction)QueueListHtml); Downloader.RouteAdd("/api/QueueMove/{From}/{To}","Queue","Move item in queue\nParams:\n{From}: where to move item from (Either number or \"last\")\n{To}: where to move item to (Either number, \"up\", \"down\", \"top\", \"bottom\" or \"remove\"", (HttpAction)QueueMove); Downloader.RouteAdd("/api/QueueMoveId/{To}/{Id}","Queue", "Move item in queue (Id is from)\nParams:\n{Id}: Video Id (some queue position)\n{To}: where to move item to (Either number, \"up\", \"down\", \"top\", \"bottom\" or \"remove\"", (HttpAction)QueueMove2); Downloader.RouteAdd("/api/Progress","Current","Get progress as json", (HttpAction)VideoProgress); Downloader.RouteAdd("/api/Progress.html","Current","Get progress as html", (HttpAction)VideoProgressHtml); Downloader.RouteAdd("/api/Redo","Current","Cancel current video, redo video (however It may act like /api/Cancel, that is a bug)", (HttpAction)Redo); Downloader.RouteAdd("/api/Cancel","Current","Cancel current video, go to next", (HttpAction)Cancel); /* Storage */ Downloader.RouteAdd("/api/Storage/GetDirectories/{Path}", "Storage","Get list of directories in Path\nAlready used Path.GetFileName(), its json array", (HttpAction)StorageGetDirectories); Downloader.RouteAdd("/api/Storage/GetFiles/{Path}","Storage","Get list of files in Path\nAlready used Path.GetFileName(), its json array", (HttpAction)StorageGetFiles); Downloader.RouteAdd("/api/Storage/DirectoryExists/{Path}", "Storage", "returns \"true\" if directory exists or \"false\" if not",(HttpAction)StorageDirectoryExists); Downloader.RouteAdd("/api/Storage/FileExists/{Path}","Storage","returns \"true\" if file exists or \"false\" if not", (HttpAction)StorageFileExists); Downloader.RouteAdd("/api/Storage/File/{Path}","Storage","Get file based on working directory", (HttpAction)StorageFile); Downloader.RouteAdd("/api/Storage/File/{Path}", "Storage", "Upload file over put (not Website Directory)", (HttpAction)UploadStorageFilePut, "PUT"); Downloader.RouteAdd("/api/Storage/Video/{Id}","Storage","",(HttpAction)Video); Downloader.RouteAdd("/api/Storage/VideoRes/{Res}/{Id}","Storage","Download Video to Computer from Downloader\nParams:\n{Res}: 0=HD (Muxed using ffmpeg), 1=SD (Premuxed Video), 2=Audio only\n{Id}: Video Id to Download",(HttpAction)VideoRes); Downloader.RouteAdd("/api/upload/","Admin","Upload file via POST", (HttpAction)UploadFiles, "POST"); Downloader.RouteAdd("/api/endpoint","Generic","POST endpoint for many functions\nDocumentation", (HttpAction)Endpoint,"POST"); Downloader.RouteAdd("/api/endpoints.html","Other","This Page", (HttpAction)Endpoints); Downloader.RouteAdd("/api/RestartServer", "Admin", "Restart server", (req, resp, args) => { if (AuthorizedAdmin(req, resp, args)) { ApiLoader.RestartApp(); } }); Downloader.RouteAdd("/api/KillServer", "Admin", "Stop server", (req, resp, args) => { if (AuthorizedAdmin(req, resp, args)) { ApiLoader.StopApp(); } }); Downloader.RouteAdd("/api/HomePageChanger.html", "Admin", "Change Home Page", (HttpAction)ChangeFrontEnd); Downloader.RouteAdd("/api/SetHomePage", "Admin", "Used by /api/HomePageChanger.html to actually change home page", (HttpAction)SetFrontEnd, "POST"); Downloader.RouteAdd("/api/RemoveUnwanted", "Admin", "Used by /api/InstallExtensionUpload", (req, resp, args) => { if(AuthorizedAdmin(req, resp, args)) { req.ParseBody(args); foreach(var a in args) { try { ApiLoader.UninstallExtension(a.Key); } catch(Exception ex) { _ = ex; } } } },"POST"); Downloader.RouteAdd("/api/InstallExtensionUpload", "Admin", "Install Extension from Upload",(request, response, arguments) => { if (Authorized(request, response, arguments)) { Directory.CreateDirectory("extension_temp"); var files = request.ParseBody(arguments, (fieldName, fileName, contentType) => { return File.Create($"extension_temp/{fileName}"); }); List<(ext_conf conf, string name)> ext_names = new List<(ext_conf, string)>(); foreach (var f in files) { f.Value.Dispose(); string key = f.Value.FileName; ext_names.Add(ApiLoader.InstallExtension($"extension_temp/{key}")); } Directory.Delete("extension_temp",true); StringBuilder fields = new StringBuilder(); foreach (var item in ext_names) { string name = WebUtility.HtmlEncode(item.name); string name_text = WebUtility.HtmlEncode(item.conf.name); string desc = string.Join("
", item.conf.desc.Split('\n').Select(e => { return WebUtility.HtmlEncode(e); })); string data = ""; string root = Path.Combine(Environment.CurrentDirectory, "config"); string fallbackIcon = Path.Combine(root, "default_icon.png"); string icon = Path.Combine(root, "apiicons", name + ".png"); string icon2 = File.Exists(icon) ? icon : fallbackIcon; if (File.Exists(icon2)) { data = Convert.ToBase64String(File.ReadAllBytes(icon2)); } fields.Append(" {name_text}{desc}"); } string html = $"Extensions Installed

Do You Want all of these Extensions

If you kill the downloader before Accept, these extensions will be installed

{fields.ToString()}
Remove ThisIcon Title Description
"; response.AsText(html); } },"POST"); Route.Add("/api/example_tripple_structure.json", (req, resp, args) => { List v = new List(); v.Add(new IDResolutionTypeTriplet() { Id = "xxxxxxxxxxx", Resolution = Resolution.NoConvert, Type = InfoType.Video }); v.Add(new IDResolutionTypeTriplet() { Id = "PLxxxxxxxxxxxxxxxxx", Resolution = Resolution.NoConvert, Type = InfoType.Playlist }); v.Add(new IDResolutionTypeTriplet() { Id = "UCxxxxxxxxxxxxxxxxxxxxxx", Resolution = Resolution.NoConvert, Type = InfoType.Channel }); v.Add(new IDResolutionTypeTriplet() { Id = "SomeUserName", Resolution = Resolution.NoConvert, Type = InfoType.User }); v.Add(new IDResolutionTypeTriplet() { Id = "xxxxxxxxxxx", Resolution = Resolution.NoConvert, Type = InfoType.ClosedCaptions }); v.Add(new IDResolutionTypeTriplet() { Id = "https://example.com/path/to/file.txt", Resolution = Resolution.NoConvert, Type = InfoType.FileDownload }); resp.AsJson(v); }); var cancel= ApiLoader.Init(info); if (string.IsNullOrWhiteSpace(Config.HomePageExtension)) { info.Change(null); } else { foreach(var ext in ApiLoader.EnumerateExtensions()) { if(ext.CanProvideHomePage) { if(ext.Name.Equals(Config.HomePageExtension)) { info.Change(ext); } } } } info.Changed += (sender, e) => { if(info.HasHomePage) { Config.HomePageExtension = info.HomePage.Name; Config.Save(); } else { Config.HomePageExtension = ""; Config.Save(); } }; Downloader.RouteAdd("/api{p}","Other","Just a redirect to /api/endpoints.html", (request, response, action) => { request.RedirectIt(response, "/api/endpoints.html"); }); /* Other */ Downloader.RouteAdd("/", "Other", "Home page", (HttpAction)Index, "GET"); Downloader.RouteAdd("/extensions.html","Other","Extensions URL", (HttpAction)Extensions); Downloader.RouteAdd("/{Path}","Other","Website Files", (HttpAction)RootPath); Downloader.RouteAdd("/{Path}","Admin","Upload file over put",(HttpAction)UploadFilePut,"PUT"); Console.CancelKeyPress += (sender, e) => { ApiLoader.Dispose();var date = DateTime.Now.ToString("yyyyMMdd_HHmmss");Directory.CreateDirectory(Path.Combine("config","queues-close")); File.WriteAllText(Path.Combine("config", "queues-close", $"{date}.json"), Downloader.GetQueue()); Console.WriteLine("TYTD has Closed"); ApiLoader.StopApp(); }; Console.WriteLine("Almost Ready To Listen"); if (arg.Length > 0) { HttpServer.ListenAsync(arg[0],cancel, Route.OnHttpRequestAsync).Wait(); } else { HttpServer.ListenAsync(3250,cancel, Route.OnHttpRequestAsync).Wait(); } if(ApiLoader.Restart) { var fileName = Assembly.GetExecutingAssembly().Location; StringBuilder args = new StringBuilder(); foreach(var arg0 in arg) { args.Append($"\"{arg0}\""); } System.Diagnostics.Process.Start(fileName,args.ToString()); } } public class Configuration { public string AdminUserName { get; set; } public string AdminPassword { get; set; } public string UserName { get; set; } public string Password { get; set; } public string HomePageExtension { get; set; } public void Save() { File.WriteAllText("config/configuration.json", JsonConvert.SerializeObject(this)); } } public static Configuration OpenConfig() { Directory.CreateDirectory("config"); if (File.Exists("config/configuration.json")) { return JsonConvert.DeserializeObject(File.ReadAllText("config/configuration.json")); } return new Configuration(); } public static bool EmptyAuthorization(this Configuration config) { return string.IsNullOrWhiteSpace(config.UserName) && string.IsNullOrWhiteSpace(config.Password); } public static bool EmptyAuthorizationAdmin(this Configuration config) { return string.IsNullOrWhiteSpace(config.AdminUserName) && string.IsNullOrWhiteSpace(config.AdminPassword); } public static bool ValidAuthAdmin(this Configuration config, HttpListenerRequest req) { if (req.Headers.AllKeys.Contains("Authorization")) { string[] authorization = req.Headers["Authorization"].Split(' '); //authorization_basic if (authorization[0] == "Basic") { string userPass = Encoding.UTF8.GetString(Convert.FromBase64String(authorization[1])); return userPass.Equals($"{config.AdminUserName}:{config.AdminPassword}", StringComparison.Ordinal); } } return false; } public static bool ValidAuth(this Configuration config,HttpListenerRequest req) { if (req.Headers.AllKeys.Contains("Authorization")) { string[] authorization=req.Headers["Authorization"].Split(' '); //authorization_basic if(authorization[0]=="Basic") { string userPass=Encoding.UTF8.GetString(Convert.FromBase64String(authorization[1])); return userPass.Equals($"{config.UserName}:{config.Password}",StringComparison.Ordinal); } } return false; } internal static Configuration Config=OpenConfig(); internal static bool AuthorizedAdmin(HttpListenerRequest req, HttpListenerResponse resp, Dictionary args) { if(Config.EmptyAuthorizationAdmin()) { return true; } if(Config.ValidAuthAdmin(req)) { return true; } resp.WithHeader("WWW-Authenticate", "Basic realm=\"TYTD_ADMIN\"").WithCode(HttpStatusCode.Unauthorized).AsText("Unauthorized"); return false; } internal static bool Authorized(HttpListenerRequest req, HttpListenerResponse resp, Dictionary args) { if (Config.EmptyAuthorization()) { return true; } if (Config.ValidAuth(req)) { return true; } if(!Config.EmptyAuthorizationAdmin()) { if(Config.ValidAuthAdmin(req)) { return true; } } resp.WithHeader("WWW-Authenticate", "Basic realm=\"TYTD_APP\"").WithCode(HttpStatusCode.Unauthorized).AsText("Unauthorized"); return false; } public static void AddEscapedHtml(this Dictionary dict,T key,string value) { dict.Add(key, WebUtility.HtmlEncode(value)); } private static async Task GetManifest(YoutubeClient arg1, VideoId arg2) { return await arg1.Videos.Streams.GetManifestAsync(arg2); } #region Generic private static void AddItems(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { var f = request.ParseBody(arguments); foreach (var file in f.Values) { using (var req = new StreamReader(file.Value)) { List tripletlst = JsonConvert.DeserializeObject>(req.ReadToEnd()); Downloader.DownloadItems(tripletlst); response.Redirect("/"); } } } public static void AddItem(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadItem(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddItemRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadItem(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"])); rq.RedirectIt(rp); } public static void AddFile(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { Downloader.DownloadFile(arguments["Url"]); request.RedirectIt(response); } public static void AddCaptions(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { Downloader.DownloadCaptions(arguments["Id"]); request.RedirectIt(response); } #endregion #region Video public static void VideoInfo(HttpListenerRequest request,HttpListenerResponse response,Dictionary args) { //"{Title}

{Title}

{AuthorTitle}

{Elements}
" //video id VideoId? id=VideoId.TryParse(args["Id"]); if(id.HasValue) { var item=JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Info", $"{id.Value.Value}.json"))); Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", item.Title); videos.AddEscapedHtml("Id", item.Id); videos.AddEscapedHtml("AuthorTitle", item.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", item.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(item.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", item.Duration.ToString()); videos.AddEscapedHtml("Likes", item.Likes.ToString()); videos.AddEscapedHtml("Dislikes", item.Dislikes.ToString()); videos.AddEscapedHtml("Views", item.Views.ToString()); videos.AddEscapedHtml("Description", item.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(item.UploadDate).ToShortDateString()); string res=ApiLoader.RenderFileOrDefault("WebSite/err/video_list/VideoInfo.html", "Information about {Title}

Video Info for {Title}

Playback: SD HD Audio
Download: SD HD Audio
Add To Server: SD HD Audio

Video Id: {Id}

Video Channel: {AuthorTitle}

Video Channel Id: {AuthorChannelId}

Likes: {Likes}, Dislikes: {Dislikes}, Views: {Views}

Upload Date: {UploadDate}

Duration: {DurationStringLong}

Description:

{Description}

", videos); response.AsText(res); } else { response.AsText("Invalid Video Id"); } } public static async Task AddVideoInfo(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { await Downloader.DownloadVideoInfo(System.Web.HttpUtility.UrlDecode(args["Id"]), Resolution.NoConvert); rq.RedirectIt(rp); } public static void AddVideo(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadVideo(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddVideoRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadVideo(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"])); rq.RedirectIt(rp); } public static void Redownload(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { foreach (var item in Directory.GetFiles("Info", "*.json")) { string id =Path.GetFileNameWithoutExtension(item); if(!File.Exists(Path.Combine("NotConverted",$"{id}.mp4"))) { Downloader.DownloadVideo(id, Resolution.NoConvert); } } rq.RedirectIt(rp); } public static void RedownloadRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { int res=int.Parse(args["R"]); if(res > 2) { rq.RedirectIt(rp); return; } string res_str = new[]{"Converted","NotConverted","Audio"}[res]; foreach (var item in Directory.GetFiles( "Info", "*.json")) { string id = Path.GetFileNameWithoutExtension(item); if (!File.Exists(Path.Combine(res_str, $"{id}.mp4"))) { Downloader.DownloadVideo(id, (Resolution)res); } } rq.RedirectIt(rp); } public static void Watch(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { var txt = Templating.RenderFile(Path.Combine("WebSite", "watch_page.thtml"), args); //populate template rp.AsText(txt); } #endregion #region Playlist public static void RedownloadPlaylistRes(HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { Resolution res=(Resolution)int.Parse(args["R"]); var id = args["Id"]; string jsonFile = Path.Combine("Playlist", $"{id}.json"); if (File.Exists(jsonFile)) { SavedPlaylist playlist = JsonConvert.DeserializeObject(File.ReadAllText(jsonFile)); if (playlist.Videos != null && playlist.Videos.Count > 0) { foreach (var v in playlist.Videos) { Downloader.DownloadVideo(v,res); } req.RedirectIt(resp); } else { AddPlaylistRes(req, resp, args); } } else { AddPlaylistRes(req, resp, args); } } public static void RedownloadPlaylist(HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { var id=args["Id"]; string jsonFile = Path.Combine("Playlist", $"{id}.json"); if(File.Exists(jsonFile)) { SavedPlaylist playlist = JsonConvert.DeserializeObject(File.ReadAllText(jsonFile)); if(playlist.Videos != null && playlist.Videos.Count > 0) { foreach(var v in playlist.Videos) { Downloader.DownloadVideo(v); } req.RedirectIt(resp); } else { AddPlaylist(req, resp, args); } } else { AddPlaylist(req, resp, args); } } public static async Task AddPlaylistOnly(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { await Downloader.DownloadPlaylistOnly(System.Web.HttpUtility.UrlDecode(args["Id"]), Resolution.NoConvert); rq.RedirectIt(rp); } public static void AddPlaylist(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadPlaylist(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddPlaylistRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadPlaylist(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"])); rq.RedirectIt(rp); } public static void PersonalPlaylist(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string playlistName=System.Web.HttpUtility.UrlDecode(args["PlaylistName"]); string playlistNameWithoutExtension =Path.GetFileNameWithoutExtension(playlistName); string path= Path.Combine("PersonalPlaylist", $"{playlistNameWithoutExtension}.json"); string extension = Path.GetExtension(playlistName); List<(string Id, Resolution Resolution)> list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); string mimeType; rp.AsText(CreatePlaylistString(rq, list, extension, out mimeType),mimeType); } public static void CreatePlaylist(HttpListenerRequest rq,HttpListenerResponse rp,Dictionary args) { // Route.Add("/api/PersonalPlaylist/{PlaylistName}", (HttpAction)PersonalPlaylist); //Route.Add("/api/CreatePlaylist/{Ids}/playlist.{extension}", (HttpAction)CreatePlaylist); //Route.Add("/api/CreatePlaylistRes/{Ids}/playlist.{extension}", (HttpAction)CreatePlaylistRes); string[] ids= System.Web.HttpUtility.UrlDecode(args["Ids"]).Split(','); var list = new List<(string Id, Resolution Resolution)>(); foreach (var id in ids) { list.Add((id, Resolution.NoConvert)); } string mimeType; rp.AsText(CreatePlaylistString(rq, list, args["extension"],out mimeType),mimeType); } public static void CreatePlaylistRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string[] ids = System.Web.HttpUtility.UrlDecode(args["Ids"]).Split(','); var list = new List<(string Id, Resolution Resolution)>(); for (int i=0;i videoIds, string ext,out string mimeType) { string[] _res = { "Converted", "NotConverted", "Audio" }; string UrlBegin = GetServerRoot(req); string ext2 = ext.TrimStart('.'); if (ext2 == "m3u" || ext2 == "m3u8") { M3uPlaylist playlist = new M3uPlaylist(); playlist.IsExtended = true; foreach (var item in videoIds) { M3uPlaylistEntry entry = new M3uPlaylistEntry(); entry.Path = UrlBegin.TrimEnd('/') + $"/api/Storage/File/{_res[(int)item.Resolution]}/{item.Id}.mp4"; var video = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Info", $"{item.Id}.json"))); entry.Title = video.Title; entry.AlbumArtist = video.AuthorTitle; entry.Duration = TimeSpan.FromSeconds(video.Duration); playlist.PlaylistEntries.Add(entry); } M3uContent content = new M3uContent(); mimeType = "audio/x-mpegurl"; return content.ToText(playlist); } else if (ext2 == "wpl") { WplPlaylist playlist = new WplPlaylist(); foreach (var item in videoIds) { WplPlaylistEntry entry = new WplPlaylistEntry(); entry.Path = UrlBegin.TrimEnd('/') + $"/api/Storage/File/{_res[(int)item.Resolution]}/{item.Id}.mp4"; var video = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Info", $"{item.Id}.json"))); entry.TrackTitle = video.Title; entry.TrackArtist = video.AuthorTitle; entry.Duration = TimeSpan.FromSeconds(video.Duration); playlist.PlaylistEntries.Add(entry); } WplContent content = new WplContent(); mimeType = "application/vnd.ms-wpl"; return content.ToText(playlist); } else if (ext2 == "pls") { PlsPlaylist playlist = new PlsPlaylist(); int i = 1; foreach (var item in videoIds) { PlsPlaylistEntry entry = new PlsPlaylistEntry(); entry.Path = UrlBegin.TrimEnd('/') + $"/api/Storage/File/{_res[(int)item.Resolution]}/{item.Id}.mp4"; var video = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Info", $"{item.Id}.json"))); entry.Title = video.Title; entry.Nr = i++; playlist.PlaylistEntries.Add(entry); } mimeType = "audio/x-scpls"; PlsContent content = new PlsContent(); return content.ToText(playlist); } else if (ext2 == "zpl") { ZplPlaylist playlist = new ZplPlaylist(); foreach (var item in videoIds) { ZplPlaylistEntry entry = new ZplPlaylistEntry(); entry.Path = UrlBegin.TrimEnd('/') + $"/api/Storage/File/{_res[(int)item.Resolution]}/{item.Id}.mp4"; var video = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Info", $"{item.Id}.json"))); entry.TrackTitle = video.Title; entry.TrackArtist = video.AuthorTitle; entry.Duration = TimeSpan.FromSeconds(video.Duration); playlist.PlaylistEntries.Add(entry); } mimeType = "application/vnd.ms-zpl"; ZplContent content = new ZplContent(); return content.ToText(playlist); } mimeType = "text/plain"; return "Invalid"; } public static void ListPlaylists(HttpListenerRequest request,HttpListenerResponse resp,Dictionary args) { string htmlBeforeProcessed = ApiLoader.ReadAllTextOrDefault("WebSite/err/playlist_list/element.html", "\"\"{Title}
{AuthorTitle}
"); StringBuilder builder = new StringBuilder(); foreach (var f in Directory.EnumerateFiles("Playlist","*.json")) { Dictionary playlist = new Dictionary(); bool add = true; var plitem = JsonConvert.DeserializeObject(File.ReadAllText(f)); try { playlist.AddEscapedHtml("Title", plitem.Title); playlist.AddEscapedHtml("Id", plitem.Id); playlist.AddEscapedHtml("AuthorTitle", plitem.AuthorTitle); playlist.AddEscapedHtml("AuthorChannelId", plitem.AuthorChannelId); playlist.AddEscapedHtml("Description", plitem.Description); playlist.AddEscapedHtml("FirstVideoId", plitem.Videos[0]); }catch(Exception) { add = false; } if(add) builder.Append(Templating.RenderString(htmlBeforeProcessed, playlist)); } Dictionary main = new Dictionary(); main.Add("Elements", builder.ToString()); string res = ApiLoader.RenderFileOrDefault("WebSite/err/playlist_list/main.html", "All Playlists

All Playlists

{Elements}
", main); resp.AsText(res); } public static void PlaylistInfo(HttpListenerRequest request, HttpListenerResponse response, Dictionary args) { //video id PlaylistId? id = PlaylistId.TryParse(args["Id"]); if (id.HasValue) { var plitem = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Playlist", $"{id.Value.Value}.json"))); string htmlBeforeProcessed = ApiLoader.ReadAllTextOrDefault("WebSite/err/video_list/element.html", "\"\"{Title}
{AuthorTitle}
"); StringBuilder builder = new StringBuilder(); foreach (var v in plitem.Videos) { string path = Path.Combine("Info", $"{v}.json"); if (!File.Exists(path)) { continue; } try { var item = JsonConvert.DeserializeObject(File.ReadAllText(path)); Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", item.Title); videos.AddEscapedHtml("Id", item.Id); videos.AddEscapedHtml("AuthorTitle", item.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", item.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(item.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", item.Duration.ToString()); videos.AddEscapedHtml("Likes", item.Likes.ToString()); videos.AddEscapedHtml("Dislikes", item.Dislikes.ToString()); videos.AddEscapedHtml("Views", item.Views.ToString()); videos.AddEscapedHtml("Description", item.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(item.UploadDate).ToShortDateString()); builder.Append(Templating.RenderString(htmlBeforeProcessed, videos)); }catch(Exception ex) { _ = ex; } } Dictionary playlist = new Dictionary(); playlist.Add("Elements", builder.ToString()); playlist.AddEscapedHtml("Title", plitem.Title); playlist.AddEscapedHtml("Id", plitem.Id); playlist.AddEscapedHtml("AuthorTitle", plitem.AuthorTitle); playlist.AddEscapedHtml("AuthorChannelId", plitem.AuthorChannelId); playlist.AddEscapedHtml("Description",plitem.Description); string res = ApiLoader.RenderFileOrDefault("WebSite/err/playlist_list/PlaylistInfo.html", "{Title}

{Title}

{AuthorTitle}

{Elements}
",playlist); response.AsText(res); } else { response.AsText("Invalid Video Id"); } } #endregion #region Search public static void SearchOnly(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string search = System.Web.HttpUtility.UrlDecode(args["text"]); string json = JsonConvert.SerializeObject(Downloader.Search(search, false)); rp.AsText(json, "application/json"); } public static void Search(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string search = System.Web.HttpUtility.UrlDecode(args["text"]); string json = JsonConvert.SerializeObject(Downloader.Search(search)); rp.AsText(json, "application/json"); } public static async Task SearchPage(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { if (rq.HttpMethod == "POST") { rq.ParseBody(args); } string search = ""; if (args.ContainsKey("query")) { search = System.Web.HttpUtility.UrlDecode(args["query"]); } try { string htmlBeforeProcessedPlaylist = ApiLoader.ReadAllTextOrDefault("WebSite/err/playlist_list/element.html", "\"\"{Title}
{AuthorTitle}
"); string htmlBeforeProcessedVideo = ApiLoader.ReadAllTextOrDefault("WebSite/err/video_list/element.html", "\"\"{Title}
{AuthorTitle}
"); StringBuilder builder = new StringBuilder(); await Downloader.GetClient().Search.GetResultsAsync(search).ForEachAsync(async (e) => { var video = e as VideoSearchResult; var playlist = e as PlaylistSearchResult; var channel = e as ChannelSearchResult; if (video != null) { await Downloader.DownloadVideoInfo(video.Id, Resolution.NoConvert); string path = Path.Combine("Info", $"{video.Id.Value}.json"); var item = JsonConvert.DeserializeObject(File.ReadAllText(path)); Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", item.Title); videos.AddEscapedHtml("Id", item.Id); videos.AddEscapedHtml("AuthorTitle", item.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", item.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(item.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", item.Duration.ToString()); videos.AddEscapedHtml("Likes", item.Likes.ToString()); videos.AddEscapedHtml("Dislikes", item.Dislikes.ToString()); videos.AddEscapedHtml("Views", item.Views.ToString()); videos.AddEscapedHtml("Description", item.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(item.UploadDate).ToShortDateString()); builder.Append(Templating.RenderString(htmlBeforeProcessedVideo, videos)); } if (playlist != null) { await Downloader.DownloadPlaylistOnly(playlist.Id, Resolution.NoConvert); Dictionary playlist0 = new Dictionary(); var plitem = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine("Playlist", $"{playlist.Id.Value}.json"))); playlist0.AddEscapedHtml("Title", plitem.Title); playlist0.AddEscapedHtml("Id", plitem.Id); playlist0.AddEscapedHtml("AuthorTitle", plitem.AuthorTitle); playlist0.AddEscapedHtml("AuthorChannelId", plitem.AuthorChannelId); playlist0.AddEscapedHtml("Description", plitem.Description); playlist0.AddEscapedHtml("FirstVideoId", plitem.Videos[0]); string res0 = Templating.RenderString(htmlBeforeProcessedPlaylist, playlist0); builder.Append(res0); } if(channel !=null) { await Downloader.DownloadChannelOnly(channel.Id); } }); //string res = ApiLoader.RenderFileOrDefault(, "All Playlists

All Playlists

{Elements}
", main); Dictionary data = new Dictionary(); data.Add("Elements", builder.ToString()); string html = ApiLoader.RenderFileOrDefault("WebSite/err/search_main.html", "Search Online
{Elements}
\n", data); rp.AsText(html, "text/html"); } catch (Exception ex) { _ = ex; } } public static void SearchVideos(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { if(rq.HttpMethod == "POST") { rq.ParseBody(args); } string search = "*"; if (args.ContainsKey("query")) { search= System.Web.HttpUtility.UrlDecode(args["query"]); } StringBuilder innerHtml = new StringBuilder(); string htmlBeforeProcessed = ApiLoader.ReadAllTextOrDefault("WebSite/err/video_list/element.html", "\"\"{Title}
{AuthorTitle}
"); long i=0; foreach (var item in Downloader.SearchFor(search)) { Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", item.Title); videos.AddEscapedHtml("Id", item.Id); videos.AddEscapedHtml("AuthorTitle", item.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", item.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(item.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", item.Duration.ToString()); videos.AddEscapedHtml("Likes", item.Likes.ToString()); videos.AddEscapedHtml("Dislikes", item.Dislikes.ToString()); videos.AddEscapedHtml("Views", item.Views.ToString()); videos.AddEscapedHtml("Description",item.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(item.UploadDate).ToShortDateString()); videos.AddEscapedHtml("Index", i.ToString()); var rend=Templating.RenderString(htmlBeforeProcessed, videos); innerHtml.Append(rend); i++; } Dictionary data = new Dictionary(); data.Add("Elements", innerHtml.ToString()); string html = ApiLoader.RenderFileOrDefault("WebSite/err/video_list/main.html", "Search Videos
{Elements}
\n", data); rp.AsText(html, "text/html"); } #endregion #region Channel public static async Task AddChannelOnly(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { await Downloader.DownloadChannelOnly(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddChannel(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadChannel(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddChannelRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadChannel(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"])); rq.RedirectIt(rp); } #endregion #region User public static async Task AddUserOnly(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { await Downloader.DownloadUserOnly(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddUser(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadUser(System.Web.HttpUtility.UrlDecode(args["Id"])); rq.RedirectIt(rp); } public static void AddUserRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.DownloadUser(System.Web.HttpUtility.UrlDecode(args["Id"]), (Resolution)int.Parse(args["R"])); rq.RedirectIt(rp); } #endregion #region Queue And Progress public static void QueueList(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string json = Downloader.GetQueue(); rp.AsText(json, "application/json"); } public static void QueueListHtml(HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { StringBuilder innerHtml = new StringBuilder(); string htmlBeforeProcessed = ApiLoader.ReadAllTextOrDefault("WebSite/err/video_list/element.html", "\"\"{Title}
{AuthorTitle}
"); long i = 0; foreach (var item0 in Downloader.GetQueueItems()) { var item = item0.Video; Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", item.Title); videos.AddEscapedHtml("Id", item.Id); videos.AddEscapedHtml("AuthorTitle", item.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", item.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(item.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", item.Duration.ToString()); videos.AddEscapedHtml("Likes", item.Likes.ToString()); videos.AddEscapedHtml("Dislikes", item.Dislikes.ToString()); videos.AddEscapedHtml("Views", item.Views.ToString()); videos.AddEscapedHtml("Resolution", ((int)item0.Resolution).ToString()); videos.AddEscapedHtml("RegularFile", (Convert.ToInt32(item0.RegularFile)).ToString()); videos.AddEscapedHtml("Description", item.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(item.UploadDate).ToShortDateString()); videos.AddEscapedHtml("Index", i.ToString()); var rend = Templating.RenderString(htmlBeforeProcessed, videos); innerHtml.Append(rend); i++; } Dictionary data = new Dictionary(); data.Add("Elements", innerHtml.ToString()); string html = ApiLoader.RenderFileOrDefault("WebSite/err/QueueList.html", "Video Queue{Elements}
\n", data); resp.AsText(html, "text/html"); } public static void QueueMove(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { Downloader.ModQueue(args["To"], args["From"]); rq.RedirectIt(rp); } public static void QueueMove2(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { Downloader.ModQueue2(arguments["To"], arguments["Id"]); response.AsRedirect("/"); } public static void VideoProgress(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string json = JsonConvert.SerializeObject(Downloader.GetProgress()); rp.AsText(json, "application/json"); } public static void VideoProgressHtml(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { var progress=Downloader.GetProgress(); if(progress==null) { progress = new VideoDownloadProgress(); } var saved = progress.Saved; if(progress.Saved == null) { saved = new SavedVideo(); } Dictionary videos = new Dictionary(); videos.AddEscapedHtml("Title", saved.Title); videos.AddEscapedHtml("Id", saved.Id); videos.AddEscapedHtml("AuthorTitle", saved.AuthorTitle); videos.AddEscapedHtml("AuthorChannelId", saved.AuthorChannelId); videos.AddEscapedHtml("DurationStringLong", TimeSpan.FromSeconds(saved.Duration).ToString()); videos.AddEscapedHtml("DurationNumber", saved.Duration.ToString()); videos.AddEscapedHtml("Likes", saved.Likes.ToString()); videos.AddEscapedHtml("Dislikes", saved.Dislikes.ToString()); videos.AddEscapedHtml("Views", saved.Views.ToString()); videos.AddEscapedHtml("Description", saved.Description); videos.AddEscapedHtml("UploadDate", DateTime.Parse(saved.UploadDate).ToShortDateString()); videos.AddEscapedHtml("Progress", progress.Progress.ToString()); var rend = ApiLoader.RenderFileOrDefault("WebSite/err/Progress.html", "TYTD Progress

TYTD Progress

Video Title: {Title}

Video Id: {Id}

Video Channel: {AuthorTitle}

Video Channel Id: {AuthorChannelId}

Likes: {Likes}, Dislikes: {Dislikes}, Views: {Views}

Upload Date: {UploadDate}

Duration: {DurationStringLong}

Progress: {Progress}

Description:

{Description}

", videos); rp.AsText(rend); } public static void Redo(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { lock (Downloader.DL.cancelSrc) { Downloader.RedownloadIt = true; Downloader.DL.cancelSrc.Item.Cancel(); } rq.RedirectIt(rp); } public static void Cancel(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { lock (Downloader.DL.cancelSrc) { Downloader.RedownloadIt = false; Downloader.DL.cancelSrc.Item.Cancel(); } rq.RedirectIt(rp); } #endregion #region Storage public static void StorageGetDirectories(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string path = System.Web.HttpUtility.UrlDecode(args["Path"]); if (Directory.Exists(path)) { string json = Newtonsoft.Json.JsonConvert.SerializeObject(Directory.EnumerateDirectories(path).Select((o) => { return Path.GetFileName(o); })); rp.AsText(json, "application/json"); } else { rp.AsText("[]", "application/json"); } } public static void StorageGetFiles(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string path = System.Web.HttpUtility.UrlDecode(args["Path"]); if (Directory.Exists(path)) { string json = Newtonsoft.Json.JsonConvert.SerializeObject(Directory.EnumerateFiles(path).Select((o) => { return Path.GetFileName(o); })); rp.AsText(json, "application/json"); } else { rp.AsText("[]", "application/json"); } } public static void StorageDirectoryExists(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string path =System.Web.HttpUtility.UrlDecode(args["Path"]); string json = Directory.Exists(path) ? "true" : "false"; rp.AsText(json, "text/plain"); } public static void StorageFileExists(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string path =System.Web.HttpUtility.UrlDecode(args["Path"]); string json = File.Exists(path) ? "true" : "false"; rp.AsText(json, "text/plain"); } public static void StorageFile(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { if (args["Path"].StartsWith("config/")) { rp.AsText("Access denied"); } else { string path = System.Web.HttpUtility.UrlDecode(args["Path"]); if (Directory.Exists(path)) { string indexHtml = Path.Combine(path, "index.html"); if (File.Exists(indexHtml)) { path = indexHtml; } else { string dir = Path.Combine("WebSite", "err", "dir.html"); StringBuilder b = new StringBuilder(); var f = Directory.GetLastWriteTime(Path.GetDirectoryName(path)); string parentModified = $"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"Up{parentModified}DIR"); foreach (var file in Directory.GetDirectories(path)) { string name = Path.GetFileName(file); string nameUrled = System.Web.HttpUtility.UrlEncode(name); string nameHtmled = System.Web.HttpUtility.HtmlEncode(name); f = Directory.GetLastWriteTime(file); string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"{nameHtmled}{dateModifed}DIR"); } foreach (var file in Directory.GetFiles(path)) { string name = Path.GetFileName(file); string nameUrled = System.Web.HttpUtility.UrlEncode(name); string nameHtmled = System.Web.HttpUtility.HtmlEncode(name); f = File.GetLastWriteTime(file); string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"{nameHtmled}{dateModifed}FILE"); } Dictionary templating = new Dictionary(); templating.Add("Items", b.ToString()); rp.AsText(Templating.RenderFile(dir, templating)); return; } } rp.AsFile(rq, path); } } public static void Video(HttpListenerRequest rq,HttpListenerResponse rp,Dictionary args) { VideoId? vid = VideoId.TryParse(System.Web.HttpUtility.UrlDecode(args["Id"])); if (vid.HasValue) { string path = $"NotConverted/{vid.Value}.mp4"; rp.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString()); rp.AsFile(rq, path); } else { rp.WithCode(HttpStatusCode.BadRequest); rp.AsText("Invalid Video ID or URL", "text/plain"); } } public static void VideoRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { VideoId? vid = VideoId.TryParse(System.Web.HttpUtility.UrlDecode(args["Id"])); if (vid.HasValue) { int res; if(int.TryParse(args["Res"],out res)) { if (res > 2 || res < 0) { rp.WithCode(HttpStatusCode.BadRequest); rp.AsText($"Invalid Resolution Number must be either 0, 1 or 2", "text/plain"); } else { string[] m = new string[] { "Converted", "NotConverted", "Audio" }; string path = $"{m[res]}/{vid.Value}.mp4"; rp.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString()); rp.AsFile(rq, path); } } else { rp.WithCode(HttpStatusCode.BadRequest); rp.AsText("Res is not a number", "text/plain"); } } else { rp.WithCode(HttpStatusCode.BadRequest); rp.AsText("Invalid Video ID or URL", "text/plain"); } } public static System.Net.Mime.ContentDisposition GetVideoContentDisposition(string id) { var cd = new System.Net.Mime.ContentDisposition(); string filename = GetVideoName(id); cd.FileName = filename; return cd; } public static string GetVideoName(string id) { string name = id + ".mp4"; string path = $"Info/{id}.json"; if (File.Exists(path)) { string info=File.ReadAllText(path); name= JsonConvert.DeserializeObject(info).Title + ".mp4"; } 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 static void UploadFiles(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { var files = rq.ParseBody(args); foreach (var f in files.Values) f.Save(Path.Combine("WebSite", f.FileName)); rp.AsText("uploaded", "text/plain"); } #endregion #region Other public static void SetFrontEnd(HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { if(AuthorizedAdmin(req,resp,args)) { req.ParseBody(args); if(args.ContainsKey("frontend")) { string value=args["frontend"]; if (string.IsNullOrWhiteSpace(value)) { info.Change(null); } else { foreach (var ext in ApiLoader.EnumerateExtensions()) { if(ext.CanProvideHomePage) { if(value.Equals(ext.Name)) { info.Change(ext); } } } } } resp.AsRedirect("../"); } } public static void ChangeFrontEnd(HttpListenerRequest req,HttpListenerResponse resp,Dictionary args) { if (AuthorizedAdmin(req, resp, args)) { Dictionary arg_ = new Dictionary(); if (info.HasHomePage) { arg_.Add("DefaultSelected", ""); } else { arg_.Add("DefaultSelected", "selected"); } StringBuilder b = new StringBuilder(); foreach (var ext in ApiLoader.EnumerateExtensions()) { if (ext.CanProvideHomePage) { string selected = ext == info.HomePage ? " selected" : ""; string htmlCode = $""; b.Append(htmlCode); } } arg_.Add("Frontends", b.ToString()); string r=ApiLoader.RenderFileOrDefault("WebPage/err/change_frontend_ui.html", "Select Home Page

Select Home Page

", arg_); resp.AsText(r); } // /err/change_frontend_ui.html } public static void Index(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string r = ApiLoader.ReadAllTextOrDefault( "WebSite/index.html", "TYTD

TYTD

Existing Videos:

Get Progress
List Queue
List Playlists
"); rp.AsText( r); } public static void Extensions(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { rp.AsText(ApiLoader.Page); } private static void UploadStorageFilePut(HttpListenerRequest request,HttpListenerResponse resp,Dictionary args) { string path = System.Web.HttpUtility.UrlDecode(args["Path"]).Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0]; bool exists = File.Exists(path); using (var instr = request.InputStream) { using (var outStr = File.Create(path)) { instr.CopyTo(outStr); } } if (exists) { resp.WithCode(HttpStatusCode.NoContent); } else { resp.WithCode(HttpStatusCode.Created); } } private static void UploadFilePut(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { string p = System.Web.HttpUtility.UrlDecode(arguments["Path"]).Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0]; string path = Path.Combine("WebSite", p); bool exists = File.Exists(path); using (var instr = request.InputStream) { using (var outStr = File.Create(path)) { instr.CopyTo(outStr); } } if (exists) { response.WithCode(HttpStatusCode.NoContent); } else { response.WithCode(HttpStatusCode.Created); } } private static void Endpoints(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { Func get_color = (meth) => { switch(meth) { case "GET": return "red"; case "POST": return "green"; case "PUT": return "blue"; case "PATCH": return "purple"; } return "orange"; }; StringBuilder builder = new StringBuilder(); builder.Append("TYTD Endpoint Documentation

TYTD Endpoint Documentation

"); foreach(var g in Downloader.Endpoints) { builder.Append($"

{g.Key}


"); foreach(var j in g.Value) { builder.Append($"

{j.Method} {j.Path}"); builder.Append($"

{j.Description}


"); } builder.Append("
"); } builder.Append(""); response.AsText(builder.ToString()); } private static void Endpoint(HttpListenerRequest request, HttpListenerResponse response, Dictionary arguments) { //MultiDictionary multi = new MultiDictionary(); request.ParseBody(arguments); List print = new List(); bool hasOtherResponse=false; bool success = true; if(arguments.ContainsKey("operation")) { if (arguments["operation"] == "create_personal_playlist") { string myName = arguments["name"]; string path = $"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = new List<(string Id, Resolution Resolution)>(); list.AddRange(ids.Select(e => (e, Resolution.NoConvert))); File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "create_personal_playlist_res") { string myName = arguments["name"]; string path=$"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = new List<(string Id, Resolution Resolution)>(); for (int i = 0; i < list.Count; i += 2) { string id = ids[i]; string res = ids[i + 1]; list.Add((id, (Resolution)int.Parse(res))); } File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "add_to_personal_playlist") { string myName = arguments["name"]; string path = $"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); list.AddRange(ids.Select(e => (e, Resolution.NoConvert))); File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "add_to_personal_playlist_res") { string myName = arguments["name"]; string path = $"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); for (int i = 0; i < list.Count; i += 2) { string id = ids[i]; string res = ids[i + 1]; list.Add((id, (Resolution)int.Parse(res))); } File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "insert_to_personal_playlist") { string myName = arguments["name"]; string path =$"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); int offset = 0; if (arguments.ContainsKey("offset")) { if (!int.TryParse(arguments["offset"], out offset)) { offset = 0; } } list.InsertRange(offset, ids.Select(e => (e, Resolution.NoConvert))); File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "remove_from_personal_playlist") { string myName = arguments["name"]; string path =$"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); List<(string, Resolution)> todel = new List<(string, Resolution)>(); foreach(var item in list) { if(ids.Contains(item.Id)) { todel.Add(item); } } list.RemoveRange(todel); File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "insert_to_personal_playlist_res") { string myName = arguments["name"]; string path =$"PersonalPlaylist/{myName}.json"; string[] ids = System.Web.HttpUtility.UrlDecode(arguments["ids"]).Split(','); var list = JsonConvert.DeserializeObject>(File.ReadAllText(path)); int offset = 0; if (arguments.ContainsKey("offset")) { if (!int.TryParse(arguments["offset"], out offset)) { offset = 0; } } for (int i = 0; i < list.Count; i += 2) { string id = ids[i]; string res = ids[i + 1]; list.Insert(offset++,(id, (Resolution)int.Parse(res))); } File.WriteAllText(path, JsonConvert.SerializeObject(list)); } else if (arguments["operation"] == "server_download") { if (arguments.ContainsKey("url")) { string myUrl = arguments["url"]; if (arguments.ContainsKey("resolution")) { uint res; if (uint.TryParse(arguments["resolution"], out res) && res <= 2) { Downloader.DownloadItem(myUrl, (Resolution)res); } else { print.Add("WARNING: argument resolution shall not be greater than 3 or less than 0"); Downloader.DownloadItem(myUrl); } } else { Downloader.DownloadItem(myUrl); } } } else if (arguments["operation"] == "download") { if (arguments.ContainsKey("url")) { VideoId? vid = VideoId.TryParse(arguments["url"]); if (vid.HasValue) { if (arguments.ContainsKey("resolution")) { int res; if (int.TryParse(arguments["resolution"], out res)) { if (res > 2 || res < 0) { print.Add("Invalid Resolution Number must be either 0, 1 or 2"); } else { string[] m = new string[] { "Converted", "NotConverted", "Audio" }; string path = $"{m[res]}/{vid.Value}.mp4"; response.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString()); response.AsFile(request, path); hasOtherResponse = true; } } else { print.Add("Res is not a number"); } } else { string path = $"NotConverted/{vid.Value}.mp4"; response.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString()); response.AsFile(request, path); hasOtherResponse = true; } } else { success = false; print.Add("Invalid Video ID or URL"); } } } else if (arguments["operation"] == "enumerate_queue") { string json = Downloader.GetQueue(); response.AsText(json, "application/json"); hasOtherResponse = true; } else if (arguments["operation"] == "progress") { string json = JsonConvert.SerializeObject(Downloader.GetProgress()); response.AsText(json, "application/json"); hasOtherResponse = true; } else if (arguments["operation"] == "queue_move") { bool containsId = arguments.ContainsKey("id"); bool containsIndex = arguments.ContainsKey("index"); if (containsId ^ containsIndex) { success = false; print.Add("You cant use both id and index"); } else { if (arguments.ContainsKey("to")) { string to_loc = arguments["to"]; if (containsId) Downloader.ModQueue2(to_loc, arguments["id"]); if (containsIndex) Downloader.ModQueue(to_loc, arguments["index"]); } else { success = false; print.Add("You must have the "to" variable set"); } } } else { success = false; } } if(success) { print.Add("

Your request was delt with successfully

"); print.Add("Click Here to go back."); } else if(!hasOtherResponse) { response.WithCode(HttpStatusCode.BadRequest); } if (!hasOtherResponse) { response.AsText(string.Join("
", print)); } } public static void RootPath(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary args) { string[] p0 = System.Web.HttpUtility.UrlDecode(args["Path"]).Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries); string p = p0[0]; args.Clear(); if (p0.Length >= 2) { foreach (var item in p0[1].Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries)) { var sub = item.Split(new char[] { '=' }); if (sub.Length == 2) { if (!args.ContainsKey(sub[0])) args.Add(sub[0], sub[1]); } else { if (!args.ContainsKey(sub[0])) args.Add(sub[0], ""); } } } string path =$"WebSite/{p}"; if (Directory.Exists(path)) { string indexHtml = Path.Combine(path, "index.html"); //bool j=false; if(info.HasHomePage) { if(info.HomePage.OnHomePage(indexHtml,rq,rp,args)) { return; } } if (File.Exists(indexHtml)) { path = indexHtml; } else { string dir = "WebSite/err/dir.html"; StringBuilder b = new StringBuilder(); var f= Directory.GetLastWriteTime(Path.GetDirectoryName(path)); string parentModified = $"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"Up{parentModified}DIR"); foreach (var file in Directory.GetDirectories(path)) { string name = Path.GetFileName(file); string nameUrled = System.Web.HttpUtility.UrlEncode(name); string nameHtmled = System.Web.HttpUtility.HtmlEncode(name); f= Directory.GetLastWriteTime(file); string dateModifed =$"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"{nameHtmled}{dateModifed}DIR"); } foreach (var file in Directory.GetFiles(path)) { string name = Path.GetFileName(file); string nameUrled = System.Web.HttpUtility.UrlEncode(name); string nameHtmled = System.Web.HttpUtility.HtmlEncode(name); f = File.GetLastWriteTime(file); string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}"; b.Append($"{nameHtmled}{dateModifed}FILE"); } Dictionary templating = new Dictionary(); templating.Add("Items", b.ToString()); rp.AsText(Templating.RenderFile(dir, templating)); return; } } if (info.HasHomePage) { if (info.HomePage.OnHomePage(p, rq, rp, args)) { return; } } rp.AsFile(rq, path); } #endregion public static bool Route_Before(HttpListenerRequest request, HttpListenerResponse response) { Dictionary args = new Dictionary(); response.WithCORS(); return !Authorized(request, response,args); } public static void RedirectIt(this HttpListenerRequest req,HttpListenerResponse resp,string path="/") { if (req.Headers.AllKeys.Contains("ServerRoot")) { resp.AsRedirect(req.Headers["ServerRoot"].TrimEnd('/') + path); } else { resp.AsRedirect(path); } } public static string GetServerRoot(HttpListenerRequest req) { if(req.Headers.AllKeys.Contains("ServerRoot")) { return req.Headers["ServerRoot"]; } else { return $"http://{req.LocalEndPoint.ToString()}/"; } } } }