district.js 0.3.0 → 0.5.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/README.md +41 -0
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/components.d.ts +34 -0
- package/dist/components.js +29 -0
- package/dist/embed.d.ts +55 -0
- package/dist/embed.js +37 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/structures.d.ts +29 -8
- package/dist/structures.js +37 -10
- package/dist/types.d.ts +6 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,6 +69,47 @@ import { Formatters } from "district.js";
|
|
|
69
69
|
channel.send(Formatters.bold("Heads up!") + " " + Formatters.code("v0.2.0"));
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
## Embeds
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
import { EmbedBuilder } from "district.js";
|
|
76
|
+
|
|
77
|
+
const embed = new EmbedBuilder()
|
|
78
|
+
.setTitle("Deploy complete")
|
|
79
|
+
.setUrl("https://example.com/builds/128")
|
|
80
|
+
.setColor("#c6a86b")
|
|
81
|
+
.setDescription("Build **#128** shipped to production.")
|
|
82
|
+
.addFields(
|
|
83
|
+
{ name: "Env", value: "prod", inline: true },
|
|
84
|
+
{ name: "By", value: "ci-bot", inline: true },
|
|
85
|
+
)
|
|
86
|
+
.setFooter({ text: "district.js" })
|
|
87
|
+
.setTimestamp();
|
|
88
|
+
|
|
89
|
+
await channel.send({ content: "New release 🎉", embeds: [embed] });
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The District app renders it as an embed card (accent bar, title, fields, image).
|
|
93
|
+
|
|
94
|
+
## Buttons
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import { ActionRowBuilder, ButtonBuilder } from "district.js";
|
|
98
|
+
|
|
99
|
+
const row = new ActionRowBuilder().addComponents(
|
|
100
|
+
new ButtonBuilder().setLabel("Approve").setStyle("success").setCustomId("approve"),
|
|
101
|
+
new ButtonBuilder().setLabel("Deny").setStyle("danger").setCustomId("deny"),
|
|
102
|
+
new ButtonBuilder().setLabel("Docs").setUrl("https://usedistrict.org/developers/docs"),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
await channel.send({ content: "Review this?", components: [row] });
|
|
106
|
+
|
|
107
|
+
// A click delivers an interactionCreate (needs an Event Subscription endpoint)
|
|
108
|
+
client.on("interactionCreate", (i) => {
|
|
109
|
+
if (i.isButton() && i.customId === "approve") i.reply("Approved ✅");
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
72
113
|
## Slash commands
|
|
73
114
|
|
|
74
115
|
Register the command in the portal (name + handler URL), then:
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import http from "node:http";
|
|
3
3
|
import { REST } from "./rest.js";
|
|
4
|
-
import { ClientUser, Message, TextChannel, Interaction, User, Space, type ClientContext } from "./structures.js";
|
|
4
|
+
import { ClientUser, Message, TextChannel, Interaction, User, Space, type ClientContext, type MessageContent } from "./structures.js";
|
|
5
5
|
import { type EventHeaders } from "./webhook.js";
|
|
6
6
|
import type { ClientOptions, ReactionEvent, DeletedMessage } from "./types.js";
|
|
7
7
|
/** The events a Client emits, and their argument tuples. */
|
|
@@ -30,8 +30,8 @@ export declare class Client extends EventEmitter implements ClientContext {
|
|
|
30
30
|
readonly channels: {
|
|
31
31
|
/** Fetch a channel's info (kind, name, space). */
|
|
32
32
|
fetch: (id: string) => Promise<TextChannel>;
|
|
33
|
-
/** Send a message to a channel. */
|
|
34
|
-
send: (channelId: string, content:
|
|
33
|
+
/** Send a message to a channel (text or { content, embeds }). */
|
|
34
|
+
send: (channelId: string, content: MessageContent) => Promise<Message>;
|
|
35
35
|
};
|
|
36
36
|
/** Fetch users by id. */
|
|
37
37
|
readonly users: {
|
package/dist/client.js
CHANGED
|
@@ -38,7 +38,7 @@ export class Client extends EventEmitter {
|
|
|
38
38
|
channels = {
|
|
39
39
|
/** Fetch a channel's info (kind, name, space). */
|
|
40
40
|
fetch: (id) => new TextChannel(this, id).fetch(),
|
|
41
|
-
/** Send a message to a channel. */
|
|
41
|
+
/** Send a message to a channel (text or { content, embeds }). */
|
|
42
42
|
send: (channelId, content) => new TextChannel(this, channelId).send(content),
|
|
43
43
|
};
|
|
44
44
|
/** Fetch users by id. */
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type ButtonStyle = "primary" | "secondary" | "success" | "danger" | "link";
|
|
2
|
+
export interface ButtonData {
|
|
3
|
+
type: "button";
|
|
4
|
+
style: ButtonStyle;
|
|
5
|
+
label: string;
|
|
6
|
+
custom_id?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
emoji?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ActionRowData {
|
|
12
|
+
type: "action_row";
|
|
13
|
+
components: ButtonData[];
|
|
14
|
+
}
|
|
15
|
+
export declare class ButtonBuilder {
|
|
16
|
+
data: Partial<ButtonData>;
|
|
17
|
+
setLabel(label: string): this;
|
|
18
|
+
setStyle(style: ButtonStyle): this;
|
|
19
|
+
/** A custom id you'll match in the interactionCreate handler (non-link buttons). */
|
|
20
|
+
setCustomId(id: string): this;
|
|
21
|
+
/** A link button — opens the URL, fires no interaction. */
|
|
22
|
+
setUrl(url: string): this;
|
|
23
|
+
setEmoji(emoji: string): this;
|
|
24
|
+
setDisabled(disabled?: boolean): this;
|
|
25
|
+
toJSON(): ButtonData;
|
|
26
|
+
}
|
|
27
|
+
export declare class ActionRowBuilder {
|
|
28
|
+
data: ActionRowData;
|
|
29
|
+
/** Add up to 5 buttons to this row. */
|
|
30
|
+
addComponents(...buttons: (ButtonBuilder | ButtonData)[]): this;
|
|
31
|
+
toJSON(): ActionRowData;
|
|
32
|
+
}
|
|
33
|
+
export type ComponentResolvable = ActionRowBuilder | ActionRowData;
|
|
34
|
+
export declare function resolveComponent(c: ComponentResolvable): ActionRowData;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Interactive message components — action rows of buttons. Built objects go in
|
|
2
|
+
// a message's payload.components; the District app renders them, and a click on
|
|
3
|
+
// a non-link button fires an `interactionCreate` (type "component") back to the
|
|
4
|
+
// bot with the button's customId.
|
|
5
|
+
export class ButtonBuilder {
|
|
6
|
+
data = { type: "button", style: "secondary" };
|
|
7
|
+
setLabel(label) { this.data.label = label; return this; }
|
|
8
|
+
setStyle(style) { this.data.style = style; return this; }
|
|
9
|
+
/** A custom id you'll match in the interactionCreate handler (non-link buttons). */
|
|
10
|
+
setCustomId(id) { this.data.custom_id = id; return this; }
|
|
11
|
+
/** A link button — opens the URL, fires no interaction. */
|
|
12
|
+
setUrl(url) { this.data.url = url; this.data.style = "link"; return this; }
|
|
13
|
+
setEmoji(emoji) { this.data.emoji = emoji; return this; }
|
|
14
|
+
setDisabled(disabled = true) { this.data.disabled = disabled; return this; }
|
|
15
|
+
toJSON() { return this.data; }
|
|
16
|
+
}
|
|
17
|
+
export class ActionRowBuilder {
|
|
18
|
+
data = { type: "action_row", components: [] };
|
|
19
|
+
/** Add up to 5 buttons to this row. */
|
|
20
|
+
addComponents(...buttons) {
|
|
21
|
+
for (const b of buttons)
|
|
22
|
+
this.data.components.push(b instanceof ButtonBuilder ? b.toJSON() : b);
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
toJSON() { return this.data; }
|
|
26
|
+
}
|
|
27
|
+
export function resolveComponent(c) {
|
|
28
|
+
return c instanceof ActionRowBuilder ? c.toJSON() : c;
|
|
29
|
+
}
|
package/dist/embed.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface EmbedField {
|
|
2
|
+
name: string;
|
|
3
|
+
value: string;
|
|
4
|
+
inline?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface EmbedData {
|
|
7
|
+
title?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
url?: string;
|
|
10
|
+
color?: string;
|
|
11
|
+
author?: {
|
|
12
|
+
name: string;
|
|
13
|
+
iconUrl?: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
};
|
|
16
|
+
fields?: EmbedField[];
|
|
17
|
+
image?: {
|
|
18
|
+
url: string;
|
|
19
|
+
};
|
|
20
|
+
thumbnail?: {
|
|
21
|
+
url: string;
|
|
22
|
+
};
|
|
23
|
+
footer?: {
|
|
24
|
+
text: string;
|
|
25
|
+
iconUrl?: string;
|
|
26
|
+
};
|
|
27
|
+
timestamp?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare class EmbedBuilder {
|
|
30
|
+
data: EmbedData;
|
|
31
|
+
constructor(data?: EmbedData);
|
|
32
|
+
setTitle(title: string): this;
|
|
33
|
+
setDescription(description: string): this;
|
|
34
|
+
setUrl(url: string): this;
|
|
35
|
+
setColor(color: string | number): this;
|
|
36
|
+
setAuthor(author: {
|
|
37
|
+
name: string;
|
|
38
|
+
iconUrl?: string;
|
|
39
|
+
url?: string;
|
|
40
|
+
}): this;
|
|
41
|
+
setImage(url: string): this;
|
|
42
|
+
setThumbnail(url: string): this;
|
|
43
|
+
setFooter(footer: {
|
|
44
|
+
text: string;
|
|
45
|
+
iconUrl?: string;
|
|
46
|
+
}): this;
|
|
47
|
+
setTimestamp(ts?: Date | string | number): this;
|
|
48
|
+
/** Add one or more fields. */
|
|
49
|
+
addFields(...fields: EmbedField[]): this;
|
|
50
|
+
/** The plain object to send (also used implicitly by JSON.stringify). */
|
|
51
|
+
toJSON(): EmbedData;
|
|
52
|
+
}
|
|
53
|
+
/** Accept either a builder or a plain embed object wherever embeds are taken. */
|
|
54
|
+
export type EmbedResolvable = EmbedBuilder | EmbedData;
|
|
55
|
+
export declare function resolveEmbed(e: EmbedResolvable): EmbedData;
|
package/dist/embed.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// A rich embed builder (discord.js-style). The built object is sent in a
|
|
2
|
+
// message's payload.embeds and rendered by the District app as an embed card.
|
|
3
|
+
function toHex(color) {
|
|
4
|
+
if (typeof color === "number")
|
|
5
|
+
return "#" + color.toString(16).padStart(6, "0");
|
|
6
|
+
return color.startsWith("#") ? color : "#" + color;
|
|
7
|
+
}
|
|
8
|
+
export class EmbedBuilder {
|
|
9
|
+
data;
|
|
10
|
+
constructor(data = {}) {
|
|
11
|
+
this.data = { ...data };
|
|
12
|
+
}
|
|
13
|
+
setTitle(title) { this.data.title = title; return this; }
|
|
14
|
+
setDescription(description) { this.data.description = description; return this; }
|
|
15
|
+
setUrl(url) { this.data.url = url; return this; }
|
|
16
|
+
setColor(color) { this.data.color = toHex(color); return this; }
|
|
17
|
+
setAuthor(author) { this.data.author = author; return this; }
|
|
18
|
+
setImage(url) { this.data.image = { url }; return this; }
|
|
19
|
+
setThumbnail(url) { this.data.thumbnail = { url }; return this; }
|
|
20
|
+
setFooter(footer) { this.data.footer = footer; return this; }
|
|
21
|
+
setTimestamp(ts = new Date()) {
|
|
22
|
+
this.data.timestamp = ts instanceof Date ? ts.toISOString() : new Date(ts).toISOString();
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
/** Add one or more fields. */
|
|
26
|
+
addFields(...fields) {
|
|
27
|
+
this.data.fields = [...(this.data.fields ?? []), ...fields];
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
/** The plain object to send (also used implicitly by JSON.stringify). */
|
|
31
|
+
toJSON() {
|
|
32
|
+
return this.data;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function resolveEmbed(e) {
|
|
36
|
+
return e instanceof EmbedBuilder ? e.toJSON() : e;
|
|
37
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { Client, type ClientEvents } from "./client.js";
|
|
2
2
|
export { REST, DistrictAPIError, DEFAULT_API_BASE } from "./rest.js";
|
|
3
|
-
export { ClientUser, Message, TextChannel, Interaction, User, Space, SpaceMember, Role, Attachment, Ban, Invite, Webhook, type ClientContext, } from "./structures.js";
|
|
3
|
+
export { ClientUser, Message, TextChannel, Interaction, User, Space, SpaceMember, Role, Attachment, Ban, Invite, Webhook, type ClientContext, type MessageContent, } from "./structures.js";
|
|
4
|
+
export { EmbedBuilder, resolveEmbed, type EmbedData, type EmbedField, type EmbedResolvable } from "./embed.js";
|
|
5
|
+
export { ButtonBuilder, ActionRowBuilder, resolveComponent, type ButtonStyle, type ButtonData, type ActionRowData, type ComponentResolvable, } from "./components.js";
|
|
4
6
|
export { Collection } from "./collection.js";
|
|
5
7
|
export { PermissionsBitField, type PermissionResolvable, type PermissionFlagName } from "./permissions.js";
|
|
6
8
|
export { Formatters } from "./formatters.js";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
export { Client } from "./client.js";
|
|
8
8
|
export { REST, DistrictAPIError, DEFAULT_API_BASE } from "./rest.js";
|
|
9
9
|
export { ClientUser, Message, TextChannel, Interaction, User, Space, SpaceMember, Role, Attachment, Ban, Invite, Webhook, } from "./structures.js";
|
|
10
|
+
export { EmbedBuilder, resolveEmbed } from "./embed.js";
|
|
11
|
+
export { ButtonBuilder, ActionRowBuilder, resolveComponent, } from "./components.js";
|
|
10
12
|
export { Collection } from "./collection.js";
|
|
11
13
|
export { PermissionsBitField } from "./permissions.js";
|
|
12
14
|
export { Formatters } from "./formatters.js";
|
package/dist/structures.d.ts
CHANGED
|
@@ -2,6 +2,14 @@ import type { REST } from "./rest.js";
|
|
|
2
2
|
import type { RawMessage, RawSelfUser, RawUser, RawSpace, RawChannel, RawRole, RawMember, RawAttachment, RawBan, RawInvite, RawWebhook } from "./types.js";
|
|
3
3
|
import { Collection } from "./collection.js";
|
|
4
4
|
import { PermissionsBitField } from "./permissions.js";
|
|
5
|
+
import { type EmbedResolvable } from "./embed.js";
|
|
6
|
+
import { type ComponentResolvable } from "./components.js";
|
|
7
|
+
/** What you can pass to send/reply: a string, or content + embeds + components. */
|
|
8
|
+
export type MessageContent = string | {
|
|
9
|
+
content?: string;
|
|
10
|
+
embeds?: EmbedResolvable[];
|
|
11
|
+
components?: ComponentResolvable[];
|
|
12
|
+
};
|
|
5
13
|
/** Minimal client surface the structures need (avoids a circular import). */
|
|
6
14
|
export interface ClientContext {
|
|
7
15
|
rest: REST;
|
|
@@ -30,8 +38,8 @@ export declare class Message {
|
|
|
30
38
|
constructor(client: ClientContext, raw: RawMessage);
|
|
31
39
|
/** True if this message was sent by the current bot. */
|
|
32
40
|
get authoredByMe(): boolean;
|
|
33
|
-
/** Reply to this message (threads it via replyTo). */
|
|
34
|
-
reply(content:
|
|
41
|
+
/** Reply to this message (threads it via replyTo). Accepts text or { content, embeds }. */
|
|
42
|
+
reply(content: MessageContent): Promise<Message>;
|
|
35
43
|
/** Edit this message (only the bot's own messages). */
|
|
36
44
|
edit(content: string): Promise<this>;
|
|
37
45
|
/** Delete this message. */
|
|
@@ -61,8 +69,8 @@ export declare class TextChannel {
|
|
|
61
69
|
fetch(): Promise<this>;
|
|
62
70
|
/** @internal populate info fields from a raw channel row. */
|
|
63
71
|
applyInfo(raw: RawChannel): this;
|
|
64
|
-
/** Send a message to this channel. */
|
|
65
|
-
send(content:
|
|
72
|
+
/** Send a message to this channel. Accepts text or { content, embeds }. */
|
|
73
|
+
send(content: MessageContent): Promise<Message>;
|
|
66
74
|
/** Fetch recent messages (oldest → newest), up to 100. */
|
|
67
75
|
fetchMessages(limit?: number): Promise<Collection<string, Message>>;
|
|
68
76
|
/** The channel's webhooks. */
|
|
@@ -197,20 +205,33 @@ export declare class Role {
|
|
|
197
205
|
}
|
|
198
206
|
export declare class Interaction {
|
|
199
207
|
private client;
|
|
208
|
+
/** "command" (slash command) or "component" (button click). */
|
|
209
|
+
type: "command" | "component";
|
|
200
210
|
commandName: string;
|
|
201
211
|
commandId: string;
|
|
212
|
+
/** The clicked button's customId (component interactions). */
|
|
213
|
+
customId: string;
|
|
214
|
+
/** The message the component is on (component interactions). */
|
|
215
|
+
messageId: string | null;
|
|
202
216
|
spaceId: string;
|
|
203
217
|
channelId: string;
|
|
204
218
|
userId: string;
|
|
205
219
|
args: Record<string, unknown>;
|
|
206
220
|
constructor(client: ClientContext, raw: {
|
|
207
|
-
|
|
208
|
-
|
|
221
|
+
type?: string;
|
|
222
|
+
command?: string;
|
|
223
|
+
command_id?: string;
|
|
224
|
+
custom_id?: string;
|
|
225
|
+
message_id?: string;
|
|
209
226
|
space_id: string;
|
|
210
227
|
channel_id: string;
|
|
211
228
|
user_id: string;
|
|
212
|
-
args
|
|
229
|
+
args?: Record<string, unknown>;
|
|
213
230
|
});
|
|
231
|
+
/** True if this is a button click. */
|
|
232
|
+
isButton(): boolean;
|
|
233
|
+
/** True if this is a slash command. */
|
|
234
|
+
isCommand(): boolean;
|
|
214
235
|
/** Respond to the command by posting a message in its channel. */
|
|
215
|
-
reply(content:
|
|
236
|
+
reply(content: MessageContent): Promise<Message>;
|
|
216
237
|
}
|
package/dist/structures.js
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
// act on it directly: message.reply(), channel.send(), interaction.reply().
|
|
3
3
|
import { Collection } from "./collection.js";
|
|
4
4
|
import { PermissionsBitField } from "./permissions.js";
|
|
5
|
+
import { resolveEmbed } from "./embed.js";
|
|
6
|
+
import { resolveComponent } from "./components.js";
|
|
7
|
+
function toPayload(input) {
|
|
8
|
+
if (typeof input === "string")
|
|
9
|
+
return { content: input };
|
|
10
|
+
return {
|
|
11
|
+
content: input.content,
|
|
12
|
+
embeds: input.embeds?.map(resolveEmbed),
|
|
13
|
+
components: input.components?.map(resolveComponent),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
5
16
|
export class ClientUser {
|
|
6
17
|
id;
|
|
7
18
|
handle;
|
|
@@ -40,10 +51,11 @@ export class Message {
|
|
|
40
51
|
}
|
|
41
52
|
/** True if this message was sent by the current bot. */
|
|
42
53
|
get authoredByMe() { return !!this.client.user && this.authorId === this.client.user.id; }
|
|
43
|
-
/** Reply to this message (threads it via replyTo). */
|
|
54
|
+
/** Reply to this message (threads it via replyTo). Accepts text or { content, embeds }. */
|
|
44
55
|
async reply(content) {
|
|
45
|
-
const
|
|
46
|
-
|
|
56
|
+
const p = toPayload(content);
|
|
57
|
+
const { message } = await this.client.rest.post(`/channels/${this.channelId}/messages`, { ...p, replyTo: this.id });
|
|
58
|
+
return new Message(this.client, { ...message, content: p.content ?? "", author_id: this.client.user?.id ?? "" });
|
|
47
59
|
}
|
|
48
60
|
/** Edit this message (only the bot's own messages). */
|
|
49
61
|
async edit(content) {
|
|
@@ -105,10 +117,11 @@ export class TextChannel {
|
|
|
105
117
|
this.position = raw.position ?? null;
|
|
106
118
|
return this;
|
|
107
119
|
}
|
|
108
|
-
/** Send a message to this channel. */
|
|
120
|
+
/** Send a message to this channel. Accepts text or { content, embeds }. */
|
|
109
121
|
async send(content) {
|
|
110
|
-
const
|
|
111
|
-
|
|
122
|
+
const p = toPayload(content);
|
|
123
|
+
const { message } = await this.client.rest.post(`/channels/${this.id}/messages`, p);
|
|
124
|
+
return new Message(this.client, { ...message, content: p.content ?? "", author_id: this.client.user?.id ?? "" });
|
|
112
125
|
}
|
|
113
126
|
/** Fetch recent messages (oldest → newest), up to 100. */
|
|
114
127
|
async fetchMessages(limit = 50) {
|
|
@@ -363,24 +376,38 @@ export class Role {
|
|
|
363
376
|
}
|
|
364
377
|
export class Interaction {
|
|
365
378
|
client;
|
|
379
|
+
/** "command" (slash command) or "component" (button click). */
|
|
380
|
+
type;
|
|
366
381
|
commandName;
|
|
367
382
|
commandId;
|
|
383
|
+
/** The clicked button's customId (component interactions). */
|
|
384
|
+
customId;
|
|
385
|
+
/** The message the component is on (component interactions). */
|
|
386
|
+
messageId;
|
|
368
387
|
spaceId;
|
|
369
388
|
channelId;
|
|
370
389
|
userId;
|
|
371
390
|
args;
|
|
372
391
|
constructor(client, raw) {
|
|
373
392
|
this.client = client;
|
|
374
|
-
this.
|
|
375
|
-
this.
|
|
393
|
+
this.type = raw.type === "component" ? "component" : "command";
|
|
394
|
+
this.commandName = raw.command ?? "";
|
|
395
|
+
this.commandId = raw.command_id ?? "";
|
|
396
|
+
this.customId = raw.custom_id ?? "";
|
|
397
|
+
this.messageId = raw.message_id ?? null;
|
|
376
398
|
this.spaceId = raw.space_id;
|
|
377
399
|
this.channelId = raw.channel_id;
|
|
378
400
|
this.userId = raw.user_id;
|
|
379
401
|
this.args = raw.args ?? {};
|
|
380
402
|
}
|
|
403
|
+
/** True if this is a button click. */
|
|
404
|
+
isButton() { return this.type === "component"; }
|
|
405
|
+
/** True if this is a slash command. */
|
|
406
|
+
isCommand() { return this.type === "command"; }
|
|
381
407
|
/** Respond to the command by posting a message in its channel. */
|
|
382
408
|
async reply(content) {
|
|
383
|
-
const
|
|
384
|
-
|
|
409
|
+
const p = toPayload(content);
|
|
410
|
+
const { message } = await this.client.rest.post(`/channels/${this.channelId}/messages`, p);
|
|
411
|
+
return new Message(this.client, { ...message, content: p.content ?? "", author_id: this.client.user?.id ?? "" });
|
|
385
412
|
}
|
|
386
413
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -146,12 +146,15 @@ export type DistrictEvent = {
|
|
|
146
146
|
emoji: string;
|
|
147
147
|
} | {
|
|
148
148
|
event: "interaction.create";
|
|
149
|
-
command
|
|
150
|
-
|
|
149
|
+
type?: "command" | "component";
|
|
150
|
+
command?: string;
|
|
151
|
+
command_id?: string;
|
|
152
|
+
custom_id?: string;
|
|
153
|
+
message_id?: string;
|
|
151
154
|
space_id: string;
|
|
152
155
|
channel_id: string;
|
|
153
156
|
user_id: string;
|
|
154
|
-
args
|
|
157
|
+
args?: Record<string, unknown>;
|
|
155
158
|
};
|
|
156
159
|
export interface ReactionEvent {
|
|
157
160
|
spaceId: string;
|
package/package.json
CHANGED