283 lines
13 KiB
C#
283 lines
13 KiB
C#
using ImmichToSlideshow.Domain;
|
|
using ImmichToSlideshow.Models;
|
|
using ImmichToSlideshow.Models.Immich;
|
|
using Npgsql;
|
|
using System.Collections.ObjectModel;
|
|
using System.Data;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
|
|
namespace ImmichToSlideshow.Services;
|
|
|
|
public class AssetService(ILogger<Program> logger, AppSettings appSettings) {
|
|
|
|
#pragma warning disable CS9124
|
|
private readonly ILogger<Program> _Logger = logger;
|
|
private readonly Settings _Settings = appSettings.Settings;
|
|
#pragma warning restore CS9124
|
|
|
|
private static int? ExecuteNonQuery(string connectionString, string commandText, ReadOnlyCollection<NpgsqlParameter> npgsqlParameters) {
|
|
int? result;
|
|
if (string.IsNullOrEmpty(connectionString)) {
|
|
result = null;
|
|
} else {
|
|
using NpgsqlConnection npgsqlConnection = new(connectionString);
|
|
npgsqlConnection.Open();
|
|
using NpgsqlCommand npgsqlCommand = new(commandText, npgsqlConnection);
|
|
npgsqlCommand.Parameters.AddRange(npgsqlParameters.ToArray());
|
|
result = npgsqlCommand.ExecuteNonQuery();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
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()) {
|
|
_ = result.Append(npgsqlDataReader.GetString(0));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public string? GetColumns() {
|
|
string result;
|
|
NpgsqlParameter[] npgsqlParameters = [];
|
|
string commandText = CommandText.GetColumns();
|
|
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
result = stringBuilder.ToString();
|
|
if (result.Length == 1) {
|
|
File.WriteAllText(".vscode/jsonl/.jsonl", result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public string? GetOwnerIds() {
|
|
string result;
|
|
NpgsqlParameter[] npgsqlParameters = [];
|
|
string commandText = CommandText.GetOwnerIdActiveImage(_Settings.LowestVersionHistory);
|
|
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
result = stringBuilder.ToString();
|
|
if (result.Length == 1) {
|
|
File.WriteAllText(".vscode/jsonl/.jsonl", result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public string? GetAssets(Guid ownerId) {
|
|
string result;
|
|
ReadOnlyCollection<string> people = Array.Empty<string>().AsReadOnly();
|
|
NpgsqlParameter[] npgsqlParameters = [new NpgsqlParameter(nameof(ownerId), ownerId)];
|
|
string commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_Settings.LowestVersionHistory, _Settings.FilterTags.AsReadOnly(), people);
|
|
StringBuilder stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
result = stringBuilder.ToString();
|
|
if (result.Length == 1) {
|
|
File.WriteAllText(".vscode/jsonl/assets.jsonl", result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public ReadOnlyCollection<string>? GetRandomPaths(Guid ownerId, string? monthDay) {
|
|
string[]? results;
|
|
string commandText;
|
|
Random random = new();
|
|
List<string> people = [];
|
|
StringBuilder stringBuilder;
|
|
if (!string.IsNullOrEmpty(monthDay)) {
|
|
foreach (KeyValuePair<string, string> keyValuePair in _Settings.People) {
|
|
if (!keyValuePair.Key.Contains(monthDay)) {
|
|
continue;
|
|
}
|
|
people.Add($"People/{keyValuePair.Value.Trim('/')}");
|
|
}
|
|
}
|
|
try {
|
|
NpgsqlParameter[] npgsqlParameters = [new NpgsqlParameter(nameof(ownerId), ownerId)];
|
|
commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_Settings.LowestVersionHistory, _Settings.FilterTags.AsReadOnly(), people.AsReadOnly());
|
|
stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
} catch (Exception) {
|
|
people.Clear();
|
|
NpgsqlParameter[] npgsqlParameters = [new NpgsqlParameter(nameof(ownerId), ownerId)];
|
|
commandText = CommandText.GetAssetActiveImagePreviewNotDuplicate(_Settings.LowestVersionHistory, _Settings.FilterTags.AsReadOnly(), people.AsReadOnly());
|
|
stringBuilder = GetForJsonPath(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
}
|
|
string json = stringBuilder.ToString();
|
|
string ownerIdValue = ownerId.ToString();
|
|
Asset[]? assets = JsonSerializer.Deserialize(json, AssetCollectionSourceGenerationContext.Default.AssetArray);
|
|
results = assets is null ? null : (from l in assets orderby random.NextSingle() select l.Path.Split(ownerIdValue)[1]).ToArray();
|
|
return results?.AsReadOnly();
|
|
}
|
|
|
|
public Tag[]? GetArchivedTag(Settings settings, Guid ownerId) {
|
|
Tag[]? results;
|
|
Guid userId = ownerId;
|
|
string value = settings.ArchivedTag;
|
|
NpgsqlParameter[] npgsqlParameters = [
|
|
new NpgsqlParameter(nameof(value), value),
|
|
new NpgsqlParameter(nameof(userId), userId),
|
|
];
|
|
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(_Settings, ownerId);
|
|
result = tags is null || tags.Length != 1 ? null : tags[0].Id;
|
|
return result;
|
|
}
|
|
|
|
public string? SaveRandomPaths(Guid ownerId, string? monthDay) {
|
|
string? results = null;
|
|
FileInfo fileInfo;
|
|
DateTime dateTime = DateTime.Now;
|
|
ReadOnlyCollection<string>? paths;
|
|
bool? check = monthDay is null ? null : monthDay == "00-00";
|
|
if (Directory.Exists(_Settings.RandomResultsDirectory)) {
|
|
_ = Directory.CreateDirectory(_Settings.RandomResultsDirectory);
|
|
}
|
|
for (int i = 0; i < 366; i++) {
|
|
if (check is null || check.Value) {
|
|
monthDay = i == 0 && check is not null && check.Value ? "02-29" : dateTime.AddDays(i).ToString("MM-dd");
|
|
}
|
|
fileInfo = new(Path.Combine(_Settings.RandomResultsDirectory, $"{monthDay}.json"));
|
|
if (fileInfo.Exists && fileInfo.CreationTime > dateTime.AddDays(_Settings.AddDays)) {
|
|
results = null;
|
|
} else {
|
|
_Logger.LogDebug("Writing <{FullName}>", fileInfo.FullName);
|
|
paths = GetRandomPaths(ownerId, monthDay);
|
|
if (paths is null) {
|
|
results = null;
|
|
} else {
|
|
_Logger.LogInformation("{count} path(s)", paths.Count.ToString());
|
|
results = JsonSerializer.Serialize(paths);
|
|
File.WriteAllText(fileInfo.FullName, results);
|
|
}
|
|
}
|
|
if (check is null || !check.Value) {
|
|
break;
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
private record Record(string Source, string Destination);
|
|
|
|
public ReadOnlyCollection<string> SyncImmich(Guid ownerId) {
|
|
List<string> results = [];
|
|
Record record;
|
|
List<Record> records = [];
|
|
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(_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])) {
|
|
continue;
|
|
}
|
|
results.Add(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++) {
|
|
record = records[i];
|
|
_Logger.LogDebug("Copying <{source}>", record.Source);
|
|
File.Copy(record.Source, record.Destination);
|
|
}
|
|
return results.AsReadOnly();
|
|
}
|
|
|
|
public ReadOnlyCollection<int>? SetArchiveImmich(Guid ownerId) {
|
|
ReadOnlyCollection<int>? results;
|
|
if (!File.Exists(_Settings.NotNinePath)) {
|
|
results = null;
|
|
} else {
|
|
string json = File.ReadAllText(_Settings.NotNinePath);
|
|
Identifier[]? identifiers = JsonSerializer.Deserialize<Identifier[]>(json);
|
|
if (identifiers is null || identifiers.Length == 0) {
|
|
results = null;
|
|
} else {
|
|
Tag[]? tags = GetArchivedTag(_Settings, ownerId);
|
|
if (tags is null || tags.Length != 1) {
|
|
results = null;
|
|
} else {
|
|
results = SetArchiveImmich(logger, _Settings, ownerId, identifiers.AsReadOnly(), tags.AsReadOnly());
|
|
}
|
|
}
|
|
}
|
|
return results?.AsReadOnly();
|
|
}
|
|
|
|
private static ReadOnlyCollection<int>? SetArchiveImmich(ILogger<Program> logger, Settings settings, Guid ownerId, string tagsId, string deviceAssetIds) {
|
|
ReadOnlyCollection<int>? results;
|
|
NpgsqlParameter[] npgsqlParameters = [
|
|
new NpgsqlParameter(nameof(tagsId), tagsId),
|
|
new NpgsqlParameter(nameof(ownerId), ownerId),
|
|
];
|
|
string commandText = CommandText.SetAssetArchived(settings.LowestVersionHistory, deviceAssetIds);
|
|
logger.LogDebug(commandText.Replace($"@{nameof(tagsId)}", $"'{tagsId}'").Replace($"@{nameof(ownerId)}", $"'{ownerId}'".ToString()));
|
|
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();
|
|
}
|
|
|
|
public ReadOnlyCollection<int>? UpdateAssetsSetLocalDateTimeForThreeAndSeven() {
|
|
ReadOnlyCollection<int>? results;
|
|
NpgsqlParameter[] npgsqlParameters = [];
|
|
string commandText = CommandText.UpdateAssetsSetLocalDateTimeForThreeAndSeven(_Settings.LowestVersionHistory);
|
|
int? result = ExecuteNonQuery(_Settings.ConnectionString, commandText, npgsqlParameters.AsReadOnly());
|
|
results = result is null ? null : new([result.Value]);
|
|
return results?.AsReadOnly();
|
|
}
|
|
|
|
} |