191 lines
7.6 KiB
C#
191 lines
7.6 KiB
C#
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<VideoSearchResult> searchResults=new List<VideoSearchResult>();
|
|
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);
|
|
|
|
}
|
|
}
|
|
} |