Web Links (#1983)
* Updated dependencies * Updated the default key to be 256 bits to meet security requirements. * Added basic implementation of web link resolving favicon. Needs lots more work and testing on all OSes. * Implemented ability to see links and click on them for an individual chapter. * Hooked up the ability to set Series web links. * Render out the web link * Refactored out the favicon so there is a backup in case it fails. Refactored the baseline image placeholders to be dark mode since that is the default. * Added Robbie's nice error weblink fallbacks.
This commit is contained in:
parent
23fde65a7b
commit
bd8a1821a7
37 changed files with 4272 additions and 80 deletions
|
|
@ -22,6 +22,7 @@ public interface IDirectoryService
|
|||
string TempDirectory { get; }
|
||||
string ConfigDirectory { get; }
|
||||
string SiteThemeDirectory { get; }
|
||||
string FaviconDirectory { get; }
|
||||
/// <summary>
|
||||
/// Original BookmarkDirectory. Only used for resetting directory. Use <see cref="ServerSettingKey.BackupDirectory"/> for actual path.
|
||||
/// </summary>
|
||||
|
|
@ -75,6 +76,7 @@ public class DirectoryService : IDirectoryService
|
|||
public string ConfigDirectory { get; }
|
||||
public string BookmarkDirectory { get; }
|
||||
public string SiteThemeDirectory { get; }
|
||||
public string FaviconDirectory { get; }
|
||||
private readonly ILogger<DirectoryService> _logger;
|
||||
private const RegexOptions MatchOptions = RegexOptions.Compiled | RegexOptions.IgnoreCase;
|
||||
|
||||
|
|
@ -98,6 +100,7 @@ public class DirectoryService : IDirectoryService
|
|||
ConfigDirectory = FileSystem.Path.Join(FileSystem.Directory.GetCurrentDirectory(), "config");
|
||||
BookmarkDirectory = FileSystem.Path.Join(FileSystem.Directory.GetCurrentDirectory(), "config", "bookmarks");
|
||||
SiteThemeDirectory = FileSystem.Path.Join(FileSystem.Directory.GetCurrentDirectory(), "config", "themes");
|
||||
FaviconDirectory = FileSystem.Path.Join(FileSystem.Directory.GetCurrentDirectory(), "config", "favicons");
|
||||
|
||||
ExistOrCreate(SiteThemeDirectory);
|
||||
ExistOrCreate(CoverImageDirectory);
|
||||
|
|
@ -105,6 +108,7 @@ public class DirectoryService : IDirectoryService
|
|||
ExistOrCreate(LogDirectory);
|
||||
ExistOrCreate(TempDirectory);
|
||||
ExistOrCreate(BookmarkDirectory);
|
||||
ExistOrCreate(FaviconDirectory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Flurl;
|
||||
using Flurl.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetVips;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Image = NetVips.Image;
|
||||
using Size = SixLabors.ImageSharp.Size;
|
||||
|
||||
namespace API.Services;
|
||||
|
||||
|
|
@ -49,6 +57,7 @@ public interface IImageService
|
|||
Task<string> ConvertToWebP(string filePath, string outputPath);
|
||||
|
||||
Task<bool> IsImage(string filePath);
|
||||
Task<string> DownloadFaviconAsync(string url);
|
||||
}
|
||||
|
||||
public class ImageService : IImageService
|
||||
|
|
@ -177,6 +186,36 @@ public class ImageService : IImageService
|
|||
return false;
|
||||
}
|
||||
|
||||
public async Task<string> DownloadFaviconAsync(string url)
|
||||
{
|
||||
// Parse the URL to get the domain (including subdomain)
|
||||
var uri = new Uri(url);
|
||||
var domain = uri.Host;
|
||||
var baseUrl = uri.Scheme + "://" + uri.Host;
|
||||
try
|
||||
{
|
||||
// Download the favicon.ico file using Flurl
|
||||
var faviconStream = await baseUrl
|
||||
.AppendPathSegment("favicon.ico")
|
||||
.AllowHttpStatus("2xx")
|
||||
.GetStreamAsync();
|
||||
|
||||
// Create the destination file path
|
||||
var filename = $"{domain}.png";
|
||||
using var icon = new Icon(faviconStream);
|
||||
using var bitmap = icon.ToBitmap();
|
||||
bitmap.Save(Path.Combine(_directoryService.FaviconDirectory, filename), ImageFormat.Png);
|
||||
|
||||
_logger.LogDebug("Favicon.png for {Domain} downloaded and saved successfully", domain);
|
||||
return filename;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error downloading favicon.png for ${Domain}", domain);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string CreateThumbnailFromBase64(string encodedImage, string fileName, bool saveAsWebP = false, int thumbnailWidth = ThumbnailWidth)
|
||||
|
|
@ -257,6 +296,11 @@ public class ImageService : IImageService
|
|||
return $"thumbnail{chapterId}";
|
||||
}
|
||||
|
||||
public static string GetWebLinkFormat(string url)
|
||||
{
|
||||
return $"{new Uri(url).Host}.png";
|
||||
}
|
||||
|
||||
|
||||
public static string CreateMergedImage(List<string> coverImages, string dest)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -120,6 +120,16 @@ public class SeriesService : ISeriesService
|
|||
series.Metadata.LanguageLocked = true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(updateSeriesMetadataDto.SeriesMetadata?.WebLinks))
|
||||
{
|
||||
series.Metadata.WebLinks = string.Join(",", updateSeriesMetadataDto.SeriesMetadata?.WebLinks
|
||||
.Split(",")
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.Select(s => s.Trim())!
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
series.Metadata.CollectionTags ??= new List<CollectionTag>();
|
||||
UpdateCollectionsList(updateSeriesMetadataDto.CollectionTags, series, allCollectionTags, (tag) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ public class BackupService : IBackupService
|
|||
await SendProgress(0.75F, "Copying themes");
|
||||
|
||||
CopyThemesToBackupDirectory(tempDirectory);
|
||||
await SendProgress(0.85F, "Copying favicons");
|
||||
CopyFaviconsToBackupDirectory(tempDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -141,6 +143,11 @@ public class BackupService : IBackupService
|
|||
_directoryService.CopyFilesToDirectory(files, _directoryService.FileSystem.Path.Join(tempDirectory, "logs"));
|
||||
}
|
||||
|
||||
private void CopyFaviconsToBackupDirectory(string tempDirectory)
|
||||
{
|
||||
_directoryService.CopyDirectoryToDirectory(_directoryService.FaviconDirectory, tempDirectory);
|
||||
}
|
||||
|
||||
private async Task CopyCoverImagesToBackupDirectory(string tempDirectory)
|
||||
{
|
||||
var outputTempDir = Path.Join(tempDirectory, "covers");
|
||||
|
|
|
|||
|
|
@ -708,12 +708,19 @@ public class ProcessSeries : IProcessSeries
|
|||
chapter.StoryArcNumber = comicInfo.StoryArcNumber;
|
||||
}
|
||||
|
||||
|
||||
if (comicInfo.AlternateCount > 0)
|
||||
{
|
||||
chapter.AlternateCount = comicInfo.AlternateCount;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(comicInfo.Web))
|
||||
{
|
||||
chapter.WebLinks = string.Join(",", comicInfo.Web
|
||||
.Split(",")
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.Select(s => s.Trim())
|
||||
);
|
||||
}
|
||||
|
||||
if (comicInfo.Count > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,13 +49,12 @@ public class TokenService : ITokenService
|
|||
|
||||
claims.AddRange(roles.Select(role => new Claim(Role, role)));
|
||||
|
||||
var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);
|
||||
|
||||
var credentials = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);
|
||||
var tokenDescriptor = new SecurityTokenDescriptor()
|
||||
{
|
||||
Subject = new ClaimsIdentity(claims),
|
||||
Expires = DateTime.UtcNow.AddDays(14),
|
||||
SigningCredentials = creds
|
||||
SigningCredentials = credentials
|
||||
};
|
||||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue