feat(server): add OCR extraction workflow filter (#32464)
feat(server): add OCR workflow filter (cherry picked from commit 2e0eb35e93dcf8468398d7015daa5ab231c7dd9c)
This commit is contained in:
@@ -78,6 +78,7 @@ import { AssetExifTable } from 'src/schema/tables/asset-exif.table.js';
|
||||
import { AssetFileTable } from 'src/schema/tables/asset-file.table.js';
|
||||
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table.js';
|
||||
import { AssetMetadataTable } from 'src/schema/tables/asset-metadata.table.js';
|
||||
import { AssetOcrTable } from 'src/schema/tables/asset-ocr.table.js';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table.js';
|
||||
import { FaceSearchTable } from 'src/schema/tables/face-search.table.js';
|
||||
import { MemoryTable } from 'src/schema/tables/memory.table.js';
|
||||
@@ -230,6 +231,28 @@ export class MediumTestContext<S extends ClassConstructor<typeof BaseService> =
|
||||
return { assetFace, result };
|
||||
}
|
||||
|
||||
async newAssetOcr(
|
||||
dto: (Partial<Insertable<AssetOcrTable>> & { assetId: string; text: string; textScore: number })[],
|
||||
) {
|
||||
const result = await this.get(OcrRepository).upsert(
|
||||
dto[0].assetId,
|
||||
dto.map((item) => ({
|
||||
...item,
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 1,
|
||||
x3: 2,
|
||||
y3: 2,
|
||||
x4: 3,
|
||||
y4: 3,
|
||||
boxScore: item.textScore,
|
||||
})),
|
||||
'',
|
||||
);
|
||||
return { ocr: dto, result };
|
||||
}
|
||||
|
||||
async newMemory(dto: Partial<Insertable<MemoryTable>> = {}) {
|
||||
const memory = mediumFactory.memoryInsert(dto);
|
||||
const result = await this.get(MemoryRepository).create(memory, new Set<string>());
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AssetFileType, JobStatus } from 'src/enum.js';
|
||||
import { AssetJobRepository } from 'src/repositories/asset-job.repository.js';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository.js';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository.js';
|
||||
import { EventRepository } from 'src/repositories/event.repository.js';
|
||||
import { JobRepository } from 'src/repositories/job.repository.js';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository.js';
|
||||
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository.js';
|
||||
@@ -20,7 +21,7 @@ const setup = (db?: Kysely<DB>) => {
|
||||
return newMediumService(OcrService, {
|
||||
database: db || defaultDatabase,
|
||||
real: [AssetRepository, AssetJobRepository, ConfigRepository, OcrRepository, SystemMetadataRepository],
|
||||
mock: [JobRepository, LoggingRepository, MachineLearningRepository],
|
||||
mock: [EventRepository, JobRepository, LoggingRepository, MachineLearningRepository],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -39,6 +40,7 @@ describe(OcrService.name, () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const { asset } = await ctx.newAsset({ ownerId: user.id });
|
||||
await ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: 'preview.jpg' });
|
||||
ctx.getMock(EventRepository).emit.mockResolvedValue();
|
||||
|
||||
const machineLearningMock = ctx.getMock(MachineLearningRepository);
|
||||
machineLearningMock.ocr.mockResolvedValue({
|
||||
@@ -91,6 +93,7 @@ describe(OcrService.name, () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const { asset } = await ctx.newAsset({ ownerId: user.id });
|
||||
await ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: 'preview.jpg' });
|
||||
ctx.getMock(EventRepository).emit.mockResolvedValue();
|
||||
|
||||
const machineLearningMock = ctx.getMock(MachineLearningRepository);
|
||||
machineLearningMock.ocr.mockResolvedValue({
|
||||
@@ -215,6 +218,7 @@ describe(OcrService.name, () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const { asset } = await ctx.newAsset({ ownerId: user.id });
|
||||
await ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: 'preview.jpg' });
|
||||
ctx.getMock(EventRepository).emit.mockResolvedValue();
|
||||
|
||||
const machineLearningMock = ctx.getMock(MachineLearningRepository);
|
||||
machineLearningMock.ocr.mockResolvedValue({ box: [], boxScore: [], text: [], textScore: [] });
|
||||
@@ -240,6 +244,7 @@ describe(OcrService.name, () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const { asset } = await ctx.newAsset({ ownerId: user.id });
|
||||
await ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: 'preview.jpg' });
|
||||
ctx.getMock(EventRepository).emit.mockResolvedValue();
|
||||
|
||||
const machineLearningMock = ctx.getMock(MachineLearningRepository);
|
||||
machineLearningMock.ocr.mockResolvedValue({
|
||||
|
||||
@@ -146,7 +146,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetArchive' }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({
|
||||
visibility: AssetVisibility.Archive,
|
||||
@@ -163,7 +169,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetArchive', config: { inverse: true } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({
|
||||
visibility: AssetVisibility.Timeline,
|
||||
@@ -182,7 +194,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetLock' }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({
|
||||
visibility: AssetVisibility.Locked,
|
||||
@@ -199,7 +217,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetLock', config: { inverse: true } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({
|
||||
visibility: AssetVisibility.Timeline,
|
||||
@@ -218,7 +242,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetFavorite' }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
@@ -233,7 +263,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetFavorite', config: { inverse: true } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
@@ -250,7 +286,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetAddToAlbums', config: { albumIds: [], albumName: 'Screenshots' } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
const albums = await ctx.get(AlbumRepository).getAll(user.id);
|
||||
expect(albums).toHaveLength(1);
|
||||
@@ -281,7 +323,13 @@ describe('core plugin', () => {
|
||||
expect(albums).toHaveLength(1);
|
||||
expect(albums[0].albumName).toEqual(album.albumName);
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AlbumRepository).getAssetIds(album.id, [asset.id])).resolves.toContain(asset.id);
|
||||
});
|
||||
@@ -297,7 +345,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetAddToAlbums', config: { albumIds: [album.id] } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AlbumRepository).getAssetIds(album.id, [asset.id])).resolves.toContain(asset.id);
|
||||
});
|
||||
@@ -316,7 +370,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetAddToAlbums', config: { albumIds: [album1.id, album2.id] } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
await expect(ctx.get(AlbumRepository).getAssetIds(album1.id, [asset.id])).resolves.toContain(asset.id);
|
||||
await expect(ctx.get(AlbumRepository).getAssetIds(album2.id, [asset.id])).resolves.toContain(asset.id);
|
||||
@@ -334,7 +394,13 @@ describe('core plugin', () => {
|
||||
steps: [{ method: 'immich-plugin-core#assetAddToAlbums', config: { albumIds: [album.id] } }],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeTruthy();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeTruthy();
|
||||
|
||||
await expect(ctx.get(AlbumRepository).getAssetIds(album.id, [asset.id])).resolves.not.toContain(asset.id);
|
||||
});
|
||||
@@ -360,7 +426,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
|
||||
@@ -383,7 +455,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetMetadataExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
@@ -406,7 +484,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetMetadataExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
});
|
||||
@@ -434,10 +518,18 @@ describe('core plugin', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset1.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset2.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
@@ -465,10 +557,18 @@ describe('core plugin', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset1.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset2.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
@@ -496,10 +596,18 @@ describe('core plugin', () => {
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset1.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset2.id }),
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
@@ -525,7 +633,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
});
|
||||
@@ -663,13 +777,25 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset1.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset2.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset3.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset3.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset3.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
@@ -700,17 +826,157 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset1.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset2.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
|
||||
await ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset3.id });
|
||||
await ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset3.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
});
|
||||
await expect(ctx.get(AssetRepository).getById(asset3.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('assetOcrFilter', () => {
|
||||
it('should match assets case-insensitively', async () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const [{ asset: asset1 }, { asset: asset2 }] = await Promise.all([
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
]);
|
||||
await ctx.newAssetOcr([{ assetId: asset1.id, text: 'test', textScore: 0.9 }]);
|
||||
await ctx.newAssetOcr([{ assetId: asset2.id, text: 'bogus', textScore: 0.9 }]);
|
||||
|
||||
const workflow = await createWorkflow({
|
||||
ownerId: user.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
steps: [
|
||||
{
|
||||
method: 'immich-plugin-core#assetOcrFilter',
|
||||
config: { matchType: 'contains', matchScope: 'box', pattern: 'Test', minScore: 0 },
|
||||
},
|
||||
{
|
||||
method: 'immich-plugin-core#assetFavorite',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
it('should match assets by regex in full text', async () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const [{ asset: asset1 }, { asset: asset2 }] = await Promise.all([
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
]);
|
||||
await ctx.newAssetOcr([
|
||||
{ assetId: asset1.id, text: 'Test', textScore: 0.9 },
|
||||
{ assetId: asset1.id, text: 'Match', textScore: 0.5 },
|
||||
]);
|
||||
await ctx.newAssetOcr([{ assetId: asset2.id, text: 'Test', textScore: 0.9 }]);
|
||||
|
||||
const workflow = await createWorkflow({
|
||||
ownerId: user.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
steps: [
|
||||
{
|
||||
method: 'immich-plugin-core#assetOcrFilter',
|
||||
config: { matchType: 'regex', matchScope: 'full', pattern: 'Test.+Match', minScore: 0 },
|
||||
},
|
||||
{
|
||||
method: 'immich-plugin-core#assetFavorite',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
it('should filter assets with low score', async () => {
|
||||
const { user } = await ctx.newUser();
|
||||
const [{ asset: asset1 }, { asset: asset2 }] = await Promise.all([
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
ctx.newAsset({ ownerId: user.id }),
|
||||
]);
|
||||
await ctx.newAssetOcr([{ assetId: asset1.id, text: 'test', textScore: 0.9 }]);
|
||||
await ctx.newAssetOcr([{ assetId: asset2.id, text: 'test', textScore: 0.5 }]);
|
||||
|
||||
const workflow = await createWorkflow({
|
||||
ownerId: user.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
steps: [
|
||||
{
|
||||
method: 'immich-plugin-core#assetOcrFilter',
|
||||
config: { matchType: 'contains', matchScope: 'box', pattern: 'test', minScore: 0.8 },
|
||||
},
|
||||
{
|
||||
method: 'immich-plugin-core#assetFavorite',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset1.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset2.id,
|
||||
trigger: WorkflowTrigger.AssetOcrExtraction,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset1.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
await expect(ctx.get(AssetRepository).getById(asset2.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('assetTagFilter', () => {
|
||||
it('should favorite asset if it matches any tag', async () => {
|
||||
const { user } = await ctx.newUser();
|
||||
@@ -732,7 +998,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
|
||||
@@ -755,7 +1027,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
@@ -779,7 +1057,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
|
||||
@@ -802,7 +1086,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
|
||||
@@ -826,7 +1116,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
|
||||
});
|
||||
});
|
||||
@@ -850,7 +1146,13 @@ describe('core plugin', () => {
|
||||
],
|
||||
});
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
expect(fetchMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -887,7 +1189,13 @@ describe('core plugin', () => {
|
||||
.execute();
|
||||
}
|
||||
|
||||
await expect(ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id })).resolves.toBeUndefined();
|
||||
await expect(
|
||||
ctx.sut.handleAssetTrigger({
|
||||
workflowId: workflow.id,
|
||||
assetId: asset.id,
|
||||
trigger: WorkflowTrigger.AssetCreate,
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user