From ca0f45d5d17ef4b610bcc85f695e576a4d1f82a3 Mon Sep 17 00:00:00 2001 From: AlejandroAkbal <37181533+AlejandroAkbal@users.noreply.github.com> Date: Sat, 14 Mar 2026 04:50:43 -0700 Subject: [PATCH] feat: preserve pipe-delimited OR groups in tags DTO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop splitting tags on | so that OR-group tokens (e.g. cat|dog) are forwarded intact to the Universal Booru Wrapper, which applies the correct engine-specific OR syntax per booru engine. Pipelines the change through the full stack: App → | (user types 'cat OR dog') API → ['cat|dog'] (kept as OR-group token) Wrapper → '{ ~ cat ~ dog }' (Gelbooru) / '~cat ~dog' (Danbooru/e621) --- src/booru/dto/booru-queries.dto.spec.ts | 16 ++++++++-------- src/booru/dto/booru-queries.dto.ts | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/booru/dto/booru-queries.dto.spec.ts b/src/booru/dto/booru-queries.dto.spec.ts index 524da3d..c918115 100644 --- a/src/booru/dto/booru-queries.dto.spec.ts +++ b/src/booru/dto/booru-queries.dto.spec.ts @@ -31,34 +31,34 @@ describe('booruQueryValuesPostsDTO request handling', () => { await app.close() }) - it('should rely on request parsing for percent-decoding and split tags by pipe', async () => { + it('should rely on request parsing for percent-decoding and preserve comma OR-groups', async () => { const response = await app.inject({ method: 'GET', - url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=panty_%26_stocking_with_garterbelt%7Crating%3Asafe' + url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=panty_%26_stocking_with_garterbelt%2Cblue_hair' }) const body = JSON.parse(response.body) expect(response.statusCode).toBe(200) - expect(body.tags).toEqual(['panty_&_stocking_with_garterbelt', 'rating:safe']) + expect(body.tags).toEqual(['panty_&_stocking_with_garterbelt,blue_hair']) }) - it('should normalize repeated tags query params and split each entry', async () => { + it('should normalize repeated tags query params and keep each OR-group token intact', async () => { const response = await app.inject({ method: 'GET', - url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=artist%3Afoo%7Crating%3Asafe&tags=score%3A%3E100' + url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=artist%3Afoo%2Crating%3Asafe&tags=score%3A%3E100' }) const body = JSON.parse(response.body) expect(response.statusCode).toBe(200) - expect(body.tags).toEqual(['artist:foo', 'rating:safe', 'score:>100']) + expect(body.tags).toEqual(['artist:foo,rating:safe', 'score:>100']) }) - it('should reject empty tags created after pipe splitting', async () => { + it('should reject empty tags produced by repeated query params', async () => { const response = await app.inject({ method: 'GET', - url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=tag1%7C' + url: '/dto-test/posts?baseEndpoint=gelbooru.com&tags=tag1&tags=' }) expect(response.statusCode).toBe(400) diff --git a/src/booru/dto/booru-queries.dto.ts b/src/booru/dto/booru-queries.dto.ts index 89a09ea..166a51c 100644 --- a/src/booru/dto/booru-queries.dto.ts +++ b/src/booru/dto/booru-queries.dto.ts @@ -186,9 +186,9 @@ export class booruQueryValuesPostsDTO extends booruQueriesDTO { return value } - return (Array.isArray(value) ? value : [value]).flatMap((tag) => - typeof tag === 'string' ? tag.trim().split('|') : [tag] - ) + return (Array.isArray(value) ? value : [value]) + .map((tag) => (typeof tag === 'string' ? tag : String(tag))) + .map((tag) => tag.trim()) }) @IsOptional() readonly tags: IBooruQueryValues['posts']['tags']