using System.Net; using Tesses.WebServer; using YoutubeExplode; using YoutubeExplode.Search; using YoutubeExplode.Videos; using YoutubeExplode.Videos.Streams; public class TYTDProxy { static YoutubeClient Youtube = new YoutubeClient(); public static async Task Main(string[] args) { using (var token = new CancellationTokenSource()) { Console.CancelKeyPress += (sender,e)=>{ token.Cancel(); }; StaticServer static_server=new StaticServer("WebSite"); RouteServer api_server=new RouteServer(); RouteApi(api_server); MountableServer mountable_server=new MountableServer(static_server); mountable_server.Mount("/api",api_server); HttpServerListener listener=new HttpServerListener(new System.Net.IPEndPoint(System.Net.IPAddress.Any,3253),mountable_server); await listener.ListenAsync(token.Token); } } public static void RouteApi(RouteServer api) { api.Add("/Video.json",Video); api.Add("/Video.json",Video,"POST"); api.Add("/PreMuxed",PreMuxed); api.Add("/VideoOnly",VideoOnly); api.Add("/AudioOnly",AudioOnly); api.Add("/PreMuxed",PreMuxed,"POST"); api.Add("/VideoOnly",VideoOnly,"POST"); api.Add("/AudioOnly",AudioOnly,"POST"); api.Add("/DownloadYTStream",DownloadYTStream,"POST"); api.Add("/Search.json",Search,"POST"); api.Add("/Search.json",Search); } public class StreamResult { public StreamResult(IStreamInfo info) { url = info.Url; ext=info.Container.Name; size = info.Size.Bytes; } public string url {get;set;} public string ext {get;set;} public long size {get;set;} } public class VideoResult { public VideoResult(StreamResult muxed,StreamResult video_only,StreamResult audio_only,SavedVideo video) { this.muxed=muxed; this.video_only=video_only; this.audio_only = audio_only; this.video_info=video; } public StreamResult muxed {get;set;} public StreamResult video_only {get;set;} public StreamResult audio_only {get;set;} public SavedVideo video_info {get;set;} } public static async Task Search(ServerContext ctx) { string q; if(ctx.QueryParams.TryGetFirst("q",out q)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") q=WebUtility.UrlDecode(q); { List searchResults=new List(); await foreach(var item in Youtube.Search.GetVideosAsync(q)) { searchResults.Add(item); } await ctx.SendJsonAsync(searchResults); } } } public static async Task PreMuxed(ServerContext ctx) { string v; if(ctx.QueryParams.TryGetFirst("v",out v)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") v=WebUtility.UrlDecode(v); var vid=await Youtube.Videos.GetAsync(v); var res= await Youtube.Videos.Streams.GetManifestAsync(v); var bestMuxed=res.GetMuxedStreams().GetWithHighestVideoQuality(); System.Net.Mime.ContentDisposition contentDisposition=new System.Net.Mime.ContentDisposition(); contentDisposition.FileName = vid.Title; contentDisposition.DispositionType = System.Net.Mime.DispositionTypeNames.Inline; ctx.ResponseHeaders.Add("Content-Disposition",contentDisposition.ToString()); await ctx.SendStreamAsync(await Youtube.Videos.Streams.GetAsync(bestMuxed),$"file.{bestMuxed.Container.Name}"); } } public static async Task VideoOnly(ServerContext ctx) { string v; if(ctx.QueryParams.TryGetFirst("v",out v)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") v=WebUtility.UrlDecode(v); var vid=await Youtube.Videos.GetAsync(v); var res= await Youtube.Videos.Streams.GetManifestAsync(v); var bestVideoOnly=res.GetVideoOnlyStreams().GetWithHighestVideoQuality(); System.Net.Mime.ContentDisposition contentDisposition=new System.Net.Mime.ContentDisposition(); contentDisposition.FileName = vid.Title; contentDisposition.DispositionType = System.Net.Mime.DispositionTypeNames.Inline; ctx.ResponseHeaders.Add("Content-Disposition",contentDisposition.ToString()); await ctx.SendStreamAsync(await Youtube.Videos.Streams.GetAsync(bestVideoOnly),$"file.{bestVideoOnly.Container.Name}"); } } public static async Task AudioOnly(ServerContext ctx) { string v; if(ctx.QueryParams.TryGetFirst("v",out v)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") v=WebUtility.UrlDecode(v); var vid=await Youtube.Videos.GetAsync(v); var res= await Youtube.Videos.Streams.GetManifestAsync(v); var bestAudioOnly=res.GetAudioOnlyStreams().GetWithHighestBitrate(); System.Net.Mime.ContentDisposition contentDisposition=new System.Net.Mime.ContentDisposition(); contentDisposition.FileName = vid.Title; contentDisposition.DispositionType = System.Net.Mime.DispositionTypeNames.Inline; ctx.ResponseHeaders.Add("Content-Disposition",contentDisposition.ToString()); await ctx.SendStreamAsync(await Youtube.Videos.Streams.GetAsync(bestAudioOnly),$"file.{bestAudioOnly.Container.Name}"); } } public class DummyStr : IStreamInfo { public DummyStr(string url,long len) { this.url = url; this.len=len; } long len; string url; public string Url => url; public Container Container => Container.Mp4; public FileSize Size => new FileSize(len); public Bitrate Bitrate => new Bitrate(420000); } public static async Task DownloadYTStream(ServerContext ctx) { string v; string lenTxt; if(ctx.QueryParams.TryGetFirst("url",out v)){ if(ctx.QueryParams.TryGetFirst("flen",out lenTxt)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") v=WebUtility.UrlDecode(v); long len; if(long.TryParse(lenTxt,out len)){ await ctx.SendStreamAsync(await Youtube.Videos.Streams.GetAsync(new DummyStr(v,len)),HeyRed.Mime.MimeTypesMap.GetMimeType("file.bin")); } } } } public static async Task Video(ServerContext ctx) { string v; if(ctx.QueryParams.TryGetFirst("v",out v)){ if(ctx.Method == "POST") ctx.ParseBody(); if(ctx.Method != "POST") v=WebUtility.UrlDecode(v); var res= await Youtube.Videos.Streams.GetManifestAsync(v); var bestMuxed=new StreamResult(res.GetMuxedStreams().GetWithHighestVideoQuality()); var bestVideoOnly=new StreamResult(res.GetVideoOnlyStreams().GetWithHighestVideoQuality()); var bestAudioOnly=new StreamResult(res.GetAudioOnlyStreams().GetWithHighestBitrate()); SavedVideo video = new SavedVideo(await Youtube.Videos.GetAsync(v)); VideoResult result = new VideoResult(bestMuxed,bestVideoOnly,bestAudioOnly,video); await ctx.SendJsonAsync(result); } } }