@went.tf/discord-bot-framework 2.9.1 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,12 @@
1
1
  import { AutocompleteInteraction, ChatInputCommandInteraction, MessageComponentInteraction, ModalSubmitInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction } from 'discord.js';
2
2
  import { BaseInteractionContext, BotChatInputCommand, BotContextMenuCommand, BotMessageComponent, BotModal } from './types.js';
3
3
  export type OnDispatchError<Ctx> = (interaction: unknown, context: Ctx, error: unknown) => void | Promise<void>;
4
+ /**
5
+ * Discord invalidates an interaction's token if it isn't acknowledged within 3 seconds of being
6
+ * sent (or when a newer autocomplete interaction supersedes it), after which every response to it
7
+ * fails with this error - including the error reply `onError` would otherwise attempt.
8
+ */
9
+ export declare const isUnknownInteractionError: (e: unknown) => boolean;
4
10
  export interface DispatchChatInputCommandOptions<Ctx extends BaseInteractionContext> {
5
11
  commands: Record<string, BotChatInputCommand<Ctx>>;
6
12
  onUnknownCommand?: (interaction: ChatInputCommandInteraction, context: Ctx) => void | Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/interactions/dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/interactions/dispatch.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,22 @@
1
+ import { RESTJSONErrorCodes } from 'discord-api-types/v10';
2
+ import { DiscordAPIError, } from 'discord.js';
1
3
  import { parseCustomIdSegments } from './custom-id.js';
4
+ /**
5
+ * Discord invalidates an interaction's token if it isn't acknowledged within 3 seconds of being
6
+ * sent (or when a newer autocomplete interaction supersedes it), after which every response to it
7
+ * fails with this error - including the error reply `onError` would otherwise attempt.
8
+ */
9
+ export const isUnknownInteractionError = (e) => e instanceof DiscordAPIError && e.code === RESTJSONErrorCodes.UnknownInteraction;
10
+ async function handleDispatchError(interaction, context, onError, error, description) {
11
+ if (isUnknownInteractionError(error)) {
12
+ // Nothing can be sent for an expired interaction, so there's no point in a stack trace or an
13
+ // error reply - the age is what tells a slow handler apart from a late delivery by Discord.
14
+ context.logger.warn(`Interaction expired before it could be responded to: ${description}, age=${Date.now() - interaction.createdTimestamp}ms`);
15
+ return;
16
+ }
17
+ context.logger.error(`Error while responding to ${description}`, error);
18
+ await onError(interaction, context, error);
19
+ }
2
20
  export async function dispatchChatInputCommand(interaction, context, options) {
3
21
  const command = options.commands[interaction.commandName];
4
22
  if (!command) {
@@ -12,8 +30,7 @@ export async function dispatchChatInputCommand(interaction, context, options) {
12
30
  await command.handle(interaction, context);
13
31
  }
14
32
  catch (e) {
15
- context.logger.error(`Error while responding to command interaction (commandName=${interaction.commandName})`, e);
16
- await options.onError(interaction, context, e);
33
+ await handleDispatchError(interaction, context, options.onError, e, `command interaction (commandName=${interaction.commandName})`);
17
34
  }
18
35
  }
19
36
  export async function dispatchAutocomplete(interaction, context, options) {
@@ -27,8 +44,7 @@ export async function dispatchAutocomplete(interaction, context, options) {
27
44
  await handler(interaction, context, focusedOption.name);
28
45
  }
29
46
  catch (e) {
30
- context.logger.error(`Error while responding to command autocomplete (commandName=${interaction.commandName})`, e);
31
- await options.onError(interaction, context, e);
47
+ await handleDispatchError(interaction, context, options.onError, e, `command autocomplete (commandName=${interaction.commandName})`);
32
48
  }
33
49
  }
34
50
  export async function dispatchComponent(interaction, context, options) {
@@ -45,8 +61,7 @@ export async function dispatchComponent(interaction, context, options) {
45
61
  await component.handle(interaction, context, resourceId);
46
62
  }
47
63
  catch (e) {
48
- context.logger.error(`Error while responding to component interaction (customId=${id},resourceId=${resourceId})`, e);
49
- await options.onError(interaction, context, e);
64
+ await handleDispatchError(interaction, context, options.onError, e, `component interaction (customId=${id},resourceId=${resourceId})`);
50
65
  }
51
66
  }
52
67
  export async function dispatchModal(interaction, context, options) {
@@ -63,8 +78,7 @@ export async function dispatchModal(interaction, context, options) {
63
78
  await modal.handle(interaction, context, resourceId);
64
79
  }
65
80
  catch (e) {
66
- context.logger.error(`Error while responding to modal submit interaction (customId=${id},resourceId=${resourceId})`, e);
67
- await options.onError(interaction, context, e);
81
+ await handleDispatchError(interaction, context, options.onError, e, `modal submit interaction (customId=${id},resourceId=${resourceId})`);
68
82
  }
69
83
  }
70
84
  export async function dispatchContextMenu(interaction, context, options) {
@@ -80,8 +94,7 @@ export async function dispatchContextMenu(interaction, context, options) {
80
94
  await command.handle(interaction, context);
81
95
  }
82
96
  catch (e) {
83
- context.logger.error(`Error while responding to context menu interaction (commandName=${interaction.commandName})`, e);
84
- await options.onError(interaction, context, e);
97
+ await handleDispatchError(interaction, context, options.onError, e, `context menu interaction (commandName=${interaction.commandName})`);
85
98
  }
86
99
  }
87
100
  //# sourceMappingURL=dispatch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/interactions/dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/interactions/dispatch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"discord-webhook-batcher.d.ts","sourceRoot":"","sources":["../../src/logger/discord-webhook-batcher.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAiBD;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAOpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IANpC,OAAO,CAAC,KAAK,CAAuB;IAEpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEZ,OAAO,EAAE,4BAA4B;IASlE,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAY5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
1
+ {"version":3,"file":"discord-webhook-batcher.d.ts","sourceRoot":"","sources":["../../src/logger/discord-webhook-batcher.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAoBD;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAOpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IANpC,OAAO,CAAC,KAAK,CAAuB;IAEpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEZ,OAAO,EAAE,4BAA4B;IASlE,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAY5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -2,6 +2,9 @@ const DEFAULT_BATCH_INTERVAL_MS = 20_000;
2
2
  const DEFAULT_MAX_BATCH_SIZE = 10;
3
3
  const DEFAULT_MAX_QUEUE_LENGTH = 500;
4
4
  const EMBED_DESCRIPTION_LIMIT = 4096;
5
+ // Discord rejects (HTTP 400) a message whose embeds' combined text exceeds this, even when every
6
+ // individual embed is within its own limits - a few long stack traces in one batch is enough.
7
+ const EMBEDS_TOTAL_TEXT_LIMIT = 6000;
5
8
  // Discord embed side-bar colors, keyed by pino's numeric levels (trace=10 ... fatal=60).
6
9
  const LEVEL_COLORS = {
7
10
  10: 0x95a5a6,
@@ -47,11 +50,22 @@ export class DiscordWebhookBatcher {
47
50
  if (this.queue.length === 0)
48
51
  return;
49
52
  const maxBatchSize = this.options.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
50
- const batch = this.queue.splice(0, maxBatchSize);
53
+ const embeds = [];
54
+ let totalTextLength = 0;
55
+ while (embeds.length < maxBatchSize && this.queue.length > 0) {
56
+ const embed = buildEmbed(this.queue[0]);
57
+ // The first embed always fits on its own (EMBED_DESCRIPTION_LIMIT < EMBEDS_TOTAL_TEXT_LIMIT),
58
+ // anything past the combined limit is carried over to the next tick.
59
+ if (embeds.length > 0 && totalTextLength + embed.description.length > EMBEDS_TOTAL_TEXT_LIMIT)
60
+ break;
61
+ this.queue.shift();
62
+ embeds.push(embed);
63
+ totalTextLength += embed.description.length;
64
+ }
51
65
  const payload = {
52
66
  username: this.options.username,
53
67
  avatar_url: this.options.avatarUrl,
54
- embeds: batch.map(buildEmbed),
68
+ embeds,
55
69
  };
56
70
  try {
57
71
  const response = await this.fetchImpl(this.options.url, {
@@ -1 +1 @@
1
- {"version":3,"file":"discord-webhook-batcher.js","sourceRoot":"","sources":["../../src/logger/discord-webhook-batcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discord-webhook-batcher.js","sourceRoot":"","sources":["../../src/logger/discord-webhook-batcher.ts"],"names":[],"mappings":"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"}
@@ -55,6 +55,22 @@ export interface HandleWebhookInteractionRequestOptions {
55
55
  * option values, etc.).
56
56
  */
57
57
  verboseSignatureDiagnostics?: boolean;
58
+ /**
59
+ * This application's Discord application/client ID. Only used to narrow
60
+ * `muteKnownConformanceCheckLogs` below - optional, but recommended when set.
61
+ */
62
+ applicationId?: string;
63
+ /**
64
+ * Mutes the `warn`/`debug` signature-rejection logs for Discord's own known
65
+ * signature-conformance check (see `isDiscordSignatureConformanceCheck`) - a
66
+ * recurring, benign `Ping` sent with a deliberately-invalid signature,
67
+ * observed in production to otherwise show up as ordinary-looking
68
+ * signature-rejection noise roughly hourly. On by default, since it's
69
+ * expected and doesn't indicate a problem; the request is still rejected
70
+ * the same either way - this only affects whether that one case logs.
71
+ * @default true
72
+ */
73
+ muteKnownConformanceCheckLogs?: boolean;
58
74
  }
59
75
  /**
60
76
  * Framework-agnostic core of an HTTP Interactions endpoint: verifies the
@@ -1 +1 @@
1
- {"version":3,"file":"handle-webhook-interaction-request.d.ts","sourceRoot":"","sources":["../../src/webhook/handle-webhook-interaction-request.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAA4C,MAAM,uBAAuB,CAAC;AACzH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,MAAM,WAAW,yBAAyB;IACxC,kDAAkD;IAClD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,oDAAoD;IACpD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,kGAAkG;IAClG,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,sBAAsB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,sCAAsC;IACrD,oGAAoG;IACpG,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,sBAAsB,GAAG,IAAI,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACvH;;;;;;;;;;OAUG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AA6CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,sCAAsC,GAC9C,OAAO,CAAC,0BAA0B,CAAC,CA0CrC"}
1
+ {"version":3,"file":"handle-webhook-interaction-request.d.ts","sourceRoot":"","sources":["../../src/webhook/handle-webhook-interaction-request.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAA4C,MAAM,uBAAuB,CAAC;AACzH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,MAAM,WAAW,yBAAyB;IACxC,kDAAkD;IAClD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,oDAAoD;IACpD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,kGAAkG;IAClG,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,sBAAsB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,sCAAsC;IACrD,oGAAoG;IACpG,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,sBAAsB,GAAG,IAAI,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACvH;;;;;;;;;;OAUG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AA6CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,sCAAsC,GAC9C,OAAO,CAAC,0BAA0B,CAAC,CAoDrC"}
@@ -1,6 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { InteractionResponseType, InteractionType } from 'discord-api-types/v10';
3
3
  import { verifyInteractionRequest } from './verify-interaction-request.js';
4
+ import { isDiscordSignatureConformanceCheck } from './is-discord-signature-conformance-check.js';
4
5
  /**
5
6
  * Best-effort source IP for the diagnostic log below - checks the headers a
6
7
  * request sitting behind a reverse proxy (Cloudflare, nginx, ...) actually
@@ -63,7 +64,7 @@ function verboseSignatureDiagnostics(request) {
63
64
  * fields; omit it and those two just come back `undefined`.
64
65
  */
65
66
  export async function handleWebhookInteractionRequest(request, options) {
66
- const { publicKey, logger, onInteraction, verboseSignatureDiagnostics: verbose = false } = options;
67
+ const { publicKey, logger, onInteraction, verboseSignatureDiagnostics: verbose = false, applicationId, muteKnownConformanceCheckLogs = true, } = options;
67
68
  const isValid = verifyInteractionRequest({
68
69
  publicKey,
69
70
  signature: request.signature,
@@ -71,8 +72,11 @@ export async function handleWebhookInteractionRequest(request, options) {
71
72
  rawBody: request.rawBody,
72
73
  });
73
74
  if (!isValid) {
74
- logger.warn('Rejected webhook interaction request with invalid signature');
75
- logger.debug('Webhook interaction signature-rejection diagnostics', {
75
+ const rejectionLogger = muteKnownConformanceCheckLogs && isDiscordSignatureConformanceCheck(request.rawBody, applicationId)
76
+ ? logger.muteMethods(['warn', 'debug'])
77
+ : logger;
78
+ rejectionLogger.warn('Rejected webhook interaction request with invalid signature');
79
+ rejectionLogger.debug('Webhook interaction signature-rejection diagnostics', {
76
80
  sourceIp: resolveSourceIp(request.headers),
77
81
  userAgent: request.headers?.['user-agent'],
78
82
  hasSignatureHeader: request.signature !== undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"handle-webhook-interaction-request.js","sourceRoot":"","sources":["../../src/webhook/handle-webhook-interaction-request.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handle-webhook-interaction-request.js","sourceRoot":"","sources":["../../src/webhook/handle-webhook-interaction-request.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export * from './verify-interaction-request.js';
2
+ export * from './is-discord-signature-conformance-check.js';
2
3
  export * from './handle-webhook-interaction-request.js';
3
4
  export * from './create-webhook-interaction-responder.js';
4
5
  export * from './create-webhook-only-client.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAKA,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAKA,cAAc,iCAAiC,CAAC;AAChD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC"}
@@ -4,6 +4,7 @@
4
4
  // `handleWebhookInteractionRequest`/`interactionFromWebhookPayload` are
5
5
  // unverified against live Discord traffic.
6
6
  export * from './verify-interaction-request.js';
7
+ export * from './is-discord-signature-conformance-check.js';
7
8
  export * from './handle-webhook-interaction-request.js';
8
9
  export * from './create-webhook-interaction-responder.js';
9
10
  export * from './create-webhook-only-client.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,uEAAuE;AACvE,oEAAoE;AACpE,wEAAwE;AACxE,2CAA2C;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,uEAAuE;AACvE,oEAAoE;AACpE,wEAAwE;AACxE,2CAA2C;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Recognizes a recurring, confirmed-benign pattern seen in production: a `Ping` (type 1)
3
+ * interaction payload, "from" Discord's own official system user, deliberately signed with a
4
+ * signature that doesn't verify against the app's public key. Everything else about it is genuine
5
+ * (real Discord source IP, `Discord-Interactions/1.0` UA, correct `application_id`) - manually
6
+ * re-verifying a captured sample confirmed the signature itself is the only thing wrong, and
7
+ * Discord confirms an application's public key can't be rotated, so a stale-key explanation is
8
+ * ruled out too. Most plausible explanation left: Discord intentionally sends a mis-signed `Ping`
9
+ * to verify endpoints actually reject bad signatures rather than trusting anything that looks like
10
+ * a Discord request. Rejecting it is correct either way - this only exists so
11
+ * `handleWebhookInteractionRequest` can recognize it and quiet its own expected, recurring
12
+ * rejection logs for just this case, without changing the rejection itself.
13
+ *
14
+ * Deliberately checks the interaction's shape, not a fixed byte length - a specific size is
15
+ * incidental and could shift if Discord adds/removes a field, but `type` + the official system
16
+ * user is what actually identifies this case. `applicationId` is optional extra narrowing (a
17
+ * request that already failed signature verification could in principle mimic this exact shape);
18
+ * omit it to match on shape alone.
19
+ */
20
+ export declare function isDiscordSignatureConformanceCheck(rawBody: string | Buffer, applicationId?: string): boolean;
21
+ //# sourceMappingURL=is-discord-signature-conformance-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-discord-signature-conformance-check.d.ts","sourceRoot":"","sources":["../../src/webhook/is-discord-signature-conformance-check.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAiB5G"}
@@ -0,0 +1,43 @@
1
+ /** Discord's own official system user - the `user` on the payload this recognizes below. */
2
+ const DISCORD_SYSTEM_USER_ID = '643945264868098049';
3
+ /**
4
+ * Recognizes a recurring, confirmed-benign pattern seen in production: a `Ping` (type 1)
5
+ * interaction payload, "from" Discord's own official system user, deliberately signed with a
6
+ * signature that doesn't verify against the app's public key. Everything else about it is genuine
7
+ * (real Discord source IP, `Discord-Interactions/1.0` UA, correct `application_id`) - manually
8
+ * re-verifying a captured sample confirmed the signature itself is the only thing wrong, and
9
+ * Discord confirms an application's public key can't be rotated, so a stale-key explanation is
10
+ * ruled out too. Most plausible explanation left: Discord intentionally sends a mis-signed `Ping`
11
+ * to verify endpoints actually reject bad signatures rather than trusting anything that looks like
12
+ * a Discord request. Rejecting it is correct either way - this only exists so
13
+ * `handleWebhookInteractionRequest` can recognize it and quiet its own expected, recurring
14
+ * rejection logs for just this case, without changing the rejection itself.
15
+ *
16
+ * Deliberately checks the interaction's shape, not a fixed byte length - a specific size is
17
+ * incidental and could shift if Discord adds/removes a field, but `type` + the official system
18
+ * user is what actually identifies this case. `applicationId` is optional extra narrowing (a
19
+ * request that already failed signature verification could in principle mimic this exact shape);
20
+ * omit it to match on shape alone.
21
+ */
22
+ export function isDiscordSignatureConformanceCheck(rawBody, applicationId) {
23
+ let parsed;
24
+ try {
25
+ parsed = JSON.parse(rawBody.toString());
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ if (typeof parsed !== 'object' || parsed === null)
31
+ return false;
32
+ const body = parsed;
33
+ if (body.type !== 1)
34
+ return false;
35
+ if (applicationId !== undefined && body.application_id !== applicationId)
36
+ return false;
37
+ const user = body.user;
38
+ if (typeof user !== 'object' || user === null)
39
+ return false;
40
+ const { id, system, bot } = user;
41
+ return id === DISCORD_SYSTEM_USER_ID && system === true && bot === true;
42
+ }
43
+ //# sourceMappingURL=is-discord-signature-conformance-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-discord-signature-conformance-check.js","sourceRoot":"","sources":["../../src/webhook/is-discord-signature-conformance-check.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,kCAAkC,CAAC,OAAwB,EAAE,aAAsB;IACjG,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAChE,MAAM,IAAI,GAAG,MAAiC,CAAC;IAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC;IAEvF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAA+B,CAAC;IAC5D,OAAO,EAAE,KAAK,sBAAsB,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,CAAC;AAC1E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@went.tf/discord-bot-framework",
3
- "version": "2.9.1",
3
+ "version": "2.10.1",
4
4
  "description": "Shared framework for building Discord bots with discord.js: logging, env validation, interaction dispatch, API client, and optional Postgres/i18next helpers",
5
5
  "author": "WentTheFox <mail@went.tf> (https://github.com/WentTheFox)",
6
6
  "license": "MIT",