Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gateway-message-null-ids.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wolfstar/plugin-gateway": patch
---

`Message#webhookId`, `applicationId`, `nonce` and `position` are `null` when the message has none, like discord.js, instead of the `undefined` they inherited from `@discordjs/structures`, so a check such as `message.webhookId !== null` no longer takes every message for the one of a webhook.
34 changes: 33 additions & 1 deletion packages/plugin-gateway/src/structures/messages/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ export type MessageSnapshot = Partialize<
* the checks answer a promise read from the cache, typed as one once `GatewayCacheConfig` declares the cache
* asynchronous. The `fetch*able()` twins also ask the API for what is not cached.
*/
export class Message<InGuild extends boolean = boolean> extends BaseMessage<""> {
// The IDs `@discordjs/structures` reads as `undefined` when the message has none, where discord.js gives `null`: omitted
// from its data type so `Message` can override them.
type NullableMessageKeys = "webhook_id" | "application_id" | "nonce" | "position";

export class Message<InGuild extends boolean = boolean> extends BaseMessage<NullableMessageKeys> {
/**
* Keeps the raw `timestamp` and `edited_timestamp`, which `@discordjs/structures` strips and re-serializes in its own
* format, so that {@link Message.toJSON} returns the message as received.
Expand Down Expand Up @@ -490,6 +494,34 @@ export class Message<InGuild extends boolean = boolean> extends BaseMessage<"">
return this.optimizedTimestamp("edited_timestamp");
}

/**
* The ID of the webhook that sent the message, `null` when no webhook did, like discord.js's `Message#webhookId`.
*/
public override get webhookId(): string | null {
return this[kData].webhook_id ?? null;
}

/**
* The ID of the application of an interaction or of a Rich Presence-related chat embed, `null` without one.
*/
public override get applicationId(): string | null {
return this[kData].application_id ?? null;
}

/**
* The nonce the message was sent with, to check that it was sent, `null` without one.
*/
public override get nonce(): string | number | null {
return this[kData].nonce ?? null;
}

/**
* The approximate position of the message in a thread, `null` outside of one.
*/
public override get position(): number | null {
return this[kData].position ?? null;
}

public get editedAt(): Date | null {
const { editedTimestamp } = this;
return editedTimestamp === null ? null : new Date(editedTimestamp);
Expand Down
26 changes: 26 additions & 0 deletions packages/plugin-gateway/tests/structures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,32 @@ describe("optimized structures", () => {
expect(clone.toJSON().joined_at).toBe("2026-01-01T00:00:00.000Z");
});

test("GIVEN a message without a webhook, an application, a nonce or a position THEN they are null like discord.js", () => {
const message = new Message({ id: "1", channel_id: "2", author: data } as never);

expect(message.webhookId).toBeNull();
expect(message.applicationId).toBeNull();
expect(message.nonce).toBeNull();
expect(message.position).toBeNull();
});

test("GIVEN a message with a webhook, an application, a nonce and a position THEN they are read from it", () => {
const message = new Message({
id: "1",
channel_id: "2",
author: data,
webhook_id: "3",
application_id: "4",
nonce: "5",
position: 0,
} as never);

expect(message.webhookId).toBe("3");
expect(message.applicationId).toBe("4");
expect(message.nonce).toBe("5");
expect(message.position).toBe(0);
});

test("GIVEN a message edit and permission overwrite THEN optimized values follow patches", () => {
const message = new Message({
id: "1",
Expand Down
Loading