Push update
This commit is contained in:
parent
8e5e58168a
commit
96d2a358b4
|
@ -1,6 +1,9 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System;
|
using System;
|
||||||
|
using YoutubeExplode.Videos;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Tesses.YouTubeDownloader.Tools.Common
|
namespace Tesses.YouTubeDownloader.Tools.Common
|
||||||
{
|
{
|
||||||
public static class SymlinkGenerator
|
public static class SymlinkGenerator
|
||||||
|
@ -14,7 +17,8 @@ namespace Tesses.YouTubeDownloader.Tools.Common
|
||||||
}else{
|
}else{
|
||||||
using(var p=new Process())
|
using(var p=new Process())
|
||||||
{
|
{
|
||||||
|
p.StartInfo.UseShellExecute=false;
|
||||||
|
p.StartInfo.WorkingDirectory="/";
|
||||||
p.StartInfo.FileName = "ln";
|
p.StartInfo.FileName = "ln";
|
||||||
p.StartInfo.ArgumentList.Add(srcPath);
|
p.StartInfo.ArgumentList.Add(srcPath);
|
||||||
p.StartInfo.ArgumentList.Add(destPath);
|
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)
|
public static async Task GenerateHardLinks(TYTDStorage storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(dest);
|
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? ext=Path.GetExtension(path);
|
||||||
|
|
||||||
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
||||||
|
@ -55,17 +62,84 @@ namespace Tesses.YouTubeDownloader.Tools.Common
|
||||||
Console.WriteLine(item.Title);
|
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)
|
public static async Task GenerateSymlinks(TYTDBase storage,string dest="GoodFileNames",Resolution res=Resolution.PreMuxed,bool verbose=false)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(dest);
|
Directory.CreateDirectory(dest);
|
||||||
await foreach(var item in storage.GetVideosAsync())
|
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? ext=Path.GetExtension(path);
|
||||||
|
|
||||||
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
string defaultExt = res == Resolution.Mux ? ".mkv" : ".mp4";
|
||||||
|
|
|
@ -7,6 +7,7 @@ Resolution res=Resolution.PreMuxed;
|
||||||
|
|
||||||
bool verbose=false;
|
bool verbose=false;
|
||||||
bool isSymlink = false;
|
bool isSymlink = false;
|
||||||
|
bool isBigExport=false;
|
||||||
List<string> _args=new List<string>();
|
List<string> _args=new List<string>();
|
||||||
foreach(var arg in args)
|
foreach(var arg in args)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +17,11 @@ foreach(var arg in args)
|
||||||
_args.Clear();
|
_args.Clear();
|
||||||
break;
|
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")
|
if( (arg.Length >= 2 && arg[1] != '-' && arg[0] == '-' && arg.Contains("s") )|| arg == "--symbolic")
|
||||||
{
|
{
|
||||||
any=true;
|
any=true;
|
||||||
|
@ -44,6 +50,7 @@ foreach(var arg in args)
|
||||||
verbose=true;
|
verbose=true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!any)
|
if(!any)
|
||||||
_args.Add(arg);
|
_args.Add(arg);
|
||||||
|
|
||||||
|
@ -53,7 +60,7 @@ if(argv.Length < 2)
|
||||||
{
|
{
|
||||||
string app = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]);
|
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();
|
||||||
Console.WriteLine("Options:");
|
Console.WriteLine("Options:");
|
||||||
Console.WriteLine(" -s, --symbolic make symbolic links instead of hard links");
|
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(" -V, --video-only set resolution to VideoOnly");
|
||||||
Console.WriteLine(" -h, --help show this help");
|
Console.WriteLine(" -h, --help show this help");
|
||||||
Console.WriteLine(" -v, --verbose print video names");
|
Console.WriteLine(" -v, --verbose print video names");
|
||||||
|
Console.WriteLine(" -g, --generate-export Export everything to human readable format");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Positional Arguments:");
|
Console.WriteLine("Positional Arguments:");
|
||||||
Console.WriteLine(" Working the folder containing the Info Directory for TYTD. (required)");
|
Console.WriteLine(" Working the folder containing the Info Directory for TYTD. (required)");
|
||||||
|
@ -76,8 +84,52 @@ TYTDCurrentDirectory currentDirectory=new TYTDCurrentDirectory();
|
||||||
currentDirectory.CanDownload=false;
|
currentDirectory.CanDownload=false;
|
||||||
|
|
||||||
if(isSymlink){
|
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{
|
}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);
|
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(
|
// 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"
|
// $"<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/"))
|
if(path.StartsWith("/AddItemRes/"))
|
||||||
{
|
{
|
||||||
|
@ -252,7 +256,7 @@ internal static class B64
|
||||||
//);
|
//);
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendRedirectAsync("/");
|
await ctx.RedirectBackAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal class ApiStorage : Tesses.WebServer.Server
|
internal class ApiStorage : Tesses.WebServer.Server
|
||||||
|
@ -846,6 +850,7 @@ internal static class B64
|
||||||
public ApiV2Server(IDownloader downloader)
|
public ApiV2Server(IDownloader downloader)
|
||||||
{
|
{
|
||||||
this.Downloader=downloader;
|
this.Downloader=downloader;
|
||||||
|
AddBoth("/CancelDownload",Cancel);
|
||||||
AddBoth("/Search",Search);
|
AddBoth("/Search",Search);
|
||||||
AddBoth("/AddItem",AddItem);
|
AddBoth("/AddItem",AddItem);
|
||||||
AddBoth("/AddChannel",AddChannel);
|
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)
|
private async Task Search(ServerContext ctx)
|
||||||
{
|
{
|
||||||
var dl = Downloader as IStorage;
|
var dl = Downloader as IStorage;
|
||||||
|
@ -942,9 +962,7 @@ internal static class B64
|
||||||
//Downloader.AddToPersonalPlaylistAsync(name);
|
//Downloader.AddToPersonalPlaylistAsync(name);
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task ReplaceList(ServerContext ctx)
|
public async Task ReplaceList(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -966,9 +984,7 @@ internal static class B64
|
||||||
//Downloader.AddToPersonalPlaylistAsync(name);
|
//Downloader.AddToPersonalPlaylistAsync(name);
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task Everything_Export(ServerContext ctx)
|
public async Task Everything_Export(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -1124,9 +1140,7 @@ internal static class B64
|
||||||
//Downloader.AddToPersonalPlaylistAsync(name);
|
//Downloader.AddToPersonalPlaylistAsync(name);
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task DeleteFromList(ServerContext ctx)
|
public async Task DeleteFromList(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -1144,9 +1158,7 @@ internal static class B64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task SetResolutionInList(ServerContext ctx)
|
public async Task SetResolutionInList(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -1173,9 +1185,7 @@ internal static class B64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task Subscriptions(ServerContext ctx)
|
public async Task Subscriptions(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -1189,9 +1199,7 @@ internal static class B64
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task Resubscribe(ServerContext ctx)
|
public async Task Resubscribe(ServerContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -1222,9 +1230,7 @@ internal static class B64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Unsubscribe(ServerContext ctx)
|
public async Task Unsubscribe(ServerContext ctx)
|
||||||
|
@ -1249,10 +1255,8 @@ internal static class B64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
public async Task Subscribe(ServerContext ctx)
|
public async Task Subscribe(ServerContext ctx)
|
||||||
{
|
{
|
||||||
IStorage storage = Downloader as IStorage;
|
IStorage storage = Downloader as IStorage;
|
||||||
|
@ -1294,9 +1298,7 @@ internal static class B64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task QueueList(ServerContext ctx)
|
public async Task QueueList(ServerContext ctx)
|
||||||
|
@ -1324,9 +1326,7 @@ internal static class B64
|
||||||
}
|
}
|
||||||
|
|
||||||
await Downloader.AddFileAsync(url,download);
|
await Downloader.AddFileAsync(url,download);
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task AddVideo(ServerContext ctx)
|
public async Task AddVideo(ServerContext ctx)
|
||||||
|
@ -1352,11 +1352,9 @@ internal static class B64
|
||||||
await Downloader.AddVideoAsync(id1.Value,resolution);
|
await Downloader.AddVideoAsync(id1.Value,resolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task AddItem(ServerContext ctx)
|
public async Task AddItem(ServerContext ctx)
|
||||||
{
|
{
|
||||||
string id;
|
string id;
|
||||||
if(ctx.QueryParams.TryGetFirst("v",out id))
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
@ -1374,11 +1372,9 @@ internal static class B64
|
||||||
await Downloader.AddItemAsync(id,resolution);
|
await Downloader.AddItemAsync(id,resolution);
|
||||||
|
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
public async Task AddUser(ServerContext ctx)
|
public async Task AddUser(ServerContext ctx)
|
||||||
{
|
{
|
||||||
string id;
|
string id;
|
||||||
if(ctx.QueryParams.TryGetFirst("id",out id))
|
if(ctx.QueryParams.TryGetFirst("id",out id))
|
||||||
|
@ -1398,12 +1394,10 @@ internal static class B64
|
||||||
await Downloader.AddUserAsync(id1.Value,resolution);
|
await Downloader.AddUserAsync(id1.Value,resolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddChannel(ServerContext ctx)
|
public async Task AddChannel(ServerContext ctx)
|
||||||
{
|
{
|
||||||
string id;
|
string id;
|
||||||
if(ctx.QueryParams.TryGetFirst("id",out id))
|
if(ctx.QueryParams.TryGetFirst("id",out id))
|
||||||
|
@ -1423,9 +1417,7 @@ internal static class B64
|
||||||
await Downloader.AddChannelAsync(id1.Value,resolution);
|
await Downloader.AddChannelAsync(id1.Value,resolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddPlaylist(ServerContext ctx)
|
public async Task AddPlaylist(ServerContext ctx)
|
||||||
|
@ -1448,9 +1440,7 @@ internal static class B64
|
||||||
await Downloader.AddPlaylistAsync(id1.Value,resolution);
|
await Downloader.AddPlaylistAsync(id1.Value,resolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.RedirectBackAsync();
|
||||||
$"<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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
<PackageId>Tesses.YouTubeDownloader.Server</PackageId>
|
<PackageId>Tesses.YouTubeDownloader.Server</PackageId>
|
||||||
<Author>Mike Nolan</Author>
|
<Author>Mike Nolan</Author>
|
||||||
<Company>Tesses</Company>
|
<Company>Tesses</Company>
|
||||||
<Version>1.1.5</Version>
|
<Version>1.1.6</Version>
|
||||||
<AssemblyVersion>1.1.5</AssemblyVersion>
|
<AssemblyVersion>1.1.6</AssemblyVersion>
|
||||||
<FileVersion>1.1.5</FileVersion>
|
<FileVersion>1.1.6</FileVersion>
|
||||||
<Description>Adds WebServer to TYTD</Description>
|
<Description>Adds WebServer to TYTD</Description>
|
||||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<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)
|
private async Task DownloadVideoAsync(SavedVideo video, Resolution resolution, CancellationToken token=default(CancellationToken),IProgress<double> progress=null,bool report=true)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
begin_download:
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if(video.DownloadFrom == "YouTube")
|
if(video.DownloadFrom == "YouTube")
|
||||||
{
|
{
|
||||||
|
@ -147,6 +150,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
await DownloadVideoOnlyAsync(video,token,progress,report);
|
await DownloadVideoOnlyAsync(video,token,progress,report);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(video.DownloadFrom.StartsWith("NormalDownload,Length="))
|
}else if(video.DownloadFrom.StartsWith("NormalDownload,Length="))
|
||||||
{
|
{
|
||||||
await DownloadFileAsync(video,token,progress,report);
|
await DownloadFileAsync(video,token,progress,report);
|
||||||
|
@ -160,7 +164,21 @@ namespace Tesses.YouTubeDownloader
|
||||||
await GetLogger().WriteAsync(ex);
|
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)
|
private async Task DownloadFileAsync(SavedVideo video, CancellationToken token, IProgress<double> progress, bool report)
|
||||||
|
@ -371,7 +389,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
byte[] buffer=new byte[bufferSize];
|
byte[] buffer=new byte[bufferSize];
|
||||||
do{
|
do{
|
||||||
read=await src.ReadAsync(buffer,0,buffer.Length,token);
|
read=await src.ReadAsync(buffer,0,buffer.Length,token);
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || restartDownload || cancelDownload)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -381,8 +399,8 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
progress.Report(curPos / len);
|
progress.Report(curPos / len);
|
||||||
}
|
}
|
||||||
}while(read>0 && !token.IsCancellationRequested);
|
}while(read>0 && !token.IsCancellationRequested && !restartDownload && !cancelDownload);
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || restartDownload || cancelDownload)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -505,17 +523,17 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
bool isValid=true;
|
bool isValid=true;
|
||||||
isValid=await DownloadVideoOnlyAsync(video,token,progress,report);
|
isValid=await DownloadVideoOnlyAsync(video,token,progress,report);
|
||||||
if(token.IsCancellationRequested || !isValid)
|
if(token.IsCancellationRequested || !isValid || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isValid = await DownloadAudioOnlyAsync(video,token,progress,report);
|
isValid = await DownloadAudioOnlyAsync(video,token,progress,report);
|
||||||
if(token.IsCancellationRequested || !isValid)
|
if(token.IsCancellationRequested || !isValid || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var streams=await BestStreamInfo.GetBestStreams(this,video.Id,token,false);
|
var streams=await BestStreamInfo.GetBestStreams(this,video.Id,token,false);
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -568,7 +586,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.VideoOnlyStreamInfo,token))
|
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.VideoOnlyStreamInfo,token))
|
||||||
{
|
{
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -670,7 +688,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
|
|
||||||
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.AudioOnlyStreamInfo,token))
|
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.AudioOnlyStreamInfo,token))
|
||||||
{
|
{
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -722,7 +740,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
|
|
||||||
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.MuxedStreamInfo,token))
|
using(var strm = await YoutubeClient.Videos.Streams.GetAsync(streams.MuxedStreamInfo,token))
|
||||||
{
|
{
|
||||||
if(token.IsCancellationRequested)
|
if(token.IsCancellationRequested || cancelDownload || restartDownload)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
public interface IDownloader : IPersonalPlaylistSet
|
public interface IDownloader : IPersonalPlaylistSet
|
||||||
{
|
{
|
||||||
|
void CancelDownload(bool restart=false);
|
||||||
Task AddVideoAsync(VideoId id,Resolution resolution=Resolution.PreMuxed);
|
Task AddVideoAsync(VideoId id,Resolution resolution=Resolution.PreMuxed);
|
||||||
Task AddPlaylistAsync(PlaylistId id,Resolution resolution=Resolution.PreMuxed);
|
Task AddPlaylistAsync(PlaylistId id,Resolution resolution=Resolution.PreMuxed);
|
||||||
Task AddChannelAsync(ChannelId 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 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> MuxVideosAsync(SavedVideo video,string videoSrc,string audioSrc,string videoDest,IProgress<double> progress=null,CancellationToken token=default(CancellationToken));
|
||||||
Task<bool> Continue(string path);
|
Task<bool> Continue(string path);
|
||||||
|
|
||||||
Task WriteVideoInfoAsync(SavedVideo channel);
|
Task WriteVideoInfoAsync(SavedVideo channel);
|
||||||
Task WritePlaylistInfoAsync(SavedPlaylist channel);
|
Task WritePlaylistInfoAsync(SavedPlaylist channel);
|
||||||
Task WriteChannelInfoAsync(SavedChannel channel);
|
Task WriteChannelInfoAsync(SavedChannel channel);
|
||||||
|
|
|
@ -131,17 +131,30 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
private void WriteStdErr(string message)
|
private void WriteStdErr(string message)
|
||||||
{
|
{
|
||||||
var col=Console.ForegroundColor;
|
if(TYTDStorage.UseConsole){
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
var col=Console.ForegroundColor;
|
||||||
Console.Error.WriteLine(message);
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.ForegroundColor = col;
|
Console.Error.WriteLine(message);
|
||||||
|
Console.ForegroundColor = col;
|
||||||
|
}else{
|
||||||
|
_storage.ConsoleWriter.WriteLine($"ERROR: {message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void WriteStd(string message,bool error)
|
private void WriteStd(string message,bool error)
|
||||||
{
|
{
|
||||||
if(error)
|
if(error)
|
||||||
WriteStdErr(message);
|
WriteStdErr(message);
|
||||||
else
|
else{
|
||||||
|
if(TYTDStorage.UseConsole){
|
||||||
|
var col=Console.ForegroundColor;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine(message);
|
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)
|
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.AuthorTitle=AuthorTitle;
|
||||||
video.Description=Description;
|
video.Description=Description;
|
||||||
video.UploadDate = DateTime.Parse(UploadDate);
|
video.UploadDate = DateTime.Parse(UploadDate);
|
||||||
|
video.Views=Views;
|
||||||
return video;
|
return video;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,29 +10,52 @@ using System.IO;
|
||||||
using YoutubeExplode.Playlists;
|
using YoutubeExplode.Playlists;
|
||||||
using YoutubeExplode.Channels;
|
using YoutubeExplode.Channels;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Tesses.YouTubeDownloader
|
namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
|
|
||||||
public abstract partial class TYTDStorage : TYTDBase, IStorage
|
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();
|
private static readonly HttpClient _default = new HttpClient();
|
||||||
public abstract Task<Stream> CreateAsync(string path);
|
public abstract Task<Stream> CreateAsync(string path);
|
||||||
|
|
||||||
public abstract void CreateDirectory(string path);
|
public abstract void CreateDirectory(string path);
|
||||||
|
|
||||||
|
public static bool UseConsole = true;
|
||||||
|
|
||||||
public TYTDStorage(HttpClient clt)
|
public TYTDStorage(HttpClient clt)
|
||||||
{
|
{
|
||||||
|
|
||||||
HttpClient=clt;
|
HttpClient=clt;
|
||||||
YoutubeClient=new YoutubeClient(HttpClient);
|
YoutubeClient=new YoutubeClient(HttpClient);
|
||||||
ExtensionContext=null;
|
ExtensionContext=null;
|
||||||
|
ConsoleWriter=new ConsoleWriterCLS((e)=>{
|
||||||
|
ConsoleWrite?.Invoke(this,new ConsoleWriteEventArgs(e));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
public TYTDStorage()
|
public TYTDStorage()
|
||||||
{
|
{
|
||||||
HttpClient=_default;
|
HttpClient=_default;
|
||||||
YoutubeClient=new YoutubeClient(HttpClient);
|
YoutubeClient=new YoutubeClient(HttpClient);
|
||||||
ExtensionContext=null;
|
ExtensionContext=null;
|
||||||
|
ConsoleWriter=new ConsoleWriterCLS((e)=>{
|
||||||
|
ConsoleWrite?.Invoke(this,new ConsoleWriteEventArgs(e));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
public async Task WriteAllBytesAsync(string path,byte[] data,CancellationToken token=default(CancellationToken))
|
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);
|
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 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 _tytd_tag=_getTYTDTag();
|
||||||
private static string _getTYTDTag()
|
private static string _getTYTDTag()
|
||||||
{
|
{
|
||||||
|
@ -175,6 +205,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
CreateDirectoryIfNotExist("FileInfo");
|
CreateDirectoryIfNotExist("FileInfo");
|
||||||
CreateDirectoryIfNotExist("Download");
|
CreateDirectoryIfNotExist("Download");
|
||||||
CreateDirectoryIfNotExist("StreamInfo");
|
CreateDirectoryIfNotExist("StreamInfo");
|
||||||
|
CreateDirectoryIfNotExist("PersonalPlaylist");
|
||||||
}
|
}
|
||||||
public void StartLoop(CancellationToken token = default(CancellationToken))
|
public void StartLoop(CancellationToken token = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
|
|
@ -507,5 +507,18 @@ internal class SegmentedHttpStream : Stream
|
||||||
_=ex;
|
_=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);
|
return await Storage.GetDownloadInfoAsync(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CancelDownload(bool restart = false)
|
||||||
|
{
|
||||||
|
Downloader.CancelDownload(restart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DownloaderMigration
|
public class DownloaderMigration
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
||||||
<Author>Mike Nolan</Author>
|
<Author>Mike Nolan</Author>
|
||||||
<Company>Tesses</Company>
|
<Company>Tesses</Company>
|
||||||
<Version>1.1.7</Version>
|
<Version>1.1.8</Version>
|
||||||
<AssemblyVersion>1.1.7</AssemblyVersion>
|
<AssemblyVersion>1.1.8</AssemblyVersion>
|
||||||
<FileVersion>1.1.7</FileVersion>
|
<FileVersion>1.1.8</FileVersion>
|
||||||
<Description>A YouTube Downloader</Description>
|
<Description>A YouTube Downloader</Description>
|
||||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
|
|
Loading…
Reference in New Issue