mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	chore(server): return duplicate assets as group (#9576)
* chore(server): return duplicate assets as group * file name
This commit is contained in:
		
							parent
							
								
									9aed736911
								
							
						
					
					
						commit
						60427f18ce
					
				@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Controller, Get } from '@nestjs/common';
 | 
					import { Controller, Get } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { AssetResponseDto } 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 { Auth, Authenticated } from 'src/middleware/auth.guard';
 | 
					import { Auth, Authenticated } from 'src/middleware/auth.guard';
 | 
				
			||||||
import { DuplicateService } from 'src/services/duplicate.service';
 | 
					import { DuplicateService } from 'src/services/duplicate.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,7 +12,7 @@ export class DuplicateController {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @Get()
 | 
					  @Get()
 | 
				
			||||||
  @Authenticated()
 | 
					  @Authenticated()
 | 
				
			||||||
  getAssetDuplicates(@Auth() auth: AuthDto): Promise<AssetResponseDto[]> {
 | 
					  getAssetDuplicates(@Auth() auth: AuthDto): Promise<DuplicateResponseDto[]> {
 | 
				
			||||||
    return this.service.getDuplicates(auth);
 | 
					    return this.service.getDuplicates(auth);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,7 @@ export class AssetResponseDto extends SanitizedAssetResponseDto {
 | 
				
			|||||||
  stack?: AssetResponseDto[];
 | 
					  stack?: AssetResponseDto[];
 | 
				
			||||||
  @ApiProperty({ type: 'integer' })
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
  stackCount!: number | null;
 | 
					  stackCount!: number | null;
 | 
				
			||||||
 | 
					  duplicateId?: string | null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type AssetMapOptions = {
 | 
					export type AssetMapOptions = {
 | 
				
			||||||
@ -130,6 +131,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
 | 
				
			|||||||
    isExternal: false,
 | 
					    isExternal: false,
 | 
				
			||||||
    isReadOnly: false,
 | 
					    isReadOnly: false,
 | 
				
			||||||
    hasMetadata: true,
 | 
					    hasMetadata: true,
 | 
				
			||||||
 | 
					    duplicateId: entity.duplicateId,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								server/src/dtos/duplicate.dto.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								server/src/dtos/duplicate.dto.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					import { groupBy } from 'lodash';
 | 
				
			||||||
 | 
					import { AssetResponseDto } from 'src/dtos/asset-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class DuplicateResponseDto {
 | 
				
			||||||
 | 
					  duplicateId!: string;
 | 
				
			||||||
 | 
					  assets!: AssetResponseDto[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function mapDuplicateResponse(assets: AssetResponseDto[]): DuplicateResponseDto[] {
 | 
				
			||||||
 | 
					  const result = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const grouped = groupBy(assets, (a) => a.duplicateId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const [duplicateId, assets] of Object.entries(grouped)) {
 | 
				
			||||||
 | 
					    result.push({ duplicateId, assets });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,7 +1,8 @@
 | 
				
			|||||||
import { Inject, Injectable } from '@nestjs/common';
 | 
					import { Inject, Injectable } from '@nestjs/common';
 | 
				
			||||||
import { SystemConfigCore } from 'src/cores/system-config.core';
 | 
					import { SystemConfigCore } from 'src/cores/system-config.core';
 | 
				
			||||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
 | 
					import { mapAsset } from 'src/dtos/asset-response.dto';
 | 
				
			||||||
import { AuthDto } from 'src/dtos/auth.dto';
 | 
					import { AuthDto } from 'src/dtos/auth.dto';
 | 
				
			||||||
 | 
					import { DuplicateResponseDto, mapDuplicateResponse } from 'src/dtos/duplicate.dto';
 | 
				
			||||||
import { AssetEntity } from 'src/entities/asset.entity';
 | 
					import { AssetEntity } from 'src/entities/asset.entity';
 | 
				
			||||||
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
 | 
					import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
 | 
				
			||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
 | 
					import { ICryptoRepository } from 'src/interfaces/crypto.interface';
 | 
				
			||||||
@ -35,9 +36,10 @@ export class DuplicateService {
 | 
				
			|||||||
    this.configCore = SystemConfigCore.create(systemMetadataRepository, logger);
 | 
					    this.configCore = SystemConfigCore.create(systemMetadataRepository, logger);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async getDuplicates(auth: AuthDto): Promise<AssetResponseDto[]> {
 | 
					  async getDuplicates(auth: AuthDto): Promise<DuplicateResponseDto[]> {
 | 
				
			||||||
    const res = await this.assetRepository.getDuplicates({ userIds: [auth.user.id] });
 | 
					    const res = await this.assetRepository.getDuplicates({ userIds: [auth.user.id] });
 | 
				
			||||||
    return res.map((a) => mapAsset(a, { auth }));
 | 
					
 | 
				
			||||||
 | 
					    return mapDuplicateResponse(res.map((a) => mapAsset(a, { auth })));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async handleQueueSearchDuplicates({ force }: IBaseJob): Promise<JobStatus> {
 | 
					  async handleQueueSearchDuplicates({ force }: IBaseJob): Promise<JobStatus> {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user