diff --git a/Tesses.YouTubeDownloader.Net6/Program.cs b/Tesses.YouTubeDownloader.Net6/Program.cs index 02daa25..2ed7555 100644 --- a/Tesses.YouTubeDownloader.Net6/Program.cs +++ b/Tesses.YouTubeDownloader.Net6/Program.cs @@ -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"); diff --git a/Tesses.YouTubeDownloader.Server/Class1.cs b/Tesses.YouTubeDownloader.Server/Class1.cs index a9f6448..119f931 100644 --- a/Tesses.YouTubeDownloader.Server/Class1.cs +++ b/Tesses.YouTubeDownloader.Server/Class1.cs @@ -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(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( + $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\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(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( + $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\n" + ); + } + public async Task QueueList(ServerContext ctx) { await ctx.SendJsonAsync(Downloader.GetQueueList()); @@ -362,7 +450,7 @@ namespace Tesses.YouTubeDownloader.Server } } await ctx.SendTextAsync( - $"

You Will Be Redirected in 5 Sec

\n" + $"You Will Be Redirected in 5 Sec

You Will Be Redirected in 5 Sec

\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; diff --git a/Tesses.YouTubeDownloader.Server/Tesses.YouTubeDownloader.Server.csproj b/Tesses.YouTubeDownloader.Server/Tesses.YouTubeDownloader.Server.csproj index 5e85ca5..9553270 100644 --- a/Tesses.YouTubeDownloader.Server/Tesses.YouTubeDownloader.Server.csproj +++ b/Tesses.YouTubeDownloader.Server/Tesses.YouTubeDownloader.Server.csproj @@ -15,9 +15,9 @@ Tesses.YouTubeDownloader.Server Mike Nolan Tesses - 1.0.1.0 - 1.0.1.0 - 1.0.1.0 + 1.0.2.0 + 1.0.2.0 + 1.0.2.0 Adds WebServer to TYTD LGPL-3.0-only true diff --git a/Tesses.YouTubeDownloader/DownloadLoop.cs b/Tesses.YouTubeDownloader/DownloadLoop.cs index d18e442..ad73e72 100644 --- a/Tesses.YouTubeDownloader/DownloadLoop.cs +++ b/Tesses.YouTubeDownloader/DownloadLoop.cs @@ -27,7 +27,11 @@ namespace Tesses.YouTubeDownloader var (Video, Resolution) = Dequeue(out hasAny); if (hasAny) { - await DownloadVideoAsync(Video, Resolution, token,new Progress(ReportProgress),true); + await DownloadVideoAsync(Video, Resolution, token,new Progress( + 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 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); } } } diff --git a/Tesses.YouTubeDownloader/Logging.cs b/Tesses.YouTubeDownloader/Logging.cs index 321e674..21dae9a 100644 --- a/Tesses.YouTubeDownloader/Logging.cs +++ b/Tesses.YouTubeDownloader/Logging.cs @@ -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(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(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); } } diff --git a/Tesses.YouTubeDownloader/PreMediaContext.cs b/Tesses.YouTubeDownloader/PreMediaContext.cs index 1d7ae2f..40cf4bc 100644 --- a/Tesses.YouTubeDownloader/PreMediaContext.cs +++ b/Tesses.YouTubeDownloader/PreMediaContext.cs @@ -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 videos=new List(); 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(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) { diff --git a/Tesses.YouTubeDownloader/SavedVideo.cs b/Tesses.YouTubeDownloader/SavedVideo.cs index c0b4fd8..0d9947b 100644 --- a/Tesses.YouTubeDownloader/SavedVideo.cs +++ b/Tesses.YouTubeDownloader/SavedVideo.cs @@ -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(); diff --git a/Tesses.YouTubeDownloader/SubscribedTo.cs b/Tesses.YouTubeDownloader/SubscribedTo.cs new file mode 100644 index 0000000..f8a6f6f --- /dev/null +++ b/Tesses.YouTubeDownloader/SubscribedTo.cs @@ -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 + { + /// + ///For Notifications Like Bell on YouTube + /// + + public event EventHandler Bell; + public event EventHandler VideoStarted; + + public event EventHandler BeforeSaveInfo; + + public event EventHandler VideoProgress; + + public event EventHandler 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 GetSubscriptionsAsync() + { + + await foreach(var item in EnumerateFilesAsync("Subscriptions")) + { + if(Path.GetExtension(item).Equals(".json")) + { + var sub=JsonConvert.DeserializeObject(item); + sub.Base=this; + yield return await Task.FromResult(sub); + } + } + } + /// + /// Subscribe to creator + /// + 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 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); + } + } + } +} \ No newline at end of file diff --git a/Tesses.YouTubeDownloader/TYTD.cs b/Tesses.YouTubeDownloader/TYTD.cs index 84b0289..ce4c9d2 100644 --- a/Tesses.YouTubeDownloader/TYTD.cs +++ b/Tesses.YouTubeDownloader/TYTD.cs @@ -115,6 +115,7 @@ namespace Tesses.YouTubeDownloader } public void CreateDirectories() { + CreateDirectoryIfNotExist("Subscriptions"); CreateDirectoryIfNotExist("VideoOnly"); CreateDirectoryIfNotExist("AudioOnly"); CreateDirectoryIfNotExist("Muxed"); diff --git a/Tesses.YouTubeDownloader/TYTDFilesystem.cs b/Tesses.YouTubeDownloader/TYTDFilesystem.cs index edb1c39..7829a3d 100644 --- a/Tesses.YouTubeDownloader/TYTDFilesystem.cs +++ b/Tesses.YouTubeDownloader/TYTDFilesystem.cs @@ -270,4 +270,4 @@ namespace Tesses.YouTubeDownloader Directory.Delete(GetPath(dir),recursive); } } -} \ No newline at end of file +} diff --git a/Tesses.YouTubeDownloader/Tesses.YouTubeDownloader.csproj b/Tesses.YouTubeDownloader/Tesses.YouTubeDownloader.csproj index a0c4203..877afac 100644 --- a/Tesses.YouTubeDownloader/Tesses.YouTubeDownloader.csproj +++ b/Tesses.YouTubeDownloader/Tesses.YouTubeDownloader.csproj @@ -7,9 +7,9 @@ Tesses.YouTubeDownloader Mike Nolan Tesses - 1.0.2.4 - 1.0.2.4 - 1.0.2.4 + 1.0.3.0 + 1.0.3.0 + 1.0.3.0 A YouTube Downloader LGPL-3.0-only true diff --git a/Tesses.YouTubeDownloader/VideoQueue.cs b/Tesses.YouTubeDownloader/VideoQueue.cs index 40634fd..a3a77e0 100644 --- a/Tesses.YouTubeDownloader/VideoQueue.cs +++ b/Tesses.YouTubeDownloader/VideoQueue.cs @@ -32,13 +32,26 @@ namespace Tesses.YouTubeDownloader { return Progress; } + List Subscriptions {get;set;} List<(SavedVideo Video, Resolution Resolution)> QueueList = new List<(SavedVideo Video, Resolution Resolution)>(); List Temporary =new List(); private async Task QueueLoop(CancellationToken token) { - + + try{ + + Subscriptions=new List(); + await foreach(var sub in GetSubscriptionsAsync()) + { + Subscriptions.Add(sub); + } + }catch(Exception ex) + { + await GetLogger().WriteAsync(ex); + } while(!token.IsCancellationRequested) { try{ + IMediaContext context; lock(Temporary) {