privage.js 0.22.0 → 0.25.0

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.
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { Client } from './Client';
2
2
  export { Intents } from './intents';
3
3
  export type { Intent } from './intents';
4
4
  export { Message, TextChannel } from './structures/Message';
5
- export type { MessageThread, MessageReference, ReferencedMessage, MessageAttachment, MessageEmbed, } from './structures/Message';
5
+ export type { MessageThread, MessageReference, ReferencedMessage, MessageAttachment, MessageEmbed, MessageInteraction, } from './structures/Message';
6
6
  export { Member } from './structures/Member';
7
7
  export { Server } from './structures/Server';
8
8
  export { Channel } from './structures/Channel';
@@ -20,7 +20,12 @@ export interface InteractionReplyData {
20
20
  * persisted, so there is nowhere for the bytes to live).
21
21
  */
22
22
  ephemeral?: boolean;
23
- /** Components on the reply — ephemeral replies only (they render, but aren't clickable v1). */
23
+ /**
24
+ * Components on the reply — ephemeral replies only. They are fully
25
+ * interactive: clicks arrive as fresh `interaction` events carrying
26
+ * `ephemeralMessageId`, recipient-locked to the user the ephemeral was
27
+ * delivered to, for 15 minutes after sending.
28
+ */
24
29
  components?: (ActionRow | ActionRowBuilder | Record<string, unknown>)[];
25
30
  /**
26
31
  * File attachments on the reply — `AttachmentBuilder`s, paths, raw bytes,
@@ -85,8 +90,18 @@ export declare class Interaction {
85
90
  readonly command: InteractionCommand | null;
86
91
  /** Submitted modal fields — `kind: 'modal_submit'` only, `null` otherwise. */
87
92
  readonly fields: ModalSubmitField[] | null;
88
- /** The source message. `null` for commands (and command-born modal submits) — `update()` is invalid then. */
93
+ /** The source message. `null` for commands, command-born modal submits, and ephemeral-born interactions — `update()` is invalid then. */
89
94
  readonly messageId: string | null;
95
+ /**
96
+ * Set when this interaction came from a component on an **ephemeral
97
+ * reply** — the synthetic ephemeral message's id. Recipient-locked:
98
+ * only the ephemeral's recipient can click, within the panel's
99
+ * 15-minute window (every click also re-checks membership/timeout).
100
+ * Respond with `update()` to morph the panel in place (the wizard
101
+ * pattern — updating refreshes the window), or `reply()` to post a
102
+ * new message.
103
+ */
104
+ readonly ephemeralMessageId: string | null;
90
105
  readonly channelId: string;
91
106
  readonly serverId: string | null;
92
107
  readonly user: {
@@ -115,10 +130,15 @@ export declare class Interaction {
115
130
  /** `kind === 'modal_submit'`. */
116
131
  isModalSubmit(): boolean;
117
132
  /**
118
- * Terminal: edit the original message (content/embeds/components).
119
- * Broadcasts a normal edit. Only valid when the interaction HAS a source
120
- * message throws client-side for `kind: 'command'` and for modal submits
121
- * born from a command (the server would 400).
133
+ * Terminal: edit the message this interaction came from
134
+ * (content/embeds/components). On a persisted message that's a normal
135
+ * edit broadcast. On an interaction born from an **ephemeral reply**
136
+ * (`ephemeralMessageId` set) it morphs the ephemeral panel in place —
137
+ * patch semantics (only the fields you send change), refreshing the
138
+ * panel's 15-minute window; clearing `components: []` ends the panel,
139
+ * and an expired panel rejects with a 404. Throws client-side for
140
+ * `kind: 'command'` and command-born modal submits (no source at all —
141
+ * the server would 400).
122
142
  */
123
143
  update(data: InteractionUpdateData): Promise<any>;
124
144
  /**
@@ -140,7 +160,12 @@ export declare class Interaction {
140
160
  * deferred reply and replying are the same terminal callback.
141
161
  */
142
162
  editReply(data: string | InteractionReplyData): Promise<any>;
143
- /** Extend the response window to 15 minutes; must still be followed by `update()` or `reply()`. */
163
+ /**
164
+ * Extend the response window to 15 minutes; must still be followed by
165
+ * `update()` or `reply()`. The invoker's client is told the bot needs
166
+ * more time, so a command's "thinking" row waits patiently instead of
167
+ * timing out at 15 seconds.
168
+ */
144
169
  defer(): Promise<any>;
145
170
  /**
146
171
  * Open a modal dialog for the interacting user; their submission arrives
@@ -49,6 +49,7 @@ class Interaction {
49
49
  ? data.modal.fields.map((f) => ({ customId: String(f?.custom_id ?? ''), value: String(f?.value ?? '') }))
50
50
  : null;
51
51
  this.messageId = data.message_id != null ? String(data.message_id) : null;
52
+ this.ephemeralMessageId = data.ephemeral_message_id != null ? String(data.ephemeral_message_id) : null;
52
53
  this.channelId = String(data.channel_id ?? '');
53
54
  this.serverId = data.server_id != null ? String(data.server_id) : null;
54
55
  this.user = {
@@ -87,17 +88,22 @@ class Interaction {
87
88
  return this.kind === 'modal_submit';
88
89
  }
89
90
  /**
90
- * Terminal: edit the original message (content/embeds/components).
91
- * Broadcasts a normal edit. Only valid when the interaction HAS a source
92
- * message throws client-side for `kind: 'command'` and for modal submits
93
- * born from a command (the server would 400).
91
+ * Terminal: edit the message this interaction came from
92
+ * (content/embeds/components). On a persisted message that's a normal
93
+ * edit broadcast. On an interaction born from an **ephemeral reply**
94
+ * (`ephemeralMessageId` set) it morphs the ephemeral panel in place —
95
+ * patch semantics (only the fields you send change), refreshing the
96
+ * panel's 15-minute window; clearing `components: []` ends the panel,
97
+ * and an expired panel rejects with a 404. Throws client-side for
98
+ * `kind: 'command'` and command-born modal submits (no source at all —
99
+ * the server would 400).
94
100
  */
95
101
  update(data) {
96
102
  if (this.kind === 'command') {
97
103
  throw new RangeError('update() is not valid for command interactions — there is no source message. Use reply() instead.');
98
104
  }
99
- if (this.kind === 'modal_submit' && !this.messageId) {
100
- throw new RangeError('update() is not valid for this modal submit its parent interaction had no source message. Use reply() instead.');
105
+ if (!this.messageId && !this.ephemeralMessageId) {
106
+ throw new RangeError('update() is not valid for this interactionit has no source message. Use reply() instead.');
101
107
  }
102
108
  return this.transition('responded', () => this.client.rest.interactionCallback(this.id, this.token, 'update', data));
103
109
  }
@@ -126,7 +132,12 @@ class Interaction {
126
132
  editReply(data) {
127
133
  return this.reply(data);
128
134
  }
129
- /** Extend the response window to 15 minutes; must still be followed by `update()` or `reply()`. */
135
+ /**
136
+ * Extend the response window to 15 minutes; must still be followed by
137
+ * `update()` or `reply()`. The invoker's client is told the bot needs
138
+ * more time, so a command's "thinking" row waits patiently instead of
139
+ * timing out at 15 seconds.
140
+ */
130
141
  defer() {
131
142
  if (this.state !== 'pending') {
132
143
  return this.client.rest.interactionCallback(this.id, this.token, 'defer');
@@ -76,6 +76,25 @@ export interface MessageEmbed {
76
76
  timestamp: string | null;
77
77
  createdAt: Date | null;
78
78
  }
79
+ /**
80
+ * Server-verified attribution on an interaction-born bot reply — who
81
+ * invoked the command/component that produced this message ("X used
82
+ * /price"). `user` is a frozen snapshot from interaction time; later
83
+ * renames never rewrite it. Ordinary messages carry `interaction: null`.
84
+ */
85
+ export interface MessageInteraction {
86
+ kind: 'command' | 'button' | 'select' | 'modal_submit';
87
+ /** Command name — `kind: 'command'` only, `null` otherwise. */
88
+ name: string | null;
89
+ /** Component/modal custom_id — component-born interactions only, `null` otherwise. */
90
+ customId: string | null;
91
+ /** The invoking user, snapshotted at interaction time. */
92
+ user: {
93
+ id: string;
94
+ username: string | null;
95
+ displayName: string | null;
96
+ };
97
+ }
79
98
  /** A frozen or live preview of the message a reference points at. */
80
99
  export interface ReferencedMessage {
81
100
  id: string;
@@ -144,6 +163,8 @@ export declare class Message {
144
163
  readonly reference: MessageReference | null;
145
164
  /** Thread badge — `null` unless this message has (or had) a thread. */
146
165
  readonly thread: MessageThread | null;
166
+ /** Attribution for interaction-born bot replies, or `null` (see {@link MessageInteraction}). */
167
+ readonly interaction: MessageInteraction | null;
147
168
  /** The raw wire payload, for anything the typed surface doesn't expose yet. */
148
169
  readonly raw: any;
149
170
  constructor(client: Client, data: any);
@@ -123,6 +123,22 @@ class Message {
123
123
  deletedAt: t.deleted_at ? new Date(t.deleted_at) : null,
124
124
  }
125
125
  : null;
126
+ const ix = data.interaction;
127
+ this.interaction =
128
+ ix && typeof ix === 'object'
129
+ ? {
130
+ kind: ix.kind === 'select' || ix.kind === 'command' || ix.kind === 'modal_submit'
131
+ ? ix.kind
132
+ : 'button',
133
+ name: ix.name != null ? String(ix.name) : null,
134
+ customId: ix.custom_id != null ? String(ix.custom_id) : null,
135
+ user: {
136
+ id: String(ix.user?.id ?? ''),
137
+ username: ix.user?.username ?? null,
138
+ displayName: ix.user?.display_name ?? null,
139
+ },
140
+ }
141
+ : null;
126
142
  }
127
143
  /**
128
144
  * Compat alias (discord.js-style): the id of the message this one replies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "privage.js",
3
- "version": "0.22.0",
3
+ "version": "0.25.0",
4
4
  "description": "Official SDK for building Privage bots.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",