fix file path logic

This commit is contained in:
mertalev 2025-04-01 15:18:04 -04:00
parent e4b0c00885
commit e7503ce3dc
No known key found for this signature in database
GPG Key ID: DF6ABC77AAD98C95
8 changed files with 36 additions and 26 deletions

View File

@ -12,7 +12,7 @@ import { MoveRepository } from 'src/repositories/move.repository';
import { PersonRepository } from 'src/repositories/person.repository'; import { PersonRepository } from 'src/repositories/person.repository';
import { StorageRepository } from 'src/repositories/storage.repository'; import { StorageRepository } from 'src/repositories/storage.repository';
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
import { getAssetFiles } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { getConfig } from 'src/utils/config'; import { getConfig } from 'src/utils/config';
export interface MoveRequest { export interface MoveRequest {
@ -117,8 +117,7 @@ export class StorageCore {
async moveAssetImage(asset: AssetEntity, pathType: GeneratedImageType, format: ImageFormat) { async moveAssetImage(asset: AssetEntity, pathType: GeneratedImageType, format: ImageFormat) {
const { id: entityId, files } = asset; const { id: entityId, files } = asset;
const { thumbnailFile, previewFile } = getAssetFiles(files); const oldFile = getAssetFile(files, pathType);
const oldFile = pathType === AssetPathType.PREVIEW ? previewFile : thumbnailFile;
return this.moveFile({ return this.moveFile({
entityId, entityId,
pathType, pathType,

View File

@ -233,8 +233,8 @@ export class AssetService extends BaseService {
} }
} }
const { thumbnailFile, previewFile } = getAssetFiles(asset.files); const { fullsizeFile, previewFile, thumbnailFile } = getAssetFiles(asset.files);
const files = [thumbnailFile?.path, previewFile?.path, asset.encodedVideoPath]; const files = [thumbnailFile?.path, previewFile?.path, fullsizeFile?.path, asset.encodedVideoPath];
if (deleteOnDisk) { if (deleteOnDisk) {
files.push(asset.sidecarPath, asset.originalPath); files.push(asset.sidecarPath, asset.originalPath);

View File

@ -136,8 +136,14 @@ export class AuditService extends BaseService {
for await (const assets of pagination) { for await (const assets of pagination) {
assetCount += assets.length; assetCount += assets.length;
for (const { id, files, originalPath, encodedVideoPath, isExternal, checksum } of assets) { for (const { id, files, originalPath, encodedVideoPath, isExternal, checksum } of assets) {
const { previewFile, thumbnailFile } = getAssetFiles(files); const { fullsizeFile, previewFile, thumbnailFile } = getAssetFiles(files);
for (const file of [originalPath, previewFile?.path, encodedVideoPath, thumbnailFile?.path]) { for (const file of [
originalPath,
fullsizeFile?.path,
previewFile?.path,
encodedVideoPath,
thumbnailFile?.path,
]) {
track(file); track(file);
} }

View File

@ -5,12 +5,12 @@ import { mapAsset } from 'src/dtos/asset-response.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { DuplicateResponseDto } from 'src/dtos/duplicate.dto'; import { DuplicateResponseDto } from 'src/dtos/duplicate.dto';
import { AssetEntity } from 'src/entities/asset.entity'; import { AssetEntity } from 'src/entities/asset.entity';
import { JobName, JobStatus, QueueName } from 'src/enum'; import { AssetFileType, JobName, JobStatus, QueueName } from 'src/enum';
import { WithoutProperty } from 'src/repositories/asset.repository'; import { WithoutProperty } from 'src/repositories/asset.repository';
import { AssetDuplicateResult } from 'src/repositories/search.repository'; import { AssetDuplicateResult } from 'src/repositories/search.repository';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { JobOf } from 'src/types'; import { JobOf } from 'src/types';
import { getAssetFiles } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { isDuplicateDetectionEnabled } from 'src/utils/misc'; import { isDuplicateDetectionEnabled } from 'src/utils/misc';
import { usePagination } from 'src/utils/pagination'; import { usePagination } from 'src/utils/pagination';
@ -69,7 +69,7 @@ export class DuplicateService extends BaseService {
return JobStatus.SKIPPED; return JobStatus.SKIPPED;
} }
const { previewFile } = getAssetFiles(asset.files); const previewFile = getAssetFile(asset.files, AssetFileType.PREVIEW);
if (!previewFile) { if (!previewFile) {
this.logger.warn(`Asset ${id} is missing preview image`); this.logger.warn(`Asset ${id} is missing preview image`);
return JobStatus.FAILED; return JobStatus.FAILED;

View File

@ -2,12 +2,12 @@ import { BadRequestException, Injectable } from '@nestjs/common';
import { OnEvent, OnJob } from 'src/decorators'; import { OnEvent, OnJob } from 'src/decorators';
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
import { AlbumEntity } from 'src/entities/album.entity'; import { AlbumEntity } from 'src/entities/album.entity';
import { JobName, JobStatus, QueueName } from 'src/enum'; import { AssetFileType, JobName, JobStatus, QueueName } from 'src/enum';
import { ArgOf } from 'src/repositories/event.repository'; import { ArgOf } from 'src/repositories/event.repository';
import { EmailTemplate } from 'src/repositories/notification.repository'; import { EmailTemplate } from 'src/repositories/notification.repository';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { EmailImageAttachment, IEntityJob, INotifyAlbumUpdateJob, JobItem, JobOf } from 'src/types'; import { EmailImageAttachment, IEntityJob, INotifyAlbumUpdateJob, JobItem, JobOf } from 'src/types';
import { getAssetFiles } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { getFilenameExtension } from 'src/utils/file'; import { getFilenameExtension } from 'src/utils/file';
import { getExternalDomain } from 'src/utils/misc'; import { getExternalDomain } from 'src/utils/misc';
import { isEqualObject } from 'src/utils/object'; import { isEqualObject } from 'src/utils/object';
@ -398,7 +398,11 @@ export class NotificationService extends BaseService {
} }
const albumThumbnail = await this.assetRepository.getById(album.albumThumbnailAssetId, { files: true }); const albumThumbnail = await this.assetRepository.getById(album.albumThumbnailAssetId, { files: true });
const { thumbnailFile } = getAssetFiles(albumThumbnail?.files); if (!albumThumbnail) {
return;
}
const thumbnailFile = getAssetFile(albumThumbnail.files, AssetFileType.THUMBNAIL);
if (!thumbnailFile) { if (!thumbnailFile) {
return; return;
} }

View File

@ -26,6 +26,7 @@ import { AssetEntity } from 'src/entities/asset.entity';
import { FaceSearchEntity } from 'src/entities/face-search.entity'; import { FaceSearchEntity } from 'src/entities/face-search.entity';
import { PersonEntity } from 'src/entities/person.entity'; import { PersonEntity } from 'src/entities/person.entity';
import { import {
AssetFileType,
AssetType, AssetType,
CacheControl, CacheControl,
ImageFormat, ImageFormat,
@ -42,7 +43,7 @@ import { BoundingBox } from 'src/repositories/machine-learning.repository';
import { UpdateFacesData } from 'src/repositories/person.repository'; import { UpdateFacesData } from 'src/repositories/person.repository';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { CropOptions, ImageDimensions, InputDimensions, JobItem, JobOf } from 'src/types'; import { CropOptions, ImageDimensions, InputDimensions, JobItem, JobOf } from 'src/types';
import { getAssetFiles } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { ImmichFileResponse } from 'src/utils/file'; import { ImmichFileResponse } from 'src/utils/file';
import { mimeTypes } from 'src/utils/mime-types'; import { mimeTypes } from 'src/utils/mime-types';
import { isFaceImportEnabled, isFacialRecognitionEnabled } from 'src/utils/misc'; import { isFaceImportEnabled, isFacialRecognitionEnabled } from 'src/utils/misc';
@ -300,7 +301,7 @@ export class PersonService extends BaseService {
const relations = { exifInfo: true, faces: { person: false, withDeleted: true }, files: true }; const relations = { exifInfo: true, faces: { person: false, withDeleted: true }, files: true };
const [asset] = await this.assetRepository.getByIds([id], relations); const [asset] = await this.assetRepository.getByIds([id], relations);
const { previewFile } = getAssetFiles(asset.files); const previewFile = getAssetFile(asset.files, AssetFileType.PREVIEW);
if (!asset || !previewFile) { if (!asset || !previewFile) {
return JobStatus.FAILED; return JobStatus.FAILED;
} }
@ -674,7 +675,7 @@ export class PersonService extends BaseService {
throw new Error(`Asset ${asset.id} dimensions are unknown`); throw new Error(`Asset ${asset.id} dimensions are unknown`);
} }
const { previewFile } = getAssetFiles(asset.files); const previewFile = getAssetFile(asset.files, AssetFileType.PREVIEW);
if (!previewFile) { if (!previewFile) {
throw new Error(`Asset ${asset.id} has no preview path`); throw new Error(`Asset ${asset.id} has no preview path`);
} }

View File

@ -2,12 +2,12 @@ import { Injectable } from '@nestjs/common';
import { SystemConfig } from 'src/config'; import { SystemConfig } from 'src/config';
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants';
import { OnEvent, OnJob } from 'src/decorators'; import { OnEvent, OnJob } from 'src/decorators';
import { DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum'; import { AssetFileType, DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum';
import { WithoutProperty } from 'src/repositories/asset.repository'; import { WithoutProperty } from 'src/repositories/asset.repository';
import { ArgOf } from 'src/repositories/event.repository'; import { ArgOf } from 'src/repositories/event.repository';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { JobOf } from 'src/types'; import { JobOf } from 'src/types';
import { getAssetFiles } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc';
import { usePagination } from 'src/utils/pagination'; import { usePagination } from 'src/utils/pagination';
@ -116,7 +116,7 @@ export class SmartInfoService extends BaseService {
return JobStatus.SKIPPED; return JobStatus.SKIPPED;
} }
const { previewFile } = getAssetFiles(asset.files); const previewFile = getAssetFile(asset.files, AssetFileType.PREVIEW);
if (!previewFile) { if (!previewFile) {
return JobStatus.FAILED; return JobStatus.FAILED;
} }

View File

@ -1,5 +1,5 @@
import { BadRequestException } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common';
import { StorageCore } from 'src/cores/storage.core'; import { GeneratedImageType, StorageCore } from 'src/cores/storage.core';
import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto';
import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { UploadFieldName } from 'src/dtos/asset-media.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
@ -13,14 +13,14 @@ import { PartnerRepository } from 'src/repositories/partner.repository';
import { IBulkAsset, ImmichFile, UploadFile } from 'src/types'; import { IBulkAsset, ImmichFile, UploadFile } from 'src/types';
import { checkAccess } from 'src/utils/access'; import { checkAccess } from 'src/utils/access';
const getFileByType = (files: AssetFileEntity[] | undefined, type: AssetFileType) => { export const getAssetFile = (files: AssetFileEntity[], type: AssetFileType | GeneratedImageType) => {
return (files || []).find((file) => file.type === type); return files.find((file) => file.type === type);
}; };
export const getAssetFiles = (files?: AssetFileEntity[]) => ({ export const getAssetFiles = (files: AssetFileEntity[]) => ({
fullsizeFile: getFileByType(files, AssetFileType.FULLSIZE), fullsizeFile: getAssetFile(files, AssetFileType.FULLSIZE),
previewFile: getFileByType(files, AssetFileType.PREVIEW), previewFile: getAssetFile(files, AssetFileType.PREVIEW),
thumbnailFile: getFileByType(files, AssetFileType.THUMBNAIL), thumbnailFile: getAssetFile(files, AssetFileType.THUMBNAIL),
}); });
export const addAssets = async ( export const addAssets = async (