From 50749ee9d6438e7f49d38cbaabf7b306a12cb041 Mon Sep 17 00:00:00 2001 From: Matty Jorgensen Date: Sun, 13 Aug 2023 14:51:55 -0500 Subject: [PATCH] Implement account ignore list Fixes #99 --- src/BookmarkSync.CLI/appsettings.Example.json | 3 +- .../Configuration/ConfigManager.cs | 7 +++ src/BookmarkSync.Core/Entities/Config/App.cs | 1 + .../Extensions/ListExtensions.cs | 15 ++++++ .../Extensions/StringExtensions.cs | 4 ++ .../Bookmarking/BookmarkSyncService.cs | 11 ++++- .../BookmarkSync.Core.Tests.csproj | 1 + .../Configuration/ConfigManagerTests.cs | 47 ++++++++++++++++--- .../Entities/Config/AppTests.cs | 3 +- .../Extensions/StringExtensionsTests.cs | 22 +++++++++ 10 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 src/BookmarkSync.Core/Extensions/ListExtensions.cs diff --git a/src/BookmarkSync.CLI/appsettings.Example.json b/src/BookmarkSync.CLI/appsettings.Example.json index 2e92091..2c7edbb 100644 --- a/src/BookmarkSync.CLI/appsettings.Example.json +++ b/src/BookmarkSync.CLI/appsettings.Example.json @@ -11,6 +11,7 @@ "Service": "LinkAce", "ApiToken": "", "LinkAceUri": "" - } + }, + "IgnoredAccounts": [] } } \ No newline at end of file diff --git a/src/BookmarkSync.Core/Configuration/ConfigManager.cs b/src/BookmarkSync.Core/Configuration/ConfigManager.cs index 68f2f40..5242e64 100644 --- a/src/BookmarkSync.Core/Configuration/ConfigManager.cs +++ b/src/BookmarkSync.Core/Configuration/ConfigManager.cs @@ -1,5 +1,6 @@ using System.Configuration; using BookmarkSync.Core.Entities.Config; +using BookmarkSync.Core.Extensions; using Microsoft.Extensions.Configuration; namespace BookmarkSync.Core.Configuration; @@ -21,6 +22,8 @@ public ConfigManager( App = Configuration.GetSection("App").Get() ?? throw new InvalidOperationException(); Instances = Configuration.GetSection("Instances").Get>(); + if (App.IgnoredAccounts is not null) CleanUpIgnoredAccounts(); + if (!App.IsValid()) { _logger.Error("App configuration is invalid"); @@ -46,4 +49,8 @@ public void SaveToFile() Console.WriteLine(Directory.GetCurrentDirectory()); throw new NotImplementedException(); } + private void CleanUpIgnoredAccounts() + { + App.IgnoredAccounts = (from account in App.IgnoredAccounts select account.RemoveLeadingAt()).ToList(); + } } diff --git a/src/BookmarkSync.Core/Entities/Config/App.cs b/src/BookmarkSync.Core/Entities/Config/App.cs index f9320e8..5fbea70 100644 --- a/src/BookmarkSync.Core/Entities/Config/App.cs +++ b/src/BookmarkSync.Core/Entities/Config/App.cs @@ -3,5 +3,6 @@ namespace BookmarkSync.Core.Entities.Config; public class App : ConfigurationBase { [ConfigRequired] public Bookmarking Bookmarking { get; set; } = null!; + public List? IgnoredAccounts { get; set; } public DateTime LastSynced { get; set; } } diff --git a/src/BookmarkSync.Core/Extensions/ListExtensions.cs b/src/BookmarkSync.Core/Extensions/ListExtensions.cs new file mode 100644 index 0000000..6868347 --- /dev/null +++ b/src/BookmarkSync.Core/Extensions/ListExtensions.cs @@ -0,0 +1,15 @@ +using BookmarkSync.Core.Entities; + +namespace BookmarkSync.Core.Extensions; + +public static class ListExtensions +{ + public static List? RemoveAllFromIgnoredAccounts( + this List? bookmarks, + List ignoredAccounts) + { + if (bookmarks is null) return bookmarks; + bookmarks.RemoveAll(b => ignoredAccounts.Contains(b.Account.Name)); + return bookmarks; + } +} diff --git a/src/BookmarkSync.Core/Extensions/StringExtensions.cs b/src/BookmarkSync.Core/Extensions/StringExtensions.cs index bd42767..da6d7c0 100644 --- a/src/BookmarkSync.Core/Extensions/StringExtensions.cs +++ b/src/BookmarkSync.Core/Extensions/StringExtensions.cs @@ -2,6 +2,10 @@ namespace BookmarkSync.Core.Extensions; public static class StringExtensions { + public static bool HasLeadingAt(this string str) + => str.StartsWith("@"); + public static string RemoveLeadingAt(this string str) + => str.HasLeadingAt() ? str[1..] : str; public static string ToSnakeCase(this string str) => string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())).ToLower(); } diff --git a/src/BookmarkSync.Infrastructure/Services/Bookmarking/BookmarkSyncService.cs b/src/BookmarkSync.Infrastructure/Services/Bookmarking/BookmarkSyncService.cs index 9cbad27..055809b 100644 --- a/src/BookmarkSync.Infrastructure/Services/Bookmarking/BookmarkSyncService.cs +++ b/src/BookmarkSync.Infrastructure/Services/Bookmarking/BookmarkSyncService.cs @@ -1,4 +1,5 @@ using BookmarkSync.Core.Entities.Config; +using BookmarkSync.Core.Extensions; using BookmarkSync.Infrastructure.Services.Mastodon; using Microsoft.Extensions.Hosting; @@ -9,14 +10,16 @@ public class BookmarkSyncService : IHostedService private static readonly ILogger _logger = Log.ForContext(); private readonly IBookmarkingService _bookmarkingService; private readonly IHostApplicationLifetime _host; + private readonly List _ignoredAccounts; private readonly List? _instances; public BookmarkSyncService(IHostApplicationLifetime host, IConfigManager configManager) { _bookmarkingService = BookmarkingService.GetBookmarkingService(configManager); _host = host; _instances = configManager.Instances; + _ignoredAccounts = configManager.App.IgnoredAccounts; } - /// + /// public async Task StartAsync(CancellationToken stoppingToken) { if (_instances == null || _instances.Count == 0) @@ -47,6 +50,10 @@ public async Task StartAsync(CancellationToken stoppingToken) _logger.Information("No bookmarks received"); continue; } + + // Remove any bookmarks from accounts in the IgnoredAccounts list + bookmarks.RemoveAllFromIgnoredAccounts(_ignoredAccounts); + foreach (var bookmark in bookmarks) { // Save bookmarks to bookmarking service @@ -72,6 +79,6 @@ public async Task StartAsync(CancellationToken stoppingToken) // Finish task _host.StopApplication(); } - /// + /// public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } diff --git a/tests/BookmarkSync.Core.Tests/BookmarkSync.Core.Tests.csproj b/tests/BookmarkSync.Core.Tests/BookmarkSync.Core.Tests.csproj index 5c2c442..c4f405f 100644 --- a/tests/BookmarkSync.Core.Tests/BookmarkSync.Core.Tests.csproj +++ b/tests/BookmarkSync.Core.Tests/BookmarkSync.Core.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/tests/BookmarkSync.Core.Tests/Configuration/ConfigManagerTests.cs b/tests/BookmarkSync.Core.Tests/Configuration/ConfigManagerTests.cs index 3254cc8..4f93bc3 100644 --- a/tests/BookmarkSync.Core.Tests/Configuration/ConfigManagerTests.cs +++ b/tests/BookmarkSync.Core.Tests/Configuration/ConfigManagerTests.cs @@ -1,5 +1,7 @@ using System.Configuration; +using System.Text; using BookmarkSync.Core.Configuration; +using BookmarkSync.Core.Extensions; using Microsoft.Extensions.Configuration; namespace BookmarkSync.Core.Tests.Configuration; @@ -38,6 +40,18 @@ public void ConfigManager_HasProperties() Assert.IsTrue(_configManager?.HasMethod("GetConfigValue")); } [TestMethod] + [ExpectedException(typeof(ConfigurationErrorsException))] + public void GetConfigValue_InvalidKey() + { + // Arrange + var expected = "Pinner"; + + // Act + string? actual = _configManager?.GetConfigValue("Apps:Bookmarking:Service"); + + // Assert - Exception + } + [TestMethod] public void GetConfigValue_Success() { // Arrange @@ -50,15 +64,34 @@ public void GetConfigValue_Success() Assert.AreEqual(expected, actual); } [TestMethod] - [ExpectedException(typeof(ConfigurationErrorsException))] - public void GetConfigValue_InvalidKey() + public void TestConfigManagerWithIgnoredAccountsConfigured() { - // Arrange - var expected = "Pinner"; + var jsonString = @" +{ + ""App"": { + ""Bookmarking"": { + ""Service"": ""LinkAce"" + }, + ""IgnoredAccounts"": [ + ""@prplecake@social.example.com"", + ""flipper@social.example.com"" + ], + }, + ""Instances"": [ + ""https://compostintraining.club"" + ] +}"; + var config = new ConfigurationBuilder() + .AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonString))) + .Build(); - // Act - string? actual = _configManager?.GetConfigValue("Apps:Bookmarking:Service"); + var configManager = new ConfigManager(config); - // Assert - Exception + // Assert + Assert.IsNotNull(configManager.App.IgnoredAccounts); + foreach (string? account in configManager.App.IgnoredAccounts) + { + Assert.IsFalse(account.HasLeadingAt()); + } } } diff --git a/tests/BookmarkSync.Core.Tests/Entities/Config/AppTests.cs b/tests/BookmarkSync.Core.Tests/Entities/Config/AppTests.cs index b33c378..2b38080 100644 --- a/tests/BookmarkSync.Core.Tests/Entities/Config/AppTests.cs +++ b/tests/BookmarkSync.Core.Tests/Entities/Config/AppTests.cs @@ -10,8 +10,9 @@ public void App_HasProperties() App obj = new(); // Assert - Assert.AreEqual(2, obj.PropertyCount()); + Assert.AreEqual(3, obj.PropertyCount()); Assert.IsTrue(obj.HasProperty("Bookmarking")); + Assert.IsTrue(obj.HasProperty("IgnoredAccounts")); Assert.IsTrue(obj.HasProperty("LastSynced")); Assert.IsTrue(obj.HasMethod("IsValid")); diff --git a/tests/BookmarkSync.Core.Tests/Extensions/StringExtensionsTests.cs b/tests/BookmarkSync.Core.Tests/Extensions/StringExtensionsTests.cs index 67a16c3..a82b6fa 100644 --- a/tests/BookmarkSync.Core.Tests/Extensions/StringExtensionsTests.cs +++ b/tests/BookmarkSync.Core.Tests/Extensions/StringExtensionsTests.cs @@ -5,6 +5,28 @@ namespace BookmarkSync.Core.Tests.Extensions; [TestClass] public class StringExtensionsTests { + [DataTestMethod] + [DataRow("@prplecake", true)] + [DataRow("flipper", false)] + public void HasLeadingAt_Success(string input, bool expected) + { + // Act + bool actual = input.HasLeadingAt(); + + // Assert + Assert.AreEqual(expected, actual); + } + [DataTestMethod] + [DataRow("@prplecake@compostintraining.club", "prplecake@compostintraining.club")] + [DataRow("flipper@compostintraining.club", "flipper@compostintraining.club")] + public void RemoveLeadingAt_Success(string input, string expected) + { + // Act + string actual = input.RemoveLeadingAt(); + + // Assert + Assert.AreEqual(expected, actual); + } [DataTestMethod] [DataRow("Example", "example")] [DataRow("TestCase", "test_case")]