using Newtonsoft.Json; using System.Linq; using System.Diagnostics; namespace ttrss_co_client { class Program { static async Task Main(string[] args) { var conf = Configure(); var ttrssClient = new ttrss.ApiClient(conf.BaseURI); await ttrssClient.Login(conf.Username, conf.Password); var loggedin = await ttrssClient.IsLoggedIn(); Console.WriteLine($"logged in: {loggedin}"); var doneLabelCaption = conf.CopilotDoneCaption.ToLower(); var miscTasks = new List(); var unreadFeeds = await ttrssClient.GetFeeds(cat_id: -3, unread_only: true); foreach (var uf in unreadFeeds) { var actionForFeed = conf.feedActions.FirstOrDefault(fa => fa.feedurl == uf.feed_url.ToString()); if (actionForFeed != null) { var headlines = await ttrssClient.GetHeadlines(uf.id, view_mode: ttrss.ApiClient.VIEWMODE.Unread); foreach (var hl in headlines) { var doneLabel = (await ttrssClient.GetLabels(hl.id)).First(l => l.caption?.ToLower() == doneLabelCaption); if (!doneLabel.@checked) { var noteString = hl.note; if (!string.IsNullOrWhiteSpace(noteString)) { noteString += $"{hl.note}\n"; } switch (actionForFeed.command) { case "dl": var tr = await standardDL(hl.link.ToString()); miscTasks.Add(ttrssClient.UpdateArticleNote($"[{DateTime.Now.ToLongTimeString()}] - {tr.Item2}", hl.id)); if (tr.Item1 == true) { miscTasks.Add(ttrssClient.SetArticleLabel(doneLabel.id, true, hl.id)); } break; default: noteString += $"[{DateTime.Now.ToLongTimeString()}] - feed configured but action not recognized"; miscTasks.Add(ttrssClient.SetArticleLabel(doneLabel.id, true, hl.id)); break; } miscTasks.Add(ttrssClient.UpdateArticleNote(noteString, hl.id)); } } } } miscTasks.Add(ttrssClient.Logout()); Console.WriteLine($"awaiting remaining tasks"); Task.WaitAll(miscTasks.ToArray()); Console.WriteLine($"done"); } static Configuration Configure(string configurationPath = "appsettings.json") { if (!File.Exists(configurationPath)) { Console.Error.WriteLine($"could not find configuration at {configurationPath}! copying sample to that spot."); File.Copy("sample-appsettings.json", configurationPath); //and you know what, if that explodes at the OS level, the OS should give you an error return null; } var fileContents = File.ReadAllText(configurationPath); if (string.IsNullOrWhiteSpace(fileContents)) { Console.Error.WriteLine($"configuration file at {configurationPath} was empty! overwriting with sample settings."); File.Copy("sample-appsettings.json", configurationPath, true); return null; } var conf = JsonConvert.DeserializeObject(fileContents); if (conf == null) { Console.Error.WriteLine($"configuration file at {configurationPath} was empty! overwriting with sample settings."); File.Copy("sample-appsettings.json", configurationPath, true); return null; } return conf; } private static async Task> standardDL(string articleLink) { var ytdl = new YoutubeDLSharp.YoutubeDL(); ytdl.YoutubeDLPath = "yt-dlp"; ytdl.FFmpegPath = "ffmpeg"; ytdl.OutputFolder = "./tmp/"; ytdl.OutputFileTemplate = "%(upload_date)s - %(title)s - [%(id)s].mp4"; var sw = new Stopwatch(); // var data = await ytdl.RunVideoDataFetch(articleLink); // if (data.Data.ReleaseDate != null && data.Data.ReleaseDate > DateTime.Now) // { // return new Tuple(false, $"release date in future? {data.Data.ReleaseDate}"); // } sw.Start(); var res = await ytdl.RunVideoDownload(articleLink); sw.Stop(); var outputStr = $"{(res.Success ? "Success" : "fail")} in {sw.Elapsed}"; if(res.ErrorOutput != null && res.ErrorOutput.Length > 0) { outputStr += "\n" + string.Join('\n', res.ErrorOutput); } return new Tuple(res.Success, outputStr); } } }