Random Stuff (#3798)

This commit is contained in:
Joe Milazzo 2025-05-10 15:57:14 -06:00 committed by GitHub
parent 574cf4b78e
commit 70f00895e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
63 changed files with 659 additions and 567 deletions

View file

@ -51,7 +51,7 @@
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="MailKit" Version="4.11.0" />
<PackageReference Include="MailKit" Version="4.12.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@ -66,7 +66,7 @@
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.4.2" />
<PackageReference Include="HtmlAgilityPack" Version="1.12.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.12.1" />
<PackageReference Include="MarkdownDeep.NET.Core" Version="1.5.0.4" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.18" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
@ -78,7 +78,7 @@
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageReference Include="MimeTypeMapOfficial" Version="1.0.17" />
<PackageReference Include="Nager.ArticleNumber" Version="1.0.7" />
<PackageReference Include="NetVips" Version="3.0.0" />
<PackageReference Include="NetVips" Version="3.0.1" />
<PackageReference Include="NetVips.Native" Version="8.16.1" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
@ -87,20 +87,20 @@
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.AspNetCore.SignalR" Version="0.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.SignalR.Core" Version="0.1.2" />
<PackageReference Include="SharpCompress" Version="0.39.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.8.0.113526">
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.8" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.9.0.115408">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.8.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.13" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.9.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.14" />
<PackageReference Include="System.Drawing.Common" Version="9.0.4" />
<PackageReference Include="VersOne.Epub" Version="3.3.3" />
<PackageReference Include="VersOne.Epub" Version="3.3.4" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />
</ItemGroup>
@ -111,17 +111,16 @@
<ItemGroup>
<None Remove="Hangfire-log.db" />
<None Remove="obj\**" />
<None Remove="cache\**" />
<None Remove="cache-long\**" />
<None Remove="backups\**" />
<None Remove="logs\**" />
<None Remove="temp\**" />
<None Remove="kavita.log" />
<None Remove="kavita.db" />
<None Remove="covers\**" />
<None Remove="config\kavita.log" />
<None Remove="config\kavita.db" />
<None Remove="config\covers\**" />
<None Remove="wwwroot\**" />
<None Remove="cache\cache-long\**" />
<None Remove="config\cache\**" />
<None Remove="config\logs\**" />
<None Remove="config\covers\**" />
@ -139,6 +138,7 @@
<Compile Remove="covers\**" />
<Compile Remove="wwwroot\**" />
<Compile Remove="config\cache\**" />
<Compile Remove="cache\cache-long\**" />
<Compile Remove="config\logs\**" />
<Compile Remove="config\covers\**" />
<Compile Remove="config\bookmarks\**" />
@ -188,7 +188,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="config\cache-long\" />
<Folder Include="config\themes" />
<Content Include="EmailTemplates\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View file

@ -4,14 +4,18 @@ using API.DTOs.Scrobbling;
namespace API.DTOs.KavitaPlus.ExternalMetadata;
#nullable enable
/// <summary>
/// Represents a request to match some series from Kavita to an external id which K+ uses.
/// </summary>
internal sealed record MatchSeriesRequestDto
{
public string SeriesName { get; set; }
public ICollection<string> AlternativeNames { get; set; }
public required string SeriesName { get; set; }
public ICollection<string> AlternativeNames { get; set; } = [];
public int Year { get; set; } = 0;
public string Query { get; set; }
public string? Query { get; set; }
public int? AniListId { get; set; }
public long? MalId { get; set; }
public string? HardcoverId { get; set; }
public int? CbrId { get; set; }
public PlusMediaFormat Format { get; set; }
}

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
@ -26,7 +27,7 @@ public class SecurityEventMiddleware(RequestDelegate next)
}
catch (KavitaUnauthenticatedUserException ex)
{
var ipAddress = context.Connection.RemoteIpAddress?.ToString();
var ipAddress = context.Request.Headers["X-Forwarded-For"].FirstOrDefault() ?? context.Connection.RemoteIpAddress?.ToString();
var requestMethod = context.Request.Method;
var requestPath = context.Request.Path;
var userAgent = context.Request.Headers.UserAgent;

View file

@ -1,4 +1,5 @@
using System;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Security.Cryptography;
@ -48,15 +49,13 @@ public class Program
var directoryService = new DirectoryService(null!, new FileSystem());
// Check if this is the first time running and if so, rename appsettings-init.json to appsettings.json
HandleFirstRunConfiguration();
// Before anything, check if JWT has been generated properly or if user still has default
if (!Configuration.CheckIfJwtTokenSet() &&
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != Environments.Development)
{
Log.Logger.Information("Generating JWT TokenKey for encrypting user sessions...");
var rBytes = new byte[256];
RandomNumberGenerator.Create().GetBytes(rBytes);
Configuration.JwtToken = Convert.ToBase64String(rBytes).Replace("/", string.Empty);
}
EnsureJwtTokenKey();
try
{
@ -70,6 +69,7 @@ public class Program
{
var logger = services.GetRequiredService<ILogger<Program>>();
var context = services.GetRequiredService<DataContext>();
var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
var isDbCreated = await context.Database.CanConnectAsync();
if (isDbCreated && pendingMigrations.Any())
@ -157,6 +157,26 @@ public class Program
}
}
private static void EnsureJwtTokenKey()
{
if (Configuration.CheckIfJwtTokenSet() || Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == Environments.Development) return;
Log.Logger.Information("Generating JWT TokenKey for encrypting user sessions...");
var rBytes = new byte[256];
RandomNumberGenerator.Create().GetBytes(rBytes);
Configuration.JwtToken = Convert.ToBase64String(rBytes).Replace("/", string.Empty);
}
private static void HandleFirstRunConfiguration()
{
var firstRunConfigFilePath = Path.Join(Directory.GetCurrentDirectory(), "config/appsettings-init.json");
if (File.Exists(firstRunConfigFilePath) &&
!File.Exists(Path.Join(Directory.GetCurrentDirectory(), "config/appsettings.json")))
{
File.Move(firstRunConfigFilePath, Path.Join(Directory.GetCurrentDirectory(), "config/appsettings.json"));
}
}
private static async Task<string> GetMigrationDirectory(DataContext context, IDirectoryService directoryService)
{
string? currentVersion = null;

View file

@ -226,7 +226,7 @@ public class ExternalMetadataService : IExternalMetadataService
AlternativeNames = altNames.Where(s => !string.IsNullOrEmpty(s)).ToList(),
Year = series.Metadata.ReleaseYear,
AniListId = potentialAnilistId ?? ScrobblingService.GetAniListId(series),
MalId = potentialMalId ?? ScrobblingService.GetMalId(series),
MalId = potentialMalId ?? ScrobblingService.GetMalId(series)
};
var token = (await _unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
@ -792,7 +792,7 @@ public class ExternalMetadataService : IExternalMetadataService
var characters = externalCharacters
.Select(w => new PersonDto()
{
Name = w.Name,
Name = w.Name.Trim(),
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListCharacterWebsite),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
@ -873,7 +873,7 @@ public class ExternalMetadataService : IExternalMetadataService
var artists = upstreamArtists
.Select(w => new PersonDto()
{
Name = w.Name,
Name = w.Name.Trim(),
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListStaffWebsite),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
@ -929,7 +929,7 @@ public class ExternalMetadataService : IExternalMetadataService
var writers = upstreamWriters
.Select(w => new PersonDto()
{
Name = w.Name,
Name = w.Name.Trim(),
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListStaffWebsite),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
@ -1353,7 +1353,7 @@ public class ExternalMetadataService : IExternalMetadataService
var people = staff!
.Select(w => new PersonDto()
{
Name = w,
Name = w.Trim(),
})
.Concat(chapter.People
.Where(p => p.Role == role)

View file

@ -501,7 +501,7 @@ public class CoverDbService : ICoverDbService
else
{
_directoryService.DeleteFiles([tempFullPath]);
person.CoverImage = Path.GetFileName(existingPath);
return;
}
}
else
@ -651,6 +651,7 @@ public class CoverDbService : ICoverDbService
else
{
_directoryService.DeleteFiles([tempFullPath]);
return;
}
chapter.CoverImage = finalFileName;

View file

@ -310,7 +310,7 @@ public class LibraryWatcher : ILibraryWatcher
if (rootFolder.Count == 0) return string.Empty;
// Select the first folder and join with library folder, this should give us the folder to scan.
return Parser.Parser.NormalizePath(_directoryService.FileSystem.Path.Join(libraryFolder, rootFolder[rootFolder.Count - 1]));
return Parser.Parser.NormalizePath(_directoryService.FileSystem.Path.Join(libraryFolder, rootFolder[^1]));
}

View file

@ -52,6 +52,7 @@ public interface IVersionUpdaterService
Task PushUpdate(UpdateNotificationDto update);
Task<IList<UpdateNotificationDto>> GetAllReleases(int count = 0);
Task<int> GetNumberOfReleasesBehind(bool stableOnly = false);
void BustGithubCache();
}
@ -384,7 +385,7 @@ public partial class VersionUpdaterService : IVersionUpdaterService
if (DateTime.UtcNow - fileInfo.LastWriteTimeUtc <= CacheDuration)
{
var cachedData = await File.ReadAllTextAsync(_cacheLatestReleaseFilePath);
return System.Text.Json.JsonSerializer.Deserialize<UpdateNotificationDto>(cachedData);
return JsonSerializer.Deserialize<UpdateNotificationDto>(cachedData);
}
return null;
@ -407,7 +408,7 @@ public partial class VersionUpdaterService : IVersionUpdaterService
{
try
{
var json = System.Text.Json.JsonSerializer.Serialize(update, JsonOptions);
var json = JsonSerializer.Serialize(update, JsonOptions);
await File.WriteAllTextAsync(_cacheLatestReleaseFilePath, json);
}
catch (Exception ex)
@ -446,6 +447,21 @@ public partial class VersionUpdaterService : IVersionUpdaterService
.Count(u => u.IsReleaseNewer);
}
/// <summary>
/// Clears the Github cache
/// </summary>
public void BustGithubCache()
{
try
{
File.Delete(_cacheFilePath);
File.Delete(_cacheLatestReleaseFilePath);
} catch (Exception ex)
{
_logger.LogError(ex, "Failed to clear Github cache");
}
}
private UpdateNotificationDto? CreateDto(GithubReleaseMetadata? update)
{
if (update == null || string.IsNullOrEmpty(update.Tag_Name)) return null;

View file

@ -55,6 +55,9 @@ public class Startup
{
_config = config;
_env = env;
// Disable Hangfire Automatic Retry
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
}
// This method gets called by the runtime. Use this method to add services to the container.
@ -223,7 +226,7 @@ public class Startup
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env,
IHostApplicationLifetime applicationLifetime, IServiceProvider serviceProvider, ICacheService cacheService,
IDirectoryService directoryService, IUnitOfWork unitOfWork, IBackupService backupService, IImageService imageService)
IDirectoryService directoryService, IUnitOfWork unitOfWork, IBackupService backupService, IImageService imageService, IVersionUpdaterService versionService)
{
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
@ -235,9 +238,10 @@ public class Startup
// Apply all migrations on startup
var dataContext = serviceProvider.GetRequiredService<DataContext>();
logger.LogInformation("Running Migrations");
#region Migrations
// v0.7.9
await MigrateUserLibrarySideNavStream.Migrate(unitOfWork, dataContext, logger);
@ -289,13 +293,23 @@ public class Startup
await ManualMigrateScrobbleSpecials.Migrate(dataContext, logger);
await ManualMigrateScrobbleEventGen.Migrate(dataContext, logger);
#endregion
// Update the version in the DB after all migrations are run
var installVersion = await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.InstallVersion);
var isVersionDifferent = installVersion.Value != BuildInfo.Version.ToString();
installVersion.Value = BuildInfo.Version.ToString();
unitOfWork.SettingsRepository.Update(installVersion);
await unitOfWork.CommitAsync();
logger.LogInformation("Running Migrations - complete");
if (isVersionDifferent)
{
// Clear the Github cache so update stuff shows correctly
versionService.BustGithubCache();
}
}).GetAwaiter()
.GetResult();
}