DigiKam4 Archive

Change to only need the one json file and changed AppSettings to not need a binder file

Editorconfig for no new line before open braces

Nuget package bumps

Database lowest-version-history
This commit is contained in:
2025-07-27 16:03:47 -07:00
parent ab90adee42
commit c4d42d79a0
31 changed files with 644 additions and 458 deletions

View File

@ -1,3 +1,4 @@
using ImmichToSlideshow.Domain;
using ImmichToSlideshow.Models;
using ImmichToSlideshow.Models.Immich;
using Npgsql;
@ -8,21 +9,18 @@ using System.Text.Json;
namespace ImmichToSlideshow.Services;
public class AssetService(ILogger<Program> logger, AppSettings appSettings)
{
public class AssetService(ILogger<Program> logger, AppSettings appSettings) {
#pragma warning disable CS9124
private readonly ILogger<Program> _Logger = logger;
private readonly AppSettings _AppSettings = appSettings;
private readonly Settings _Settings = appSettings.Settings;
#pragma warning restore CS9124
private static int? ExecuteNonQuery(string connectionString, string commandText, ReadOnlyCollection<NpgsqlParameter> npgsqlParameters)
{
private static int? ExecuteNonQuery(string connectionString, string commandText, ReadOnlyCollection<NpgsqlParameter> npgsqlParameters) {
int? result;
if (string.IsNullOrEmpty(connectionString))
if (string.IsNullOrEmpty(connectionString)) {
result = null;
else
{
} else {
using NpgsqlConnection npgsqlConnection = new(connectionString);
npgsqlConnection.Open();
using NpgsqlCommand npgsqlCommand = new(commandText, npgsqlConnection);
@ -32,61 +30,60 @@ public class AssetService(ILogger<Program> logger, AppSettings appSettings)
return result;
}
private static StringBuilder GetForJsonPath(string connectionString, string commandText, ReadOnlyCollection<NpgsqlParameter> npgsqlParameters)
{
private static StringBuilder GetForJsonPath(string connectionString, string commandText, ReadOnlyCollection<NpgsqlParameter> npgsqlParameters) {
StringBuilder result = new();
using NpgsqlConnection npgsqlConnection = new(connectionString);
npgsqlConnection.Open();
using NpgsqlCommand npgsqlCommand = new(commandText, npgsqlConnection);
npgsqlCommand.Parameters.AddRange(npgsqlParameters.ToArray());
NpgsqlDataReader npgsqlDataReader = npgsqlCommand.ExecuteReader(CommandBehavior.SequentialAccess);
while (npgsqlDataReader.Read())
while (npgsqlDataReader.Read()) {
_ = result.Append(npgsqlDataReader.GetString(0));
}
return result;
}
public string? GetColumns()
{
public string? GetColumns() {
string result;
NpgsqlParameter[] npgsqlParameters = [];
string commandText = CommandText.GetColumns();
StringBuilder stringBuilder = GetForJsonPath(_AppSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
result = stringBuilder.ToString();
if (result.Length == 1)
if (result.Length == 1) {
File.WriteAllText(".vscode/jsonl/.jsonl", result);
}
return result;
}
public string? GetOwnerIds()
{
public string? GetOwnerIds() {
string result;
NpgsqlParameter[] npgsqlParameters = [];
string commandText = CommandText.GetOwnerIdActiveImage();
StringBuilder stringBuilder = GetForJsonPath(_AppSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string commandText = CommandText.GetOwnerIdActiveImage(_Settings.LowestVersionHistory);
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
result = stringBuilder.ToString();
if (result.Length == 1)
if (result.Length == 1) {
File.WriteAllText(".vscode/jsonl/.jsonl", result);
}
return result;
}
public string? GetAssets(Guid ownerId)
{
public string? GetAssets(Guid ownerId) {
string result;
NpgsqlParameter[] npgsqlParameters = [new NpgsqlParameter(nameof(ownerId), ownerId)];
string commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_AppSettings.FilterTags);
StringBuilder stringBuilder = GetForJsonPath(_AppSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_Settings.LowestVersionHistory, _Settings.FilterTags);
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
result = stringBuilder.ToString();
if (result.Length == 1)
if (result.Length == 1) {
File.WriteAllText(".vscode/jsonl/assets.jsonl", result);
}
return result;
}
public ReadOnlyCollection<string>? GetRandomPaths(Guid ownerId)
{
public ReadOnlyCollection<string>? GetRandomPaths(Guid ownerId) {
string[]? results;
NpgsqlParameter[] npgsqlParameters = [new NpgsqlParameter(nameof(ownerId), ownerId)];
string commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_AppSettings.FilterTags);
StringBuilder stringBuilder = GetForJsonPath(_AppSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_Settings.LowestVersionHistory, _Settings.FilterTags);
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string json = stringBuilder.ToString();
Random random = new();
string ownerIdValue = ownerId.ToString();
@ -95,49 +92,44 @@ public class AssetService(ILogger<Program> logger, AppSettings appSettings)
return results?.AsReadOnly();
}
public Tag[]? GetArchivedTag(AppSettings appSettings, Guid ownerId)
{
Tag[] results;
public Tag[]? GetArchivedTag(Settings settings, Guid ownerId) {
Tag[]? results;
Guid userId = ownerId;
string value = appSettings.ArchivedTag;
NpgsqlParameter[] npgsqlParameters =
[
string value = settings.ArchivedTag;
NpgsqlParameter[] npgsqlParameters = [
new NpgsqlParameter(nameof(value), value),
new NpgsqlParameter(nameof(userId), userId),
];
string commandText = CommandText.GetArchivedTag();
StringBuilder stringBuilder = GetForJsonPath(appSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string commandText = CommandText.GetArchivedTag(_Settings.LowestVersionHistory);
StringBuilder stringBuilder = GetForJsonPath(settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
string json = stringBuilder.ToString();
results = JsonSerializer.Deserialize(json, TagCollectionSourceGenerationContext.Default.TagArray);
return results;
}
public string? GetArchivedTag(Guid ownerId)
{
string result;
Tag[]? tags = GetArchivedTag(_AppSettings, ownerId);
public string? GetArchivedTag(Guid ownerId) {
string? result;
Tag[]? tags = GetArchivedTag(_Settings, ownerId);
result = tags is null || tags.Length != 1 ? null : tags[0].Id;
return result;
}
public string? SaveRandomPaths(Guid ownerId)
{
public string? SaveRandomPaths(Guid ownerId) {
string? results;
DateTime dateTime = DateTime.Now;
string tomorrow = dateTime.AddDays(1).ToString("MM-dd");
if (Directory.Exists(_AppSettings.RandomResultsDirectory))
_ = Directory.CreateDirectory(_AppSettings.RandomResultsDirectory);
FileInfo fileInfo = new(Path.Combine(_AppSettings.RandomResultsDirectory, $"{tomorrow}.json"));
if (fileInfo.Exists && fileInfo.CreationTime > dateTime.AddDays(_AppSettings.AddDays))
if (Directory.Exists(_Settings.RandomResultsDirectory)) {
_ = Directory.CreateDirectory(_Settings.RandomResultsDirectory);
}
FileInfo fileInfo = new(Path.Combine(_Settings.RandomResultsDirectory, $"{tomorrow}.json"));
if (fileInfo.Exists && fileInfo.CreationTime > dateTime.AddDays(_Settings.AddDays)) {
results = null;
else
{
} else {
_Logger.LogDebug("Writing <{FullName}>", fileInfo.FullName);
ReadOnlyCollection<string>? paths = GetRandomPaths(ownerId);
if (paths is null)
if (paths is null) {
results = null;
else
{
} else {
_Logger.LogInformation("{count} path(s)", paths.Count.ToString());
results = JsonSerializer.Serialize(paths);
File.WriteAllText(fileInfo.FullName, results);
@ -148,32 +140,32 @@ public class AssetService(ILogger<Program> logger, AppSettings appSettings)
private record Record(string Source, string Destination);
public ReadOnlyCollection<string> SyncImmich(Guid ownerId)
{
public ReadOnlyCollection<string> SyncImmich(Guid ownerId) {
List<string> results = [];
Record record;
List<Record> records = [];
if (Directory.Exists(_AppSettings.SyncDirectory))
_ = Directory.CreateDirectory(_AppSettings.SyncDirectory);
int syncLength = _AppSettings.SyncDirectory.Length;
string[] syncFiles = Directory.GetFiles(_AppSettings.SyncDirectory, "*", SearchOption.AllDirectories);
if (Directory.Exists(_Settings.SyncDirectory)) {
_ = Directory.CreateDirectory(_Settings.SyncDirectory);
}
int syncLength = _Settings.SyncDirectory.Length;
string[] syncFiles = Directory.GetFiles(_Settings.SyncDirectory, "*", SearchOption.AllDirectories);
string[] syncCheck = syncFiles.Select(l => l[syncLength..]).ToArray();
if (Directory.Exists(_AppSettings.ImmichUploadDirectory))
_ = Directory.CreateDirectory(_AppSettings.ImmichUploadDirectory);
int immichUploadLength = _AppSettings.ImmichUploadDirectory.Length;
string[] immichUploadFiles = Directory.GetFiles(_AppSettings.ImmichUploadDirectory, "*", SearchOption.AllDirectories);
if (Directory.Exists(_Settings.ImmichUploadDirectory)) {
_ = Directory.CreateDirectory(_Settings.ImmichUploadDirectory);
}
int immichUploadLength = _Settings.ImmichUploadDirectory.Length;
string[] immichUploadFiles = Directory.GetFiles(_Settings.ImmichUploadDirectory, "*", SearchOption.AllDirectories);
string[] immichUploadCheck = immichUploadFiles.Select(l => l[immichUploadLength..]).ToArray();
for (int i = 0; i < immichUploadFiles.Length; i++)
{
if (syncCheck.Contains(immichUploadCheck[i]))
for (int i = 0; i < immichUploadFiles.Length; i++) {
if (syncCheck.Contains(immichUploadCheck[i])) {
continue;
}
results.Add(immichUploadCheck[i]);
record = new(immichUploadFiles[i], string.Concat(_AppSettings.SyncDirectory, immichUploadCheck[i]));
record = new(immichUploadFiles[i], string.Concat(_Settings.SyncDirectory, immichUploadCheck[i]));
records.Add(record);
}
_Logger.LogInformation("{count} file(s)", results.Count.ToString());
for (int i = 0; i < records.Count; i++)
{
for (int i = 0; i < records.Count; i++) {
record = records[i];
_Logger.LogDebug("Copying <{source}>", record.Source);
File.Copy(record.Source, record.Destination);
@ -181,51 +173,73 @@ public class AssetService(ILogger<Program> logger, AppSettings appSettings)
return results.AsReadOnly();
}
public ReadOnlyCollection<int> SetArchiveImmich(Guid ownerId)
{
public ReadOnlyCollection<int>? SetArchiveImmich(Guid ownerId) {
ReadOnlyCollection<int>? results;
string checkDirectory = Path.Combine(_AppSettings.CurrentResultsDirectory, "B)Metadata", _AppSettings.CurrentCommit, "[]");
if (!Directory.Exists(checkDirectory))
if (!File.Exists(_Settings.NotNinePath)) {
results = null;
else
{
string checkFile = Path.Combine(checkDirectory, "!9.json");
if (!File.Exists(checkFile))
} else {
string json = File.ReadAllText(_Settings.NotNinePath);
Identifier[]? identifiers = JsonSerializer.Deserialize<Identifier[]>(json);
if (identifiers is null || identifiers.Length == 0) {
results = null;
else
{
string json = File.ReadAllText(checkFile);
Identifier[]? identifiers = JsonSerializer.Deserialize<Identifier[]>(json);
if (identifiers is null || identifiers.Length == 0)
} else {
Tag[]? tags = GetArchivedTag(_Settings, ownerId);
if (tags is null || tags.Length != 1) {
results = null;
else
{
Tag[]? tags = GetArchivedTag(_AppSettings, ownerId);
if (tags is null || tags.Length != 1)
results = null;
else
results = SetArchiveImmich(logger, appSettings, ownerId, identifiers.AsReadOnly(), tags.AsReadOnly());
} else {
results = SetArchiveImmich(logger, _Settings, ownerId, identifiers.AsReadOnly(), tags.AsReadOnly());
}
}
}
return results?.AsReadOnly();
}
private static ReadOnlyCollection<int> SetArchiveImmich(ILogger<Program> logger, AppSettings appSettings, Guid ownerId, ReadOnlyCollection<Identifier> identifiers, ReadOnlyCollection<Tag> tags)
{
private static ReadOnlyCollection<int>? SetArchiveImmich(ILogger<Program> logger, Settings settings, Guid ownerId, string tagsId, string deviceAssetIds) {
ReadOnlyCollection<int>? results;
string tagsId = tags[0].Id;
NpgsqlParameter[] npgsqlParameters =
[
NpgsqlParameter[] npgsqlParameters = [
new NpgsqlParameter(nameof(tagsId), tagsId),
new NpgsqlParameter(nameof(ownerId), ownerId),
];
string deviceAssetIds = Identifier.GetDeviceAssetIds(identifiers);
string commandText = CommandText.SetAssetArchived(deviceAssetIds);
string commandText = CommandText.SetAssetArchived(settings.LowestVersionHistory, deviceAssetIds);
logger.LogDebug(commandText.Replace($"@{nameof(tagsId)}", $"'{tagsId}'").Replace($"@{nameof(ownerId)}", $"'{ownerId}'".ToString()));
int? result = ExecuteNonQuery(appSettings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
int? result = ExecuteNonQuery(settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
results = result is null ? null : new([result.Value]);
return results?.AsReadOnly();
}
private static ReadOnlyCollection<int>? SetArchiveImmich(ILogger<Program> logger, Settings settings, Guid ownerId, ReadOnlyCollection<Identifier> identifiers, ReadOnlyCollection<Tag> tags) {
ReadOnlyCollection<int>? results;
string tagsId = tags[0].Id;
string deviceAssetIds = Identifier.GetDeviceAssetIds(identifiers);
results = SetArchiveImmich(logger, settings, ownerId, tagsId, deviceAssetIds);
return results?.AsReadOnly();
}
public ReadOnlyCollection<int>? SetDigiKam4ArchiveImmich(Guid ownerId) {
ReadOnlyCollection<int>? results;
ReadOnlyCollection<ImageTag>? imageTags = ImageTag.Get(tag: _Settings.ArchivedTag,
tagsPath: _Settings.DigiKam4?.Tags,
imageTagsPath: _Settings.DigiKam4?.ImageTags,
imagesPath: _Settings.DigiKam4?.Images);
if (imageTags is null || imageTags.Count == 0) {
results = null;
} else {
Tag[]? tags = GetArchivedTag(_Settings, ownerId);
if (tags is null || tags.Length != 1) {
results = null;
} else {
results = SetArchiveImmich(logger, _Settings, ownerId, imageTags, tags.AsReadOnly());
}
}
return results?.AsReadOnly();
}
private static ReadOnlyCollection<int>? SetArchiveImmich(ILogger<Program> logger, Settings settings, Guid ownerId, ReadOnlyCollection<ImageTag> imageTags, ReadOnlyCollection<Tag> tags) {
ReadOnlyCollection<int>? results;
string tagsId = tags[0].Id;
string deviceAssetIds = Identifier.GetDeviceAssetIds(imageTags);
results = SetArchiveImmich(logger, settings, ownerId, tagsId, deviceAssetIds);
return results?.AsReadOnly();
}
}