using System; using System.Collections.Generic; using System.Threading.Tasks; using YoutubeExplode.Channels; using YoutubeExplode.Playlists; using YoutubeExplode.Videos; using MailKit.Net.Smtp; using MimeKit; using MailKit; using MailKit.Net.Imap; using System.IO; using System.Threading; namespace Tesses.YouTubeDownloader.MailKit { public sealed class SMTPDownloader : IDownloader { string fromEmail; string toEmail; Func> new_client; public SMTPDownloader(Func> client,string fromEmail,string toEmail) { this.new_client = client; this.fromEmail=fromEmail; this.toEmail=toEmail; } public SMTPDownloader(string smtpServer,string fromEmail,string toEmail,string username,string password,int port=587,global::MailKit.Security.SecureSocketOptions options=global::MailKit.Security.SecureSocketOptions.StartTls) { this.new_client = async ()=>{ var clt= new SmtpClient(); await clt.ConnectAsync(smtpServer,port,options); await clt.AuthenticateAsync(username,password); return clt; }; this.fromEmail=fromEmail; this.toEmail = toEmail; } public event EventHandler VideoStarted; public event EventHandler VideoProgress; public event EventHandler VideoFinished; public event EventHandler Error; public event EventHandler Bell; private async Task AddItemToAsync(string url) { using(var clt = await new_client()) { var messageToSend = new MimeMessage(); messageToSend.From.Add(MailboxAddress.Parse(fromEmail)); messageToSend.To.Add(MailboxAddress.Parse(toEmail)); messageToSend.Body = new TextPart(MimeKit.Text.TextFormat.Plain){Text=url}; messageToSend.Subject="Sent By Tesses.YouTubeDownloader.MailKit"; await clt.SendAsync(messageToSend); await clt.DisconnectAsync(true); } } public async Task AddChannelAsync(ChannelId id, Resolution resolution = Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/channel/{id.Value}"); } public async Task AddFileAsync(string url, bool download = true) { await Task.CompletedTask; } public async Task AddPlaylistAsync(PlaylistId id, Resolution resolution = Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/playlist?list={id.Value}"); } public async Task AddToPersonalPlaylistAsync(string name, IEnumerable items) { await Task.CompletedTask; } public async Task AddUserAsync(UserName userName, Resolution resolution = Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/user/{userName.Value}"); } public async Task AddVideoAsync(VideoId id, Resolution resolution = Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/watch?v={id.Value}"); } public async Task AddSlugAsync(ChannelSlug slug,Resolution resolution=Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/c/{slug.Value}"); } public async Task AddHandleAsync(ChannelHandle handle,Resolution resolution =Resolution.PreMuxed) { await AddItemToAsync($"https://www.youtube.com/@{handle.Value}"); } public void CancelDownload(bool restart = false) { } public void DeletePersonalPlaylist(string name) { } public ExtraData GetExtraData() { return new ExtraData(); } public async IAsyncEnumerable GetPersonalPlaylistContentsAsync(string name) { await Task.CompletedTask; yield break; } public SavedVideoProgress GetProgress() { return new SavedVideoProgress(); } public IReadOnlyList<(SavedVideo Video, Resolution Resolution)> GetQueueList() { return new List<(SavedVideo Video,Resolution Resolution)>(); } public async IAsyncEnumerable GetSubscriptionsAsync() { await Task.CompletedTask; yield break; } public bool PersonalPlaylistExists(string name) { return false; } public async Task RemoveItemFromPersonalPlaylistAsync(string name, VideoId id) { await Task.CompletedTask; } public async Task ReplacePersonalPlaylistAsync(string name, IEnumerable items) { await Task.CompletedTask; } public async Task ResubscribeAsync(ChannelId id, ChannelBellInfo info = ChannelBellInfo.NotifyAndDownload) { await Task.CompletedTask; } public async Task SetResolutionForItemInPersonalPlaylistAsync(string name, VideoId id, Resolution resolution) { await Task.CompletedTask; } public async Task SubscribeAsync(ChannelId id, ChannelBellInfo bellInfo = ChannelBellInfo.NotifyAndDownload) { await Task.CompletedTask; } public async Task SubscribeAsync(UserName name, ChannelBellInfo info = ChannelBellInfo.NotifyAndDownload) { await Task.CompletedTask; } public async Task UnsubscribeAsync(ChannelId id) { await Task.CompletedTask; } } public sealed class IMAPDownloader { IDownloader downloader; string imapServer; int imapPort; bool ssl; string username; string password; string[] folders; public IMAPDownloader(IDownloader downloader,string imapServer,int imapPort,bool ssl,string username,string password,params string[] folders) { this.downloader=downloader; this.imapServer =imapServer; this.imapPort = imapPort; this.ssl = ssl; this.username = username; this.password = password; this.folders = folders; } public void Scan() { using (var client = new ImapClient()) { client.Connect(imapServer, imapPort,ssl); client.Authenticate(username,password); foreach (var folder_name in folders) { var folder = client.GetFolder(folder_name); folder.Open(FolderAccess.ReadOnly); foreach(var item in folder) { using (var ms = new MemoryStream()) { item.Body.WriteTo(ms); ms.Position = 0; using (var sr = new StreamReader(ms)) { string line; while((line=sr.ReadLine()) != null) { try { Task.Run(async () => await downloader.AddItemAsync(line)).Wait(); } catch(Exception ex) { _ = ex; } } } } } } client.Disconnect(true); } } public async Task ScanAsync(CancellationToken token=default) { using (var client = new ImapClient()) { await client.ConnectAsync(imapServer, imapPort,ssl,token); await client.AuthenticateAsync(username,password,token); foreach (var folder_name in folders) { if(token.IsCancellationRequested) break; var folder = await client.GetFolderAsync(folder_name,token); await folder.OpenAsync(FolderAccess.ReadOnly,token); foreach(var item in folder) { if(token.IsCancellationRequested) break; using (var ms = new MemoryStream()) { item.Body.WriteTo(ms); ms.Position = 0; using (var sr = new StreamReader(ms)) { string line; while((line=await sr.ReadLineAsync()) != null) { if(token.IsCancellationRequested) break; try { await downloader.AddItemAsync(line); } catch(Exception ex) { _ = ex; } } } } } } await client.DisconnectAsync(true,token); } } public void ScanLoop(TimeSpan interval,CancellationToken token=default) { Thread t = new Thread(async()=>{ try{ while(!token.IsCancellationRequested) { await ScanAsync(token); await Task.Delay(interval.Milliseconds,token); } }catch(Exception ex) { _=ex; } }); t.Start(); } } }