requestmovies/Program.cs

278 lines
9.2 KiB
C#

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("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<string> torrents = new List<string>();
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<YTSMovie>(jsonStrm);
}
if(movie != null)
{
List<object> torrents=new List<object>();
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});
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<object> results = new List<object>();
if(ctx.QueryParams.TryGetFirst("q",out var q))
{
var res=await client.GetFromJsonAsync<YTSSearchResponse>($"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)});
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<string> Genres {get;set;}=new List<string>();
[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<YTSTorrent> Torrents {get;set;}=new List<YTSTorrent>();
[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<YTSMovie> Movies {get;set;}=new List<YTSMovie>();
}
public class YTSSearchResponse {
[JsonPropertyName("status")]
public string Status {get;set;}="";
[JsonPropertyName("data")]
public YTSSearchResponseData Data {get;set;}=new YTSSearchResponseData();
}