From 325e72a4a7aaf8def1c608b538ad178b1e53e5af Mon Sep 17 00:00:00 2001 From: JButler Date: Tue, 10 Feb 2026 16:11:33 -0500 Subject: [PATCH] Correct json array parsing When JSONStream tries to read an empty array, it failed because it was trying to parse the empty string. To correct this, we just need to double check in State.END_VALUE_ARRAY that there's actually something to parse. When DiscordChatExporter encounters an empty channel (or DM, voice chat, or otherwise), it still creates a file, but the messages field is set to `[]`. This fix makes sure that we can still parse it. One potential issue is that we may be breaking the way that `pipeline/Time.ts` is used with reference to figuring out the min/max time. Also included tests for this case. --- pipeline/parse/JSONStream.ts | 7 +++++-- tests/parse/Parsers.test.ts | 1 + tests/samples/discord/DM_0A_0M.json | 21 +++++++++++++++++++++ tests/samples/discord/DM_0A_0M.json.ts | 16 ++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/samples/discord/DM_0A_0M.json create mode 100644 tests/samples/discord/DM_0A_0M.json.ts diff --git a/pipeline/parse/JSONStream.ts b/pipeline/parse/JSONStream.ts index 0992de8b..37c31058 100644 --- a/pipeline/parse/JSONStream.ts +++ b/pipeline/parse/JSONStream.ts @@ -222,8 +222,11 @@ export class JSONStream { break; case State.END_VALUE_ARRAY: - // console.log("EMITTING ARRAY", this.key, this.value); - this.arrayCallbacks[this.key!](this.parseValue()); + // Check if the captured value is actually empty/whitespace + if (this.buffer.slice(this.valueStart, i).trim().length > 0) { + // console.log("EMITTING ARRAY", this.key, this.value); + this.arrayCallbacks[this.key!](this.parseValue()); + } // read next item this.state = State.NEXT_ARRAY_ITEM; diff --git a/tests/parse/Parsers.test.ts b/tests/parse/Parsers.test.ts index e4eb615b..40ff6859 100644 --- a/tests/parse/Parsers.test.ts +++ b/tests/parse/Parsers.test.ts @@ -14,6 +14,7 @@ import { loadSample } from "@tests/samples"; describe("should parse correctly", () => { // prettier-ignore const cases: { parser: new () => Parser; inputs: string[] }[] = [ + { parser: DiscordParser, inputs: ["discord/DM_0A_0M.json"] }, { parser: DiscordParser, inputs: ["discord/DM_2A_2M.json"] }, { parser: DiscordParser, inputs: ["discord/GC_3A_5M.json"] }, { parser: DiscordParser, inputs: ["discord/SV_5A_5M.json"] }, diff --git a/tests/samples/discord/DM_0A_0M.json b/tests/samples/discord/DM_0A_0M.json new file mode 100644 index 00000000..2a0aa342 --- /dev/null +++ b/tests/samples/discord/DM_0A_0M.json @@ -0,0 +1,21 @@ +{ + "guild": { + "id": "0", + "name": "Direct Messages", + "iconUrl": "https://cdn.discordapp.com/embed/avatars/0.png" + }, + "channel": { + "id": "530805775262679064", + "type": "DirectTextChat", + "categoryId": "0", + "category": "Private", + "name": "Someones name", + "topic": null + }, + "dateRange": { + "after": null, + "before": null + }, + "messages": [], + "messageCount": 0 +} diff --git a/tests/samples/discord/DM_0A_0M.json.ts b/tests/samples/discord/DM_0A_0M.json.ts new file mode 100644 index 00000000..2b324539 --- /dev/null +++ b/tests/samples/discord/DM_0A_0M.json.ts @@ -0,0 +1,16 @@ +import type { ExpectedPartialParseResult } from "@tests/parse/Parse"; +import { PGUILD_DM } from "@tests/samples/discord/Common"; + +export const expectedParse: ExpectedPartialParseResult = { + guilds: [PGUILD_DM], + channels: [ + { + id: "530805775262679064", + type: "dm", + avatar: undefined, + }, + ], + authors: [], + messages: [], + calls: [], +};