mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	fix: live photo uploads (#4167)
* fix: live photo uploads * fix: format --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
		@@ -19,11 +19,14 @@ export interface AssetOwnerCheck extends AssetCheck {
 | 
			
		||||
  ownerId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type AssetCreate = Omit<
 | 
			
		||||
  AssetEntity,
 | 
			
		||||
  'id' | 'createdAt' | 'updatedAt' | 'owner' | 'livePhotoVideoId' | 'library'
 | 
			
		||||
>;
 | 
			
		||||
 | 
			
		||||
export interface IAssetRepository {
 | 
			
		||||
  get(id: string): Promise<AssetEntity | null>;
 | 
			
		||||
  create(
 | 
			
		||||
    asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'libraryId' | 'livePhotoVideoId'>,
 | 
			
		||||
  ): Promise<AssetEntity>;
 | 
			
		||||
  create(asset: AssetCreate): Promise<AssetEntity>;
 | 
			
		||||
  remove(asset: AssetEntity): Promise<void>;
 | 
			
		||||
  getAllByUserId(userId: string, dto: AssetSearchDto): Promise<AssetEntity[]>;
 | 
			
		||||
  getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
 | 
			
		||||
@@ -151,9 +154,7 @@ export class AssetRepository implements IAssetRepository {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  create(
 | 
			
		||||
    asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'livePhotoVideoId'>,
 | 
			
		||||
  ): Promise<AssetEntity> {
 | 
			
		||||
  create(asset: AssetCreate): Promise<AssetEntity> {
 | 
			
		||||
    return this.assetRepository.save(asset);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { AuthUserDto, IJobRepository, JobName, mimeTypes, UploadFile } from '@app/domain';
 | 
			
		||||
import { AssetEntity, LibraryEntity, UserEntity } from '@app/infra/entities';
 | 
			
		||||
import { AssetEntity } from '@app/infra/entities';
 | 
			
		||||
import { parse } from 'node:path';
 | 
			
		||||
import { IAssetRepository } from './asset-repository';
 | 
			
		||||
import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
 | 
			
		||||
@@ -12,14 +12,14 @@ export class AssetCore {
 | 
			
		||||
 | 
			
		||||
  async create(
 | 
			
		||||
    authUser: AuthUserDto,
 | 
			
		||||
    dto: CreateAssetDto | ImportAssetDto,
 | 
			
		||||
    dto: (CreateAssetDto | ImportAssetDto) & { libraryId: string },
 | 
			
		||||
    file: UploadFile,
 | 
			
		||||
    livePhotoAssetId?: string,
 | 
			
		||||
    sidecarPath?: string,
 | 
			
		||||
  ): Promise<AssetEntity> {
 | 
			
		||||
    const asset = await this.repository.create({
 | 
			
		||||
      owner: { id: authUser.id } as UserEntity,
 | 
			
		||||
      library: { id: dto.libraryId } as LibraryEntity,
 | 
			
		||||
      ownerId: authUser.id,
 | 
			
		||||
      libraryId: dto.libraryId,
 | 
			
		||||
 | 
			
		||||
      checksum: file.checksum,
 | 
			
		||||
      originalPath: file.originalPath,
 | 
			
		||||
 
 | 
			
		||||
@@ -90,22 +90,19 @@ export class AssetService {
 | 
			
		||||
    let livePhotoAsset: AssetEntity | null = null;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const libraryId = await this.getLibraryId(authUser, dto.libraryId);
 | 
			
		||||
      if (livePhotoFile) {
 | 
			
		||||
        const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false };
 | 
			
		||||
        const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false, libraryId };
 | 
			
		||||
        livePhotoAsset = await this.assetCore.create(authUser, livePhotoDto, livePhotoFile);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!dto.libraryId) {
 | 
			
		||||
        // No library given, fall back to default upload library
 | 
			
		||||
        const defaultUploadLibrary = await this.libraryRepository.getDefaultUploadLibrary(authUser.id);
 | 
			
		||||
 | 
			
		||||
        if (!defaultUploadLibrary) {
 | 
			
		||||
          throw new InternalServerErrorException('Cannot find default upload library for user ' + authUser.id);
 | 
			
		||||
        }
 | 
			
		||||
        dto.libraryId = defaultUploadLibrary.id;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const asset = await this.assetCore.create(authUser, dto, file, livePhotoAsset?.id, sidecarFile?.originalPath);
 | 
			
		||||
      const asset = await this.assetCore.create(
 | 
			
		||||
        authUser,
 | 
			
		||||
        { ...dto, libraryId },
 | 
			
		||||
        file,
 | 
			
		||||
        livePhotoAsset?.id,
 | 
			
		||||
        sidecarFile?.originalPath,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      return { id: asset.id, duplicate: false };
 | 
			
		||||
    } catch (error: any) {
 | 
			
		||||
@@ -164,7 +161,8 @@ export class AssetService {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const asset = await this.assetCore.create(authUser, dto, assetFile, undefined, dto.sidecarPath);
 | 
			
		||||
      const libraryId = await this.getLibraryId(authUser, dto.libraryId);
 | 
			
		||||
      const asset = await this.assetCore.create(authUser, { ...dto, libraryId }, assetFile, undefined, dto.sidecarPath);
 | 
			
		||||
      return { id: asset.id, duplicate: false };
 | 
			
		||||
    } catch (error: QueryFailedError | Error | any) {
 | 
			
		||||
      // handle duplicates with a success response
 | 
			
		||||
@@ -505,4 +503,25 @@ export class AssetService {
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async getLibraryId(authUser: AuthUserDto, libraryId?: string) {
 | 
			
		||||
    if (libraryId) {
 | 
			
		||||
      return libraryId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let library = await this.libraryRepository.getDefaultUploadLibrary(authUser.id);
 | 
			
		||||
    if (!library) {
 | 
			
		||||
      library = await this.libraryRepository.create({
 | 
			
		||||
        ownerId: authUser.id,
 | 
			
		||||
        name: 'Default Library',
 | 
			
		||||
        assets: [],
 | 
			
		||||
        type: LibraryType.UPLOAD,
 | 
			
		||||
        importPaths: [],
 | 
			
		||||
        exclusionPatterns: [],
 | 
			
		||||
        isVisible: true,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return library.id;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user