Added Subscriptions

This commit is contained in:
Mike Nolan 2022-05-09 17:00:19 -05:00
parent a87aad366b
commit ebcc4cda54
12 changed files with 439 additions and 59 deletions

View File

@ -10,7 +10,7 @@ namespace Tesses.YouTubeDownloader.Net6
TYTDCurrentDirectory currentDirectory=new TYTDCurrentDirectory(new HttpClient());
TYTDServer server=new TYTDServer(currentDirectory);
server.RootServer.Server=new StaticServer("WebSite");
HttpServerListener listener=new HttpServerListener(server.InnerServer);
HttpServerListener listener=new HttpServerListener(new System.Net.IPEndPoint(System.Net.IPAddress.Any,42440),server.InnerServer);
currentDirectory.StartLoop();
TYTDStorage.FFmpeg ="/usr/bin/ffmpeg";
Console.WriteLine("Almost Ready to Listen");

View File

@ -325,6 +325,7 @@ namespace Tesses.YouTubeDownloader.Server
public ApiV2Server(IDownloader downloader)
{
this.Downloader=downloader;
Add("/AddItem",AddItem);
Add("/AddChannel",AddChannel);
Add("/AddUser",AddUser);
@ -332,7 +333,94 @@ namespace Tesses.YouTubeDownloader.Server
Add("/AddVideo",AddVideo);
Add("/Progress",ProgressFunc);
Add("/QueueList",QueueList);
Add("/subscribe",Subscribe);
Add("/resubscribe",Resubscribe);
}
public async Task Resubscribe(ServerContext ctx)
{
TYTDStorage storage = Downloader as TYTDStorage;
if(storage != null)
{
string id;
if(ctx.QueryParams.TryGetFirst("id",out id))
{
string confstr;
ChannelBellInfo conf=ChannelBellInfo.NotifyAndDownload;
if(ctx.QueryParams.TryGetFirst("conf",out confstr))
{
if(!Enum.TryParse<ChannelBellInfo>(confstr,out conf))
{
conf = ChannelBellInfo.NotifyAndDownload;
}
}
ChannelId? cid=ChannelId.TryParse(WebUtility.UrlDecode(id));
if(cid.HasValue)
{
var sub=storage.GetSubscription(cid.Value);
if(sub != null)
{
sub.BellInfo = conf;
await storage.SaveSubscription(sub);
}
}
}
}
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"
);
}
public async Task Subscribe(ServerContext ctx)
{
TYTDStorage storage = Downloader as TYTDStorage;
if(storage != null)
{
string id;
if(ctx.QueryParams.TryGetFirst("id",out id))
{
string getinfostr;
bool getinfo=true;
if(ctx.QueryParams.TryGetFirst("getinfo",out getinfostr))
{
if(getinfostr == "false")
{
getinfo=false;
}
}
string confstr;
ChannelBellInfo conf=ChannelBellInfo.NotifyAndDownload;
if(ctx.QueryParams.TryGetFirst("conf",out confstr))
{
if(!Enum.TryParse<ChannelBellInfo>(confstr,out conf))
{
conf = ChannelBellInfo.NotifyAndDownload;
}
}
ChannelId? cid=ChannelId.TryParse(WebUtility.UrlDecode(id));
if(cid.HasValue)
{
await storage.Subscribe(cid.Value,getinfo,conf);
}else{
UserName? uname=UserName.TryParse(WebUtility.UrlDecode(id));
await storage.Subscribe(uname.Value,conf);
}
}
}
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"
);
}
public async Task QueueList(ServerContext ctx)
{
await ctx.SendJsonAsync(Downloader.GetQueueList());
@ -362,7 +450,7 @@ namespace Tesses.YouTubeDownloader.Server
}
}
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><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)
@ -390,7 +478,7 @@ namespace Tesses.YouTubeDownloader.Server
public async Task AddUser(ServerContext ctx)
{
string id;
if(ctx.QueryParams.TryGetFirst("v",out id))
if(ctx.QueryParams.TryGetFirst("id",out id))
{
Resolution resolution=Resolution.PreMuxed;
string res;
@ -415,7 +503,7 @@ namespace Tesses.YouTubeDownloader.Server
public async Task AddChannel(ServerContext ctx)
{
string id;
if(ctx.QueryParams.TryGetFirst("v",out id))
if(ctx.QueryParams.TryGetFirst("id",out id))
{
Resolution resolution=Resolution.PreMuxed;
string res;
@ -440,7 +528,7 @@ namespace Tesses.YouTubeDownloader.Server
public async Task AddPlaylist(ServerContext ctx)
{
string id;
if(ctx.QueryParams.TryGetFirst("v",out id))
if(ctx.QueryParams.TryGetFirst("id",out id))
{
Resolution resolution=Resolution.PreMuxed;
string res;

View File

@ -15,9 +15,9 @@
<PackageId>Tesses.YouTubeDownloader.Server</PackageId>
<Author>Mike Nolan</Author>
<Company>Tesses</Company>
<Version>1.0.1.0</Version>
<AssemblyVersion>1.0.1.0</AssemblyVersion>
<FileVersion>1.0.1.0</FileVersion>
<Version>1.0.2.0</Version>
<AssemblyVersion>1.0.2.0</AssemblyVersion>
<FileVersion>1.0.2.0</FileVersion>
<Description>Adds WebServer to TYTD</Description>
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>

View File

@ -27,7 +27,11 @@ namespace Tesses.YouTubeDownloader
var (Video, Resolution) = Dequeue(out hasAny);
if (hasAny)
{
await DownloadVideoAsync(Video, Resolution, token,new Progress<double>(ReportProgress),true);
await DownloadVideoAsync(Video, Resolution, token,new Progress<double>(
async (e)=>{
await ReportProgress(e);
}
),true);
}
}catch(Exception ex)
@ -38,7 +42,7 @@ namespace Tesses.YouTubeDownloader
}
public readonly SavedVideoProgress Progress = new SavedVideoProgress();
private void ReportProgress(double progress)
private async Task ReportProgress(double progress)
{
Progress.Progress = (int)(progress * 100);
Progress.ProgressRaw = progress;
@ -47,11 +51,19 @@ namespace Tesses.YouTubeDownloader
{
foreach (var ext in ExtensionContext.Extensions)
{
ext.VideoProgress(Progress.Video, progress);
await ext.VideoProgress(Progress.Video, progress);
}
}
VideoProgressEventArgs args=new VideoProgressEventArgs();
args.VideoInfo=Progress.Video;
args.Progress=progress;
VideoProgress?.Invoke(this,args);
}
private void ReportStartVideo(SavedVideo video, Resolution resolution, long length)
private async Task ReportStartVideo(SavedVideo video, Resolution resolution, long length)
{
GetLogger().WriteAsync(video).Wait();
Progress.Video = video;
@ -63,11 +75,17 @@ namespace Tesses.YouTubeDownloader
{
foreach (var item in ExtensionContext.Extensions)
{
item.VideoStarted(video, resolution, length);
await item.VideoStarted(video, resolution, length);
}
}
VideoStartedEventArgs args=new VideoStartedEventArgs();
args.VideoInfo=video;
args.Resolution=resolution;
args.EstimatedLength=length;
VideoStarted?.Invoke(this,args);
}
private void ReportEndVideo(SavedVideo video, Resolution resolution)
private async Task ReportEndVideo(SavedVideo video, Resolution resolution)
{
Progress.Progress = 100;
Progress.ProgressRaw = 1;
@ -77,10 +95,15 @@ namespace Tesses.YouTubeDownloader
{
foreach (var item in ExtensionContext.Extensions)
{
item.VideoFinished(video, resolution);
await item.VideoFinished(video, resolution);
}
}
VideoFinishedEventArgs args=new VideoFinishedEventArgs();
args.VideoInfo=video;
args.Resolution = resolution;
VideoFinished?.Invoke(this,args);
}
public async Task DownloadNoQueue(SavedVideo info,Resolution resolution=Resolution.Mux,CancellationToken token=default(CancellationToken),IProgress<double> progress=null)
{
@ -399,7 +422,7 @@ namespace Tesses.YouTubeDownloader
return;
}
if(report)
ReportStartVideo(video,Resolution.Mux,0);
await ReportStartVideo(video,Resolution.Mux,0);
string complete = $"Muxed/{video.Id}.mkv";
string incomplete = $"Muxed/{video.Id}incomplete.mkv";
string complete_vidonly = $"VideoOnly/{video.Id}.{streams.VideoOnlyStreamInfo.Container}";
@ -414,7 +437,7 @@ namespace Tesses.YouTubeDownloader
}
}
if(report)
ReportEndVideo(video,Resolution.Mux);
await ReportEndVideo(video,Resolution.Mux);
}
private void DeleteIfExists(string path)
{
@ -447,7 +470,7 @@ namespace Tesses.YouTubeDownloader
return false;
}
if(report)
ReportStartVideo(video, Resolution.VideoOnly,streams.VideoOnlyStreamInfo.Size.Bytes);
await ReportStartVideo(video, Resolution.VideoOnly,streams.VideoOnlyStreamInfo.Size.Bytes);
long len=await GetLengthAsync(incomplete);
using(var dest = await OpenOrCreateAsync(incomplete))
@ -458,7 +481,7 @@ namespace Tesses.YouTubeDownloader
{
RenameFile(incomplete,complete);
if(report)
ReportEndVideo(video, Resolution.VideoOnly);
await ReportEndVideo(video, Resolution.VideoOnly);
}
}
}
@ -543,7 +566,7 @@ namespace Tesses.YouTubeDownloader
return false;
}
if(report)
ReportStartVideo(video, Resolution.AudioOnly,streams.AudioOnlyStreamInfo.Size.Bytes);
await ReportStartVideo(video, Resolution.AudioOnly,streams.AudioOnlyStreamInfo.Size.Bytes);
long len=await GetLengthAsync(incomplete);
using(var dest = await OpenOrCreateAsync(incomplete))
@ -554,7 +577,7 @@ namespace Tesses.YouTubeDownloader
{
RenameFile(incomplete,complete);
if(report)
ReportEndVideo(video, Resolution.AudioOnly);
await ReportEndVideo(video, Resolution.AudioOnly);
}
}
}
@ -591,7 +614,7 @@ namespace Tesses.YouTubeDownloader
return;
}
if(report)
ReportStartVideo(video,Resolution.PreMuxed,streams.MuxedStreamInfo.Size.Bytes);
await ReportStartVideo(video,Resolution.PreMuxed,streams.MuxedStreamInfo.Size.Bytes);
long len=await GetLengthAsync(incomplete);
bool ret;
using(var dest = await OpenOrCreateAsync(incomplete))
@ -603,7 +626,7 @@ namespace Tesses.YouTubeDownloader
{
RenameFile(incomplete,complete);
if(report)
ReportEndVideo(video, Resolution.PreMuxed);
await ReportEndVideo(video, Resolution.PreMuxed);
}
}
}

View File

@ -24,6 +24,36 @@ namespace Tesses.YouTubeDownloader
}
public partial class TYTDStorage
{
internal LoggerProperties Properties {get;set;}
public LoggerProperties GetProperties()
{
CreateDirectoryIfNotExist("config");
CreateDirectoryIfNotExist("config/logs");
if(FileExists("config/tytdprop.json"))
{
string data=ReadAllTextAsync("config/tytdprop.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;
prop.SubscriptionInterval=TimeSpan.FromHours(1);
prop.AlwaysDownloadChannel = false;
return prop;
}
}
public LoggerProperties GetLoggerProperties()
{
if(Properties == null)
{
Properties=GetProperties();
}
return Properties;
}
internal static LockObj o=new LockObj();
private Logger _log=null;
@ -41,6 +71,9 @@ namespace Tesses.YouTubeDownloader
}
public class LoggerProperties
{
public bool AlwaysDownloadChannel {get;set;}
public TimeSpan SubscriptionInterval {get;set;}
public bool UseLogs {get;set;}
public bool PrintVideoIds {get;set;}
@ -58,29 +91,11 @@ namespace Tesses.YouTubeDownloader
private string _filename;
private TYTDStorage _storage;
public LoggerProperties Properties {get;set;}
private LoggerProperties GetProperties(TYTDStorage storage)
internal Logger(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)
{
storage.CreateDirectoryIfNotExist("config");
storage.CreateDirectoryIfNotExist("config/logs");
Properties = GetProperties(storage);
_storage=storage;
string dateTime = DateTime.Now.ToString("yyyyMMdd_hhmmss");
@ -110,11 +125,11 @@ namespace Tesses.YouTubeDownloader
{
if(writeToConsole) WriteStd(message,isError);
if(!log || !Properties.UseLogs) return;
if(!log || !_storage.GetLoggerProperties().UseLogs) return;
// DateTime time = DateTime.Now;
var msg= new StringBuilder();
if(Properties.AddDateInLog)
if(_storage.GetLoggerProperties().AddDateInLog)
{
var dat=DateTime.Now;
msg.AppendLine($"{dat.ToShortDateString()} at {dat.ToShortTimeString()}:");
@ -142,11 +157,11 @@ namespace Tesses.YouTubeDownloader
public async Task WriteAsync(Exception ex)
{
await WriteAsync($"Exception Catched:\n{ex.ToString()}",Properties.PrintErrors,true);
await WriteAsync($"Exception Catched:\n{ex.ToString()}",_storage.GetLoggerProperties().PrintErrors,true);
}
public async Task WriteAsync(SavedVideo video)
{
await WriteAsync($"Download: {video.Title} with Id: {video.Id}",Properties.PrintVideoIds,false,Properties.LogVideoIds);
await WriteAsync($"Download: {video.Title} with Id: {video.Id}",_storage.GetLoggerProperties().PrintVideoIds,false,_storage.GetLoggerProperties().LogVideoIds);
}
}

View File

@ -110,6 +110,7 @@ namespace Tesses.YouTubeDownloader
}
public async Task FillQueue(TYTDStorage storage, List<(SavedVideo video, Resolution resolution)> Queue)
{
string path=$"Playlist/{Id}.json";
List<IVideo> videos=new List<IVideo>();
await foreach(var vid in storage.YoutubeClient.Playlists.GetVideosAsync(Id))
@ -117,6 +118,13 @@ namespace Tesses.YouTubeDownloader
videos.Add(vid);
}
var p=new SavedPlaylist(await storage.YoutubeClient.Playlists.GetAsync(Id),videos);
if(storage.GetLoggerProperties().AlwaysDownloadChannel)
{
var c=ChannelId.Parse(p.AuthorChannelId);
ChannelMediaContext cmc=new ChannelMediaContext(c,Resolution.NoDownload);
await cmc.GetChannel(storage);
}
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(p));
if(Resolution == Resolution.NoDownload) return;
foreach(var item in videos)
@ -146,6 +154,8 @@ namespace Tesses.YouTubeDownloader
{
try{
video = new SavedVideo(await storage.YoutubeClient.Videos.GetAsync(Id));
storage.SendBeforeSaveInfo(video);
await storage.WriteAllTextAsync(path,JsonConvert.SerializeObject(video));
await video.DownloadThumbnails(storage);
}catch(Exception ex)
@ -157,6 +167,13 @@ namespace Tesses.YouTubeDownloader
}else{
video = JsonConvert.DeserializeObject<SavedVideo>(await storage.ReadAllTextAsync(path));
}
if(storage.GetLoggerProperties().AlwaysDownloadChannel)
{
var c=ChannelId.Parse(video.AuthorChannelId);
ChannelMediaContext cmc=new ChannelMediaContext(c,Resolution.NoDownload);
await cmc.GetChannel(storage);
}
if(resolution == Resolution.NoDownload) return;
lock(queue)
{

View File

@ -231,14 +231,14 @@ namespace Tesses.YouTubeDownloader
{
StringBuilder b=new StringBuilder();
b.AppendLine($"Title: {Title}");
b.AppendLine($"💁 {AuthorTitle}");
b.AppendLine($"AuthorTitle: {AuthorTitle}");
DateTime date=UploadDate;
b.AppendLine($"📅 {date.ToShortDateString()}");
b.AppendLine($"Upload Date: {date.ToShortDateString()}");
b.AppendLine($"👍 {Likes}, 👎 {Dislikes}, 👁 {Views}");
b.AppendLine($"🕒 {Duration.ToString()}");
b.AppendLine($"🔑 {string.Join(", ",Keywords)}");
b.AppendLine($"Likes: {Likes}, Dislikes: {Dislikes}, Views: {Views}");
b.AppendLine($"Duration: {Duration.ToString()}");
b.AppendLine($"Tags: {string.Join(", ",Keywords)}");
b.AppendLine("Description:");
b.AppendLine(Description);
return b.ToString();

View File

@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml;
using Newtonsoft.Json;
using YoutubeExplode.Channels;
using YoutubeExplode.Videos;
namespace Tesses.YouTubeDownloader
{
public class BellEventArgs : EventArgs
{
public VideoId Id {get;set;}
}
public class VideoProgressEventArgs : EventArgs
{
public SavedVideo VideoInfo {get;set;}
public double Progress {get;set;}
}
public class BeforeSaveInfoEventArgs : EventArgs
{
public SavedVideo VideoInfo {get;set;}
}
public class VideoStartedEventArgs : EventArgs
{
public SavedVideo VideoInfo {get;set;}
public Resolution Resolution {get;set;}
public long EstimatedLength {get;set;}
}
public class VideoFinishedEventArgs : EventArgs
{
public SavedVideo VideoInfo {get;set;}
public Resolution Resolution {get;set;}
}
public abstract partial class TYTDStorage
{
///<summary>
///For Notifications Like Bell on YouTube
///</summary>
public event EventHandler<BellEventArgs> Bell;
public event EventHandler<VideoStartedEventArgs> VideoStarted;
public event EventHandler<BeforeSaveInfoEventArgs> BeforeSaveInfo;
public event EventHandler<VideoProgressEventArgs> VideoProgress;
public event EventHandler<VideoFinishedEventArgs> VideoFinished;
internal void SendBeforeSaveInfo(SavedVideo video)
{
BeforeSaveInfo?.Invoke(this,new BeforeSaveInfoEventArgs() {VideoInfo=video});
}
internal void SendBell(VideoId i)
{
Bell?.Invoke(this,new BellEventArgs() {Id=i});
}
public DateTime LastSubscriptionTime = DateTime.MinValue;
public async Task HandleSubscriptions()
{
var date=DateTime.Now;
var interval=GetLoggerProperties().SubscriptionInterval;
if(date - interval < LastSubscriptionTime)
{
return;
}
foreach(var sub in Subscriptions)
{
await sub.LookOnYouTube();
}
LastSubscriptionTime=date;
}
public async IAsyncEnumerable<Subscription> GetSubscriptionsAsync()
{
await foreach(var item in EnumerateFilesAsync("Subscriptions"))
{
if(Path.GetExtension(item).Equals(".json"))
{
var sub=JsonConvert.DeserializeObject<Subscription>(item);
sub.Base=this;
yield return await Task.FromResult(sub);
}
}
}
/// <summary>
/// Subscribe to creator
/// </summary>
public async Task Subscribe(ChannelId id, bool downloadChannelInfo=false,ChannelBellInfo bellInfo = ChannelBellInfo.NotifyAndDownload)
{
if(downloadChannelInfo)
{
ChannelMediaContext context=new ChannelMediaContext(id,Resolution.NoDownload);
var c=await context.GetChannel(this);
}
Subscription sub=new Subscription();
sub.BellInfo = bellInfo;
sub.Base=this;
sub.Id=id.Value;
Subscriptions.Add(sub);
await SaveSubscription(sub);
}
public async Task SaveSubscription(Subscription sub)
{
await WriteAllTextAsync($"Subscriptions/{sub.Id}",JsonConvert.SerializeObject(sub));
}
public async Task Subscribe(UserName name,ChannelBellInfo bellInfo=ChannelBellInfo.NotifyAndDownload)
{
ChannelMediaContext context=new ChannelMediaContext(name,Resolution.NoDownload);
var c=await context.GetChannel(this);
await Subscribe(ChannelId.Parse(c.Id),false,bellInfo);
}
public void Unsubscribe(ChannelId id)
{
Subscription sub= Subscriptions.FirstOrDefault(e=>e.Id==id.Value);
if(sub != null)
{
Subscriptions.Remove(sub);
}
DeleteFile($"Subscriptions/{sub.Id}.json");
}
public Subscription GetSubscription(ChannelId id)
{
return Subscriptions.FirstOrDefault(e=>e.Id==id.Value);
}
}
[Flags]
public enum ChannelBellInfo
{
DoNothing=0,
GetInfo=1,
Notify=2,
Download=3,
NotifyAndDownload=Notify|Download
}
public class Subscription
{
[Newtonsoft.Json.JsonIgnore]
public TYTDStorage Base {get;set;}
[Newtonsoft.Json.JsonIgnore]
public DateTime LastCheckTime = DateTime.Now;
public string Id {get;set;}
public ChannelBellInfo BellInfo {get;set;}
public async Task<SavedChannel> GetChannelInfo()
{
if(await Base.FileExistsAsync($"Channel/{Id}.json"))
{
return await Base.GetChannelInfoAsync(Id);
}
return null;
}
public async Task LookOnYouTube()
{
try{
List<(string Id,DateTime Time)> items=new List<(string Id, DateTime Time)>();
XmlDocument doc=new XmlDocument();
doc.LoadXml(await Base.HttpClient.GetStringAsync($"https://www.youtube.com/feeds/videos.xml?channel_id={Id}"));
foreach(XmlNode item in doc.GetElementsByTagName("entry"))
{
string Id="";
DateTime Time=LastCheckTime-TimeSpan.FromMinutes(1);
foreach(XmlNode item2 in item.ChildNodes)
{
if(item2.Name == "yt:videoId")
{
if(BellInfo.HasFlag(ChannelBellInfo.Download))
{
await Base.AddVideoAsync(item2.InnerText);
}
Id=item2.InnerText;
}
if(item2.Name == "published")
{
Time = DateTime.Parse(item2.InnerText);
}
}
items.Add((Id,Time));
}
if(BellInfo.HasFlag(ChannelBellInfo.Notify) )
{
foreach(var item in items)
{
if(item.Time > LastCheckTime)
{
Base.SendBell(item.Id);
}
}
}
LastCheckTime=DateTime.Now;
}catch(Exception ex)
{
await Base.GetLogger().WriteAsync(ex);
}
}
}
}

View File

@ -115,6 +115,7 @@ namespace Tesses.YouTubeDownloader
}
public void CreateDirectories()
{
CreateDirectoryIfNotExist("Subscriptions");
CreateDirectoryIfNotExist("VideoOnly");
CreateDirectoryIfNotExist("AudioOnly");
CreateDirectoryIfNotExist("Muxed");

View File

@ -270,4 +270,4 @@ namespace Tesses.YouTubeDownloader
Directory.Delete(GetPath(dir),recursive);
}
}
}
}

View File

@ -7,9 +7,9 @@
<PackageId>Tesses.YouTubeDownloader</PackageId>
<Author>Mike Nolan</Author>
<Company>Tesses</Company>
<Version>1.0.2.4</Version>
<AssemblyVersion>1.0.2.4</AssemblyVersion>
<FileVersion>1.0.2.4</FileVersion>
<Version>1.0.3.0</Version>
<AssemblyVersion>1.0.3.0</AssemblyVersion>
<FileVersion>1.0.3.0</FileVersion>
<Description>A YouTube Downloader</Description>
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>

View File

@ -32,13 +32,26 @@ namespace Tesses.YouTubeDownloader
{
return Progress;
}
List<Subscription> Subscriptions {get;set;}
List<(SavedVideo Video, Resolution Resolution)> QueueList = new List<(SavedVideo Video, Resolution Resolution)>();
List<IMediaContext> Temporary =new List<IMediaContext>();
private async Task QueueLoop(CancellationToken token)
{
try{
Subscriptions=new List<Subscription>();
await foreach(var sub in GetSubscriptionsAsync())
{
Subscriptions.Add(sub);
}
}catch(Exception ex)
{
await GetLogger().WriteAsync(ex);
}
while(!token.IsCancellationRequested)
{ try{
IMediaContext context;
lock(Temporary)
{