2024-12-02 16:36:27 +00:00
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using Renci.SshNet;
|
|
|
|
|
using YoutubeExplode;
|
|
|
|
|
using YoutubeExplode.Videos;
|
|
|
|
|
using Tesses.WebServer;
|
|
|
|
|
using static Creds;
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
using YoutubeExplode.Playlists;
|
|
|
|
|
using YoutubeExplode.Channels;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
HttpClient http=new HttpClient();
|
|
|
|
|
YoutubeClient ytc=new YoutubeClient(http);
|
2025-02-12 15:17:16 +00:00
|
|
|
|
ConcurrentStack<string> ids=new ConcurrentStack<string>();
|
2024-12-02 16:36:27 +00:00
|
|
|
|
bool isRunning=true;
|
2025-02-12 15:17:16 +00:00
|
|
|
|
Box<long> videosDownloaded=0;
|
2025-02-12 15:00:23 +00:00
|
|
|
|
|
|
|
|
|
async Task NewVideoDL()
|
|
|
|
|
{
|
|
|
|
|
long dl;
|
|
|
|
|
lock(videosDownloaded)
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
dl = videosDownloaded.Item++;
|
2025-02-12 15:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-12 15:17:16 +00:00
|
|
|
|
if((dl % 4) == 3) await Task.Delay(45000);
|
2025-02-12 15:00:23 +00:00
|
|
|
|
}
|
2024-12-02 16:36:27 +00:00
|
|
|
|
|
|
|
|
|
async Task AddVideo(VideoId id)
|
|
|
|
|
{
|
|
|
|
|
if(!string.IsNullOrWhiteSpace(AlreadyExistsUrl))
|
|
|
|
|
{
|
|
|
|
|
try{
|
|
|
|
|
if(await http.GetStringAsync($"{AlreadyExistsUrl}{id.Value}") == "true")
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"{AlreadyExistsUrl}{id.Value} returned true skipping: https://www.youtube.com/watch?v={id.Value}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}catch(Exception)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using(SshClient client = new SshClient(IP,Port,Username,Password)){
|
|
|
|
|
await client.ConnectAsync(default);
|
|
|
|
|
using(var res=client.CreateCommand($"echo {DirectoryOnServer}/*-{id.Value}.mp4"))
|
|
|
|
|
{
|
|
|
|
|
await res.ExecuteAsync();
|
|
|
|
|
|
|
|
|
|
if(res.Result == $"{DirectoryOnServer}/*-{id.Value}.mp4\n")
|
|
|
|
|
{
|
|
|
|
|
using(var res2=client.CreateCommand($"cd {DirectoryOnServer} && tytd {id.Value}"))
|
|
|
|
|
{
|
|
|
|
|
await res2.ExecuteAsync();
|
|
|
|
|
Console.WriteLine($"Downloaded: https://www.youtube.com/watch?v={id.Value}");
|
|
|
|
|
_=res2.Result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"Video already exists: https://www.youtube.com/watch?v={id.Value}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
client.Disconnect();
|
2025-01-24 19:56:28 +00:00
|
|
|
|
|
2025-02-12 15:00:23 +00:00
|
|
|
|
await NewVideoDL();
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async Task AddItem(string url)
|
|
|
|
|
{
|
|
|
|
|
VideoId? vId = VideoId.TryParse(url);
|
|
|
|
|
PlaylistId? pId = PlaylistId.TryParse(url);
|
|
|
|
|
ChannelId? cId = ChannelId.TryParse(url);
|
|
|
|
|
UserName? username = UserName.TryParse(url);
|
|
|
|
|
ChannelSlug? slug = ChannelSlug.TryParse(url);
|
|
|
|
|
ChannelHandle? handle = ChannelHandle.TryParse(url);
|
|
|
|
|
|
|
|
|
|
if(url.Length == 11 && vId.HasValue)
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(vId.Value);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
else if(pId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
await foreach(var v in ytc.Playlists.GetVideosAsync(pId.Value))
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(v.Id);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(vId.HasValue)
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(vId.Value);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
else if(cId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
await foreach(var c in ytc.Channels.GetUploadsAsync(cId.Value))
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(c.Id);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(username.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cId = (await ytc.Channels.GetByUserAsync(username.Value)).Id;
|
|
|
|
|
await foreach(var c in ytc.Channels.GetUploadsAsync(cId.Value))
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(c.Id);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(slug.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cId = (await ytc.Channels.GetBySlugAsync(slug.Value)).Id;
|
|
|
|
|
await foreach(var c in ytc.Channels.GetUploadsAsync(cId.Value))
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(c.Id);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(handle.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cId = (await ytc.Channels.GetByHandleAsync(handle.Value)).Id;
|
|
|
|
|
await foreach(var c in ytc.Channels.GetUploadsAsync(cId.Value))
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddVideo(c.Id);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-12 15:17:16 +00:00
|
|
|
|
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Task.Factory.StartNew(async()=>{
|
|
|
|
|
while(isRunning)
|
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
if(ids.TryPop(out var res))
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await AddItem(res);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},TaskCreationOptions.LongRunning).Wait(0);
|
|
|
|
|
|
|
|
|
|
MountableServer msvr=new MountableServer(new StaticServer("wwwroot"));
|
|
|
|
|
|
2025-02-12 15:17:16 +00:00
|
|
|
|
msvr.Mount("/api/AddItemRes/1/",new TYTDServer(false,ids));
|
|
|
|
|
msvr.Mount("/api/AddItem/",new TYTDServer(false,ids));
|
|
|
|
|
msvr.Mount("/api/AddVideoRes/1/",new TYTDServer(true,ids));
|
|
|
|
|
msvr.Mount("/api/AddVideo/",new TYTDServer(true,ids));
|
2024-12-02 16:36:27 +00:00
|
|
|
|
RouteServer routeServer=new RouteServer(msvr);
|
|
|
|
|
routeServer.Add("/itemsInQueue",async(ctx)=>{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
await ctx.SendJsonAsync(ids.Count);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
});
|
|
|
|
|
routeServer.Add("/queue.json", async(ctx)=>{
|
|
|
|
|
List<string> items = new List<string>();
|
2025-02-12 15:17:16 +00:00
|
|
|
|
foreach(var item in ids)
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
items.Add(item);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
await ctx.SendJsonAsync(items);
|
|
|
|
|
});
|
|
|
|
|
routeServer.Add("/add",async(ctx)=>{
|
2024-12-08 22:33:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(ctx.QueryParams.TryGetFirst("v",out var v) && ctx.QueryParams.TryGetFirst("mode",out var mode))
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2024-12-08 22:33:13 +00:00
|
|
|
|
if(mode == "add")
|
2025-02-12 15:17:16 +00:00
|
|
|
|
ids.Push(v);
|
2024-12-08 22:33:13 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var id = VideoId.TryParse(v);
|
|
|
|
|
if(id.HasValue)
|
|
|
|
|
{
|
|
|
|
|
using(SftpClient sftpClient=new SftpClient(IP,Port,Username,Password))
|
|
|
|
|
{
|
|
|
|
|
await sftpClient.ConnectAsync(default);
|
|
|
|
|
await foreach(var item in sftpClient.ListDirectoryAsync(DirectoryOnServer,default))
|
|
|
|
|
{
|
|
|
|
|
if(item.Name.EndsWith($"-{id.Value.Value}.mp4"))
|
|
|
|
|
{
|
|
|
|
|
await ctx.WithFileName(item.Name,false).SendStreamAsync(sftpClient.OpenRead(item.FullName));
|
|
|
|
|
sftpClient.Disconnect();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sftpClient.Disconnect();
|
|
|
|
|
}
|
|
|
|
|
await ctx.SendRedirectAsync(GetRedirectUrl(id.Value));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
await ctx.SendRedirectAsync("/");
|
|
|
|
|
});
|
|
|
|
|
routeServer.StartServer(3252);
|
|
|
|
|
|
2025-02-12 15:17:16 +00:00
|
|
|
|
public class Box<T>
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
public Box(T item) {
|
|
|
|
|
this.Item = item;
|
|
|
|
|
}
|
|
|
|
|
public T Item {get;set;}
|
|
|
|
|
|
|
|
|
|
public static implicit operator Box<T>(T item)
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
return new Box<T>(item);
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
2025-02-12 15:17:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class TYTDServer : Server
|
|
|
|
|
{
|
|
|
|
|
bool onlyVideos;
|
|
|
|
|
ConcurrentStack<string> stk;
|
2024-12-02 16:36:27 +00:00
|
|
|
|
|
2025-02-12 15:17:16 +00:00
|
|
|
|
public TYTDServer(bool onlyVids,ConcurrentStack<string> stk)
|
2024-12-02 16:36:27 +00:00
|
|
|
|
{
|
2025-02-12 15:17:16 +00:00
|
|
|
|
this.onlyVideos=onlyVids;
|
|
|
|
|
this.stk = stk;
|
2024-12-02 16:36:27 +00:00
|
|
|
|
}
|
|
|
|
|
public override async Task GetAsync(ServerContext ctx)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if(onlyVideos)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string url=ctx.UrlAndQuery.Substring(1);
|
|
|
|
|
|
|
|
|
|
stk?.Push(url);
|
|
|
|
|
await ctx.SendTextAsync("<script>window.history.back();</script>");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-19 05:17:43 +00:00
|
|
|
|
}
|