mirror of
https://github.com/immich-app/immich.git
synced 2024-11-28 09:33:27 +02:00
fix(server): DateTimeOriginal overwrite issue with sidecar file (#11306)
* fix(server): DateTimeOriginal overwrite issue with sidecar file * update unit test
This commit is contained in:
parent
6394b4a9a3
commit
8725656fd2
@ -472,6 +472,44 @@ describe('/asset', () => {
|
|||||||
expect(status).toEqual(200);
|
expect(status).toEqual(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should update date time original when sidecar file contains DateTimeOriginal', async () => {
|
||||||
|
const sidecarData = `<?xpacket begin='?' id='W5M0MpCehiHzreSzNTczkc9d'?>
|
||||||
|
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 12.40'>
|
||||||
|
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
|
||||||
|
<rdf:Description rdf:about=''
|
||||||
|
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
|
||||||
|
<exif:ExifVersion>0220</exif:ExifVersion> <exif:DateTimeOriginal>2024-07-11T10:32:52Z</exif:DateTimeOriginal>
|
||||||
|
<exif:GPSVersionID>2.3.0.0</exif:GPSVersionID>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>
|
||||||
|
<?xpacket end='w'?>`;
|
||||||
|
|
||||||
|
const { id } = await utils.createAsset(user1.accessToken, {
|
||||||
|
sidecarData: {
|
||||||
|
bytes: Buffer.from(sidecarData),
|
||||||
|
filename: 'example.xmp',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
|
||||||
|
|
||||||
|
const assetInfo = await utils.getAssetInfo(user1.accessToken, id);
|
||||||
|
expect(assetInfo.exifInfo?.dateTimeOriginal).toBe('2024-07-11T10:32:52.000Z');
|
||||||
|
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.put(`/assets/${id}`)
|
||||||
|
.set('Authorization', `Bearer ${user1.accessToken}`)
|
||||||
|
.send({ dateTimeOriginal: '2023-11-19T18:11:00.000-07:00' });
|
||||||
|
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
id,
|
||||||
|
exifInfo: expect.objectContaining({
|
||||||
|
dateTimeOriginal: '2023-11-20T01:11:00.000Z',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
expect(status).toEqual(200);
|
||||||
|
});
|
||||||
|
|
||||||
it('should reject invalid gps coordinates', async () => {
|
it('should reject invalid gps coordinates', async () => {
|
||||||
for (const test of [
|
for (const test of [
|
||||||
{ latitude: 12 },
|
{ latitude: 12 },
|
||||||
|
@ -50,7 +50,7 @@ type CommandResponse = { stdout: string; stderr: string; exitCode: number | null
|
|||||||
type EventType = 'assetUpload' | 'assetUpdate' | 'assetDelete' | 'userDelete' | 'assetHidden';
|
type EventType = 'assetUpload' | 'assetUpdate' | 'assetDelete' | 'userDelete' | 'assetHidden';
|
||||||
type WaitOptions = { event: EventType; id?: string; total?: number; timeout?: number };
|
type WaitOptions = { event: EventType; id?: string; total?: number; timeout?: number };
|
||||||
type AdminSetupOptions = { onboarding?: boolean };
|
type AdminSetupOptions = { onboarding?: boolean };
|
||||||
type AssetData = { bytes?: Buffer; filename: string };
|
type FileData = { bytes?: Buffer; filename: string };
|
||||||
|
|
||||||
const dbUrl = 'postgres://postgres:postgres@127.0.0.1:5433/immich';
|
const dbUrl = 'postgres://postgres:postgres@127.0.0.1:5433/immich';
|
||||||
export const baseUrl = 'http://127.0.0.1:2283';
|
export const baseUrl = 'http://127.0.0.1:2283';
|
||||||
@ -291,7 +291,10 @@ export const utils = {
|
|||||||
|
|
||||||
createAsset: async (
|
createAsset: async (
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
dto?: Partial<Omit<AssetMediaCreateDto, 'assetData'>> & { assetData?: AssetData },
|
dto?: Partial<Omit<AssetMediaCreateDto, 'assetData' | 'sidecarData'>> & {
|
||||||
|
assetData?: FileData;
|
||||||
|
sidecarData?: FileData;
|
||||||
|
},
|
||||||
) => {
|
) => {
|
||||||
const _dto = {
|
const _dto = {
|
||||||
deviceAssetId: 'test-1',
|
deviceAssetId: 'test-1',
|
||||||
@ -313,6 +316,10 @@ export const utils = {
|
|||||||
.attach('assetData', assetData, filename)
|
.attach('assetData', assetData, filename)
|
||||||
.set('Authorization', `Bearer ${accessToken}`);
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
|
|
||||||
|
if (dto?.sidecarData?.bytes) {
|
||||||
|
void builder.attach('sidecarData', dto.sidecarData.bytes, dto.sidecarData.filename);
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(_dto)) {
|
for (const [key, value] of Object.entries(_dto)) {
|
||||||
void builder.field(key, String(value));
|
void builder.field(key, String(value));
|
||||||
}
|
}
|
||||||
@ -325,7 +332,7 @@ export const utils = {
|
|||||||
replaceAsset: async (
|
replaceAsset: async (
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
assetId: string,
|
assetId: string,
|
||||||
dto?: Partial<Omit<AssetMediaCreateDto, 'assetData'>> & { assetData?: AssetData },
|
dto?: Partial<Omit<AssetMediaCreateDto, 'assetData'>> & { assetData?: FileData },
|
||||||
) => {
|
) => {
|
||||||
const _dto = {
|
const _dto = {
|
||||||
deviceAssetId: 'test-1',
|
deviceAssetId: 'test-1',
|
||||||
|
@ -911,7 +911,7 @@ describe(MetadataService.name, () => {
|
|||||||
expect(metadataMock.writeTags).toHaveBeenCalledWith(assetStub.sidecar.sidecarPath, {
|
expect(metadataMock.writeTags).toHaveBeenCalledWith(assetStub.sidecar.sidecarPath, {
|
||||||
Description: description,
|
Description: description,
|
||||||
ImageDescription: description,
|
ImageDescription: description,
|
||||||
CreationDate: date,
|
DateTimeOriginal: date,
|
||||||
GPSLatitude: gps,
|
GPSLatitude: gps,
|
||||||
GPSLongitude: gps,
|
GPSLongitude: gps,
|
||||||
});
|
});
|
||||||
|
@ -316,7 +316,7 @@ export class MetadataService implements OnEvents {
|
|||||||
{
|
{
|
||||||
Description: description,
|
Description: description,
|
||||||
ImageDescription: description,
|
ImageDescription: description,
|
||||||
CreationDate: dateTimeOriginal,
|
DateTimeOriginal: dateTimeOriginal,
|
||||||
GPSLatitude: latitude,
|
GPSLatitude: latitude,
|
||||||
GPSLongitude: longitude,
|
GPSLongitude: longitude,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user