Merge branch 'develop' into feature/frontend
This commit is contained in:
104
Butter/MimeTypes.cs
Normal file
104
Butter/MimeTypes.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
namespace Butter;
|
||||
|
||||
public struct MimeTypeMap(string mimeType, string[] extensions) {
|
||||
public string MimeType { get; set; } = mimeType;
|
||||
public string[] Extensions { get; set; } = extensions;
|
||||
}
|
||||
|
||||
public static class MimeTypes{
|
||||
// ReSharper disable ArrangeObjectCreationWhenTypeEvident
|
||||
public static readonly MimeTypeMap[] Image = [
|
||||
new("image/avif", [".avif", ".avifs"]),
|
||||
new("image/bmp}", [".bmp"]),
|
||||
new("image/cgm", [".cgm"]),
|
||||
new("image/g3fax", [".g3"]),
|
||||
new("image/gif", [".gif"]),
|
||||
new("image/heic", [".heif", ".heic"]),
|
||||
new("image/ief", [".ief"]),
|
||||
new("image/jpeg", [".jpe", ".jpeg", ".jpg", ".pjpg", ".jfif", ".jfif-tbnl", ".jif"]),
|
||||
new("image/pjpeg", [".jpe", ".jpeg", ".jpg", ".pjpg", ".jfi", ".jfif", ".jfif-tbnl", ".jif"]),
|
||||
new("image/png", [".png"]),
|
||||
new("image/prs.btif", [".btif"]),
|
||||
new("image/svg+xml", [".svg", ".svgz"]),
|
||||
new("image/tiff", [".tif", ".tiff"]),
|
||||
new("image/vnd.adobe.photoshop", [".psd"]),
|
||||
new("image/vnd.djvu", [".djv", ".djvu"]),
|
||||
new("image/vnd.dwg", [".dwg"]),
|
||||
new("image/vnd.dxf", [".dxf"]),
|
||||
new("image/vnd.fastbidsheet", [".fbs"]),
|
||||
new("image/vnd.fpx", [".fpx"]),
|
||||
new("image/vnd.fst", [".fst"]),
|
||||
new("image/vnd.fujixerox.edmics-mmr", [".mmr"]),
|
||||
new("image/vnd.fujixerox.edmics-rlc", [".rlc"]),
|
||||
new("image/vnd.ms-modi", [".mdi"]),
|
||||
new("image/vnd.net-fpx", [".npx"]),
|
||||
new("image/vnd.wap.wbmp", [".wbmp"]),
|
||||
new("image/vnd.xiff", [".xif"]),
|
||||
new("image/webp", [".webp"]),
|
||||
new("image/x-adobe-dng", [".dng"]),
|
||||
new("image/x-canon-cr2", [".cr2"]),
|
||||
new("image/x-canon-crw", [".crw"]),
|
||||
new("image/x-cmu-raster", [".ras"]),
|
||||
new("image/x-cmx", [".cmx"]),
|
||||
new("image/x-epson-erf", [".erf"]),
|
||||
new("image/x-freehand", [".fh", ".fh4", ".fh5", ".fh7", ".fhc"]),
|
||||
new("image/x-fuji-raf", [".raf"]),
|
||||
new("image/x-icns", [".icns"]),
|
||||
new("image/x-icon", [".ico"]),
|
||||
new("image/x-kodak-dcr", [".dcr"]),
|
||||
new("image/x-kodak-k25", [".k25"]),
|
||||
new("image/x-kodak-kdc", [".kdc"]),
|
||||
new("image/x-minolta-mrw", [".mrw"]),
|
||||
new("image/x-nikon-nef", [".nef"]),
|
||||
new("image/x-olympus-orf", [".orf"]),
|
||||
new("image/x-panasonic-raw", [".raw", ".rw2", ".rwl"]),
|
||||
new("image/x-pcx", [".pcx"]),
|
||||
new("image/x-pentax-pef", [".pef", ".ptx"]),
|
||||
new("image/x-pict", [".pct", ".pic"]),
|
||||
new("image/x-portable-anymap", [".pnm"]),
|
||||
new("image/x-portable-bitmap", [".pbm"]),
|
||||
new("image/x-portable-graymap", [".pgm"]),
|
||||
new("image/x-portable-pixmap", [".ppm"]),
|
||||
new("image/x-rgb", [".rgb"]),
|
||||
new("image/x-sigma-x3f", [".x3f"]),
|
||||
new("image/x-sony-arw", [".arw"]),
|
||||
new("image/x-sony-sr2", [".sr2"]),
|
||||
new("image/x-sony-srf", [".srf"]),
|
||||
new("image/x-xbitmap", [".xbm"]),
|
||||
new("image/x-xpixmap", [".xpm"]),
|
||||
new("image/x-xwindowdump", [".xwd"])
|
||||
];
|
||||
|
||||
public static readonly MimeTypeMap[] Video = [
|
||||
new("video/3gpp", [".3gp"]),
|
||||
new("video/3gpp2", [".3g2"]),
|
||||
new("video/h261", [".h261"]),
|
||||
new("video/h263", [".h263"]),
|
||||
new("video/h264", [".h264"]),
|
||||
new("video/jpeg", [".jpgv"]),
|
||||
new("video/jpm", [".jpgm, .jpm"]),
|
||||
new("video/mj2", [".mj2, .mjp2"]),
|
||||
new("video/mp2t", [".ts"]),
|
||||
new("video/mp4", [".mp4, .mp4v, .mpg4"]),
|
||||
new("video/mpeg", [".m1v, .m2v, .mpa, .mpe, .mpeg, .mpg"]),
|
||||
new("video/ogg", [".ogv"]),
|
||||
new("video/quicktime", [".mov", ".qt"]),
|
||||
new("video/vnd.fvt", [".fvt"]),
|
||||
new("video/vnd.mpegurl", [".m4u", ".mxu"]),
|
||||
new("video/vnd.ms-playready.media.pyv", [".pyv"]),
|
||||
new("video/vnd.vivo", [".viv"]),
|
||||
new("video/webm", [".webm"]),
|
||||
new("video/x-f4v", [".f4v"]),
|
||||
new("video/x-fli", [".fli"]),
|
||||
new("video/x-flv", [".flv"]),
|
||||
new("video/x-m4v", [".m4v"]),
|
||||
new("video/x-matroska", [".mkv"]),
|
||||
new("video/x-ms-asf", [".asf", ".asx"]),
|
||||
new("video/x-ms-wm", [".wm"]),
|
||||
new("video/x-ms-wmv", [".wmv"]),
|
||||
new("video/x-ms-wmx", [".wmx"]),
|
||||
new("video/x-ms-wvx", [".wvx"]),
|
||||
new("video/x-msvideo", [".avi"]),
|
||||
new("video/x-sgi-movie", [".movie"])
|
||||
];
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Lactose;
|
||||
namespace Butter;
|
||||
|
||||
public enum Settings {
|
||||
UserRegistrationEnabled, //Enable or disable self user registration
|
||||
@@ -63,7 +63,6 @@ AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||
// Add services to initialize an empty the database
|
||||
builder.Services.AddScoped<IDbInitializer, DbInitializer>();
|
||||
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddTransient<IPasswordHasher<User>, PasswordHasher<User>>();
|
||||
builder.Services.AddTransient<ISettingsRepository, SettingsRepository>();
|
||||
@@ -75,7 +74,7 @@ builder.Services.AddTransient<IAlbumRepository, AlbumRepository>();
|
||||
builder.Services.AddTransient<IMediaRepository, MediaRepository>();
|
||||
builder.Services.AddTransient<ITokenService, TokenService>();
|
||||
builder.Services.AddTransient<LactoseAuthService>();
|
||||
builder.Services.AddTransient<FileSystemScannerService>();
|
||||
builder.Services.AddSingleton<FileSystemScannerService>();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddControllers();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using Lactose.Models;
|
||||
|
||||
namespace Lactose.Repositories;
|
||||
|
||||
public class FolderRepository(LactoseDbContext context) : IFolderRepository {
|
||||
public class FolderRepository(LactoseDbContext context) : IFolderRepository, IAsyncDisposable {
|
||||
public void Create(Folder folder) => context.Folders.Add(folder);
|
||||
|
||||
public void Update(Guid id, Folder folder) {
|
||||
@@ -25,4 +25,8 @@ public class FolderRepository(LactoseDbContext context) : IFolderRepository {
|
||||
public Folder? Get(Guid id) => context.Folders.Find(id);
|
||||
|
||||
public IEnumerable<Folder> GetAll() => context.Folders;
|
||||
|
||||
public void Dispose() { context.Dispose(); }
|
||||
|
||||
public async ValueTask DisposeAsync() { await context.DisposeAsync(); }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Lactose.Repositories;
|
||||
/// <summary>
|
||||
/// Interface for folder repository operations.
|
||||
/// </summary>
|
||||
public interface IFolderRepository {
|
||||
public interface IFolderRepository : IDisposable {
|
||||
/// <summary>
|
||||
/// Creates a new folder.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Lactose.Repositories;
|
||||
/// <summary>
|
||||
/// Interface for managing settings in the repository.
|
||||
/// </summary>
|
||||
public interface ISettingsRepository {
|
||||
public interface ISettingsRepository : IDisposable {
|
||||
/// <summary>
|
||||
/// Creates a settings entry in the repository. If a settings entry already exists, it will be overwritten.
|
||||
/// </summary>
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Data;
|
||||
|
||||
namespace Lactose.Repositories;
|
||||
|
||||
public class SettingsRepository(LactoseDbContext context) : ISettingsRepository {
|
||||
public class SettingsRepository(LactoseDbContext context) : ISettingsRepository, IAsyncDisposable {
|
||||
public void Create(Setting setting) {
|
||||
//Check if the settings already exist
|
||||
var existingSettings = context.Settings.FirstOrDefault(s => s.Name == setting.Name);
|
||||
@@ -46,4 +46,8 @@ public class SettingsRepository(LactoseDbContext context) : ISettingsRepository
|
||||
if (existingSettings == null) throw new KeyNotFoundException("The setting with the specified name does not exist: " + name);
|
||||
Delete(existingSettings);
|
||||
}
|
||||
|
||||
public void Dispose() { context.Dispose(); }
|
||||
|
||||
public async ValueTask DisposeAsync() { await context.DisposeAsync(); }
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using Butter;
|
||||
using Butter.Types;
|
||||
using Lactose.Context;
|
||||
using Lactose.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Lactose.Services;
|
||||
|
||||
@@ -9,23 +11,23 @@ interface IDbInitializer {
|
||||
void Initialize();
|
||||
}
|
||||
|
||||
class DbInitializer(
|
||||
LactoseDbContext dbContext,
|
||||
IPasswordHasher<User> passwordHasher
|
||||
): IDbInitializer
|
||||
{
|
||||
class DbInitializer(LactoseDbContext dbContext, IPasswordHasher<User> passwordHasher) : IDbInitializer {
|
||||
public void Initialize() {
|
||||
ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext));
|
||||
|
||||
var task = dbContext.Database.GetPendingMigrationsAsync();
|
||||
|
||||
task.ContinueWith(
|
||||
(r) => {
|
||||
task.ContinueWith((r) => {
|
||||
if (r.Result.Any()) dbContext.Database.Migrate();
|
||||
}
|
||||
).Wait();
|
||||
)
|
||||
.Wait();
|
||||
|
||||
// if(dbContext.Database.GetPendingMigrations().Any()) // Timeoout
|
||||
if (dbContext.Users.Any()) return;
|
||||
|
||||
#region Users
|
||||
|
||||
if (!dbContext.Users.Any()) {
|
||||
var user = new User {
|
||||
Username = "admin",
|
||||
Email = "admin@admin.com",
|
||||
@@ -33,8 +35,52 @@ class DbInitializer(
|
||||
CreatedAt = DateTime.Now,
|
||||
UpdatedAt = DateTime.Now
|
||||
};
|
||||
|
||||
user.Password = passwordHasher.HashPassword(user, "admin");
|
||||
dbContext.Users.Add(user);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Settings
|
||||
|
||||
if (!dbContext.Settings.Any()) {
|
||||
foreach (Settings settingRow in Enum.GetValues(typeof(Settings))) {
|
||||
var setting = new Setting {
|
||||
Name = settingRow.AsString(),
|
||||
Value = settingRow.AsValueType() switch {
|
||||
// note: ReSharper tries to convert this to a {} t when t == typeof(T). This actually adds
|
||||
// an extra allocation and is even less readable.
|
||||
// ReSharper disable ConvertTypeCheckPatternToNullCheck
|
||||
Type t when t == typeof(bool) => "true",
|
||||
Type t when t == typeof(int) => "0",
|
||||
Type t when t == typeof(string) => string.Empty,
|
||||
// ReSharper restore ConvertTypeCheckPatternToNullCheck
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(settingRow), settingRow, null)
|
||||
}
|
||||
};
|
||||
|
||||
dbContext.Settings.Add(setting);
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Folders
|
||||
|
||||
if (!dbContext.Folders.Any()) {
|
||||
dbContext.Folders.Add(
|
||||
new Folder() {
|
||||
BasePath = "/diary",
|
||||
Active = false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,121 +1,25 @@
|
||||
using Butter;
|
||||
using Butter.Types;
|
||||
using Butter.Dtos.Settings;
|
||||
using Lactose.Models;
|
||||
using Lactose.Repositories;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using static System.String;
|
||||
|
||||
namespace Lactose.Services;
|
||||
|
||||
public class FileSystemScannerService(
|
||||
ILogger<FileSystemScannerService> logger,
|
||||
IAssetRepository assetRepository,
|
||||
IFolderRepository folderRepository,
|
||||
ISettingsRepository settingsRepository
|
||||
) : BackgroundService {
|
||||
public class FileSystemScannerService(ILogger<FileSystemScannerService> logger, IServiceProvider serviceProvider)
|
||||
: BackgroundService {
|
||||
public bool IsRunning { get; private set; } = false;
|
||||
public bool IsInitialized { get; private set; } = false;
|
||||
public TimeSpan ScanInterval { get; private set; }
|
||||
List<Folder> folders = [];
|
||||
readonly List<Task> tasks = [];
|
||||
|
||||
// ReSharper disable ArrangeObjectCreationWhenTypeEvident
|
||||
static readonly MimeTypeMap[] ImageMime = [
|
||||
new("image/avif", [".avif", ".avifs"]),
|
||||
new("image/bmp}", [".bmp"]),
|
||||
new("image/cgm", [".cgm"]),
|
||||
new("image/g3fax", [".g3"]),
|
||||
new("image/gif", [".gif"]),
|
||||
new("image/heic", [".heif", ".heic"]),
|
||||
new("image/ief", [".ief"]),
|
||||
new("image/jpeg", [".jpe", ".jpeg", ".jpg", ".pjpg", ".jfif", ".jfif-tbnl", ".jif"]),
|
||||
new("image/pjpeg", [".jpe", ".jpeg", ".jpg", ".pjpg", ".jfi", ".jfif", ".jfif-tbnl", ".jif"]),
|
||||
new("image/png", [".png"]),
|
||||
new("image/prs.btif", [".btif"]),
|
||||
new("image/svg+xml", [".svg", ".svgz"]),
|
||||
new("image/tiff", [".tif", ".tiff"]),
|
||||
new("image/vnd.adobe.photoshop", [".psd"]),
|
||||
new("image/vnd.djvu", [".djv", ".djvu"]),
|
||||
new("image/vnd.dwg", [".dwg"]),
|
||||
new("image/vnd.dxf", [".dxf"]),
|
||||
new("image/vnd.fastbidsheet", [".fbs"]),
|
||||
new("image/vnd.fpx", [".fpx"]),
|
||||
new("image/vnd.fst", [".fst"]),
|
||||
new("image/vnd.fujixerox.edmics-mmr", [".mmr"]),
|
||||
new("image/vnd.fujixerox.edmics-rlc", [".rlc"]),
|
||||
new("image/vnd.ms-modi", [".mdi"]),
|
||||
new("image/vnd.net-fpx", [".npx"]),
|
||||
new("image/vnd.wap.wbmp", [".wbmp"]),
|
||||
new("image/vnd.xiff", [".xif"]),
|
||||
new("image/webp", [".webp"]),
|
||||
new("image/x-adobe-dng", [".dng"]),
|
||||
new("image/x-canon-cr2", [".cr2"]),
|
||||
new("image/x-canon-crw", [".crw"]),
|
||||
new("image/x-cmu-raster", [".ras"]),
|
||||
new("image/x-cmx", [".cmx"]),
|
||||
new("image/x-epson-erf", [".erf"]),
|
||||
new("image/x-freehand", [".fh", ".fh4", ".fh5", ".fh7", ".fhc"]),
|
||||
new("image/x-fuji-raf", [".raf"]),
|
||||
new("image/x-icns", [".icns"]),
|
||||
new("image/x-icon", [".ico"]),
|
||||
new("image/x-kodak-dcr", [".dcr"]),
|
||||
new("image/x-kodak-k25", [".k25"]),
|
||||
new("image/x-kodak-kdc", [".kdc"]),
|
||||
new("image/x-minolta-mrw", [".mrw"]),
|
||||
new("image/x-nikon-nef", [".nef"]),
|
||||
new("image/x-olympus-orf", [".orf"]),
|
||||
new("image/x-panasonic-raw", [".raw", ".rw2", ".rwl"]),
|
||||
new("image/x-pcx", [".pcx"]),
|
||||
new("image/x-pentax-pef", [".pef", ".ptx"]),
|
||||
new("image/x-pict", [".pct", ".pic"]),
|
||||
new("image/x-portable-anymap", [".pnm"]),
|
||||
new("image/x-portable-bitmap", [".pbm"]),
|
||||
new("image/x-portable-graymap", [".pgm"]),
|
||||
new("image/x-portable-pixmap", [".ppm"]),
|
||||
new("image/x-rgb", [".rgb"]),
|
||||
new("image/x-sigma-x3f", [".x3f"]),
|
||||
new("image/x-sony-arw", [".arw"]),
|
||||
new("image/x-sony-sr2", [".sr2"]),
|
||||
new("image/x-sony-srf", [".srf"]),
|
||||
new("image/x-xbitmap", [".xbm"]),
|
||||
new("image/x-xpixmap", [".xpm"]),
|
||||
new("image/x-xwindowdump", [".xwd"])
|
||||
];
|
||||
|
||||
static readonly MimeTypeMap[] VideoMime = [
|
||||
new("video/3gpp", [".3gp"]),
|
||||
new("video/3gpp2", [".3g2"]),
|
||||
new("video/h261", [".h261"]),
|
||||
new("video/h263", [".h263"]),
|
||||
new("video/h264", [".h264"]),
|
||||
new("video/jpeg", [".jpgv"]),
|
||||
new("video/jpm", [".jpgm, .jpm"]),
|
||||
new("video/mj2", [".mj2, .mjp2"]),
|
||||
new("video/mp2t", [".ts"]),
|
||||
new("video/mp4", [".mp4, .mp4v, .mpg4"]),
|
||||
new("video/mpeg", [".m1v, .m2v, .mpa, .mpe, .mpeg, .mpg"]),
|
||||
new("video/ogg", [".ogv"]),
|
||||
new("video/quicktime", [".mov", ".qt"]),
|
||||
new("video/vnd.fvt", [".fvt"]),
|
||||
new("video/vnd.mpegurl", [".m4u", ".mxu"]),
|
||||
new("video/vnd.ms-playready.media.pyv", [".pyv"]),
|
||||
new("video/vnd.vivo", [".viv"]),
|
||||
new("video/webm", [".webm"]),
|
||||
new("video/x-f4v", [".f4v"]),
|
||||
new("video/x-fli", [".fli"]),
|
||||
new("video/x-flv", [".flv"]),
|
||||
new("video/x-m4v", [".m4v"]),
|
||||
new("video/x-matroska", [".mkv"]),
|
||||
new("video/x-ms-asf", [".asf", ".asx"]),
|
||||
new("video/x-ms-wm", [".wm"]),
|
||||
new("video/x-ms-wmv", [".wmv"]),
|
||||
new("video/x-ms-wmx", [".wmx"]),
|
||||
new("video/x-ms-wvx", [".wvx"]),
|
||||
new("video/x-msvideo", [".avi"]),
|
||||
new("video/x-sgi-movie", [".movie"])
|
||||
];
|
||||
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken) {
|
||||
// Resolve the repositories from the service provider
|
||||
var settingsRepository = serviceProvider.GetRequiredService<ISettingsRepository>();
|
||||
|
||||
if (settingsRepository.Get(Settings.FolderScanEnabled.AsString())?.Value == "false") {
|
||||
logger.LogInformation("Folder scanning is disabled. Service will not start.");
|
||||
return Task.CompletedTask;
|
||||
@@ -128,10 +32,14 @@ public class FileSystemScannerService(
|
||||
|
||||
//TODO: This really needs a decent name.
|
||||
void ServiceLogic(CancellationToken stoppingToken) {
|
||||
// Resolve the repositories from the service provider
|
||||
using var folderRepository = serviceProvider.GetRequiredService<IFolderRepository>();
|
||||
using var settingsRepository = serviceProvider.GetRequiredService<ISettingsRepository>();
|
||||
PeriodicTimer scanTimer;
|
||||
logger.LogInformation("Filesystem Scan Service starting...");
|
||||
|
||||
var value = settingsRepository.Get(Settings.FolderScanInterval.AsString())?.Value;
|
||||
|
||||
if (value != null && !int.TryParse(value, out var interval)) {
|
||||
logger.LogWarning("Invalid scan interval setting. Defaulting to 30 minutes.");
|
||||
interval = 30; // Default to 30 minutes if parsing fails
|
||||
@@ -145,6 +53,7 @@ public class FileSystemScannerService(
|
||||
while (!stoppingToken.IsCancellationRequested) {
|
||||
logger.LogInformation("Retrieving folder paths to scan...");
|
||||
folders = folderRepository.GetAll().ToList();
|
||||
|
||||
// Wait for all tasks to complete before starting a new scan
|
||||
if (tasks.Count > 0) {
|
||||
logger.LogInformation("Waiting for {count} tasks to complete...", tasks.Count);
|
||||
@@ -166,6 +75,8 @@ public class FileSystemScannerService(
|
||||
}
|
||||
|
||||
void ScanFolder(string path) {
|
||||
using var assetRepository = serviceProvider.GetRequiredService<IAssetRepository>();
|
||||
|
||||
List<string> filePaths = [];
|
||||
List<string> folderPaths = [];
|
||||
|
||||
@@ -179,8 +90,7 @@ public class FileSystemScannerService(
|
||||
folderPaths.ForEach(folderPath => { tasks.Add(Task.Run(() => ScanFolder(folderPath))); });
|
||||
|
||||
// Process all files
|
||||
filePaths.ForEach(
|
||||
filePath => {
|
||||
filePaths.ForEach(filePath => {
|
||||
// Check if the file is already in the database
|
||||
if (assetRepository.FindByPath(filePath) != null) return;
|
||||
|
||||
@@ -192,8 +102,8 @@ public class FileSystemScannerService(
|
||||
EAssetType? type;
|
||||
|
||||
// ReSharper disable ArrangeObjectCreationWhenTypeNotEvident
|
||||
var mimeImg = ImageMime.FirstOrDefault(mime => mime.Extensions.Contains(ext), new(Empty, []));
|
||||
var mimeVid = VideoMime.FirstOrDefault(mime => mime.Extensions.Contains(ext), new(Empty, []));
|
||||
var mimeImg = MimeTypes.Image.FirstOrDefault(mime => mime.Extensions.Contains(ext), new(Empty, []));
|
||||
var mimeVid = MimeTypes.Video.FirstOrDefault(mime => mime.Extensions.Contains(ext), new(Empty, []));
|
||||
|
||||
if (mimeImg.MimeType != Empty) type = EAssetType.Image;
|
||||
else if (mimeVid.MimeType != Empty) type = EAssetType.Video;
|
||||
@@ -218,15 +128,10 @@ public class FileSystemScannerService(
|
||||
|
||||
//TODO: check if the file is already in the database
|
||||
// Add the asset to the database
|
||||
try { assetRepository.Insert(asset); }
|
||||
catch (DuplicateNameException e) {
|
||||
logger.LogError(e, $"Duplicate asset name \"{finfo.FullName}\", skipped."); }
|
||||
try { assetRepository.Insert(asset); } catch (DuplicateNameException e) {
|
||||
logger.LogError(e, $"Duplicate asset name \"{finfo.FullName}\", skipped.");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public struct MimeTypeMap(string mimeType, string[] extensions) {
|
||||
public string MimeType { get; set; } = mimeType;
|
||||
public string[] Extensions { get; set; } = extensions;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user