Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update existing links if present in LinkAce #96

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/BookmarkSync.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace BookmarkSync.Core.Extensions;

public static class StringExtensions
{
public static string ToSnakeCase(this string str)
=> string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())).ToLower();
}
13 changes: 13 additions & 0 deletions src/BookmarkSync.Core/Json/SnakeCaseContractResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using BookmarkSync.Core.Extensions;
using Newtonsoft.Json.Serialization;

namespace BookmarkSync.Core.Json;

public class SnakeCaseContractResolver : DefaultContractResolver
{
public static readonly SnakeCaseContractResolver Instance = new();
override protected string ResolvePropertyName(string propertyName)
{
return propertyName.ToSnakeCase();
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
using System.Web;
using BookmarkSync.Core.Json;
using Newtonsoft.Json;

namespace BookmarkSync.Infrastructure.Services.Bookmarking.LinkAce;

public class LinkAceBookmarkingService : BookmarkingService, IBookmarkingService
{
private static readonly ILogger _logger = Log.ForContext<LinkAceBookmarkingService>();
private readonly string _linkAceUri;
public LinkAceBookmarkingService(IConfigManager configManager)
{
ApiToken = configManager.App.Bookmarking.ApiToken ?? throw new InvalidOperationException("Missing API token");
string linkAceUri = configManager.GetConfigValue("App:Bookmarking:LinkAceUri") ??
throw new InvalidOperationException("Missing LinkAce Uri");
ApiUri = $"{linkAceUri}/api/v1/links";
_linkAceUri = configManager.GetConfigValue("App:Bookmarking:LinkAceUri") ??
throw new InvalidOperationException("Missing LinkAce Uri");
ApiUri = $"{_linkAceUri}/api/v1/links";
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiToken);
}
/// <inheritdoc />
/// <inheritdoc/>
public async Task<HttpResponseMessage> Save(Bookmark bookmark)
{
// Prep payload
Expand All @@ -40,7 +43,34 @@ public async Task<HttpResponseMessage> Save(Bookmark bookmark)
};
var stringContent = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8,
MediaTypeNames.Application.Json);
var response = await Client.PostAsync(ApiUri, stringContent);

// Check for existing bookmarks with the same URL.
var uriBuilder = new UriBuilder($"{_linkAceUri}/api/v1/search/links");
var query = HttpUtility.ParseQueryString(string.Empty);
query["query"] = bookmark.Uri;
uriBuilder.Query = query.ToString();
var linksResponse = await Client.GetAsync(uriBuilder.ToString());
linksResponse.EnsureSuccessStatusCode();
string responseContent = await linksResponse.Content.ReadAsStringAsync();
var responseObj = JsonConvert.DeserializeObject<LinkAceApiSearchResponse>(responseContent,
new JsonSerializerSettings
{
ContractResolver = SnakeCaseContractResolver.Instance
});

HttpResponseMessage? response;
var existingLink = responseObj?.Data?.Where(b => b.Url == bookmark.Uri).FirstOrDefault();
if (existingLink != null)
{
// Bookmark exists in LinkAce, try to update.
_logger.Information("Bookmark {Uri} exists in LinkAce, updating...", bookmark.Uri);
response = await Client.PatchAsync($"{ApiUri}/{existingLink.Id}", stringContent);
response.EnsureSuccessStatusCode();
_logger.Debug("Response status: {StatusCode}", response.StatusCode);
return response;
}

response = await Client.PostAsync(ApiUri, stringContent);
response.EnsureSuccessStatusCode();
_logger.Debug("Response status: {StatusCode}", response.StatusCode);
return response;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace BookmarkSync.Infrastructure.Services.Bookmarking.LinkAce;

public class LinkAceApiSearchResponse
{
public int CurrentPage { get; set; }
public List<LinkAceBookmark>? Data { get; set; }
public string? FirstPageUrl { get; set; }
public int? From { get; set; }
public int LastPage { get; set; }
public string? LastPageUrl { get; set; }
public string? NextPageUrl { get; set; }
public string Path { get; set; }
public string PerPage { get; set; }
public string? PreviousPageUrl { get; set; }
public int? To { get; set; }
public int Total { get; set; }
}
public class LinkAceBookmark
{
public bool CheckDisabled { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? DeletedAt { get; set; }
public string? Description { get; set; }
public string Icon { get; set; }
public int Id { get; set; }
public bool IsPrivate { get; set; }
public int Status { get; set; }
public string Title { get; set; }
public DateTime UpdatedAt { get; set; }
public string Url { get; set; }
public int UserId { get; set; }
}