- Rename the filesystem browse route from /api/asset/fs-browse to /api/asset/directory (controller route, client URL, REST tests, and service log label). - Remove the old /api/asset/browse endpoint and its BrowseAssets/GetDirectoryNames repository code, plus the client BrowseAsync method. Repoint AlbumAssetPicker's admin/curator folder browse to the /directory endpoint. - Drop the now-unused pg_catalog.split_part DbFunction mapping. - Refresh .env GIT_VERSION.
266 lines
13 KiB
C#
266 lines
13 KiB
C#
using Butter.Dtos.Asset;
|
|
using Butter.Types;
|
|
using Lactose.Models;
|
|
|
|
namespace Lactose.Repositories;
|
|
|
|
/// <summary>
|
|
/// Interface for asset repository operations.
|
|
/// </summary>
|
|
public interface IAssetRepository : IDisposable {
|
|
/// <summary>
|
|
/// Finds an asset by its ID.
|
|
/// </summary>
|
|
/// <param name="id">The ID of the asset.</param>
|
|
/// <returns>Null if not found, otherwise the requested asset.</returns>
|
|
public Asset? Find(Guid id);
|
|
|
|
/// <summary>
|
|
/// Finds an asset by its ID, respecting the requesting user's access level.
|
|
/// Returns null if the asset does not exist or is not visible to the user.
|
|
/// </summary>
|
|
/// <param name="id">The ID of the asset.</param>
|
|
/// <param name="userId">The requesting user's ID.</param>
|
|
/// <param name="accessLevel">The requesting user's access level.</param>
|
|
/// <returns>The asset if found and visible; otherwise null.</returns>
|
|
public Asset? FindVisible(Guid id, Guid? userId, EAccessLevel accessLevel);
|
|
|
|
/// <summary>
|
|
/// Finds an asset by its ID with its album navigation properties loaded.
|
|
/// </summary>
|
|
/// <param name="id">The ID of the asset.</param>
|
|
/// <returns>Null if not found, otherwise the requested asset with albums.</returns>
|
|
public Asset? FindWithAlbums(Guid id);
|
|
|
|
/// <summary>
|
|
/// Finds a set of assets by their IDs.
|
|
/// </summary>
|
|
/// <param name="ids">The IDs of the assets.</param>
|
|
/// <returns>A collection of assets with the specified IDs.</returns>
|
|
public IEnumerable<Asset> FindBulk(IEnumerable<Guid> ids);
|
|
|
|
/// <summary>
|
|
/// Finds all assets uploaded by the user.
|
|
/// </summary>
|
|
/// <param name="uploaderId">The ID of the uploader.</param>
|
|
/// <returns>A collection of assets uploaded by the specified user.</returns>
|
|
public IEnumerable<Asset> FindByUploader(Guid uploaderId);
|
|
|
|
/// <summary>
|
|
/// Bulk-updates the visibility of non-deleted assets in the specified albums via a single SQL UPDATE,
|
|
/// respecting the requesting user's access level.
|
|
/// </summary>
|
|
/// <param name="albumIds">The IDs of the albums.</param>
|
|
/// <param name="visibility">The target visibility level.</param>
|
|
/// <param name="userId">The requesting user's ID.</param>
|
|
/// <param name="accessLevel">The requesting user's access level.</param>
|
|
/// <returns>The number of assets updated.</returns>
|
|
public int BulkSetVisibilityByAlbumIds(IEnumerable<Guid> albumIds, EVisibility visibility, Guid? userId, EAccessLevel accessLevel);
|
|
|
|
/// <summary>
|
|
/// Bulk-updates the visibility of non-deleted assets in any album owned by the specified people
|
|
/// via a single SQL UPDATE.
|
|
/// </summary>
|
|
/// <param name="personIds">The IDs of the people whose album assets to update.</param>
|
|
/// <param name="visibility">The target visibility level.</param>
|
|
/// <returns>The number of assets updated.</returns>
|
|
public int BulkSetVisibilityByPersonIds(IEnumerable<Guid> personIds, EVisibility visibility);
|
|
|
|
/// <summary>
|
|
/// Finds all assets created or updated between the given dates.
|
|
/// </summary>
|
|
/// <param name="from">The start date of the range.</param>
|
|
/// <param name="to">The end date of the range.</param>
|
|
/// <returns>A collection of assets created or updated within the specified date range.</returns>
|
|
public IEnumerable<Asset> FindByDateRange(DateTime from, DateTime to);
|
|
|
|
/// <summary>
|
|
/// Finds all assets created or updated between the given dates with pagination.
|
|
/// </summary>
|
|
/// <param name="from">The start date of the range.</param>
|
|
/// <param name="to">The end date of the range.</param>
|
|
/// <param name="pageNumber">The page number for pagination.</param>
|
|
/// <param name="pageSize">The number of items per page.</param>
|
|
/// <returns>A collection of assets created or updated within the specified date range.</returns>
|
|
public IEnumerable<Asset> FindByDateRange(DateTime from, DateTime to, int pageNumber, int pageSize);
|
|
|
|
/// <summary>
|
|
/// Saves all the changes to the model.
|
|
/// </summary>
|
|
void Save();
|
|
|
|
/// <summary>
|
|
/// Inserts a new asset.
|
|
/// </summary>
|
|
/// <param name="asset">The asset to insert.</param>
|
|
public void Insert(Asset asset);
|
|
|
|
/// <summary>
|
|
/// Updates a given asset.
|
|
/// </summary>
|
|
/// <param name="asset">The asset to update.</param>
|
|
public void Update(Asset asset);
|
|
|
|
/// <summary>
|
|
/// Updates a list of assets.
|
|
/// </summary>
|
|
/// <param name="assets">The list of assets to update.</param>
|
|
public void UpdateBulk(IEnumerable<Asset> assets);
|
|
|
|
/// <summary>
|
|
/// Gets an asset by its file path.
|
|
/// </summary>
|
|
/// <param name="filePath">The file path of the asset.</param>
|
|
/// <returns>Null if not found, otherwise the requested asset.</returns>
|
|
Asset? FindByPath(string filePath);
|
|
|
|
/// <summary>
|
|
/// Counts all assets that are missing a perceptual hash (pHash).
|
|
/// </summary>
|
|
int CountAssetsMissingPHash();
|
|
|
|
/// <summary>
|
|
/// Finds a page of assets that are missing a perceptual hash (pHash).
|
|
/// </summary>
|
|
/// <param name="limit">Maximum number of assets to return.</param>
|
|
/// <param name="offset">Number of assets to skip.</param>
|
|
IEnumerable<Asset> GetAssetsMissingPHash(int limit, int offset);
|
|
|
|
/// <summary>
|
|
/// Finds assets within a normalized Hamming distance (0 to 1).
|
|
/// </summary>
|
|
/// <param name="phash">The perceptual hash to compare against.</param>
|
|
/// <param name="distance">The maximum distance as a fraction (0 to 1).</param>
|
|
/// <returns>Assets whose hash is within the specified distance.</returns>
|
|
public IEnumerable<Asset> GetWithinHammingDistance(ulong phash, float distance);
|
|
|
|
/// <summary>
|
|
/// Finds all assets that are missing a thumbnail.
|
|
/// </summary>
|
|
/// <param name="totalAssets">The total number of assets missing thumbnails.</param>
|
|
/// <returns>Assets that do not have a thumbnail path set.</returns>
|
|
IEnumerable<Asset> GetAssetsMissingThumbnail(out int totalAssets);
|
|
|
|
/// <summary>
|
|
/// Counts all assets that need thumbnails — either missing entirely, with wrong dimensions, or wrong format.
|
|
/// </summary>
|
|
/// <param name="thumbnailSize">The expected longest-side size in pixels.</param>
|
|
/// <param name="expectedFormat">The expected thumbnail format (e.g. "webp").</param>
|
|
/// <returns>The total count of assets needing thumbnails.</returns>
|
|
int CountAssetsMissingOrWrongThumbnail(int thumbnailSize, string expectedFormat);
|
|
|
|
/// <summary>
|
|
/// Finds a page of assets that need thumbnails — either missing entirely, with wrong dimensions, or wrong format.
|
|
/// </summary>
|
|
/// <param name="thumbnailSize">The expected longest-side size in pixels.</param>
|
|
/// <param name="expectedFormat">The expected thumbnail format (e.g. "webp").</param>
|
|
/// <param name="limit">Maximum number of assets to return.</param>
|
|
/// <param name="offset">Number of assets to skip.</param>
|
|
/// <returns>A page of assets that need thumbnails regenerated.</returns>
|
|
IEnumerable<Asset> GetAssetsMissingOrWrongThumbnail(int thumbnailSize, string expectedFormat, int limit, int offset);
|
|
|
|
/// <summary>
|
|
/// Counts all assets that need previews — either missing entirely, with wrong dimensions, or wrong format.
|
|
/// </summary>
|
|
/// <param name="previewSize">The expected longest-side size in pixels.</param>
|
|
/// <param name="expectedFormat">The expected preview format (e.g. "webp").</param>
|
|
/// <returns>The total count of assets needing previews.</returns>
|
|
int CountAssetsMissingOrWrongPreview(int previewSize, string expectedFormat);
|
|
|
|
/// <summary>
|
|
/// Finds a page of assets that need previews — either missing entirely, with wrong dimensions, or wrong format.
|
|
/// </summary>
|
|
/// <param name="previewSize">The expected longest-side size in pixels.</param>
|
|
/// <param name="expectedFormat">The expected preview format (e.g. "webp").</param>
|
|
/// <param name="limit">Maximum number of assets to return.</param>
|
|
/// <param name="offset">Number of assets to skip.</param>
|
|
/// <returns>A page of assets that need previews regenerated.</returns>
|
|
IEnumerable<Asset> GetAssetsMissingOrWrongPreview(int previewSize, string expectedFormat, int limit, int offset);
|
|
|
|
/// <summary>
|
|
/// Counts image assets that are missing resolution metadata.
|
|
/// </summary>
|
|
int CountAssetsMissingMetadata();
|
|
|
|
/// <summary>
|
|
/// Finds a page of image assets missing resolution metadata.
|
|
/// </summary>
|
|
/// <param name="limit">Maximum number of assets to return.</param>
|
|
/// <param name="offset">Number of assets to skip.</param>
|
|
IEnumerable<Asset> GetAssetsMissingMetadata(int limit, int offset);
|
|
|
|
/// <summary>
|
|
/// Counts animated assets (GIF) that need a converted video and/or first-frame thumbnail.
|
|
/// Excludes deleted and broken assets.
|
|
/// </summary>
|
|
int CountAssetsNeedingConversion();
|
|
|
|
/// <summary>
|
|
/// Finds a page of animated assets (GIF) that need a converted video and/or first-frame thumbnail.
|
|
/// </summary>
|
|
/// <param name="limit">Maximum number of assets to return.</param>
|
|
/// <param name="offset">Number of assets to skip.</param>
|
|
IEnumerable<Asset> GetAssetsNeedingConversion(int limit, int offset);
|
|
|
|
/// <summary>
|
|
/// Counts assets currently marked broken (processing failed, not deleted).
|
|
/// </summary>
|
|
int CountBrokenAssets();
|
|
|
|
/// <summary>
|
|
/// Finds a page of assets marked broken (processing failed, not deleted), most recently broken first.
|
|
/// </summary>
|
|
/// <param name="page">The zero-based page number.</param>
|
|
/// <param name="pageSize">The number of assets per page.</param>
|
|
/// <param name="total">The total count of broken assets.</param>
|
|
/// <returns>A page of broken assets as preview DTOs.</returns>
|
|
IEnumerable<AssetPreviewDto> GetBrokenAssets(int page, int pageSize, out int total);
|
|
|
|
/// <summary>
|
|
/// Clears the broken (processing failed) state for the given assets so they are picked up for
|
|
/// re-processing on the next job run. Caller must invoke <see cref="Save"/> afterwards.
|
|
/// </summary>
|
|
/// <param name="ids">The IDs of the assets to retry.</param>
|
|
void ClearProcessError(IEnumerable<Guid> ids);
|
|
|
|
/// <summary>
|
|
/// Gets a random sample of asset paths from the specified folder.
|
|
/// </summary>
|
|
/// <param name="folderId">The folder ID.</param>
|
|
/// <param name="count">The number of random paths to return.</param>
|
|
/// <returns>A list of asset original paths.</returns>
|
|
List<string> GetRandomPathsByFolder(Guid folderId, int count);
|
|
|
|
/// <summary>
|
|
/// Queries assets with optional type filter, date range, random ordering, and visibility scoping.
|
|
/// </summary>
|
|
/// <param name="type">Optional asset type to filter by.</param>
|
|
/// <param name="from">Optional start date for the date range filter.</param>
|
|
/// <param name="to">Optional end date for the date range filter.</param>
|
|
/// <param name="orderRandomly">If true, orders randomly instead of by date.</param>
|
|
/// <param name="seed">An optional seed for deterministic random ordering across paginated requests.</param>
|
|
/// <param name="pageNumber">The zero-based page number.</param>
|
|
/// <param name="pageSize">The number of items per page.</param>
|
|
/// <param name="total">The total count of matching assets (after visibility filtering).</param>
|
|
/// <param name="userId">The requesting user's ID for visibility filtering.</param>
|
|
/// <param name="accessLevel">The requesting user's access level for visibility filtering.</param>
|
|
/// <param name="unlinked">If true, filters for assets not assigned to any album.</param>
|
|
/// <param name="folderId">Optional folder ID to filter assets by their scan folder.</param>
|
|
/// <param name="uploadedBy">Optional uploader user ID to filter assets by their uploader.</param>
|
|
/// <param name="search">Optional search term for ILike matching against OriginalFilename.</param>
|
|
/// <param name="includeCount">If true (default), computes the total matching count. When false, <paramref name="total"/> is set to zero and the count query is skipped.</param>
|
|
/// <returns>A paginated collection of asset previews matching the filters.</returns>
|
|
IEnumerable<AssetPreviewDto> GetAssets(EAssetType? type, DateTime? from, DateTime? to, bool orderRandomly, Guid? seed, int pageNumber, int pageSize, out int total, Guid? userId = null, EAccessLevel accessLevel = EAccessLevel.User, bool unlinked = false, Guid? folderId = null, Guid? uploadedBy = null, string? search = null, bool includeCount = true);
|
|
|
|
/// <summary>
|
|
/// Returns groups of unlinked assets (not assigned to any album), grouped by folder for drill-down browsing.
|
|
/// Admins and curators receive all folders with their unlinked asset counts. Maintainers receive a single
|
|
/// "My Uploads" group with their own unlinked upload count.
|
|
/// </summary>
|
|
/// <param name="userId">The requesting user's ID.</param>
|
|
/// <param name="accessLevel">The requesting user's access level.</param>
|
|
/// <param name="unlinkedOnly">If true (default), only counts assets not assigned to any album.</param>
|
|
/// <returns>A list of unlinked asset groups with folder ID, name, and asset count.</returns>
|
|
List<Butter.Dtos.Asset.AssetGroupDto> GetFolderGroups(Guid? userId, EAccessLevel accessLevel, bool unlinkedOnly = true);
|
|
}
|