mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:29:32 -05: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:
		
							parent
							
								
									86f5ceb80e
								
							
						
					
					
						commit
						f0a5d39625
					
				@ -19,11 +19,14 @@ export interface AssetOwnerCheck extends AssetCheck {
 | 
				
			|||||||
  ownerId: string;
 | 
					  ownerId: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AssetCreate = Omit<
 | 
				
			||||||
 | 
					  AssetEntity,
 | 
				
			||||||
 | 
					  'id' | 'createdAt' | 'updatedAt' | 'owner' | 'livePhotoVideoId' | 'library'
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IAssetRepository {
 | 
					export interface IAssetRepository {
 | 
				
			||||||
  get(id: string): Promise<AssetEntity | null>;
 | 
					  get(id: string): Promise<AssetEntity | null>;
 | 
				
			||||||
  create(
 | 
					  create(asset: AssetCreate): Promise<AssetEntity>;
 | 
				
			||||||
    asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'libraryId' | 'livePhotoVideoId'>,
 | 
					 | 
				
			||||||
  ): Promise<AssetEntity>;
 | 
					 | 
				
			||||||
  remove(asset: AssetEntity): Promise<void>;
 | 
					  remove(asset: AssetEntity): Promise<void>;
 | 
				
			||||||
  getAllByUserId(userId: string, dto: AssetSearchDto): Promise<AssetEntity[]>;
 | 
					  getAllByUserId(userId: string, dto: AssetSearchDto): Promise<AssetEntity[]>;
 | 
				
			||||||
  getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
 | 
					  getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
 | 
				
			||||||
@ -151,9 +154,7 @@ export class AssetRepository implements IAssetRepository {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  create(
 | 
					  create(asset: AssetCreate): Promise<AssetEntity> {
 | 
				
			||||||
    asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'livePhotoVideoId'>,
 | 
					 | 
				
			||||||
  ): Promise<AssetEntity> {
 | 
					 | 
				
			||||||
    return this.assetRepository.save(asset);
 | 
					    return this.assetRepository.save(asset);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { AuthUserDto, IJobRepository, JobName, mimeTypes, UploadFile } from '@app/domain';
 | 
					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 { parse } from 'node:path';
 | 
				
			||||||
import { IAssetRepository } from './asset-repository';
 | 
					import { IAssetRepository } from './asset-repository';
 | 
				
			||||||
import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
 | 
					import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
 | 
				
			||||||
@ -12,14 +12,14 @@ export class AssetCore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  async create(
 | 
					  async create(
 | 
				
			||||||
    authUser: AuthUserDto,
 | 
					    authUser: AuthUserDto,
 | 
				
			||||||
    dto: CreateAssetDto | ImportAssetDto,
 | 
					    dto: (CreateAssetDto | ImportAssetDto) & { libraryId: string },
 | 
				
			||||||
    file: UploadFile,
 | 
					    file: UploadFile,
 | 
				
			||||||
    livePhotoAssetId?: string,
 | 
					    livePhotoAssetId?: string,
 | 
				
			||||||
    sidecarPath?: string,
 | 
					    sidecarPath?: string,
 | 
				
			||||||
  ): Promise<AssetEntity> {
 | 
					  ): Promise<AssetEntity> {
 | 
				
			||||||
    const asset = await this.repository.create({
 | 
					    const asset = await this.repository.create({
 | 
				
			||||||
      owner: { id: authUser.id } as UserEntity,
 | 
					      ownerId: authUser.id,
 | 
				
			||||||
      library: { id: dto.libraryId } as LibraryEntity,
 | 
					      libraryId: dto.libraryId,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      checksum: file.checksum,
 | 
					      checksum: file.checksum,
 | 
				
			||||||
      originalPath: file.originalPath,
 | 
					      originalPath: file.originalPath,
 | 
				
			||||||
 | 
				
			|||||||
@ -90,22 +90,19 @@ export class AssetService {
 | 
				
			|||||||
    let livePhotoAsset: AssetEntity | null = null;
 | 
					    let livePhotoAsset: AssetEntity | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
					      const libraryId = await this.getLibraryId(authUser, dto.libraryId);
 | 
				
			||||||
      if (livePhotoFile) {
 | 
					      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);
 | 
					        livePhotoAsset = await this.assetCore.create(authUser, livePhotoDto, livePhotoFile);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!dto.libraryId) {
 | 
					      const asset = await this.assetCore.create(
 | 
				
			||||||
        // No library given, fall back to default upload library
 | 
					        authUser,
 | 
				
			||||||
        const defaultUploadLibrary = await this.libraryRepository.getDefaultUploadLibrary(authUser.id);
 | 
					        { ...dto, libraryId },
 | 
				
			||||||
 | 
					        file,
 | 
				
			||||||
        if (!defaultUploadLibrary) {
 | 
					        livePhotoAsset?.id,
 | 
				
			||||||
          throw new InternalServerErrorException('Cannot find default upload library for user ' + authUser.id);
 | 
					        sidecarFile?.originalPath,
 | 
				
			||||||
        }
 | 
					      );
 | 
				
			||||||
        dto.libraryId = defaultUploadLibrary.id;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const asset = await this.assetCore.create(authUser, dto, file, livePhotoAsset?.id, sidecarFile?.originalPath);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return { id: asset.id, duplicate: false };
 | 
					      return { id: asset.id, duplicate: false };
 | 
				
			||||||
    } catch (error: any) {
 | 
					    } catch (error: any) {
 | 
				
			||||||
@ -164,7 +161,8 @@ export class AssetService {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    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 };
 | 
					      return { id: asset.id, duplicate: false };
 | 
				
			||||||
    } catch (error: QueryFailedError | Error | any) {
 | 
					    } catch (error: QueryFailedError | Error | any) {
 | 
				
			||||||
      // handle duplicates with a success response
 | 
					      // 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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user