[CHANGE] Fixed auditing, storing images from account import
This commit is contained in:
@@ -2,11 +2,13 @@ using DotBased.Monads;
|
||||
using Manager.App.Models.Library;
|
||||
using Manager.App.Models.System;
|
||||
using Manager.Data.Entities.LibraryContext;
|
||||
using Manager.YouTube.Models.Innertube;
|
||||
|
||||
namespace Manager.App.Services;
|
||||
|
||||
public interface ILibraryService
|
||||
{
|
||||
public Task<Result> FetchChannelImagesAsync(Channel channel);
|
||||
public Task<Result<ChannelEntity>> GetChannelByIdAsync(string id, CancellationToken cancellationToken = default);
|
||||
public Task<Result> SaveChannelAsync(ChannelEntity channel, CancellationToken cancellationToken = default);
|
||||
public Task<Result<LibraryInformation>> GetLibraryInfoAsync(CancellationToken cancellationToken = default);
|
||||
|
@@ -1,9 +1,12 @@
|
||||
using DotBased.Monads;
|
||||
using Manager.App.Constants;
|
||||
using Manager.App.Models.Library;
|
||||
using Manager.App.Models.Settings;
|
||||
using Manager.App.Models.System;
|
||||
using Manager.Data.Contexts;
|
||||
using Manager.Data.Entities.LibraryContext;
|
||||
using Manager.YouTube;
|
||||
using Manager.YouTube.Models.Innertube;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -15,8 +18,7 @@ public class LibraryService : ILibraryService
|
||||
private readonly LibrarySettings _librarySettings;
|
||||
private readonly IDbContextFactory<LibraryDbContext> _dbContextFactory;
|
||||
private readonly DirectoryInfo _libraryDirectory;
|
||||
private const string SubDirMedia = "Media";
|
||||
private const string SubDirChannels = "Channels";
|
||||
|
||||
|
||||
public LibraryService(ILogger<LibraryService> logger, IOptions<LibrarySettings> librarySettings, IDbContextFactory<LibraryDbContext> contextFactory)
|
||||
{
|
||||
@@ -25,8 +27,76 @@ public class LibraryService : ILibraryService
|
||||
_dbContextFactory = contextFactory;
|
||||
_libraryDirectory = Directory.CreateDirectory(_librarySettings.Path);
|
||||
logger.LogDebug("Working dir for library: {LibraryWorkingDir}", _libraryDirectory.FullName);
|
||||
Directory.CreateDirectory(Path.Combine(_librarySettings.Path, SubDirMedia));
|
||||
Directory.CreateDirectory(Path.Combine(_librarySettings.Path, SubDirChannels));
|
||||
Directory.CreateDirectory(Path.Combine(_librarySettings.Path, LibraryConstants.Directories.SubDirMedia));
|
||||
Directory.CreateDirectory(Path.Combine(_librarySettings.Path, LibraryConstants.Directories.SubDirChannels));
|
||||
}
|
||||
|
||||
public async Task<Result> FetchChannelImagesAsync(Channel channel)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
await AddWebImagesAsync(context, channel.AvatarImages, channel.Id, "avatars", LibraryConstants.FileTypes.ChannelAvatar, LibraryConstants.Directories.SubDirChannels);
|
||||
await AddWebImagesAsync(context, channel.BannerImages, channel.Id, "banners", LibraryConstants.FileTypes.ChannelBanner, LibraryConstants.Directories.SubDirChannels);
|
||||
|
||||
if (!context.ChangeTracker.HasChanges())
|
||||
{
|
||||
_logger.LogInformation("No changes detected. Skipping.");
|
||||
return Result.Success();
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return ResultError.Error(e);
|
||||
}
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
|
||||
private async Task AddWebImagesAsync(LibraryDbContext context, List<WebImage> images, string foreignKey, string libSubDir, string fileType, string subDir)
|
||||
{
|
||||
foreach (var image in images)
|
||||
{
|
||||
if (context.Files.Any(f => image.Url.Equals(f.OriginalUrl, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var downloadResult = await NetworkService.DownloadBytesAsync(new HttpRequestMessage(HttpMethod.Get, image.Url));
|
||||
if (!downloadResult.IsSuccess)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var download = downloadResult.Value;
|
||||
|
||||
var fileId = Guid.NewGuid();
|
||||
var fileName = download.FileName ?? $"{fileId}.{download.ContentType?.Split('/').Last() ?? "unknown"}";
|
||||
var relativePath = Path.Combine(foreignKey, libSubDir, $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}_{fileName}");
|
||||
var savePath = Path.Combine(_libraryDirectory.FullName, subDir, relativePath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(savePath) ?? savePath);
|
||||
await using var fileStream = File.Create(savePath);
|
||||
await fileStream.WriteAsync(download.Data.AsMemory(0, download.Data.Length));
|
||||
|
||||
var file = new FileEntity
|
||||
{
|
||||
Id = fileId,
|
||||
OriginalUrl = image.Url,
|
||||
OriginalFileName = download.FileName,
|
||||
ForeignKey = foreignKey,
|
||||
FileType = fileType,
|
||||
RelativePath = relativePath.Replace('\\', '/'),
|
||||
MimeType = download.ContentType,
|
||||
SizeBytes = download.ContentLength,
|
||||
Height = image.Height,
|
||||
Width = image.Width
|
||||
};
|
||||
|
||||
await context.Files.AddAsync(file);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<ChannelEntity>> GetChannelByIdAsync(string id, CancellationToken cancellationToken = default)
|
||||
@@ -68,7 +138,7 @@ public class LibraryService : ILibraryService
|
||||
}
|
||||
|
||||
var changed = await context.SaveChangesAsync(cancellationToken);
|
||||
return changed <= 0 ? Result.Success() : ResultError.Fail("Failed to save channel!");
|
||||
return changed <= 0 ? ResultError.Fail("Failed to save channel!") : Result.Success();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@@ -46,20 +46,29 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
||||
LogEvent("Failed to store client no ID!", LogSeverity.Warning);
|
||||
return ResultError.Fail("Client does not have an ID, cannot save to library database!");
|
||||
}
|
||||
|
||||
if (channelInfo != null)
|
||||
{
|
||||
var imagesResult = await _libraryService.FetchChannelImagesAsync(channelInfo);
|
||||
if (!imagesResult.IsSuccess)
|
||||
{
|
||||
logger.LogWarning("Failed to fetch channel images!");
|
||||
}
|
||||
}
|
||||
|
||||
var channelResult = await _libraryService.GetChannelByIdAsync(client.Id, cancellationToken);
|
||||
|
||||
ChannelEntity? channel;
|
||||
ChannelEntity? channelEntity;
|
||||
try
|
||||
{
|
||||
if (channelResult.IsSuccess)
|
||||
{
|
||||
channel = channelResult.Value;
|
||||
UpdateChannelEntity(client, channel, channelInfo);
|
||||
channelEntity = channelResult.Value;
|
||||
UpdateChannelEntity(client, channelEntity, channelInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
channel = CreateNewChannelFromClient(client, channelInfo);
|
||||
channelEntity = CreateNewChannelFromClient(client, channelInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -68,7 +77,7 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
||||
return ResultError.Error(e);
|
||||
}
|
||||
|
||||
var saveResult = await _libraryService.SaveChannelAsync(channel, cancellationToken);
|
||||
var saveResult = await _libraryService.SaveChannelAsync(channelEntity, cancellationToken);
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
@@ -113,7 +122,7 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
||||
{
|
||||
if (channelInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(channelInfo), "Channel information required to store new client/account.");
|
||||
throw new ArgumentNullException(nameof(channelInfo), "Channel information is required to store new client/account.");
|
||||
}
|
||||
|
||||
var cookies = new List<HttpCookieEntity>();
|
||||
@@ -147,7 +156,7 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
||||
|
||||
var channel = new ChannelEntity
|
||||
{
|
||||
Id = client.Id,
|
||||
Id = channelInfo.Id,
|
||||
Name = channelInfo.ChannelName,
|
||||
Handle = channelInfo.Handle,
|
||||
Description = channelInfo.Description,
|
||||
@@ -155,14 +164,4 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
||||
};
|
||||
return channel;
|
||||
}
|
||||
|
||||
/*public async Task<Result<YouTubeClient>> LoadClientByIdAsync(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
return ResultError.Fail("Client ID is empty!");
|
||||
}
|
||||
|
||||
return ResultError.Fail("Not implemented");
|
||||
}*/
|
||||
}
|
Reference in New Issue
Block a user