added exception handling
This commit is contained in:
parent
47e5f21315
commit
3210b98a08
|
@ -22,6 +22,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
try{
|
||||||
bool hasAny;
|
bool hasAny;
|
||||||
var (Video, Resolution) = Dequeue(out hasAny);
|
var (Video, Resolution) = Dequeue(out hasAny);
|
||||||
if (hasAny)
|
if (hasAny)
|
||||||
|
@ -29,6 +30,10 @@ namespace Tesses.YouTubeDownloader
|
||||||
await DownloadVideoAsync(Video, Resolution, token,new Progress<double>(ReportProgress),true);
|
await DownloadVideoAsync(Video, Resolution, token,new Progress<double>(ReportProgress),true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}catch(Exception ex)
|
||||||
|
{
|
||||||
|
await GetLogger().WriteAsync(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +53,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
private void ReportStartVideo(SavedVideo video, Resolution resolution, long length)
|
private void ReportStartVideo(SavedVideo video, Resolution resolution, long length)
|
||||||
{
|
{
|
||||||
|
GetLogger().WriteAsync(video).Wait();
|
||||||
Progress.Video = video;
|
Progress.Video = video;
|
||||||
Progress.Progress = 0;
|
Progress.Progress = 0;
|
||||||
Progress.ProgressRaw = 0;
|
Progress.ProgressRaw = 0;
|
||||||
|
@ -97,6 +103,7 @@ 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)
|
||||||
{
|
{
|
||||||
|
try{
|
||||||
switch (resolution)
|
switch (resolution)
|
||||||
{
|
{
|
||||||
case Resolution.Mux:
|
case Resolution.Mux:
|
||||||
|
@ -112,6 +119,10 @@ namespace Tesses.YouTubeDownloader
|
||||||
await DownloadVideoOnlyAsync(video,token,progress,report);
|
await DownloadVideoOnlyAsync(video,token,progress,report);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}catch(Exception ex)
|
||||||
|
{
|
||||||
|
await GetLogger().WriteAsync(ex);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public async Task<bool> Continue(string path)
|
public async Task<bool> Continue(string path)
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using YoutubeExplode;
|
||||||
|
using YoutubeExplode.Videos;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using YoutubeExplode.Playlists;
|
||||||
|
using YoutubeExplode.Channels;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Tesses.YouTubeDownloader
|
||||||
|
{
|
||||||
|
public partial class TYTDStorage
|
||||||
|
{
|
||||||
|
private Mutex mtx0=new Mutex();
|
||||||
|
private Logger _log=null;
|
||||||
|
public Logger GetLogger()
|
||||||
|
{
|
||||||
|
mtx0.WaitOne();
|
||||||
|
if(_log == null)
|
||||||
|
{
|
||||||
|
_log = new Logger(this);
|
||||||
|
}
|
||||||
|
mtx0.ReleaseMutex();
|
||||||
|
return _log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class LoggerProperties
|
||||||
|
{
|
||||||
|
public bool UseLogs {get;set;}
|
||||||
|
|
||||||
|
public bool PrintVideoIds {get;set;}
|
||||||
|
|
||||||
|
public bool PrintErrors {get;set;}
|
||||||
|
|
||||||
|
public bool LogVideoIds {get;set;}
|
||||||
|
|
||||||
|
|
||||||
|
public bool AddDateInLog {get;set;}
|
||||||
|
}
|
||||||
|
public class Logger
|
||||||
|
{
|
||||||
|
Mutex mtx=new Mutex();
|
||||||
|
private string _filename;
|
||||||
|
private TYTDStorage _storage;
|
||||||
|
|
||||||
|
public LoggerProperties Properties {get;set;}
|
||||||
|
|
||||||
|
private LoggerProperties GetProperties(TYTDStorage storage)
|
||||||
|
{
|
||||||
|
if(storage.FileExists("config/logger.json"))
|
||||||
|
{
|
||||||
|
string data=storage.ReadAllTextAsync("config/lggger.json").GetAwaiter().GetResult();
|
||||||
|
return JsonConvert.DeserializeObject<LoggerProperties>(data);
|
||||||
|
}else{
|
||||||
|
LoggerProperties prop=new LoggerProperties();
|
||||||
|
prop.AddDateInLog=true;
|
||||||
|
prop.LogVideoIds=true;
|
||||||
|
prop.PrintErrors =false;
|
||||||
|
prop.PrintVideoIds=true;
|
||||||
|
prop.UseLogs=true;
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal Logger(TYTDStorage storage)
|
||||||
|
{
|
||||||
|
Properties = GetProperties(storage);
|
||||||
|
_storage=storage;
|
||||||
|
|
||||||
|
string dateTime = DateTime.Now.ToString("yyyyMMdd_hhmmss");
|
||||||
|
_filename = $"config/logs/{dateTime}.log";
|
||||||
|
}
|
||||||
|
private void WriteStdErr(string message)
|
||||||
|
{
|
||||||
|
var col=Console.ForegroundColor;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.Error.WriteLine(message);
|
||||||
|
Console.ForegroundColor = col;
|
||||||
|
}
|
||||||
|
private void WriteStd(string message,bool error)
|
||||||
|
{
|
||||||
|
if(error)
|
||||||
|
WriteStdErr(message);
|
||||||
|
else
|
||||||
|
Console.WriteLine(message);
|
||||||
|
}
|
||||||
|
public async Task WriteAsync(string message,bool writeToConsole=false, bool isError=false,bool log=true)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(writeToConsole) WriteStd(message,isError);
|
||||||
|
if(!log || !Properties.UseLogs) return;
|
||||||
|
|
||||||
|
// DateTime time = DateTime.Now;
|
||||||
|
var msg= new StringBuilder();
|
||||||
|
if(Properties.AddDateInLog)
|
||||||
|
{
|
||||||
|
var dat=DateTime.Now;
|
||||||
|
msg.AppendLine($"{dat.ToShortDateString()} at {dat.ToShortTimeString()}:");
|
||||||
|
}
|
||||||
|
msg.AppendLine(message);
|
||||||
|
mtx.WaitOne();
|
||||||
|
using(var strm = await _storage.OpenOrCreateAsync(_filename))
|
||||||
|
{
|
||||||
|
if(!strm.CanSeek) return;
|
||||||
|
|
||||||
|
strm.Seek(0,SeekOrigin.End);
|
||||||
|
using(var sw = new StreamWriter(strm))
|
||||||
|
{
|
||||||
|
await sw.WriteLineAsync(msg.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mtx.ReleaseMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsync(Exception ex)
|
||||||
|
{
|
||||||
|
await WriteAsync($"Exception Catched:\n{ex.ToString()}",Properties.PrintErrors,true);
|
||||||
|
}
|
||||||
|
public async Task WriteAsync(SavedVideo video)
|
||||||
|
{
|
||||||
|
await WriteAsync($"Download: {video.Title} with Id: {video.Id}",Properties.PrintVideoIds,false,Properties.LogVideoIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -371,6 +371,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static string[] resStr = new string[] {"Muxed","PreMuxed","AudioOnly","VideoOnly"};
|
private static string[] resStr = new string[] {"Muxed","PreMuxed","AudioOnly","VideoOnly"};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert DirectoryName to Resolution
|
/// Convert DirectoryName to Resolution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -138,4 +138,136 @@ namespace Tesses.YouTubeDownloader
|
||||||
Directory.Delete(dir,recursive);
|
Directory.Delete(dir,recursive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Abstracted directory from path
|
||||||
|
/// </summary>
|
||||||
|
public class TYTDPathDirectory : TYTDStorage
|
||||||
|
{
|
||||||
|
public TYTDPathDirectory(string path,HttpClient clt) : base(clt)
|
||||||
|
{
|
||||||
|
_path=path;
|
||||||
|
}
|
||||||
|
public TYTDPathDirectory(string path) : base()
|
||||||
|
{
|
||||||
|
_path=path;
|
||||||
|
}
|
||||||
|
string _path;
|
||||||
|
public string GetPath(string internalPath)
|
||||||
|
{
|
||||||
|
return Path.Combine(_path,internalPath.TrimStart('/'));
|
||||||
|
}
|
||||||
|
public override Task<(string Path, bool Delete)> GetRealUrlOrPathAsync(string path)
|
||||||
|
{
|
||||||
|
return Task.FromResult((GetPath(path),false));
|
||||||
|
}
|
||||||
|
public override async Task<bool> MuxVideosAsync(SavedVideo video, string videoSrc, string audioSrc, string videoDest, IProgress<double> progress = null, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(FFmpeg))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Func<string,TimeSpan> get_percent=(e)=>{
|
||||||
|
if(string.IsNullOrWhiteSpace(e))
|
||||||
|
return TimeSpan.Zero;
|
||||||
|
|
||||||
|
int index=e.IndexOf("time=");
|
||||||
|
if(index < 0)
|
||||||
|
return TimeSpan.Zero;
|
||||||
|
|
||||||
|
int spaceIndex=e.IndexOf(' ',index+5);
|
||||||
|
string j=e.Substring(index+5,spaceIndex-(index+5));
|
||||||
|
|
||||||
|
double val;
|
||||||
|
if(double.TryParse(j,out val))
|
||||||
|
return TimeSpan.FromSeconds(val);
|
||||||
|
|
||||||
|
return TimeSpan.ParseExact(j, "c", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
//return TimeSpan.Zero;
|
||||||
|
};
|
||||||
|
Directory.CreateDirectory(GetPath("TYTD_TEMP"));
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
ret=await this.Convert(video,GetPath(videoSrc),GetPath(audioSrc),GetPath(videoDest),token,new Progress<string>((e)=>{
|
||||||
|
// time=\"\"
|
||||||
|
if(progress!=null)
|
||||||
|
{
|
||||||
|
var progr=get_percent(e).TotalSeconds / video.Duration.TotalSeconds;
|
||||||
|
progress.Report(progr / 4 + 0.50);
|
||||||
|
}
|
||||||
|
}),FFmpeg);
|
||||||
|
|
||||||
|
Directory.Delete(GetPath("TYTD_TEMP"),true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public override async Task<Stream> CreateAsync(string path)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(File.Create(GetPath(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(GetPath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<bool> DirectoryExistsAsync(string path)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(Directory.Exists(GetPath(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async IAsyncEnumerable<string> EnumerateDirectoriesAsync(string path)
|
||||||
|
{
|
||||||
|
foreach(var dir in Directory.EnumerateDirectories(GetPath(path)))
|
||||||
|
{
|
||||||
|
yield return await Task.FromResult(Path.GetFileName(dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async IAsyncEnumerable<string> EnumerateFilesAsync(string path)
|
||||||
|
{
|
||||||
|
foreach(var file in Directory.EnumerateFiles(GetPath(path)))
|
||||||
|
{
|
||||||
|
yield return await Task.FromResult(Path.GetFileName(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<bool> FileExistsAsync(string path)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(File.Exists(GetPath(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Stream> OpenOrCreateAsync(string path)
|
||||||
|
{
|
||||||
|
if(File.Exists(path))
|
||||||
|
{
|
||||||
|
return await Task.FromResult(File.OpenWrite(GetPath(path)));
|
||||||
|
}
|
||||||
|
return await CreateAsync(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Stream> OpenReadAsync(string path)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(File.OpenRead(GetPath(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RenameFile(string src, string dest)
|
||||||
|
{
|
||||||
|
File.Move(GetPath(src),GetPath(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MoveDirectory(string src, string dest)
|
||||||
|
{
|
||||||
|
Directory.Move(GetPath(src),GetPath(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DeleteFile(string file)
|
||||||
|
{
|
||||||
|
File.Delete(GetPath(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DeleteDirectory(string dir, bool recursive = false)
|
||||||
|
{
|
||||||
|
Directory.Delete(GetPath(dir),recursive);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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.0.1.0</Version>
|
<Version>1.0.2.0</Version>
|
||||||
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
<AssemblyVersion>1.0.2.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.1.0</FileVersion>
|
<FileVersion>1.0.2.0</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>
|
||||||
|
|
|
@ -36,8 +36,9 @@ namespace Tesses.YouTubeDownloader
|
||||||
List<IMediaContext> Temporary =new List<IMediaContext>();
|
List<IMediaContext> Temporary =new List<IMediaContext>();
|
||||||
private async Task QueueLoop(CancellationToken token)
|
private async Task QueueLoop(CancellationToken token)
|
||||||
{
|
{
|
||||||
|
|
||||||
while(!token.IsCancellationRequested)
|
while(!token.IsCancellationRequested)
|
||||||
{
|
{ try{
|
||||||
IMediaContext context;
|
IMediaContext context;
|
||||||
lock(Temporary)
|
lock(Temporary)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +55,13 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
await context.FillQueue(this,QueueList);
|
await context.FillQueue(this,QueueList);
|
||||||
}
|
}
|
||||||
}
|
} catch(Exception ex)
|
||||||
|
{
|
||||||
|
//did this so app can keep running
|
||||||
|
await GetLogger().WriteAsync(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue