diff --git a/src/Domain/Core/Abstraction/ILinkdingService.cs b/src/Domain/Core/Abstraction/ILinkdingService.cs index c3fc637..1c653a5 100644 --- a/src/Domain/Core/Abstraction/ILinkdingService.cs +++ b/src/Domain/Core/Abstraction/ILinkdingService.cs @@ -8,6 +8,10 @@ namespace Linkding.Client { Task> GetBookmarksAsync(int limit = 100, int offset = 0); Task> GetAllBookmarksAsync(); + Task AddBookmarkCollectionAsync(IEnumerable bookmarks); + Task AddBookmarkCollectionAsync(IEnumerable bookmarks); + Task AddBookmarkAsync(BookmarkCreatePayload bookmark); + Task UpdateBookmarkCollectionAsync(IEnumerable bookmarks); Task UpdateBookmarkCollectionAsync(IEnumerable bookmarks); Task UpdateBookmarkAsync(BookmarkUpdatePayload bookmark); diff --git a/src/Domain/Core/Handler/ILinkdingSyncTaskHandler.cs b/src/Domain/Core/Handler/ILinkdingSyncTaskHandler.cs new file mode 100644 index 0000000..447fde5 --- /dev/null +++ b/src/Domain/Core/Handler/ILinkdingSyncTaskHandler.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Core.Entities.Linkding; +using Linkding.Client; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace Core.Handler +{ + public interface ILinkdingSyncTaskHandler + { + string Command { get; } + Task ProcessAsync(IEnumerable bookmarks, ILinkdingService linkdingService, ILogger logger, IConfiguration configuration); + } +} \ No newline at end of file diff --git a/src/Linkding/Handler/UpdateTargetLinkdingHandler.cs b/src/Linkding/Handler/UpdateTargetLinkdingHandler.cs new file mode 100644 index 0000000..ff06288 --- /dev/null +++ b/src/Linkding/Handler/UpdateTargetLinkdingHandler.cs @@ -0,0 +1,73 @@ +using Core.Entities.Linkding; +using Core.Handler; +using Linkding.Client; +using Linkding.Client.Extensions; + +namespace Linkding.Handler; + +public class UpdateTargetLinkdingHandler : ILinkdingSyncTaskHandler +{ + public string Command { get; } = "UpdateTargetLinkding"; + + public async Task ProcessAsync(IEnumerable bookmarks, ILinkdingService linkdingService, ILogger logger, + IConfiguration configuration) + { + var linkdingBookmarks = await linkdingService.GetAllBookmarksAsync(); + var addedBookmarks = new List(); + var updatedBookmarks = new List(); + + if (linkdingBookmarks.Count() > 0) + { + + foreach (var bookmark in bookmarks) + { + var linkdingBookmark = linkdingBookmarks.FirstOrDefault(x => x.Url == bookmark.Url); + if (linkdingBookmark == null) + { + addedBookmarks.Add(bookmark.MapToCreatePayload()); + } + else + { + bookmark.Id = linkdingBookmark.Id; + bookmark.Title = !string.IsNullOrEmpty(bookmark.Title) ? bookmark.Title.Trim() : bookmark.WebsiteTitle; + bookmark.Description = !string.IsNullOrEmpty(bookmark.Description) ? bookmark.Description.Trim() : bookmark.WebsiteDescription; + + if (!string.IsNullOrEmpty(bookmark.Title) && !string.IsNullOrEmpty(bookmark.Description) && + (!linkdingBookmark.Title.Equals(bookmark.Title.Trim(), StringComparison.OrdinalIgnoreCase) || + !linkdingBookmark.Description.Equals(bookmark.Description.Trim(), StringComparison.OrdinalIgnoreCase) || + linkdingBookmark.TagNames.Count() != bookmark.TagNames.Count())) + { + updatedBookmarks.Add(bookmark.MapToUpdatePayload()); + } + else + { + var difference = linkdingBookmark.TagNames.Where(t => + !bookmark.TagNames.Any(b => b.Equals(t, StringComparison.OrdinalIgnoreCase))); + + if (difference.Count() > 0) + { + updatedBookmarks.Add(bookmark.MapToUpdatePayload()); + } + } + } + } + } + else + { + foreach (var bookmark in linkdingBookmarks) + { + addedBookmarks.Add(bookmark.MapToCreatePayload()); + } + } + + if (updatedBookmarks.Count > 0) + { + await linkdingService.UpdateBookmarkCollectionAsync(updatedBookmarks); + } + + if (addedBookmarks.Count > 0) + { + await linkdingService.AddBookmarkCollectionAsync(addedBookmarks); + } + } +} \ No newline at end of file diff --git a/src/Linkding/Options/WorkerSettings.cs b/src/Linkding/Options/WorkerSettings.cs index 60847b7..bf46284 100644 --- a/src/Linkding/Options/WorkerSettings.cs +++ b/src/Linkding/Options/WorkerSettings.cs @@ -7,4 +7,6 @@ public class WorkerSettings public int Interval { get; set; } = 0; public int TagNameLength { get; set; } = 64; public List Tasks { get; set; } = new List(); + public List TargetLinkdingUrl { get; set; } = new List(); + public List TargetLinkdingKey { get; set; } = new List(); } \ No newline at end of file diff --git a/src/Linkding/Worker.cs b/src/Linkding/Worker.cs index 249791d..16611b1 100644 --- a/src/Linkding/Worker.cs +++ b/src/Linkding/Worker.cs @@ -53,28 +53,29 @@ public class Worker : BackgroundService public async Task RunBookmarksTaskHandler() { + IEnumerable linkdingBookmarks = null; if (!string.IsNullOrEmpty(_linkdingSettings.Url) && _linkdingSettings.UpdateBookmarks) { _logger.LogInformation($"Starting updating bookmarks for {_linkdingSettings.Url}"); - _logger.LogInformation("Collecting Handler"); - var handlers = AppDomain.CurrentDomain.GetAssemblies() + _logger.LogInformation("Collecting Tag Handler"); + var tagHandlers = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => typeof(ILinkdingTaskHandler).IsAssignableFrom(p) && p.IsClass); var updatedBookmarksCount = 0; var updateBookmarks = new List(); var deleteBookmarks = new List(); - if (handlers != null && handlers.Count() > 0) + if (tagHandlers != null && tagHandlers.Count() > 0) { - var linkdingBookmarks = await _linkdingService.GetAllBookmarksAsync(); + linkdingBookmarks = await _linkdingService.GetAllBookmarksAsync(); if (linkdingBookmarks.Count() > 0) { var tasksLowerCase = _settings.Tasks.Select(x => x.ToLower()); _logger.LogInformation($"{linkdingBookmarks.Count()} bookmarks found in {_linkdingSettings.Url}"); - foreach (var handler in handlers) + foreach (var handler in tagHandlers) { ILinkdingTaskHandler handlerInstance = null; try @@ -93,7 +94,7 @@ public class Worker : BackgroundService { try { - _logger.LogDebug($"Start executing {handlerInstance.Command}"); + _logger.LogDebug($"Start executing {task}"); // var updateBookmark = updateBookmarks.FirstOrDefault(x => x.Id == linkdingBookmark.Id); var existingBookmarkIndexInt = updateBookmarks.FindIndex(x => x.Id == linkdingBookmark.Id); @@ -136,6 +137,8 @@ public class Worker : BackgroundService { updateBookmarks.Add(result.Instance); } + + linkdingBookmark.TagNames = result.Instance.TagNames; } } } @@ -164,7 +167,7 @@ public class Worker : BackgroundService catch (Exception e) { Console.WriteLine(e); - throw; + // throw; } } } @@ -182,6 +185,85 @@ public class Worker : BackgroundService } _logger.LogInformation($"Finished updating bookmarks for {_linkdingSettings.Url}"); + + _logger.LogInformation("Collecting Sync Handler"); + var syncHandlers = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => typeof(ILinkdingSyncTaskHandler).IsAssignableFrom(p) && p.IsClass); + + if (syncHandlers != null && syncHandlers.Count() > 0) + { + if (linkdingBookmarks == null) + { + linkdingBookmarks = await _linkdingService.GetAllBookmarksAsync(); + } + + if (linkdingBookmarks.Count() > 0) + { + var tasksLowerCase = _settings.Tasks.Select(x => x.ToLower()); + + if (_settings.TargetLinkdingKey.Count == _settings.TargetLinkdingUrl.Count) + { + var targetInstances = new Dictionary(); + for (var i = 0; i < _settings.TargetLinkdingKey.Count(); i++) + { + LinkdingService targetService = null; + try + { + var url = _settings.TargetLinkdingUrl[i]; + var key = _settings.TargetLinkdingKey[i]; + targetService = LinkdingService.Create(url, key); + + foreach (var syncHandler in syncHandlers) + { + ILinkdingSyncTaskHandler handlerInstance = null; + try + { + handlerInstance = (ILinkdingSyncTaskHandler) Activator.CreateInstance(syncHandler); + + var task = tasksLowerCase.FirstOrDefault(x => + x.Equals(handlerInstance.Command, StringComparison.InvariantCultureIgnoreCase)); + + if (string.IsNullOrEmpty(task)) + { + continue; + } + + _logger.LogDebug($"Start executing {task}"); + await handlerInstance.ProcessAsync(linkdingBookmarks, targetService, _logger, _configuration); + _logger.LogDebug($"{task} executed successfully!"); + } + catch (Exception ex) + { + Console.WriteLine(ex); + var message = $"... {ex.Message}"; + + if (handlerInstance != null && !string.IsNullOrEmpty(handlerInstance.Command)) + { + message = $"Error while executing {handlerInstance.Command}! {message}"; + } + else + { + message = $"Error while executing handler! {message}"; + } + + _logger.LogError(message, "Calling Handler", ex); + } + } + } + catch (Exception e) + { + Console.WriteLine(e); + {throw;} + } + finally + { + targetService = null; + } + } + } + } + } } } } \ No newline at end of file diff --git a/src/Services/Linkding.Client/Automapper/LinkdingBookmarkProfile.cs b/src/Services/Linkding.Client/Automapper/LinkdingBookmarkProfile.cs index df39869..0f69ac7 100644 --- a/src/Services/Linkding.Client/Automapper/LinkdingBookmarkProfile.cs +++ b/src/Services/Linkding.Client/Automapper/LinkdingBookmarkProfile.cs @@ -8,5 +8,6 @@ public class LinkdingBookmarkProfile : Profile public LinkdingBookmarkProfile() { CreateMap(); + CreateMap(); } } \ No newline at end of file diff --git a/src/Services/Linkding.Client/Extensions/BookmarkExtensions.cs b/src/Services/Linkding.Client/Extensions/BookmarkExtensions.cs new file mode 100644 index 0000000..abdfd0a --- /dev/null +++ b/src/Services/Linkding.Client/Extensions/BookmarkExtensions.cs @@ -0,0 +1,38 @@ +using Core.Entities.Linkding; + +namespace Linkding.Client.Extensions; + +public static class BookmarkExtensions +{ + public static BookmarkCreatePayload MapToCreatePayload(this Bookmark bookmark) + { + var payload = new BookmarkCreatePayload(); + payload.Title = bookmark.Title; + payload.Description = bookmark.Description; + payload.Url = bookmark.Url; + payload.Unread = bookmark.Unread; + payload.IsArchived = payload.IsArchived; + + foreach (var tagName in bookmark.TagNames) + { + payload.TagNames = payload.TagNames.Add(tagName); + } + + return payload; + } + + public static BookmarkUpdatePayload MapToUpdatePayload(this Bookmark bookmark) + { + var payload = new BookmarkUpdatePayload(); + payload.Title = bookmark.Title; + payload.Description = bookmark.Description; + payload.Url = bookmark.Url; + + foreach (var tagName in bookmark.TagNames) + { + payload.TagNames = payload.TagNames.Add(tagName); + } + + return payload; + } +} \ No newline at end of file diff --git a/src/Services/Linkding.Client/LinkdingService.cs b/src/Services/Linkding.Client/LinkdingService.cs index 74e9265..c9ae909 100644 --- a/src/Services/Linkding.Client/LinkdingService.cs +++ b/src/Services/Linkding.Client/LinkdingService.cs @@ -69,13 +69,51 @@ public class LinkdingService : ILinkdingService return bookmarks; } + + public async Task AddBookmarkCollectionAsync(IEnumerable bookmarks) + { + foreach (var bookmark in bookmarks) + { + var payload = _mapper.Map(bookmark); + await AddBookmarkAsync(payload); + } + } + public async Task AddBookmarkCollectionAsync(IEnumerable bookmarks) + { + foreach (var bookmark in bookmarks) + { + await AddBookmarkAsync(bookmark); + } + } + + public async Task AddBookmarkAsync(BookmarkCreatePayload bookmark) + { + var result = await _client.PostAsJsonAsync($"/api/bookmarks/", bookmark); + if (result.IsSuccessStatusCode) + { + + } + else + { + + } + } + public async Task UpdateBookmarkCollectionAsync(IEnumerable bookmarks) { foreach (var bookmark in bookmarks) { - var payload = _mapper.Map(bookmark); - await UpdateBookmarkAsync(payload); + try + { + var payload = _mapper.Map(bookmark); + await UpdateBookmarkAsync(payload); + } + catch (Exception e) + { + Console.WriteLine(e); + // throw; + } } }