Push update
This commit is contained in:
		
							parent
							
								
									8e5e58168a
								
							
						
					
					
						commit
						96d2a358b4
					
				|  | @ -1,6 +1,9 @@ | |||
| using System.Diagnostics; | ||||
| using System.Runtime.InteropServices; | ||||
| using System; | ||||
| using YoutubeExplode.Videos; | ||||
| using Newtonsoft.Json; | ||||
| 
 | ||||
| namespace Tesses.YouTubeDownloader.Tools.Common | ||||
| { | ||||
|     public static class SymlinkGenerator | ||||
|  | @ -14,7 +17,8 @@ namespace Tesses.YouTubeDownloader.Tools.Common | |||
|                 }else{ | ||||
|             using(var p=new Process()) | ||||
|             { | ||||
|                  | ||||
|                 p.StartInfo.UseShellExecute=false; | ||||
|                 p.StartInfo.WorkingDirectory="/"; | ||||
|                 p.StartInfo.FileName = "ln"; | ||||
|                 p.StartInfo.ArgumentList.Add(srcPath); | ||||
|                 p.StartInfo.ArgumentList.Add(destPath); | ||||
|  | @ -26,11 +30,14 @@ namespace Tesses.YouTubeDownloader.Tools.Common | |||
|         public static async Task GenerateHardLinks(TYTDStorage storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false) | ||||
|         { | ||||
|             Directory.CreateDirectory(dest); | ||||
|                  await foreach(var item in storage.GetVideosAsync()) | ||||
|             await foreach(var item in storage.GetVideosAsync()) | ||||
|             { | ||||
|                 if(await item.VideoExistsAsync(storage,res)) | ||||
|                 try{ | ||||
|                 var v=await BestStreams.GetPathResolution(storage,item,res); | ||||
|                 if(storage.FileExists(v)) | ||||
|                 { | ||||
|                    var (path,delete)= await storage.GetRealUrlOrPathAsync(await BestStreams.GetPathResolution(storage,item,res)); | ||||
|                      | ||||
|                    var (path,delete)= await storage.GetRealUrlOrPathAsync(v); | ||||
|                    string? ext=Path.GetExtension(path); | ||||
|                    | ||||
|                      string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";  | ||||
|  | @ -55,17 +62,84 @@ namespace Tesses.YouTubeDownloader.Tools.Common | |||
|                        Console.WriteLine(item.Title); | ||||
|                    } | ||||
|                 } | ||||
|             }catch(Exception ex) | ||||
|             { | ||||
|                 Console.WriteLine($"ERROR: {item.Id}"); | ||||
|                 Console.WriteLine(ex.ToString()); | ||||
|             } | ||||
|             } | ||||
|          | ||||
|         } | ||||
|         public static async Task<bool> VideoExistsAsync(ITYTDBase b,SavedVideo id) | ||||
|         { | ||||
|             var res=await BestStreams.GetPathResolution(b,id,Resolution.PreMuxed); | ||||
|             if(b.FileExists(res)) return true; | ||||
|             await BestStreams.GetPathResolution(b,id,Resolution.Mux); | ||||
|             if(b.FileExists(res)) return true; | ||||
|             await BestStreams.GetPathResolution(b,id,Resolution.VideoOnly); | ||||
|             if(b.FileExists(res)) return true; | ||||
|             await BestStreams.GetPathResolution(b,id,Resolution.AudioOnly); | ||||
|             if(b.FileExists(res)) return true; | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
|         public static async Task GenerateMeta(List<string> items,TYTDStorage storage,string dest="GoodInfos",bool verbose=false) | ||||
|         { | ||||
|             items.Add("Videos"); | ||||
|             if(verbose) | ||||
|             { | ||||
|                 Console.WriteLine("[Generating Meta]"); | ||||
|             } | ||||
|              Directory.CreateDirectory(dest); | ||||
|             await foreach(var item in storage.GetVideosAsync()) | ||||
|             { | ||||
|                 if(await VideoExistsAsync(storage,item)) | ||||
|                 { | ||||
|                      string destPathJson=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}.json"); | ||||
|                      string destPathText=Path.Combine(dest,$"{item.Title.GetSafeFileName()}-{item.Id}.txt"); | ||||
|                      if(!File.Exists(destPathJson)) | ||||
|                      File.WriteAllText(destPathJson,JsonConvert.SerializeObject(item,Formatting.Indented)); | ||||
|                      if(!File.Exists(destPathText)){                     using(var f=new StreamWriter(destPathText)) | ||||
|                      { | ||||
|                         f.WriteLine($"Title: {item.Title}"); | ||||
|                         f.WriteLine($"Id: {item.Id}"); | ||||
|                         f.WriteLine($"AuthorTitle: {item.AuthorTitle}"); | ||||
|                         f.WriteLine($"AuthorChannelId: {item.AuthorChannelId}"); | ||||
|                          f.WriteLine($"Tags: {string.Join(", ",item.Keywords)}"); | ||||
|                        | ||||
|                          f.WriteLine($"Views: {item.Views}"); | ||||
|                         f.WriteLine($"Likes: {item.Likes}"); | ||||
|                         f.WriteLine($"Dislikes: {item.Dislikes}"); | ||||
|                         | ||||
|                         f.WriteLine($"Duration: {item.Duration.ToString()}"); | ||||
|                          f.WriteLine($"Upload Date: {item.UploadDate}"); | ||||
|                           f.WriteLine($"Add Date: {item.AddDate.ToShortDateString()}"); | ||||
|                        | ||||
|                           f.WriteLine($"DownloadFrom: {item.DownloadFrom}"); | ||||
|                         f.WriteLine($"Legacy Video: {item.LegacyVideo}"); | ||||
|                          f.WriteLine($"Downloader Tag: {item.TYTDTag}"); | ||||
|                         f.WriteLine($"Video Frozen: {item.VideoFrozen}"); | ||||
|                         | ||||
|                        f.WriteLine("Description:"); | ||||
|                         f.WriteLine($"{item.Description}"); | ||||
|                      }} | ||||
|                     items.Add($"{item.Title}-{item.Id}"); | ||||
|                     if(verbose) | ||||
|                     { | ||||
|                         Console.WriteLine($"[META] {item.Title}"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         public static async Task GenerateSymlinks(TYTDBase storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false) | ||||
|         { | ||||
|             Directory.CreateDirectory(dest); | ||||
|             await foreach(var item in storage.GetVideosAsync()) | ||||
|             { | ||||
|                 if(await item.VideoExistsAsync(storage,res)) | ||||
|                var v=await BestStreams.GetPathResolution(storage,item,res); | ||||
|                 if(storage.FileExists(v)) | ||||
|                 { | ||||
|                    var (path,delete)= await storage.GetRealUrlOrPathAsync(await BestStreams.GetPathResolution(storage,item,res)); | ||||
|                    var (path,delete)= await storage.GetRealUrlOrPathAsync(v); | ||||
|                    string? ext=Path.GetExtension(path); | ||||
|                    | ||||
|                      string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";  | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ Resolution res=Resolution.PreMuxed; | |||
| 
 | ||||
| bool verbose=false; | ||||
| bool isSymlink = false; | ||||
| bool isBigExport=false; | ||||
| List<string> _args=new List<string>(); | ||||
| foreach(var arg in args) | ||||
| { | ||||
|  | @ -16,6 +17,11 @@ foreach(var arg in args) | |||
|         _args.Clear(); | ||||
|         break; | ||||
|     } | ||||
|     if( (arg.Length >= 2 &&  arg[1] != '-' && arg[0] == '-'  && arg.Contains("g") )|| arg == "--generate-export") | ||||
|     { | ||||
|         any=true; | ||||
|         isBigExport=true; | ||||
|     } | ||||
|     if( (arg.Length >= 2 &&  arg[1] != '-' && arg[0] == '-'  && arg.Contains("s") )|| arg == "--symbolic") | ||||
|     { | ||||
|         any=true; | ||||
|  | @ -44,6 +50,7 @@ foreach(var arg in args) | |||
|         verbose=true; | ||||
|          | ||||
|     } | ||||
|      | ||||
|         if(!any) | ||||
|         _args.Add(arg); | ||||
|      | ||||
|  | @ -53,7 +60,7 @@ if(argv.Length < 2) | |||
| { | ||||
|     string app = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]); | ||||
| 
 | ||||
|     Console.WriteLine($"usage: {app} [-smaVv] <Working> <Destination> [<Resolution>]"); | ||||
|     Console.WriteLine($"usage: {app} [-smaVvg] <Working> <Destination> [<Resolution>]"); | ||||
|     Console.WriteLine(); | ||||
|     Console.WriteLine("Options:"); | ||||
|     Console.WriteLine("  -s, --symbolic              make symbolic links instead of hard links"); | ||||
|  | @ -62,6 +69,7 @@ if(argv.Length < 2) | |||
|     Console.WriteLine("  -V, --video-only            set resolution to VideoOnly"); | ||||
|     Console.WriteLine("  -h, --help                  show this help"); | ||||
|     Console.WriteLine("  -v, --verbose               print video names"); | ||||
|     Console.WriteLine("  -g, --generate-export       Export everything to human readable format"); | ||||
|     Console.WriteLine(); | ||||
|     Console.WriteLine("Positional Arguments:"); | ||||
|     Console.WriteLine("  Working                     the folder containing the Info Directory for TYTD. (required)"); | ||||
|  | @ -76,8 +84,52 @@ TYTDCurrentDirectory currentDirectory=new TYTDCurrentDirectory(); | |||
| currentDirectory.CanDownload=false; | ||||
| 
 | ||||
| if(isSymlink){ | ||||
| await SymlinkGenerator.GenerateSymlinks(currentDirectory,argv[1],res,verbose); | ||||
|     if(isBigExport) | ||||
|     { | ||||
|         string outDir = argv[1]; | ||||
|         string sd = Path.Combine(outDir,"PreMuxed"); | ||||
|         string hd = Path.Combine(outDir,"Muxed"); | ||||
|         string vo = Path.Combine(outDir,"VideoOnly"); | ||||
|         string ao = Path.Combine(outDir,"AudioOnly"); | ||||
|         string meta=Path.Combine(outDir,"Meta"); | ||||
|          | ||||
|         List<string> videos=new List<string>(); | ||||
|         try{ | ||||
|               await SymlinkGenerator.GenerateSymlinks(currentDirectory,sd,Resolution.PreMuxed,verbose); | ||||
|               await SymlinkGenerator.GenerateSymlinks(currentDirectory,hd,Resolution.Mux,verbose); | ||||
|               await SymlinkGenerator.GenerateSymlinks(currentDirectory,vo,Resolution.VideoOnly,verbose); | ||||
|               await SymlinkGenerator.GenerateSymlinks(currentDirectory,ao,Resolution.AudioOnly,verbose); | ||||
|               await SymlinkGenerator.GenerateMeta(videos,currentDirectory,meta,verbose); | ||||
|         }catch(Exception ex){ | ||||
|             _=ex; | ||||
|         } | ||||
|         File.WriteAllLines(Path.Combine(outDir,"videos.txt"),videos); | ||||
|     }else{ | ||||
|         await SymlinkGenerator.GenerateSymlinks(currentDirectory,argv[1],res,verbose); | ||||
|     } | ||||
| }else{ | ||||
| await SymlinkGenerator.GenerateHardLinks(currentDirectory,argv[1],res,verbose); | ||||
|     if(isBigExport) | ||||
|     { | ||||
|         string outDir = argv[1]; | ||||
|         string sd = Path.Combine(outDir,"PreMuxed"); | ||||
|         string hd = Path.Combine(outDir,"Muxed"); | ||||
|         string vo = Path.Combine(outDir,"VideoOnly"); | ||||
|         string ao = Path.Combine(outDir,"AudioOnly"); | ||||
|         string meta=Path.Combine(outDir,"Meta"); | ||||
|         List<string> videos=new List<string>(); | ||||
|          try{ | ||||
|               await SymlinkGenerator.GenerateHardLinks(currentDirectory,sd,Resolution.PreMuxed,verbose); | ||||
|               await SymlinkGenerator.GenerateHardLinks(currentDirectory,hd,Resolution.Mux,verbose); | ||||
|               await SymlinkGenerator.GenerateHardLinks(currentDirectory,vo,Resolution.VideoOnly,verbose); | ||||
|               await SymlinkGenerator.GenerateHardLinks(currentDirectory,ao,Resolution.AudioOnly,verbose); | ||||
|               await SymlinkGenerator.GenerateMeta(videos,currentDirectory,meta,verbose); | ||||
|               File.WriteAllLines(Path.Combine(outDir,"videos.txt"),videos); | ||||
|         }catch(Exception ex){ | ||||
|             _=ex; | ||||
|         } | ||||
| 
 | ||||
|     }else{ | ||||
|         await SymlinkGenerator.GenerateHardLinks(currentDirectory,argv[1],res,verbose); | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,10 @@ namespace Tesses.Extensions | |||
|         { | ||||
|             return value.Substring(str.Length); | ||||
|         } | ||||
|         public static async Task RedirectBackAsync(this ServerContext ctx) | ||||
|         { | ||||
|             await ctx.SendTextAsync("<script>history.back()</script>\n"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -165,7 +169,7 @@ internal static class B64 | |||
|                 // await ctx.SendTextAsync( | ||||
|                // $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             //); | ||||
|             await ctx.SendRedirectAsync("/"); | ||||
|              | ||||
|             } | ||||
|             if(path.StartsWith("/AddItemRes/")) | ||||
|             { | ||||
|  | @ -252,7 +256,7 @@ internal static class B64 | |||
|             //); | ||||
|              | ||||
|             } | ||||
|             await ctx.SendRedirectAsync("/"); | ||||
|            await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|     } | ||||
|     internal class ApiStorage : Tesses.WebServer.Server | ||||
|  | @ -846,6 +850,7 @@ internal static class B64 | |||
|         public ApiV2Server(IDownloader downloader) | ||||
|         { | ||||
|                 this.Downloader=downloader; | ||||
|                 AddBoth("/CancelDownload",Cancel); | ||||
|                 AddBoth("/Search",Search); | ||||
|                 AddBoth("/AddItem",AddItem); | ||||
|                 AddBoth("/AddChannel",AddChannel); | ||||
|  | @ -899,6 +904,21 @@ internal static class B64 | |||
|         }*/ | ||||
|         } | ||||
| 
 | ||||
|         private async Task Cancel(ServerContext ctx) | ||||
|         { | ||||
|             bool restart=false; | ||||
|             string restartString="false"; | ||||
|             if(ctx.QueryParams.TryGetFirst("restart",out restartString)) | ||||
|             { | ||||
|                 if(!bool.TryParse(restartString,out restart)) | ||||
|                 { | ||||
|                     restart=false; | ||||
|                 } | ||||
|             } | ||||
|             Downloader.CancelDownload(restart); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         } | ||||
| 
 | ||||
|         private async Task Search(ServerContext ctx) | ||||
|         { | ||||
|             var dl = Downloader as IStorage; | ||||
|  | @ -942,9 +962,7 @@ internal static class B64 | |||
|                 //Downloader.AddToPersonalPlaylistAsync(name); | ||||
| 
 | ||||
|             } | ||||
|               await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|            public async Task ReplaceList(ServerContext ctx) | ||||
|         { | ||||
|  | @ -966,9 +984,7 @@ internal static class B64 | |||
|                 //Downloader.AddToPersonalPlaylistAsync(name); | ||||
| 
 | ||||
|             } | ||||
|               await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|              await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         public async Task Everything_Export(ServerContext ctx) | ||||
|         { | ||||
|  | @ -1124,9 +1140,7 @@ internal static class B64 | |||
|                 //Downloader.AddToPersonalPlaylistAsync(name); | ||||
| 
 | ||||
|             } | ||||
|               await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|              await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         public async Task DeleteFromList(ServerContext ctx) | ||||
|         { | ||||
|  | @ -1144,9 +1158,7 @@ internal static class B64 | |||
|                 } | ||||
|             } | ||||
|             } | ||||
|               await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|            await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|          public async Task SetResolutionInList(ServerContext ctx) | ||||
|         { | ||||
|  | @ -1173,9 +1185,7 @@ internal static class B64 | |||
|                 } | ||||
|             } | ||||
|             } | ||||
|               await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         public async Task Subscriptions(ServerContext ctx) | ||||
|         { | ||||
|  | @ -1189,9 +1199,7 @@ internal static class B64 | |||
|                       | ||||
|                   | ||||
|             } | ||||
|                await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|            await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         public async Task Resubscribe(ServerContext ctx) | ||||
|                 { | ||||
|  | @ -1222,9 +1230,7 @@ internal static class B64 | |||
|                      } | ||||
|                  } | ||||
|             } | ||||
|              await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|            await ctx.RedirectBackAsync(); | ||||
|         } | ||||
| 
 | ||||
|         public async Task Unsubscribe(ServerContext ctx) | ||||
|  | @ -1249,10 +1255,8 @@ internal static class B64 | |||
|                      } | ||||
|                  } | ||||
|             } | ||||
|              await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|     } | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         public async Task Subscribe(ServerContext ctx) | ||||
|         { | ||||
|             IStorage storage = Downloader as IStorage; | ||||
|  | @ -1294,9 +1298,7 @@ internal static class B64 | |||
|                      } | ||||
|                  } | ||||
|             } | ||||
|              await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         } | ||||
|         | ||||
|         public async Task QueueList(ServerContext ctx) | ||||
|  | @ -1324,9 +1326,7 @@ internal static class B64 | |||
|                 } | ||||
| 
 | ||||
|                 await Downloader.AddFileAsync(url,download); | ||||
|                   await ctx.SendTextAsync( | ||||
|                 $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|                 await ctx.RedirectBackAsync(); | ||||
|             } | ||||
|         } | ||||
|          public async Task AddVideo(ServerContext ctx) | ||||
|  | @ -1352,11 +1352,9 @@ internal static class B64 | |||
|                     await Downloader.AddVideoAsync(id1.Value,resolution); | ||||
|                 } | ||||
|             }                         | ||||
|             await ctx.SendTextAsync( | ||||
|                 $"<html><head><title>You Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|            await ctx.RedirectBackAsync(); | ||||
|         }     | ||||
|             public async Task AddItem(ServerContext ctx) | ||||
|         public async Task AddItem(ServerContext ctx) | ||||
|         { | ||||
|             string id; | ||||
|             if(ctx.QueryParams.TryGetFirst("v",out id)) | ||||
|  | @ -1374,11 +1372,9 @@ internal static class B64 | |||
|                     await Downloader.AddItemAsync(id,resolution); | ||||
|                  | ||||
|             }                         | ||||
|             await ctx.SendTextAsync( | ||||
|                 $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         }     | ||||
|                 public async Task AddUser(ServerContext ctx) | ||||
|         public async Task AddUser(ServerContext ctx) | ||||
|         { | ||||
|             string id; | ||||
|             if(ctx.QueryParams.TryGetFirst("id",out id)) | ||||
|  | @ -1398,12 +1394,10 @@ internal static class B64 | |||
|                     await Downloader.AddUserAsync(id1.Value,resolution); | ||||
|                 } | ||||
|             }                         | ||||
|             await ctx.SendTextAsync( | ||||
|                 $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         }     | ||||
|     | ||||
|                 public async Task AddChannel(ServerContext ctx) | ||||
|         public async Task AddChannel(ServerContext ctx) | ||||
|         { | ||||
|             string id; | ||||
|             if(ctx.QueryParams.TryGetFirst("id",out id)) | ||||
|  | @ -1423,9 +1417,7 @@ internal static class B64 | |||
|                     await Downloader.AddChannelAsync(id1.Value,resolution); | ||||
|                 } | ||||
|             }                         | ||||
|             await ctx.SendTextAsync( | ||||
|                 $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         }     | ||||
|     | ||||
|             public async Task AddPlaylist(ServerContext ctx) | ||||
|  | @ -1448,9 +1440,7 @@ internal static class B64 | |||
|                     await Downloader.AddPlaylistAsync(id1.Value,resolution); | ||||
|                 } | ||||
|             }                         | ||||
|             await ctx.SendTextAsync( | ||||
|                 $"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n" | ||||
|             ); | ||||
|             await ctx.RedirectBackAsync(); | ||||
|         }     | ||||
|     | ||||
|     } | ||||
|  |  | |||
|  | @ -15,9 +15,9 @@ | |||
|       <PackageId>Tesses.YouTubeDownloader.Server</PackageId> | ||||
|     <Author>Mike Nolan</Author> | ||||
|     <Company>Tesses</Company> | ||||
|      <Version>1.1.5</Version> | ||||
|     <AssemblyVersion>1.1.5</AssemblyVersion> | ||||
|     <FileVersion>1.1.5</FileVersion> | ||||
|      <Version>1.1.6</Version> | ||||
|     <AssemblyVersion>1.1.6</AssemblyVersion> | ||||
|     <FileVersion>1.1.6</FileVersion> | ||||
|     <Description>Adds WebServer to TYTD</Description> | ||||
|     <PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression> | ||||
|      <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
|  |  | |||
|  | @ -0,0 +1,16 @@ | |||
| using System; | ||||
| namespace Tesses.YouTubeDownloader | ||||
| { | ||||
|     public class ConsoleWriteEventArgs : EventArgs | ||||
|     { | ||||
|         ///<summary> | ||||
|         ///Use Console.Write(e.Text); not Console.WriteLine(e.Text); | ||||
|         ///</summary> | ||||
|         public string Text {get;set;} | ||||
| 
 | ||||
|         internal ConsoleWriteEventArgs(string e) | ||||
|         { | ||||
|             Text=e; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -129,6 +129,9 @@ namespace Tesses.YouTubeDownloader | |||
|          | ||||
|         private async Task DownloadVideoAsync(SavedVideo video, Resolution resolution, CancellationToken token=default(CancellationToken),IProgress<double> progress=null,bool report=true) | ||||
|         { | ||||
|              | ||||
|             begin_download: | ||||
|              | ||||
|             try{ | ||||
|                 if(video.DownloadFrom == "YouTube") | ||||
|                 { | ||||
|  | @ -147,6 +150,7 @@ namespace Tesses.YouTubeDownloader | |||
|                     await DownloadVideoOnlyAsync(video,token,progress,report); | ||||
|                     break; | ||||
|             } | ||||
|              | ||||
|             }else if(video.DownloadFrom.StartsWith("NormalDownload,Length=")) | ||||
|             { | ||||
|                 await DownloadFileAsync(video,token,progress,report); | ||||
|  | @ -160,9 +164,23 @@ namespace Tesses.YouTubeDownloader | |||
|                     await GetLogger().WriteAsync(ex); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             cancelDownload=false; | ||||
|             if(restartDownload) | ||||
|             { | ||||
|                 restartDownload=false; | ||||
|                 goto begin_download; | ||||
|                 | ||||
|             } | ||||
|         } | ||||
|         public bool cancelDownload=false; | ||||
|         public bool restartDownload=false; | ||||
| 
 | ||||
|         public void CancelDownload(bool restart=false) | ||||
|         { | ||||
|             cancelDownload=true; | ||||
|             restartDownload=restart; | ||||
|         } | ||||
|          | ||||
|         private async Task DownloadFileAsync(SavedVideo video, CancellationToken token, IProgress<double> progress, bool report) | ||||
|         { | ||||
|             string incomplete_file_path = $"Download/{B64.Base64UrlEncodes(video.Id)}-incomplete.part"; | ||||
|  | @ -371,7 +389,7 @@ namespace Tesses.YouTubeDownloader | |||
|             byte[] buffer=new byte[bufferSize]; | ||||
|             do{ | ||||
|                 read=await src.ReadAsync(buffer,0,buffer.Length,token); | ||||
|                 if(token.IsCancellationRequested) | ||||
|                 if(token.IsCancellationRequested || restartDownload || cancelDownload) | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
|  | @ -381,8 +399,8 @@ namespace Tesses.YouTubeDownloader | |||
|                 { | ||||
|                     progress.Report(curPos / len); | ||||
|                 } | ||||
|             }while(read>0 && !token.IsCancellationRequested); | ||||
|             if(token.IsCancellationRequested) | ||||
|             }while(read>0 && !token.IsCancellationRequested && !restartDownload && !cancelDownload); | ||||
|             if(token.IsCancellationRequested || restartDownload || cancelDownload) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | @ -505,17 +523,17 @@ namespace Tesses.YouTubeDownloader | |||
|         { | ||||
|             bool isValid=true; | ||||
|             isValid=await DownloadVideoOnlyAsync(video,token,progress,report); | ||||
|             if(token.IsCancellationRequested || !isValid) | ||||
|             if(token.IsCancellationRequested || !isValid || cancelDownload || restartDownload) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             isValid = await DownloadAudioOnlyAsync(video,token,progress,report); | ||||
|             if(token.IsCancellationRequested || !isValid) | ||||
|             if(token.IsCancellationRequested || !isValid || cancelDownload || restartDownload) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|              var streams=await BestStreamInfo.GetBestStreams(this,video.Id,token,false); | ||||
|              if(token.IsCancellationRequested) | ||||
|              if(token.IsCancellationRequested || cancelDownload || restartDownload) | ||||
|              { | ||||
|                  return; | ||||
|              } | ||||
|  | @ -568,7 +586,7 @@ namespace Tesses.YouTubeDownloader | |||
|                     { | ||||
|                         using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.VideoOnlyStreamInfo,token)) | ||||
|                         { | ||||
|                             if(token.IsCancellationRequested) | ||||
|                             if(token.IsCancellationRequested || cancelDownload || restartDownload) | ||||
|                             { | ||||
|                                 return false; | ||||
|                             } | ||||
|  | @ -670,7 +688,7 @@ namespace Tesses.YouTubeDownloader | |||
|                          | ||||
|                         using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.AudioOnlyStreamInfo,token)) | ||||
|                         { | ||||
|                             if(token.IsCancellationRequested) | ||||
|                             if(token.IsCancellationRequested || cancelDownload || restartDownload) | ||||
|                             { | ||||
|                                 return false; | ||||
|                             } | ||||
|  | @ -722,7 +740,7 @@ namespace Tesses.YouTubeDownloader | |||
|                          | ||||
|                         using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.MuxedStreamInfo,token)) | ||||
|                         { | ||||
|                              if(token.IsCancellationRequested) | ||||
|                              if(token.IsCancellationRequested || cancelDownload || restartDownload) | ||||
|                             { | ||||
|                                 return; | ||||
|                             } | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ namespace Tesses.YouTubeDownloader | |||
| { | ||||
|     public interface IDownloader : IPersonalPlaylistSet | ||||
|     { | ||||
|         void CancelDownload(bool restart=false); | ||||
|         Task AddVideoAsync(VideoId id,Resolution resolution=Resolution.PreMuxed); | ||||
|         Task AddPlaylistAsync(PlaylistId id,Resolution resolution=Resolution.PreMuxed); | ||||
|         Task AddChannelAsync(ChannelId id,Resolution resolution=Resolution.PreMuxed); | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ namespace Tesses.YouTubeDownloader | |||
|         Task WriteBestStreamInfoAsync(VideoId id,BestStreamInfo.BestStreamsSerialized serialized); | ||||
|         Task<bool> MuxVideosAsync(SavedVideo video,string videoSrc,string audioSrc,string videoDest,IProgress<double> progress=null,CancellationToken token=default(CancellationToken)); | ||||
|         Task<bool> Continue(string path); | ||||
|          | ||||
|         Task WriteVideoInfoAsync(SavedVideo channel); | ||||
|         Task WritePlaylistInfoAsync(SavedPlaylist channel); | ||||
|         Task WriteChannelInfoAsync(SavedChannel channel); | ||||
|  |  | |||
|  | @ -131,17 +131,30 @@ namespace Tesses.YouTubeDownloader | |||
|         } | ||||
|         private void WriteStdErr(string message) | ||||
|         { | ||||
|             var col=Console.ForegroundColor; | ||||
|             Console.ForegroundColor = ConsoleColor.Red; | ||||
|             Console.Error.WriteLine(message); | ||||
|             Console.ForegroundColor = col; | ||||
|             if(TYTDStorage.UseConsole){ | ||||
|                 var col=Console.ForegroundColor; | ||||
|                 Console.ForegroundColor = ConsoleColor.Red; | ||||
|                 Console.Error.WriteLine(message); | ||||
|                 Console.ForegroundColor = col; | ||||
|             }else{ | ||||
|                 _storage.ConsoleWriter.WriteLine($"ERROR: {message}"); | ||||
|             } | ||||
|         } | ||||
|         private void WriteStd(string message,bool error) | ||||
|         { | ||||
|             if(error) | ||||
|                 WriteStdErr(message); | ||||
|             else | ||||
|             else{ | ||||
|                 if(TYTDStorage.UseConsole){ | ||||
|                 var col=Console.ForegroundColor; | ||||
|                 Console.ForegroundColor = ConsoleColor.Red; | ||||
|                 Console.WriteLine(message); | ||||
|                 Console.ForegroundColor = col; | ||||
|             }else{ | ||||
|                 _storage.ConsoleWriter.WriteLine(message); | ||||
|             } | ||||
|             } | ||||
|                  | ||||
|         } | ||||
|         public async Task WriteAsync(string message,bool writeToConsole=false,bool isError=false,bool log=true) | ||||
|         { | ||||
|  |  | |||
|  | @ -63,6 +63,7 @@ namespace Tesses.YouTubeDownloader | |||
|             video.AuthorTitle=AuthorTitle; | ||||
|             video.Description=Description; | ||||
|             video.UploadDate = DateTime.Parse(UploadDate); | ||||
|             video.Views=Views; | ||||
|             return video; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -10,29 +10,52 @@ using System.IO; | |||
| using YoutubeExplode.Playlists; | ||||
| using YoutubeExplode.Channels; | ||||
| using Newtonsoft.Json; | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace Tesses.YouTubeDownloader | ||||
| { | ||||
|      | ||||
|     public abstract partial class TYTDStorage : TYTDBase, IStorage | ||||
|     { | ||||
|         internal class ConsoleWriterCLS : TextWriter | ||||
|         { | ||||
|             Action<string> cls; | ||||
|             public ConsoleWriterCLS(Action<string> cls) | ||||
|             { | ||||
|                 this.cls=cls; | ||||
|             } | ||||
| 
 | ||||
|             public override Encoding Encoding => Encoding.UTF8; | ||||
|             public override void Write(string value) | ||||
|             { | ||||
|                 cls(value); | ||||
|             } | ||||
|         } | ||||
|         private static readonly HttpClient _default = new HttpClient(); | ||||
|         public abstract Task<Stream> CreateAsync(string path); | ||||
| 
 | ||||
|         public abstract void CreateDirectory(string path); | ||||
| 
 | ||||
|         public static bool UseConsole = true; | ||||
| 
 | ||||
|         public TYTDStorage(HttpClient clt) | ||||
|         { | ||||
|              | ||||
|             HttpClient=clt; | ||||
|             YoutubeClient=new YoutubeClient(HttpClient); | ||||
|             ExtensionContext=null; | ||||
|              | ||||
|             ConsoleWriter=new ConsoleWriterCLS((e)=>{ | ||||
|                 ConsoleWrite?.Invoke(this,new ConsoleWriteEventArgs(e)); | ||||
|             }); | ||||
|         } | ||||
|         public TYTDStorage() | ||||
|         { | ||||
|             HttpClient=_default; | ||||
|              YoutubeClient=new YoutubeClient(HttpClient); | ||||
|             ExtensionContext=null; | ||||
|              ConsoleWriter=new ConsoleWriterCLS((e)=>{ | ||||
|                 ConsoleWrite?.Invoke(this,new ConsoleWriteEventArgs(e)); | ||||
|             }); | ||||
|         } | ||||
|         public async Task WriteAllBytesAsync(string path,byte[] data,CancellationToken token=default(CancellationToken)) | ||||
|         { | ||||
|  | @ -41,7 +64,14 @@ namespace Tesses.YouTubeDownloader | |||
|                 await s.WriteAsync(data,0,data.Length,token); | ||||
|             } | ||||
|         } | ||||
|         public EventHandler<ConsoleWriteEventArgs> ConsoleWrite; | ||||
|         public TextWriter ConsoleWriter {get; private set;} | ||||
|          public static string TYTDTag {get {return _tytd_tag;}} | ||||
|          public static void SetTYTDTag(string tag) | ||||
|          { | ||||
|             //for use on mobile phones | ||||
|             _tytd_tag= tag; | ||||
|          } | ||||
|          private static string _tytd_tag=_getTYTDTag(); | ||||
|          private static string _getTYTDTag() | ||||
|          { | ||||
|  | @ -175,6 +205,7 @@ namespace Tesses.YouTubeDownloader | |||
|             CreateDirectoryIfNotExist("FileInfo"); | ||||
|             CreateDirectoryIfNotExist("Download"); | ||||
|             CreateDirectoryIfNotExist("StreamInfo"); | ||||
|              CreateDirectoryIfNotExist("PersonalPlaylist"); | ||||
|         } | ||||
|         public void StartLoop(CancellationToken token = default(CancellationToken)) | ||||
|         { | ||||
|  |  | |||
|  | @ -507,5 +507,18 @@ internal class SegmentedHttpStream : Stream | |||
|                 _=ex; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void CancelDownload(bool restart = false) | ||||
|         { | ||||
|              try{ | ||||
|                  | ||||
|                    | ||||
|                   client.GetStringAsync($"{url}api/v2/CancelDownload?restart={restart}").GetAwaiter().GetResult(); | ||||
|              | ||||
|             }catch(Exception ex) | ||||
|             { | ||||
|                 _=ex; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -715,6 +715,11 @@ namespace Tesses.YouTubeDownloader | |||
|         { | ||||
|             return await Storage.GetDownloadInfoAsync(url); | ||||
|         } | ||||
| 
 | ||||
|         public void CancelDownload(bool restart = false) | ||||
|         { | ||||
|             Downloader.CancelDownload(restart); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public class DownloaderMigration | ||||
|  |  | |||
|  | @ -7,9 +7,9 @@ | |||
|       <PackageId>Tesses.YouTubeDownloader</PackageId> | ||||
|     <Author>Mike Nolan</Author> | ||||
|     <Company>Tesses</Company> | ||||
|      <Version>1.1.7</Version> | ||||
|     <AssemblyVersion>1.1.7</AssemblyVersion> | ||||
|     <FileVersion>1.1.7</FileVersion> | ||||
|      <Version>1.1.8</Version> | ||||
|     <AssemblyVersion>1.1.8</AssemblyVersion> | ||||
|     <FileVersion>1.1.8</FileVersion> | ||||
|     <Description>A YouTube Downloader</Description> | ||||
|     <PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression> | ||||
|      <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue