using Tesses.WebServer; using Scriban; using System.Web; using System.Text.Json.Serialization; using System.Net.Http.Json; using System.Text.Json; using System.Diagnostics; Directory.CreateDirectory("data/cache/movie"); Directory.CreateDirectory("data/torrents"); HttpClient client = new HttpClient(); MountableServer msvr=new MountableServer(new StaticServer("data/wwwroot")); msvr.Mount("/torrents/",new StaticServer("data/torrents",true)); RouteServer routeServer=new RouteServer(msvr); routeServer.Add("/",async(ctx)=>{ var template = Template.Parse(File.ReadAllText("data/wwwroot/template.html")); var index = Template.Parse(File.ReadAllText("data/wwwroot/index.html")); await ctx.SendTextAsync(await template.RenderAsync(new{title="Request Movies", body=index.RenderAsync()})); }); routeServer.Add("/torrents.json",async(ctx)=>{ List torrents = new List(); foreach(var item in Directory.EnumerateFiles("data/torrents","*.torrent")) { torrents.Add(Path.GetFileName(item)); } await ctx.SendJsonAsync(torrents); }); routeServer.Add("/add_torrent",async(ctx)=>{ if(ctx.QueryParams.TryGetFirst("url",out var url)) { using(var res=await client.GetAsync(url)) { if(res.IsSuccessStatusCode) { var hdr = res.Content.Headers.ContentDisposition; if(hdr != null) { string? file=hdr.FileName; if(!string.IsNullOrWhiteSpace(file)) { file = file.TrimStart('\"').TrimEnd('\"'); if(!File.Exists($"data/torrents/{file}.part") && !File.Exists($"data/torrents/{file}")) { await File.WriteAllBytesAsync($"data/torrents/{file}.part", await res.Content.ReadAsByteArrayAsync()); File.Move($"data/torrents/{file}.part",$"data/torrents/{file}"); } } } } } if(!ctx.RequestHeaders.TryGetFirst("Referer",out var referer)) { referer="/"; } await ctx.SendRedirectAsync(referer); } }); routeServer.Add("/movie",async(ctx)=>{ var template = Template.Parse(File.ReadAllText("data/wwwroot/template.html")); var index = Template.Parse(File.ReadAllText("data/wwwroot/movie/index.html")); if(ctx.QueryParams.TryGetFirstInt64("id",out var id)) { string file = $"data/cache/movie/{id}.json"; YTSMovie? movie=null; if(File.Exists(file)) { using(var jsonStrm = File.OpenRead(file)) movie=await JsonSerializer.DeserializeAsync(jsonStrm); } else { var res=await client.GetFromJsonAsync($"https://yts.mx/api/v2/movie_details.json?movie_id={id}"); if(res != null) { if(res.Status == "ok") { if(res.Data.Movie.Id != 0) { string _file = $"data/cache/movie/{res.Data.Movie.Id}.json"; if(!File.Exists(_file)) { using(var f = File.Create(_file)) { await System.Text.Json.JsonSerializer.SerializeAsync(f,res.Data.Movie); } movie=res.Data.Movie; } } } } } if(movie != null) { List torrents=new List(); foreach(var item in movie.Torrents) { torrents.Add(new{quality=HttpUtility.HtmlEncode(item.Quality),url=HttpUtility.HtmlAttributeEncode(item.Url),size = HttpUtility.HtmlEncode(item.Size), addurl=$"./add_torrent?url={HttpUtility.UrlEncode(item.Url)}"}); } int hrs=movie.Runtime / 60; int mins=movie.Runtime % 60; string runtime = $"{hrs}:{mins.ToString("D2")}"; var body=await index.RenderAsync(new{yts_url =HttpUtility.HtmlAttributeEncode(movie.Url) ,mpa_rating =HttpUtility.HtmlEncode(movie.MpaRating),runtime,thumbnail = HttpUtility.HtmlAttributeEncode(movie.MediumCoverImage), name=HttpUtility.HtmlEncode(movie.TitleLong),torrents,next=id+1,prev=id-1,id}); string title = $"{HttpUtility.HtmlEncode(movie.TitleLong)} - Request Movies"; await ctx.SendTextAsync(await template.RenderAsync(new{body,title})); } else { await ctx.SendNotFoundAsync(); } } }); routeServer.Add("/search",async(ctx)=>{ var template = Template.Parse(File.ReadAllText("data/wwwroot/template.html")); var index = Template.Parse(File.ReadAllText("data/wwwroot/search/index.html")); int page = 1; if(!ctx.QueryParams.TryGetFirstInt32("page",out page)) { page = 1; } List results = new List(); if(ctx.QueryParams.TryGetFirst("q",out var q)) { var res=await client.GetFromJsonAsync($"https://yts.mx/api/v2/list_movies.json?query_term={HttpUtility.UrlEncode(q)}&page={page}"); if(res != null) { if(res.Status == "ok") { foreach(var item in res.Data.Movies) { string file = $"data/cache/movie/{item.Id}.json"; if(!File.Exists(file)) { using(var f = File.Create(file)) { await System.Text.Json.JsonSerializer.SerializeAsync(f,item); } } results.Add(new{url=$"./movie?id={item.Id}", title=HttpUtility.HtmlEncode(item.Title),thumbnail=HttpUtility.HtmlAttributeEncode(item.SmallCoverImage)}); } } } } string body = await index.RenderAsync(new{results,search_text=HttpUtility.HtmlEncode(q), search_text_attr=HttpUtility.HtmlAttributeEncode(q),prev=page-1,next=page+1,page}); await ctx.SendTextAsync(await template.RenderAsync(new{title = $"{HttpUtility.HtmlEncode(q)} - Request Movies",body})); }); routeServer.StartServer(9204); public class YTSMovie { [JsonPropertyName("id")] public long Id {get;set;}=0; [JsonPropertyName("url")] public string Url {get;set;}=""; [JsonPropertyName("imdb_code")] public string ImdbCode {get;set;}=""; [JsonPropertyName("title")] public string Title {get;set;}=""; [JsonPropertyName("title_english")] public string TitleEnglish {get;set;}=""; [JsonPropertyName("title_long")] public string TitleLong {get;set;}=""; [JsonPropertyName("slug")] public string Slug {get;set;}=""; [JsonPropertyName("year")] public int Year {get;set;}=0; [JsonPropertyName("rating")] public double Rating {get;set;}=0.0; [JsonPropertyName("runtime")] public int Runtime {get;set;}=0; [JsonPropertyName("genres")] public List Genres {get;set;}=new List(); [JsonPropertyName("summary")] public string Summary {get;set;}=""; [JsonPropertyName("description_full")] public string DescriptionFull {get;set;}=""; [JsonPropertyName("synopsis")] public string Synopsis {get;set;}=""; [JsonPropertyName("yt_trailer_code")] public string TrailerVideoId {get;set;}=""; [JsonPropertyName("language")] public string Language {get;set;}=""; [JsonPropertyName("mpa_rating")] public string MpaRating {get;set;}=""; [JsonPropertyName("background_image")] public string BackgroundImage {get;set;}=""; [JsonPropertyName("background_image_original")] public string BackgroundImageOriginal {get;set;}=""; [JsonPropertyName("small_cover_image")] public string SmallCoverImage {get;set;}=""; [JsonPropertyName("medium_cover_image")] public string MediumCoverImage {get;set;}=""; [JsonPropertyName("large_cover_image")] public string LargeCoverImage {get;set;}=""; [JsonPropertyName("torrents")] public List Torrents {get;set;}=new List(); [JsonPropertyName("state")] public string State {get;set;}=""; [JsonPropertyName("date_uploaded_unix")] public long DateUploadedUnix {get;set;}=0; } public class YTSTorrent { [JsonPropertyName("url")] public string Url {get;set;}=""; [JsonPropertyName("hash")] public string Hash {get;set;}=""; [JsonPropertyName("quality")] public string Quality {get;set;}=""; [JsonPropertyName("type")] public string Type {get;set;}=""; [JsonPropertyName("is_repack")] public string IsRepackStr {get;set;}=""; [JsonIgnore] public bool IsRepack {get=>IsRepackStr=="1"; set=>IsRepackStr = value ? "1" : "0";} [JsonPropertyName("video_codec")] public string VideoCodec {get;set;}=""; [JsonPropertyName("bit_depth")] public string BitDepth {get;set;}=""; [JsonPropertyName("audio_channels")] public string AudioChannels {get;set;}=""; [JsonPropertyName("seeds")] public long Seeds {get;set;}=0; [JsonPropertyName("peers")] public long Peers {get;set;}=0; [JsonPropertyName("size")] public string Size {get;set;}=""; [JsonPropertyName("size_bytes")] public long SizeBytes {get;set;}=0; [JsonPropertyName("date_uploaded_unix")] public long DateUploadedUnix {get;set;}=0; } public class YTSSearchResponseData { [JsonPropertyName("movies")] public List Movies {get;set;}=new List(); } public class YTSMovieResponseData { [JsonPropertyName("movie")] public YTSMovie Movie {get;set;}=new YTSMovie(); } public class YTSMovieResponse { [JsonPropertyName("status")] public string Status {get;set;}=""; [JsonPropertyName("data")] public YTSMovieResponseData Data {get;set;}=new YTSMovieResponseData(); } public class YTSSearchResponse { [JsonPropertyName("status")] public string Status {get;set;}=""; [JsonPropertyName("data")] public YTSSearchResponseData Data {get;set;}=new YTSSearchResponseData(); }