var TYTDResources = [ {path="/beer.min.css",value=embed("beer.min.css")}, {path="/beer.min.js",value=embed("beer.min.js")}, {path="/material-symbols-outlined.woff2",value=embed("material-symbols-outlined.woff2")}, {path="/material-symbols-rounded.woff2",value=embed("material-symbols-rounded.woff2")}, {path="/material-symbols-sharp.woff2",value=embed("material-symbols-sharp.woff2")}, {path="/material-symbols-subset.woff2",value=embed("material-symbols-subset.woff2")}, {path="/htmx.min.js",value=embed("htmx.min.js")}, {path="/favicon.ico",value=embed("favicon.ico")}, {path="/tytd.svg",value=embed("tytd.svg")}, {path="/loading-indicator.svg",value=embed("loading-indicator.svg")}, {path="/theme.css",value=embed("theme.css")} ]; var times=1; class TYTDApp { private TYTD; public TYTDApp() { var tytdfs = new SubdirFilesystem(FS.Local, "TYTD"); this.TYTD = new TYTD.Downloader(tytdfs,FS.MakeFull("TYTD")); this.TYTD.Start(); } public Handle(ctx) { if(ctx.Path == "/") { ctx.WithMimeType("text/html").SendText(Pages.Index(this.TYTD)); return true; } else if(ctx.Path == "/api/v1/download") { var v = ctx.QueryParams.TryGetFirst("v"); var inline = ctx.QueryParams.GetFirstBoolean("inline"); var res = ctx.QueryParams.TryGetFirst("res"); if(TypeOf(res) != "String") res = Resolution.LowVideo; var path = this.TYTD.GetVideoPath(v,res); if(path != null) { var info = this.TYTD.GetVideo(v); var filename = $"{info.title}-{info.videoId}.{path.GetExtension()}"; var strm = this.TYTD.Storage.OpenFile(path,"rb"); ctx.WithMimeType(Net.Http.MimeType(path.ToString())).WithContentDisposition(filename,inline).SendStream(strm); strm.Close(); } } else if(ctx.Path == "/api/v1/playlist.json") { var id = ctx.QueryParams.TryGetFirst("id"); var page = ctx.QueryParams.TryGetFirstInt("page"); var count = ctx.QueryParams.TryGetFirstInt("count"); if(TypeOf(page)!="Long") page = 1; if(TypeOf(count)!="Long") count = 20; if(TypeOf(id)!="String") id = ""; ctx.WithMimeType("application/json").SendJson(this.TYTD.GetPlaylistContents(id,page-1,count)); return true; } else if(ctx.Path == "/api/v1/channel.json") { var id = ctx.QueryParams.TryGetFirst("id"); var page = ctx.QueryParams.TryGetFirstInt("page"); var count = ctx.QueryParams.TryGetFirstInt("count"); if(TypeOf(page)!="Long") page = 1; if(TypeOf(count)!="Long") count = 20; if(TypeOf(id)!="String") id = ""; ctx.WithMimeType("application/json").SendJson(this.TYTD.GetChannelContents(id,page-1,count)); return true; } else if(ctx.Path == "/api/v1/downloads.json") { var q = ctx.QueryParams.TryGetFirst("q"); var type = ctx.QueryParams.TryGetFirst("type"); var page = ctx.QueryParams.TryGetFirstInt("page"); var count = ctx.QueryParams.TryGetFirstInt("count"); if(TypeOf(page)!="Long") page = 1; if(TypeOf(count)!="Long") count = 20; if(TypeOf(type)!="String") type = "videos"; if(TypeOf(q)!="String") q = ""; var result = { entries = [] }; switch(type) { case "videos": result.entries = this.TYTD.GetVideos(q,page-1,count); break; case "playlists": result.entries = this.TYTD.GetPlaylists(q,page-1,count); break; case "channels": result.entries = this.TYTD.GetChannels(q,page-1,count); break; } ctx.WithMimeType("application/json").SendJson(result); return true; } else if(ctx.Path == "/subscribe") { var id = ctx.QueryParams.TryGetFirst("id"); var bell = ctx.QueryParams.TryGetFirst("bell"); var type = ctx.QueryParams.TryGetFirst("type"); switch(type) { case "subscribe": this.TYTD.SetSubscriptionBell(id, SubscriptionBell.BellLow); break; case "unsubscribe": this.TYTD.SetSubscriptionBell(id, null); break; case "bell": this.TYTD.SetSubscriptionBell(id, bell); break; } ctx.WithMimeType("text/html").SendText(Components.Subscribe(this.TYTD,id)); return true; } else if(ctx.Path == "/downloads") { ctx.WithMimeType("text/html").SendText(Pages.Downloads(this.TYTD,ctx)); return true; } else if(ctx.Path == "/list") { ctx.WithMimeType("text/html").SendText(Pages.List(this.TYTD,ctx)); return true; } else if(ctx.Path == "/settings") { if(ctx.Method == "POST") { /* hours minutes seconds tag enablePlugins */ var enablePlugins = ctx.QueryParams.GetFirstBoolean("enablePlugins"); var tag = ctx.QueryParams.TryGetFirst("tag"); var hours = ctx.QueryParams.TryGetFirstInt("hours"); var minutes = ctx.QueryParams.TryGetFirstInt("minutes"); var seconds = ctx.QueryParams.TryGetFirstInt("seconds"); if(TypeOf(tag) == "String" && TypeOf(hours) == "Long" && TypeOf(minutes) == "Long" && TypeOf(seconds) == "Long") { seconds += minutes * 60; seconds += hours * 3600; this.TYTD.Config.TYTDTag = tag; this.TYTD.Config.BellTimer = seconds; this.TYTD.Config.EnablePlugins = enablePlugins; this.TYTD.SaveConfig(); } } ctx.WithMimeType("text/html").SendText(Pages.Settings(this.TYTD,ctx)); return true; } else if(ctx.Path == "/video") { ctx.WithMimeType("text/html").SendText(Pages.VideoInfo(this.TYTD,ctx)); return true; } else if(ctx.Path == "/playlist") { ctx.WithMimeType("text/html").SendText(Pages.PlaylistInfo(this.TYTD,ctx)); return true; } else if(ctx.Path == "/channel") { ctx.WithMimeType("text/html").SendText(Pages.ChannelInfo(this.TYTD,ctx)); return true; } else if(ctx.Path == "/add") { var url = ctx.QueryParams.TryGetFirst("url"); var action =ctx.QueryParams.TryGetFirst("action"); var res = ctx.QueryParams.TryGetFirst("res"); if(action == "add") { this.TYTD.DownloadItem(url,res); } else if(action == "info") { ctx.ResponseHeaders.SetValue("HX-Redirect", TYTD.PageRedirect(url)); } else if(action == "download") { ctx.ResponseHeaders.SetValue("HX-Redirect", $"./api/v1/download?v={Net.Http.UrlEncode(url)}&res={Net.Http.UrlEncode(res)}"); } else if(action == "play") { ctx.ResponseHeaders.SetValue("HX-Redirect", $"./api/v1/download?v={Net.Http.UrlEncode(url)}&res={Net.Http.UrlEncode(res)}&inline=true"); } ctx.WithMimeType("text/html").SendText(Components.Add()); return true; } else if(ctx.Path == "/add-video") { var url = ctx.QueryParams.TryGetFirst("url"); var action =ctx.QueryParams.TryGetFirst("action"); var res = ctx.QueryParams.TryGetFirst("res"); if(action == "add") { this.TYTD.DownloadItem(url,res); } else if(action == "download") { ctx.ResponseHeaders.SetValue("HX-Redirect", $"./api/v1/download?v={Net.Http.UrlEncode(url)}&res={Net.Http.UrlEncode(res)}"); } else if(action == "play") { ctx.ResponseHeaders.SetValue("HX-Redirect", $"./api/v1/download?v={Net.Http.UrlEncode(url)}&res={Net.Http.UrlEncode(res)}&inline=true"); } ctx.WithMimeType("text/html").SendText(Components.AddVideo(url)); return true; } else if(ctx.Path == "/add-to-list") { var id = ctx.QueryParams.TryGetFirst("id"); if(TypeOf(id) != "String") id = ""; var name = ctx.QueryParams.TryGetFirst("name"); if(TypeOf(name) != "String") name = ""; if(name == "") { ctx.WithMimeType("text/html").SendText(Components.CreateNewList(this.TYTD,id)); } else { this.TYTD.AddToPersonalList(name,id); ctx.WithMimeType("text/html").SendText(Components.AddToPersonalList(this.TYTD,id)); } return true; } else if(ctx.Path == "/progress") { ctx.WithMimeType("text/html").SendText(Components.Progress(this.TYTD)); return true; } else if(ctx.Path == "/plugins") { ctx.WithMimeType("text/html").SendText(Pages.Plugins(this.TYTD,ctx)); return true; } else if(ctx.Path == "/plugins-download") { ctx.WithMimeType("text/html").SendText(Pages.DownloadPlugins(this.TYTD,ctx)); return true; } else if(ctx.Path == "/package-manage" && ctx.Method == "POST") { var data = { name = ctx.QueryParams.TryGetFirst("name"), version = ctx.QueryParams.TryGetFirst("version"), action = ctx.QueryParams.TryGetFirst("action") }; var mustConfirm = false; switch(data.action) { case "install": { var v = Version.Parse(data.version); if(v != null) this.TYTD.PackageInstall(data.name,v); } break; case "uninstall": { mustConfirm = true; } break; case "confirm": { this.TYTD.PackageUninstall(data.name); } break; } ctx.WithMimeType("text/html").SendText(Components.InstallButton(this.TYTD, data.name, data.version, mustConfirm)); return true; } else if(ctx.Path == "/api/v1/video-thumbnail") { var v = ctx.QueryParams.TryGetFirst("v"); var res = ctx.QueryParams.TryGetFirst("res"); if(TypeOf(res) != "String") res = "0"; var thu = this.TYTD.GetVideoThumbnail(v,res); if(thu == null) return false; ctx.WithMimeType("image/jpg").SendBytes(thu); return true; } else if(ctx.Path == "/api/v1/playlist-thumbnail") { var id = ctx.QueryParams.TryGetFirst("id"); var res = ctx.QueryParams.TryGetFirst("res"); if(TypeOf(res) != "String") res = "0"; var thu = this.TYTD.GetPlaylistThumbnail(id,res); if(thu == null) return false; ctx.WithMimeType("image/jpg").SendBytes(thu); return true; } else if(ctx.Path == "/api/v1/channel-thumbnail") { var id = ctx.QueryParams.TryGetFirst("id"); var res = ctx.QueryParams.TryGetFirst("res"); if(TypeOf(res) != "String") res = "0"; var thu = this.TYTD.GetChannelThumbnail(id,res); if(thu == null) return false; ctx.WithMimeType("image/jpg").SendBytes(thu); return true; } else if(ctx.Path == "/api/v1/plugin-thumbnail.png") { var name = ctx.QueryParams.TryGetFirst("name"); ctx.WithMimeType().SendBytes(this.TYTD.GetPluginThumbnail(name)); return true; } else if(ctx.Path.StartsWith("/plugin/")) { return this.TYTD.Servers.Handle(ctx); } else { each(var file : TYTDResources) { if(ctx.Path == file.path) { ctx.WithMimeType(Net.Http.MimeType(file.path)).SendBytes(file.value); return true; } } } return false; } public Close() { this.TYTD.Stop(); } } func WebAppMain(args) { return new TYTDApp(); } func main(args) { var res = WebAppMain(args); Net.Http.ListenSimpleWithLoop(res,3255); res.Close(); return 0; }