@seedcord/http 0.10.2 → 0.11.0-next.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 +55 -9
- package/dist/index.d.mts +42 -57
- package/dist/index.mjs +144 -239
- package/dist/index.mjs.map +1 -1
- package/dist/shared-vsj1uwIH.d.mts +977 -0
- package/dist/{edge.index-DCP1BD6f.mjs → username-3UsqzTSd.mjs} +1634 -1519
- package/dist/username-3UsqzTSd.mjs.map +1 -0
- package/dist/workerd.index.d.mts +65 -0
- package/dist/workerd.index.mjs +177 -0
- package/dist/workerd.index.mjs.map +1 -0
- package/package.json +19 -27
- package/dist/Manifest-D5MEsTmH.d.mts +0 -485
- package/dist/edge.index-DCP1BD6f.mjs.map +0 -1
- package/dist/edge.index-DFszgCJp.d.mts +0 -502
- package/dist/edge.index.d.mts +0 -10
- package/dist/edge.index.mjs +0 -15
- package/dist/manifest.index.d.mts +0 -10
- package/dist/manifest.index.mjs +0 -26
- package/dist/manifest.index.mjs.map +0 -1
|
@@ -0,0 +1,977 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { AutocompletableNames, AutocompleteRouteBrand, ChoiceValueOf, ComponentDefsBrand, ComponentKindBrand, ContextMenuKindBrand, ContextMenuNamesBrand, EntryFor, FixedScope, FocusedField, GateFitsWith, HasComponentDefs, MatchArms, MiddlewareKindsBrand, MiddlewareRegistry, NamesFor, PageCursor, SingleParams, SlashOptions, SlashRouteBrand } from "@seedcord/core/internal";
|
|
3
|
+
import { Plugin, PluginLifecycleSpec, PluginOptions, PluginOptions as PluginOptions$1 } from "@seedcord/core/plugin";
|
|
4
|
+
import { APIApplicationCommandAutocompleteInteraction, APIApplicationCommandOptionChoice, APIAttachment, APIChatInputApplicationCommandInteraction, APIContextMenuInteraction, APIInteraction, APIInteractionDataResolvedChannel, APIInteractionDataResolvedChannelBase, APIInteractionDataResolvedGuildMember, APIInteractionGuildMember, APIMessage, APIMessageApplicationCommandInteraction, APIMessageChannelSelectInteractionData, APIMessageComponentButtonInteraction, APIMessageComponentInteraction, APIMessageComponentSelectMenuInteraction, APIMessageMentionableSelectInteractionData, APIMessageRoleSelectInteractionData, APIMessageStringSelectInteractionData, APIMessageUserSelectInteractionData, APIModalInteractionResponseCallbackData, APIModalSubmission, APIModalSubmitInteraction, APIRole, APIThreadChannel, APIUser, APIUserApplicationCommandInteraction, ApplicationCommandType, ChannelType, ModalSubmitComponent, ThreadChannelType } from "discord-api-types/v10";
|
|
5
|
+
import { Collection } from "@discordjs/collection";
|
|
6
|
+
import { ArraySourceBase, AutocompleteOptions, BaseHandler, BaseReplySender, Bus, CoreBase, CursorSourceBase, DispatchContext, DispatchResult, Gate, GateContextBase, GuildPermissionsContext, InteractionKind, MiddlewareKind, ModalLike, PageSourceBase, PaginatorBase, PaginatorConfig, RepliableHandler, RequiredOf, ResolvedEmoji, SlashRegistry, Subscriber, SubscriptionKey, WebhookLog } from "@seedcord/core";
|
|
7
|
+
import { HmrModuleHandler as HmrModuleHandler$1 } from "@seedcord/core/hmr";
|
|
8
|
+
import { API } from "@discordjs/core/http-only";
|
|
9
|
+
import { CoordinatedShutdown, CoordinatedStartup as CoordinatedStartup$1 } from "@seedcord/core/node";
|
|
10
|
+
import { REST, RESTOptions } from "@discordjs/rest";
|
|
11
|
+
import { AnyCustomId } from "@seedcord/custom-id";
|
|
12
|
+
import { BotConfig, Config, DeferOpts, EmojiMap, HealthCheckConfig, ReplyResponse, SendOpts, TypedOmit } from "@seedcord/types";
|
|
13
|
+
import { NonEmptyTuple, Promisable } from "type-fest";
|
|
14
|
+
//#region src/subscriptions.d.ts
|
|
15
|
+
declare module '@seedcord/core/internal' {
|
|
16
|
+
interface DefaultSubscriptions {
|
|
17
|
+
/** Triggered for every verified interaction, before routing. */
|
|
18
|
+
anyInteraction: {
|
|
19
|
+
interaction: APIInteraction;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/interfaces/Config.d.ts
|
|
25
|
+
type EdgeSweeperKey = 'hashSweepInterval' | 'handlerSweepInterval';
|
|
26
|
+
interface HttpBotConfig<Options> extends BotConfig {
|
|
27
|
+
/**
|
|
28
|
+
* Passed to the `REST` client from `@discordjs/rest`.
|
|
29
|
+
*/
|
|
30
|
+
restOptions?: Options;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Config for a long-running node server. Pass to `new Seedcord(config).start()`.
|
|
34
|
+
*/
|
|
35
|
+
interface HttpServerConfig extends Config {
|
|
36
|
+
bot: HttpBotConfig<Partial<RESTOptions>>;
|
|
37
|
+
/**
|
|
38
|
+
* Port the interactions server uses. `false` turns off the built-in server. Mount
|
|
39
|
+
* `seedcord.fetch()` in your own server to answer requests.
|
|
40
|
+
*
|
|
41
|
+
* @defaultValue `3000`
|
|
42
|
+
*/
|
|
43
|
+
port?: number | false;
|
|
44
|
+
/**
|
|
45
|
+
* The health path on the interactions server. It answers 503 until startup finishes, then 200.
|
|
46
|
+
* `false` turns it off, `true` or omit for `/health`, `{ path }` sets the path.
|
|
47
|
+
*/
|
|
48
|
+
healthCheck?: boolean | Pick<HealthCheckConfig, 'path'>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Config for a bot on Cloudflare Workers. Pass to `new Seedcord(config)`.
|
|
52
|
+
*/
|
|
53
|
+
interface HttpEdgeConfig extends Config {
|
|
54
|
+
bot: HttpBotConfig<Partial<TypedOmit<RESTOptions, EdgeSweeperKey>>>;
|
|
55
|
+
port?: never;
|
|
56
|
+
lifecycle?: never;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The http transport's configuration on either runtime.
|
|
60
|
+
*/
|
|
61
|
+
type HttpConfig = HttpServerConfig | HttpEdgeConfig;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/interfaces/Core.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* Main interface for Seedcord core functionality on the HTTP transport.
|
|
66
|
+
*
|
|
67
|
+
* This interface can be augmented via declaration merging to add type-safe plugin definitions when
|
|
68
|
+
* using `this.core` in handlers.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* declare module '@seedcord/http' {
|
|
73
|
+
* interface Core {
|
|
74
|
+
* db: Mongoose;
|
|
75
|
+
* }
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
interface Core extends CoreBase {
|
|
80
|
+
readonly startup: Pick<CoordinatedStartup$1, 'addTask'>;
|
|
81
|
+
readonly shutdown: Pick<CoordinatedShutdown, 'addTask'>;
|
|
82
|
+
readonly config: HttpConfig;
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/handlers/interaction/AutocompleteHandler.d.ts
|
|
86
|
+
type FocusedArms<Route extends keyof SlashRegistry, Ret> = { [Name in AutocompletableNames<Route>]: (value: string, respond: (choices: readonly APIApplicationCommandOptionChoice<ChoiceValueOf<EntryFor<Route, Name>>>[]) => Promise<void>) => Promisable<Ret>; };
|
|
87
|
+
/**
|
|
88
|
+
* Base class for an autocomplete handler on the HTTP transport.
|
|
89
|
+
*
|
|
90
|
+
* Pass the command route(s) from the generated registry as the generic. Branch on the focused field with
|
|
91
|
+
* `this.match`, read already-entered sibling options with `this.options`, and find which command fired
|
|
92
|
+
* with `this.route`.
|
|
93
|
+
*
|
|
94
|
+
* @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'search'`.
|
|
95
|
+
*/
|
|
96
|
+
declare abstract class AutocompleteHandler<Route extends keyof SlashRegistry> extends BaseHandler<APIApplicationCommandAutocompleteInteraction, Core> {
|
|
97
|
+
constructor(event: APIApplicationCommandAutocompleteInteraction, core: Core, dispatch: DispatchContext);
|
|
98
|
+
/** @internal */
|
|
99
|
+
readonly [AutocompleteRouteBrand]?: Route;
|
|
100
|
+
/**
|
|
101
|
+
* Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.
|
|
102
|
+
*/
|
|
103
|
+
protected get api(): API;
|
|
104
|
+
private resolver?;
|
|
105
|
+
private get reader();
|
|
106
|
+
/**
|
|
107
|
+
* The focused option for this interaction. `value` is always the raw partial string the user is typing,
|
|
108
|
+
* even for an integer or number option, so coerce it yourself when you need a number.
|
|
109
|
+
*/
|
|
110
|
+
protected get focused(): FocusedField<Route>;
|
|
111
|
+
/**
|
|
112
|
+
* Run the arm for the focused field. An autocomplete always dispatches by which field is focused.
|
|
113
|
+
* Match is how you read it.
|
|
114
|
+
*
|
|
115
|
+
* Provide one arm per autocompletable field across the registered commands, keyed by field name. Each
|
|
116
|
+
* arm receives the focused partial value and a `respond` typed to that field's choice value. The
|
|
117
|
+
* arms must cover every autocompletable field. A missing field or an unknown key is a compile error.
|
|
118
|
+
*
|
|
119
|
+
* @param arms - One handler per autocompletable field, keyed by field name.
|
|
120
|
+
* @returns The result of the arm that ran.
|
|
121
|
+
* @throws A **SeedcordTypeError** with `MatchArmMissing` when the focused field has no arm. Only a stale-deployed command can send one.
|
|
122
|
+
*/
|
|
123
|
+
protected match<Ret>(arms: FocusedArms<Route, Ret>): Promise<Ret>;
|
|
124
|
+
/** Send autocomplete suggestions, callback type 8. Prefer {@link match}, which restricts each field's choices to its declared type. */
|
|
125
|
+
protected respond(choices: readonly APIApplicationCommandOptionChoice[]): Promise<void>;
|
|
126
|
+
/** The firing command route, for a field whose completion differs per registered command. */
|
|
127
|
+
protected get route(): Route;
|
|
128
|
+
/**
|
|
129
|
+
* The already-entered options on this command, restricted to the kinds Discord resolves during autocomplete
|
|
130
|
+
* (string, integer, number, boolean) with every read nullable, since a sibling is partial while the user
|
|
131
|
+
* types the focused field. The focused field is on `this.focused`.
|
|
132
|
+
*/
|
|
133
|
+
protected get options(): AutocompleteOptions<Route>;
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/reply/ReplySender.d.ts
|
|
137
|
+
/** The interaction payload fields the sender writes its wire from. */
|
|
138
|
+
interface InteractionRef {
|
|
139
|
+
readonly application_id: string;
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly token: string;
|
|
142
|
+
}
|
|
143
|
+
/** The created message an http reply resolves to (the http `SentMessage` lens). */
|
|
144
|
+
type SentMessage = APIMessage;
|
|
145
|
+
/**
|
|
146
|
+
* Writes interaction responses over the Discord REST callback and webhook endpoints. Construction is
|
|
147
|
+
* internal to the repliable handler bases and the dispatcher.
|
|
148
|
+
*/
|
|
149
|
+
declare class ReplySender extends BaseReplySender<SentMessage> {
|
|
150
|
+
private readonly ref;
|
|
151
|
+
private readonly rest;
|
|
152
|
+
constructor(ref: InteractionRef, rest: REST, dispatch: DispatchContext, bus: Bus);
|
|
153
|
+
protected writeReply(response: ReplyResponse | string, opts?: SendOpts): Promise<SentMessage | undefined>;
|
|
154
|
+
protected writeDefer(opts?: DeferOpts): Promise<void>;
|
|
155
|
+
protected writeDeferUpdate(): Promise<void>;
|
|
156
|
+
protected writeUpdate(response: ReplyResponse | string): Promise<SentMessage | undefined>;
|
|
157
|
+
protected writeFollowUp(response: ReplyResponse | string, opts?: SendOpts): Promise<SentMessage>;
|
|
158
|
+
protected writeEditOriginal(response: ReplyResponse | string): Promise<SentMessage>;
|
|
159
|
+
protected writeEditTarget(targetId: string, response: ReplyResponse | string): Promise<SentMessage>;
|
|
160
|
+
protected writeDeleteOriginal(): Promise<void>;
|
|
161
|
+
protected writeDeleteTarget(targetId: string): Promise<void>;
|
|
162
|
+
protected writeModal(data: APIModalInteractionResponseCallbackData): Promise<void>;
|
|
163
|
+
private callback;
|
|
164
|
+
private editMessage;
|
|
165
|
+
private rawFiles;
|
|
166
|
+
private createdMessage;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/handlers/interactionTypes.d.ts
|
|
170
|
+
type ValidInteractionTypes = APIChatInputApplicationCommandInteraction | APIContextMenuInteraction | APIMessageComponentInteraction | APIModalSubmitInteraction | APIApplicationCommandAutocompleteInteraction;
|
|
171
|
+
type Repliables = Exclude<ValidInteractionTypes, APIApplicationCommandAutocompleteInteraction>;
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/handlers/RepliableHandler.d.ts
|
|
174
|
+
/**
|
|
175
|
+
* Shared base the repliable HTTP interaction handlers extend.
|
|
176
|
+
*
|
|
177
|
+
* Not a public entry point. Extend {@link SlashHandler}, {@link ButtonHandler}, {@link ModalHandler},
|
|
178
|
+
* {@link ContextMenuHandler}, or one of the select menu bases instead. This class binds the core
|
|
179
|
+
* reply base to the http sender.
|
|
180
|
+
*
|
|
181
|
+
* @typeParam Event - The repliable interaction type this handler processes
|
|
182
|
+
*/
|
|
183
|
+
declare abstract class RepliableHandler$1<Event extends Repliables> extends RepliableHandler<Event, Core, SentMessage, never, ReplySender> {
|
|
184
|
+
/** @internal */
|
|
185
|
+
getEvent(): Event;
|
|
186
|
+
protected buildSender(event: Event, core: Core, dispatch: DispatchContext): ReplySender;
|
|
187
|
+
/**
|
|
188
|
+
* Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.
|
|
189
|
+
* The interaction callbacks on `api.interactions` bypass the reply surface. The
|
|
190
|
+
* `no-raw-interaction-acks` rule flags them in handler classes.
|
|
191
|
+
*/
|
|
192
|
+
protected get api(): API;
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/handlers/interaction/InteractionHandler.d.ts
|
|
196
|
+
/**
|
|
197
|
+
* Shared base the repliable interaction handlers extend.
|
|
198
|
+
*
|
|
199
|
+
* Not a public entry point. Extend {@link SlashHandler}, {@link ContextMenuHandler}, {@link ButtonHandler},
|
|
200
|
+
* {@link ModalHandler}, or one of the select menu bases instead. This class adds `showModal` on top
|
|
201
|
+
* of the reply members.
|
|
202
|
+
*
|
|
203
|
+
* @typeParam Event - The repliable interaction type this handler processes
|
|
204
|
+
*/
|
|
205
|
+
declare abstract class InteractionHandler<Event extends Repliables> extends RepliableHandler$1<Event> {
|
|
206
|
+
constructor(event: Event, core: Core, dispatch: DispatchContext);
|
|
207
|
+
/**
|
|
208
|
+
* Open a modal. Must be the initial response to this interaction. The modal kind rejects this call at
|
|
209
|
+
* compile time (Discord forbids a modal in response to a modal).
|
|
210
|
+
*/
|
|
211
|
+
protected showModal(this: InteractionHandler<Exclude<Repliables, APIModalSubmitInteraction>>, modal: ModalLike): Promise<void>;
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/handlers/interaction/components/ComponentHandler.d.ts
|
|
215
|
+
/**
|
|
216
|
+
* Shared base the customId-routed component handlers extend on the HTTP transport.
|
|
217
|
+
*
|
|
218
|
+
* Not a public entry point. Extend {@link ButtonHandler}, {@link ModalHandler}, or one of the select menu
|
|
219
|
+
* bases instead. This class defines the customId decode, the route matching, and the source-message
|
|
220
|
+
* verbs `update` and `deferUpdate`.
|
|
221
|
+
*
|
|
222
|
+
* @typeParam Event - The component or modal interaction type this handler processes
|
|
223
|
+
* @typeParam Defs - The customId route definitions registered on the concrete handler
|
|
224
|
+
*/
|
|
225
|
+
declare abstract class ComponentHandler<Event extends APIMessageComponentInteraction | APIModalSubmitInteraction, Defs extends readonly AnyCustomId[]> extends InteractionHandler<Event> implements HasComponentDefs<Defs> {
|
|
226
|
+
/** @internal */
|
|
227
|
+
readonly [ComponentDefsBrand]?: Defs;
|
|
228
|
+
/** Rewrite the source message this component interaction came from. */
|
|
229
|
+
protected update(response: ReplyResponse | string): Promise<SentMessage>;
|
|
230
|
+
/** Acknowledge the component without changing the source message. */
|
|
231
|
+
protected deferUpdate(): Promise<void>;
|
|
232
|
+
private decoded?;
|
|
233
|
+
private get route();
|
|
234
|
+
/**
|
|
235
|
+
* The decoded params of the single route this handler is registered for.
|
|
236
|
+
*
|
|
237
|
+
* Reading this decodes `this.event.data.custom_id` once and caches the result. On a handler
|
|
238
|
+
* registered for several routes this is `never`. Use {@link match} instead.
|
|
239
|
+
*
|
|
240
|
+
* @throws A **StaleCustomId** when the wire was encoded under an older shape. The dispatcher boundary turns it into a reply.
|
|
241
|
+
* @throws An **InvalidCustomId** when the wire is corrupt. The dispatcher boundary turns it into a reply.
|
|
242
|
+
*/
|
|
243
|
+
protected get params(): SingleParams<Defs>;
|
|
244
|
+
/**
|
|
245
|
+
* Run the arm for whichever route the component was minted from. Use this only when the handler is
|
|
246
|
+
* registered for several routes. A single-route handler reads `this.params` directly. On a multi-route
|
|
247
|
+
* handler `this.params` is `never`, so match is the only way to read the decoded params.
|
|
248
|
+
*
|
|
249
|
+
* Provide one arm per registered route, keyed by its prefix, and each arm receives that route's own
|
|
250
|
+
* decoded params. The compiler checks that the arms cover every registered route prefix. `match`
|
|
251
|
+
* decodes the wire before it runs an arm.
|
|
252
|
+
*
|
|
253
|
+
* @param arms - One callback per registered route, keyed by prefix.
|
|
254
|
+
* @returns The result of the arm that ran.
|
|
255
|
+
* @throws A **SeedcordTypeError** with `MatchArmMissing` when the wire's prefix has no arm.
|
|
256
|
+
* @throws A **StaleCustomId** when the wire was encoded under an older shape.
|
|
257
|
+
* @throws An **InvalidCustomId** when the wire is corrupt.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* \@ButtonRoute(Approve, Reject)
|
|
262
|
+
* class ReviewButtons extends ButtonHandler<[typeof Approve, typeof Reject]> {
|
|
263
|
+
* async execute() {
|
|
264
|
+
* await this.match({
|
|
265
|
+
* approve: ({ userId }) => this.reply(`approved <@${userId}>`),
|
|
266
|
+
* reject: ({ userId }) => this.reply(`rejected <@${userId}>`)
|
|
267
|
+
* });
|
|
268
|
+
* }
|
|
269
|
+
* }
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
protected match<Ret>(arms: MatchArms<Defs, Ret>): Promise<Ret>;
|
|
273
|
+
}
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/handlers/interaction/components/SelectMenuHandler.d.ts
|
|
276
|
+
/** @internal */
|
|
277
|
+
type SelectInteraction<Data> = APIMessageComponentSelectMenuInteraction & {
|
|
278
|
+
data: Data;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Shared base the select menu handlers extend on the HTTP transport.
|
|
282
|
+
*
|
|
283
|
+
* Not a public entry point. Extend {@link StringMenuHandler}, {@link UserMenuHandler},
|
|
284
|
+
* {@link RoleMenuHandler}, {@link ChannelMenuHandler}, or {@link MentionableMenuHandler} instead. This
|
|
285
|
+
* class defines the `values` getter those bases share.
|
|
286
|
+
*
|
|
287
|
+
* @typeParam Event - The select menu interaction type this handler processes
|
|
288
|
+
* @typeParam Defs - The customId route definitions registered on the concrete handler
|
|
289
|
+
*/
|
|
290
|
+
declare abstract class SelectMenuHandler<Event extends APIMessageComponentSelectMenuInteraction, Defs extends readonly AnyCustomId[]> extends ComponentHandler<Event, Defs> {
|
|
291
|
+
/** The values this select picked. On every kind but the string menu they are snowflake ids. */
|
|
292
|
+
protected get values(): string[];
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Base class for a string select menu handler on the HTTP transport.
|
|
296
|
+
*
|
|
297
|
+
* Register the customId definitions with `@StringMenuRoute`, list the same ones in the generic, then read
|
|
298
|
+
* the chosen option values from `this.values`. Read `this.params` for a single route or `this.match` for
|
|
299
|
+
* several. Reply through the handler members, or rewrite the source message with `this.update`.
|
|
300
|
+
*
|
|
301
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof TopicsId]`.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* \@StringMenuRoute(TopicsId)
|
|
306
|
+
* class Topics extends StringMenuHandler<[typeof TopicsId]> {
|
|
307
|
+
* async execute() {
|
|
308
|
+
* const { userId } = this.params;
|
|
309
|
+
* await this.update(`<@${userId}> now follows ${this.values.join(', ')}`);
|
|
310
|
+
* }
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
declare abstract class StringMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<SelectInteraction<APIMessageStringSelectInteractionData>, Defs> {
|
|
315
|
+
/** @internal */
|
|
316
|
+
readonly [ComponentKindBrand]?: InteractionKind.StringMenu;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Base class for a user select menu handler on the HTTP transport.
|
|
320
|
+
*
|
|
321
|
+
* Beside `this.values` this handler declares `this.users` and `this.members`. Register the customId
|
|
322
|
+
* definitions with `@UserMenuRoute` and list the same ones in the generic.
|
|
323
|
+
*
|
|
324
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof AssignId]`.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* \@UserMenuRoute(AssignId)
|
|
329
|
+
* class Assign extends UserMenuHandler<[typeof AssignId]> {
|
|
330
|
+
* async execute() {
|
|
331
|
+
* const { roleId } = this.params;
|
|
332
|
+
* await this.reply(`assigning ${this.users.size} member(s) to <@&${roleId}>`);
|
|
333
|
+
* }
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare abstract class UserMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<SelectInteraction<APIMessageUserSelectInteractionData>, Defs> {
|
|
338
|
+
/** @internal */
|
|
339
|
+
readonly [ComponentKindBrand]?: InteractionKind.UserMenu;
|
|
340
|
+
/** The users this select picked. */
|
|
341
|
+
protected get users(): Collection<string, APIUser>;
|
|
342
|
+
/** The guild members behind the picked users. Discord resolves these only inside a guild. */
|
|
343
|
+
protected get members(): Collection<string, APIInteractionDataResolvedGuildMember>;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Base class for a role select menu handler on the HTTP transport.
|
|
347
|
+
*
|
|
348
|
+
* Beside `this.values` this handler declares `this.roles`. Register the customId definitions with
|
|
349
|
+
* `@RoleMenuRoute` and list the same ones in the generic.
|
|
350
|
+
*
|
|
351
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof GrantId]`.
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```ts
|
|
355
|
+
* \@RoleMenuRoute(GrantId)
|
|
356
|
+
* class Grant extends RoleMenuHandler<[typeof GrantId]> {
|
|
357
|
+
* async execute() {
|
|
358
|
+
* await this.update(`granting ${this.roles.size} role(s)`);
|
|
359
|
+
* }
|
|
360
|
+
* }
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
declare abstract class RoleMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<SelectInteraction<APIMessageRoleSelectInteractionData>, Defs> {
|
|
364
|
+
/** @internal */
|
|
365
|
+
readonly [ComponentKindBrand]?: InteractionKind.RoleMenu;
|
|
366
|
+
/** The roles this select picked. */
|
|
367
|
+
protected get roles(): Collection<string, APIRole>;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Base class for a channel select menu handler on the HTTP transport.
|
|
371
|
+
*
|
|
372
|
+
* Beside `this.values` this handler declares `this.channels`. Register the customId definitions with
|
|
373
|
+
* `@ChannelMenuRoute` and list the same ones in the generic.
|
|
374
|
+
*
|
|
375
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof LogTargetId]`.
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```ts
|
|
379
|
+
* \@ChannelMenuRoute(LogTargetId)
|
|
380
|
+
* class LogTarget extends ChannelMenuHandler<[typeof LogTargetId]> {
|
|
381
|
+
* async execute() {
|
|
382
|
+
* await this.update(`logging to ${this.channels.size} channel(s)`);
|
|
383
|
+
* }
|
|
384
|
+
* }
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
declare abstract class ChannelMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<SelectInteraction<APIMessageChannelSelectInteractionData>, Defs> {
|
|
388
|
+
/** @internal */
|
|
389
|
+
readonly [ComponentKindBrand]?: InteractionKind.ChannelMenu;
|
|
390
|
+
/** The channels this select picked. */
|
|
391
|
+
protected get channels(): Collection<string, APIInteractionDataResolvedChannel>;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Base class for a mentionable select menu handler on the HTTP transport.
|
|
395
|
+
*
|
|
396
|
+
* A mentionable menu accepts users and roles together. `this.users`, `this.members`, and `this.roles`
|
|
397
|
+
* can each come back empty.
|
|
398
|
+
*
|
|
399
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof InviteId]`.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* ```ts
|
|
403
|
+
* \@MentionableMenuRoute(InviteId)
|
|
404
|
+
* class Invite extends MentionableMenuHandler<[typeof InviteId]> {
|
|
405
|
+
* async execute() {
|
|
406
|
+
* await this.update(`inviting ${this.users.size} user(s) and ${this.roles.size} role(s)`);
|
|
407
|
+
* }
|
|
408
|
+
* }
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
declare abstract class MentionableMenuHandler<Defs extends readonly AnyCustomId[]> extends SelectMenuHandler<SelectInteraction<APIMessageMentionableSelectInteractionData>, Defs> {
|
|
412
|
+
/** @internal */
|
|
413
|
+
readonly [ComponentKindBrand]?: InteractionKind.MentionableMenu;
|
|
414
|
+
/** The users this select picked. */
|
|
415
|
+
protected get users(): Collection<string, APIUser>;
|
|
416
|
+
/** The guild members behind the picked users. Discord resolves these only inside a guild. */
|
|
417
|
+
protected get members(): Collection<string, APIInteractionDataResolvedGuildMember>;
|
|
418
|
+
/** The roles this select picked. */
|
|
419
|
+
protected get roles(): Collection<string, APIRole>;
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
422
|
+
//#region src/handlers/interaction/middlewareKinds.d.ts
|
|
423
|
+
interface Payloads {
|
|
424
|
+
[InteractionKind.Slash]: APIChatInputApplicationCommandInteraction;
|
|
425
|
+
[InteractionKind.Button]: APIMessageComponentButtonInteraction;
|
|
426
|
+
[InteractionKind.Modal]: APIModalSubmitInteraction;
|
|
427
|
+
[InteractionKind.StringMenu]: SelectInteraction<APIMessageStringSelectInteractionData>;
|
|
428
|
+
[InteractionKind.UserMenu]: SelectInteraction<APIMessageUserSelectInteractionData>;
|
|
429
|
+
[InteractionKind.RoleMenu]: SelectInteraction<APIMessageRoleSelectInteractionData>;
|
|
430
|
+
[InteractionKind.ChannelMenu]: SelectInteraction<APIMessageChannelSelectInteractionData>;
|
|
431
|
+
[InteractionKind.MentionableMenu]: SelectInteraction<APIMessageMentionableSelectInteractionData>;
|
|
432
|
+
[InteractionKind.MessageContextMenu]: APIMessageApplicationCommandInteraction;
|
|
433
|
+
[InteractionKind.UserContextMenu]: APIUserApplicationCommandInteraction;
|
|
434
|
+
}
|
|
435
|
+
type InteractionForKind = { [Kind in MiddlewareKind]: Payloads[Kind]; };
|
|
436
|
+
/** @internal */
|
|
437
|
+
type InteractionOf<Kind extends MiddlewareKind> = InteractionForKind[Kind];
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/handlers/interaction/InteractionMiddleware.d.ts
|
|
440
|
+
/**
|
|
441
|
+
* Base class for interaction middleware on the HTTP transport.
|
|
442
|
+
*
|
|
443
|
+
* Middleware runs after the dispatcher builds the handler and before the gates, over the handler's own
|
|
444
|
+
* reply surface. Name the kinds in the generic and list the same ones in `{ kinds }`. Several kinds give
|
|
445
|
+
* `this.event` a union. Narrow it on `type` and `data.component_type`. A catchall reads every repliable
|
|
446
|
+
* kind.
|
|
447
|
+
*
|
|
448
|
+
* @typeParam Kind - One or more {@link InteractionKind} members. Defaults to every repliable kind.
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```ts
|
|
452
|
+
* \@RegisterInteractionMiddleware({ kinds: [InteractionKind.Button] })
|
|
453
|
+
* class Audit extends InteractionMiddleware<InteractionKind.Button> {
|
|
454
|
+
* async execute() {
|
|
455
|
+
* this.logger.info(this.event.data.custom_id);
|
|
456
|
+
* }
|
|
457
|
+
* }
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
declare abstract class InteractionMiddleware<in out Kind extends MiddlewareKind = MiddlewareKind> extends RepliableHandler$1<InteractionOf<Kind>> {
|
|
461
|
+
/** @internal */
|
|
462
|
+
readonly [MiddlewareKindsBrand]?: Kind;
|
|
463
|
+
constructor(event: InteractionOf<Kind>, core: Core, dispatch: DispatchContext, sender: ReplySender);
|
|
464
|
+
/**
|
|
465
|
+
* Runs once the handler settles, newest middleware first. A refusal or a throw still reaches it,
|
|
466
|
+
* since seedcord calls it on every middleware whose `execute()` started. Implement it to release
|
|
467
|
+
* something this middleware took in `execute()`, such as a lock or an open span. A throw in here
|
|
468
|
+
* is logged and goes no further.
|
|
469
|
+
*
|
|
470
|
+
* @param result - How the dispatch ended. Either failure state carries the thrown value on `caught`.
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* ```ts
|
|
474
|
+
* // the base declares it. an implementation carries `override`.
|
|
475
|
+
* override async after(result: DispatchResult) {
|
|
476
|
+
* this.lock.release();
|
|
477
|
+
* }
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
after?(result: DispatchResult): Promise<void>;
|
|
481
|
+
}
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/engine.d.ts
|
|
484
|
+
/** Matches the shape of the Workers `ExecutionContext`. Work that continues after the 202 response runs under its `waitUntil`. */
|
|
485
|
+
interface EngineContext {
|
|
486
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/Plugin.d.ts
|
|
490
|
+
/** The options an HTTP plugin declares, narrowed to the transports this base serves. */
|
|
491
|
+
type HttpPluginOptions = TypedOmit<PluginOptions, 'transport'> & {
|
|
492
|
+
transport?: 'http';
|
|
493
|
+
};
|
|
494
|
+
declare const HTTP_SCOPE: {
|
|
495
|
+
readonly transport: "http";
|
|
496
|
+
};
|
|
497
|
+
/**
|
|
498
|
+
* Base class for an HTTP plugin, binding `this.core` to the HTTP {@link Core}.
|
|
499
|
+
*
|
|
500
|
+
* A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose
|
|
501
|
+
* `this.core` is typed to the shared members only.
|
|
502
|
+
*
|
|
503
|
+
* @typeParam Opts - The transport and runtime the plugin declares.
|
|
504
|
+
*/
|
|
505
|
+
declare abstract class Plugin$1<Opts extends HttpPluginOptions = {
|
|
506
|
+
transport: 'http';
|
|
507
|
+
}> extends Plugin<Opts, Core, keyof typeof HTTP_SCOPE> {
|
|
508
|
+
/** @internal */
|
|
509
|
+
protected static readonly [FixedScope]: {
|
|
510
|
+
readonly transport: "http";
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/inputs/SlashOptions.d.ts
|
|
515
|
+
type ResolvedChannelOf<Type extends ChannelType> = APIInteractionDataResolvedChannelBase<Type> & (Type extends ThreadChannelType ? Pick<APIThreadChannel, 'parent_id' | 'thread_metadata'> : unknown);
|
|
516
|
+
type AnyResolvedChannel = { [Type in ChannelType]: ResolvedChannelOf<Type>; }[ChannelType];
|
|
517
|
+
interface HttpLens {
|
|
518
|
+
user: APIUser;
|
|
519
|
+
member: APIInteractionDataResolvedGuildMember;
|
|
520
|
+
channel: AnyResolvedChannel;
|
|
521
|
+
role: APIRole;
|
|
522
|
+
mentionable: APIUser | APIInteractionDataResolvedGuildMember | APIRole;
|
|
523
|
+
attachment: APIAttachment;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* The typed view over a chat-input command's options for one route on the HTTP transport. Each getter
|
|
527
|
+
* restricts its `name` to that route's options of the matching kind, drops the null on required options,
|
|
528
|
+
* narrows `choices` to their literal union, and only appears when the route has an option of that kind.
|
|
529
|
+
* The rich kinds return `discord-api-types` payloads resolved from the interaction's `resolved` data.
|
|
530
|
+
*
|
|
531
|
+
* A channel option declared with `addChannelTypes` narrows `getChannel` to the matching resolved-channel
|
|
532
|
+
* subtype.
|
|
533
|
+
*
|
|
534
|
+
* @typeParam Route - A route key from the generated {@link SlashRegistry}.
|
|
535
|
+
*/
|
|
536
|
+
type SlashOptions$1<Route extends keyof SlashRegistry> = SlashOptions<Route, HttpLens>;
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region src/inputs/ModalFields.d.ts
|
|
539
|
+
type FieldKind = ModalSubmitComponent['type'];
|
|
540
|
+
/** The users, members, and roles a mentionable select picked. */
|
|
541
|
+
interface SelectedMentionables {
|
|
542
|
+
users: Collection<string, APIUser>;
|
|
543
|
+
members: Collection<string, APIInteractionDataResolvedGuildMember>;
|
|
544
|
+
roles: Collection<string, APIRole>;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The fields a modal carries, read by custom id.
|
|
548
|
+
*
|
|
549
|
+
* A select getter resolves the ids its field picked against the interaction's `resolved` data and returns a
|
|
550
|
+
* `Collection` keyed by id. A field that picked nothing returns null.
|
|
551
|
+
*
|
|
552
|
+
* @throws A **SeedcordTypeError** from every getter when no field in the modal has that custom id.
|
|
553
|
+
* @throws A **SeedcordTypeError** from every getter when the field holds a kind that getter does not read. The message gives the getter that does.
|
|
554
|
+
* @throws A **SeedcordTypeError** from a select getter called with `required` when its field picked nothing.
|
|
555
|
+
*/
|
|
556
|
+
declare class ModalFields {
|
|
557
|
+
private readonly entries;
|
|
558
|
+
private readonly resolved;
|
|
559
|
+
constructor(data: APIModalSubmission);
|
|
560
|
+
private entry;
|
|
561
|
+
private field;
|
|
562
|
+
private selected;
|
|
563
|
+
/**
|
|
564
|
+
* Returns the field with this custom id, as Discord sent it. Use it for a component type the typed
|
|
565
|
+
* getters do not cover.
|
|
566
|
+
*
|
|
567
|
+
* Pass a component type to get that exact type back.
|
|
568
|
+
*
|
|
569
|
+
* @throws A **SeedcordTypeError** when no field has this custom id.
|
|
570
|
+
* @throws A **SeedcordTypeError** when you pass a component type and the field holds a different one.
|
|
571
|
+
*/
|
|
572
|
+
getField<Kind extends FieldKind>(customId: string, kind: Kind): Extract<ModalSubmitComponent, {
|
|
573
|
+
type: Kind;
|
|
574
|
+
}>;
|
|
575
|
+
getField(customId: string): ModalSubmitComponent;
|
|
576
|
+
getTextInputValue(customId: string): string;
|
|
577
|
+
getStringSelectValues(customId: string): string[];
|
|
578
|
+
getSelectedUsers(customId: string, required: true): Collection<string, APIUser>;
|
|
579
|
+
getSelectedUsers(customId: string, required?: boolean): Collection<string, APIUser> | null;
|
|
580
|
+
/** The guild members behind the picked users. Discord resolves these only inside a guild. */
|
|
581
|
+
getSelectedMembers(customId: string): Collection<string, APIInteractionDataResolvedGuildMember> | null;
|
|
582
|
+
getSelectedRoles(customId: string, required: true): Collection<string, APIRole>;
|
|
583
|
+
getSelectedRoles(customId: string, required?: boolean): Collection<string, APIRole> | null;
|
|
584
|
+
/** Pass `channelTypes` to throw when a pick falls outside those types. */
|
|
585
|
+
getSelectedChannels(customId: string, required: true, channelTypes?: readonly ChannelType[]): Collection<string, APIInteractionDataResolvedChannel>;
|
|
586
|
+
getSelectedChannels(customId: string, required?: boolean, channelTypes?: readonly ChannelType[]): Collection<string, APIInteractionDataResolvedChannel> | null;
|
|
587
|
+
getSelectedMentionables(customId: string, required: true): SelectedMentionables;
|
|
588
|
+
getSelectedMentionables(customId: string, required?: boolean): SelectedMentionables | null;
|
|
589
|
+
getUploadedFiles(customId: string, required: true): Collection<string, APIAttachment>;
|
|
590
|
+
getUploadedFiles(customId: string, required?: boolean): Collection<string, APIAttachment> | null;
|
|
591
|
+
getRadioGroup(customId: string, required: true): string;
|
|
592
|
+
getRadioGroup(customId: string, required?: boolean): string | null;
|
|
593
|
+
getCheckboxGroup(customId: string): string[];
|
|
594
|
+
getCheckbox(customId: string): boolean;
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
597
|
+
//#region src/emojis/EmojiInjector.d.ts
|
|
598
|
+
/** The global {@link Emojis} accessor type. */
|
|
599
|
+
type InjectedEmojiMap = { [K in keyof EmojiMap]: ResolvedEmoji; };
|
|
600
|
+
/**
|
|
601
|
+
* The bot's resolved emojis, keyed by {@link EmojiMap}. A node bot fills these during startup. An edge
|
|
602
|
+
* bot fills them on its first request, from the ids `seedcord build` wrote into the worker.
|
|
603
|
+
*
|
|
604
|
+
* @throws A **SeedcordError** when you read a key that was not filled.
|
|
605
|
+
*/
|
|
606
|
+
declare const Emojis: InjectedEmojiMap;
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/handlers/interaction/SlashHandler.d.ts
|
|
609
|
+
type SlashMatchArms<Route extends keyof SlashRegistry, Ret> = { [Key in Route]: (options: SlashOptions$1<Key>) => Promisable<Ret>; };
|
|
610
|
+
/**
|
|
611
|
+
* Base class for a chat-input (slash) command handler on the HTTP transport.
|
|
612
|
+
*
|
|
613
|
+
* Pass the route from the generated registry as the generic, then read `this.options` for a single
|
|
614
|
+
* command or `this.match` for several. Command authoring stays plain discord.js, `seedcord codegen`
|
|
615
|
+
* reads its `toJSON()` to type these options.
|
|
616
|
+
*
|
|
617
|
+
* @typeParam Route - One or more route keys from {@link SlashRegistry}, e.g. `'ban'` or `'ban' | 'kick'`.
|
|
618
|
+
*/
|
|
619
|
+
declare abstract class SlashHandler<Route extends keyof SlashRegistry> extends InteractionHandler<APIChatInputApplicationCommandInteraction> {
|
|
620
|
+
/** @internal */
|
|
621
|
+
readonly [SlashRouteBrand]?: Route;
|
|
622
|
+
private resolver?;
|
|
623
|
+
/**
|
|
624
|
+
* The typed options for this command's route. Only the getters for kinds this command declares appear.
|
|
625
|
+
* Each getter's name argument is restricted to that command's options of its kind.
|
|
626
|
+
*
|
|
627
|
+
* - A required option drops the null.
|
|
628
|
+
*
|
|
629
|
+
* - Choices narrow to their literal union.
|
|
630
|
+
*
|
|
631
|
+
* - A channel option declared with `addChannelTypes` narrows to those types.
|
|
632
|
+
*
|
|
633
|
+
* Rich kinds resolve from the interaction's `resolved` data.
|
|
634
|
+
*/
|
|
635
|
+
protected get options(): SlashOptions$1<Route>;
|
|
636
|
+
/**
|
|
637
|
+
* Run the arm for whichever command fired. Use this only when the handler is registered for several
|
|
638
|
+
* routes.
|
|
639
|
+
*
|
|
640
|
+
* Provide one arm per registered route, keyed by its route string, and each arm receives that route's
|
|
641
|
+
* own narrowed options. The arms must cover every route in the generic, a missing route or an unknown
|
|
642
|
+
* key is a compile error.
|
|
643
|
+
*
|
|
644
|
+
* @param arms - One handler per registered route, keyed by route string.
|
|
645
|
+
* @returns The result of the arm that ran.
|
|
646
|
+
*/
|
|
647
|
+
protected match<Ret>(arms: SlashMatchArms<Route, Ret>): Promise<Ret>;
|
|
648
|
+
}
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/handlers/interaction/ContextMenuHandler.d.ts
|
|
651
|
+
type UserMenuArms<Names extends NamesFor<ApplicationCommandType.User>, Ret> = Record<Names, (target: APIUser, member: APIInteractionDataResolvedGuildMember | null) => Promisable<Ret>>;
|
|
652
|
+
type MessageMenuArms<Names extends NamesFor<ApplicationCommandType.Message>, Ret> = Record<Names, (target: APIMessage) => Promisable<Ret>>;
|
|
653
|
+
/**
|
|
654
|
+
* Base class for a user context-menu command handler on the HTTP transport (right-click a user).
|
|
655
|
+
*
|
|
656
|
+
* Pass the command name(s) as the generic, the same as `@UserContextMenuRoute`. Read the right-clicked user
|
|
657
|
+
* from `this.target` and that same user's guild member from `this.targetMember`.
|
|
658
|
+
*
|
|
659
|
+
* @typeParam Names - One or more command names from the generated user registry.
|
|
660
|
+
*/
|
|
661
|
+
declare abstract class UserContextMenuHandler<Names extends NamesFor<ApplicationCommandType.User>> extends InteractionHandler<APIUserApplicationCommandInteraction> {
|
|
662
|
+
/** @internal */
|
|
663
|
+
readonly [ContextMenuKindBrand]?: ApplicationCommandType.User;
|
|
664
|
+
/** @internal */
|
|
665
|
+
readonly [ContextMenuNamesBrand]?: Names;
|
|
666
|
+
protected get target(): APIUser;
|
|
667
|
+
/** The right-clicked user's guild member, null outside a guild. */
|
|
668
|
+
protected get targetMember(): APIInteractionDataResolvedGuildMember | null;
|
|
669
|
+
/** Which of the registered commands fired. */
|
|
670
|
+
protected get commandName(): Names;
|
|
671
|
+
/**
|
|
672
|
+
* Run the arm for whichever command fired. Use this only when the handler is registered for several
|
|
673
|
+
* names.
|
|
674
|
+
*
|
|
675
|
+
* Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each
|
|
676
|
+
* arm receives the clicked user and that user's guild member. The arms must cover every name in the
|
|
677
|
+
* generic. A missing name or an unknown key is a compile error.
|
|
678
|
+
*
|
|
679
|
+
* @param arms - One handler per registered command name.
|
|
680
|
+
* @returns The result of the arm that ran.
|
|
681
|
+
*
|
|
682
|
+
* @example
|
|
683
|
+
* ```ts
|
|
684
|
+
* \@UserContextMenuRoute('View Profile', 'Warn')
|
|
685
|
+
* class Moderation extends UserContextMenuHandler<'View Profile' | 'Warn'> {
|
|
686
|
+
* async execute() {
|
|
687
|
+
* await this.match({
|
|
688
|
+
* 'View Profile': (user) => this.reply(`Profile for ${user.username}.`),
|
|
689
|
+
* Warn: (user, member) => this.reply(`Warned ${member?.nick ?? user.username}.`)
|
|
690
|
+
* });
|
|
691
|
+
* }
|
|
692
|
+
* }
|
|
693
|
+
* ```
|
|
694
|
+
*/
|
|
695
|
+
protected match<Ret>(arms: UserMenuArms<Names, Ret>): Promise<Ret>;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Base class for a message context-menu command handler on the HTTP transport (right-click a message).
|
|
699
|
+
*
|
|
700
|
+
* Pass the command name(s) as the generic, the same as `@MessageContextMenuRoute`. Read the right-clicked
|
|
701
|
+
* message from `this.target`.
|
|
702
|
+
*
|
|
703
|
+
* @typeParam Names - One or more command names from the generated message registry.
|
|
704
|
+
*/
|
|
705
|
+
declare abstract class MessageContextMenuHandler<Names extends NamesFor<ApplicationCommandType.Message>> extends InteractionHandler<APIMessageApplicationCommandInteraction> {
|
|
706
|
+
/** @internal */
|
|
707
|
+
readonly [ContextMenuKindBrand]?: ApplicationCommandType.Message;
|
|
708
|
+
/** @internal */
|
|
709
|
+
readonly [ContextMenuNamesBrand]?: Names;
|
|
710
|
+
protected get target(): APIMessage;
|
|
711
|
+
/** Which of the registered commands fired. */
|
|
712
|
+
protected get commandName(): Names;
|
|
713
|
+
/**
|
|
714
|
+
* Run the arm for whichever command fired. Use this only when the handler is registered for several
|
|
715
|
+
* names.
|
|
716
|
+
*
|
|
717
|
+
* Provide one arm per registered name, keyed by the name Discord shows in the right-click menu. Each
|
|
718
|
+
* arm receives the clicked message. The arms must cover every name in the generic. A missing name or
|
|
719
|
+
* an unknown key is a compile error.
|
|
720
|
+
*
|
|
721
|
+
* @param arms - One handler per registered command name.
|
|
722
|
+
* @returns The result of the arm that ran.
|
|
723
|
+
*
|
|
724
|
+
* @example
|
|
725
|
+
* ```ts
|
|
726
|
+
* \@MessageContextMenuRoute('Report Message', 'Quote Message')
|
|
727
|
+
* class MessageTools extends MessageContextMenuHandler<'Report Message' | 'Quote Message'> {
|
|
728
|
+
* async execute() {
|
|
729
|
+
* await this.match({
|
|
730
|
+
* 'Report Message': (message) => this.report(message),
|
|
731
|
+
* 'Quote Message': (message) => this.reply(`> ${message.content}`)
|
|
732
|
+
* });
|
|
733
|
+
* }
|
|
734
|
+
* }
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
protected match<Ret>(arms: MessageMenuArms<Names, Ret>): Promise<Ret>;
|
|
738
|
+
}
|
|
739
|
+
//#endregion
|
|
740
|
+
//#region src/handlers/interaction/components/ButtonHandler.d.ts
|
|
741
|
+
/**
|
|
742
|
+
* Base class for a button interaction handler on the HTTP transport.
|
|
743
|
+
*
|
|
744
|
+
* Register the customId definitions this handler decodes with `@ButtonRoute`, list the same ones in the
|
|
745
|
+
* generic, then read `this.params` for a single route or `this.match` for several. Reply through the
|
|
746
|
+
* handler members, or rewrite the source message with `this.update`. Passing different definitions to the
|
|
747
|
+
* decorator and the generic is a compile error.
|
|
748
|
+
*
|
|
749
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ApproveId]`.
|
|
750
|
+
*/
|
|
751
|
+
declare abstract class ButtonHandler<Defs extends readonly AnyCustomId[]> extends ComponentHandler<APIMessageComponentButtonInteraction, Defs> {
|
|
752
|
+
/** @internal */
|
|
753
|
+
readonly [ComponentKindBrand]?: InteractionKind.Button;
|
|
754
|
+
}
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region src/handlers/interaction/components/ModalHandler.d.ts
|
|
757
|
+
/**
|
|
758
|
+
* Base class for a modal submit handler on the HTTP transport.
|
|
759
|
+
*
|
|
760
|
+
* Register the customId definitions this handler decodes with `@ModalRoute` and list the same ones in the
|
|
761
|
+
* generic. Read the submitted inputs from `this.fields`. Reply through the handler members. `showModal`
|
|
762
|
+
* fails compilation on this kind, because Discord forbids opening a modal in response to a modal.
|
|
763
|
+
*
|
|
764
|
+
* @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ConfigId]`.
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* ```ts
|
|
768
|
+
* \@ModalRoute(ConfigId)
|
|
769
|
+
* class ConfigModal extends ModalHandler<[typeof ConfigId]> {
|
|
770
|
+
* async execute() {
|
|
771
|
+
* const { guildId } = this.params;
|
|
772
|
+
* const name = this.fields.getTextInputValue('name');
|
|
773
|
+
* await this.reply(`saved ${name} for ${guildId}`);
|
|
774
|
+
* }
|
|
775
|
+
* }
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
778
|
+
declare abstract class ModalHandler<Defs extends readonly AnyCustomId[]> extends ComponentHandler<APIModalSubmitInteraction, Defs> {
|
|
779
|
+
/** @internal */
|
|
780
|
+
readonly [ComponentKindBrand]?: InteractionKind.Modal;
|
|
781
|
+
private reader?;
|
|
782
|
+
/** The fields this modal submitted, read by custom id. */
|
|
783
|
+
protected get fields(): ModalFields;
|
|
784
|
+
/** Rewrite the message this modal was opened from. Throws when a command opened the modal. */
|
|
785
|
+
protected update(response: ReplyResponse | string): Promise<SentMessage>;
|
|
786
|
+
/** Acknowledge the submit without changing the source message. Throws when a command opened the modal. */
|
|
787
|
+
protected deferUpdate(): Promise<void>;
|
|
788
|
+
private ensureSourceMessage;
|
|
789
|
+
}
|
|
790
|
+
//#endregion
|
|
791
|
+
//#region src/subscribers/index.d.ts
|
|
792
|
+
/**
|
|
793
|
+
* Base class for an HTTP subscriber, binding `this.core` to the HTTP {@link Core}.
|
|
794
|
+
*
|
|
795
|
+
* @typeParam KeyOfSubscribers - The subscription key this handler receives
|
|
796
|
+
*/
|
|
797
|
+
declare abstract class Subscriber$1<KeyOfSubscribers extends SubscriptionKey> extends Subscriber<KeyOfSubscribers, Core> {}
|
|
798
|
+
/**
|
|
799
|
+
* Base class for an HTTP subscriber that delivers its event to a Discord webhook, binding
|
|
800
|
+
* `this.core` to the HTTP {@link Core}.
|
|
801
|
+
*
|
|
802
|
+
* @typeParam KeyOfSubscribers - The subscription key this reporter receives
|
|
803
|
+
*/
|
|
804
|
+
declare abstract class WebhookLog$1<KeyOfSubscribers extends SubscriptionKey> extends WebhookLog<KeyOfSubscribers, Core> {}
|
|
805
|
+
//#endregion
|
|
806
|
+
//#region src/pagination/PageContext.d.ts
|
|
807
|
+
/**
|
|
808
|
+
* The context passed to a source loader. The raw payload carries a guild id with no guild object, so a
|
|
809
|
+
* loader that requires guild data fetches it through `core.rest`.
|
|
810
|
+
*/
|
|
811
|
+
interface PageContext {
|
|
812
|
+
/** The interaction that triggered this load (a command or a nav click). */
|
|
813
|
+
interaction: Repliables;
|
|
814
|
+
/** The acting user, always present. */
|
|
815
|
+
user: APIUser;
|
|
816
|
+
/** The guild id, or `null` in a DM. */
|
|
817
|
+
guildId: string | null;
|
|
818
|
+
core: Core;
|
|
819
|
+
}
|
|
820
|
+
//#endregion
|
|
821
|
+
//#region src/pagination/Paginator.d.ts
|
|
822
|
+
type PaginatorHandlerCtor<Prefix extends string> = new (...args: ConstructorParameters<typeof ButtonHandler>) => ButtonHandler<[PageCursor<Prefix>]> & {
|
|
823
|
+
execute(): Promise<void>;
|
|
824
|
+
};
|
|
825
|
+
/**
|
|
826
|
+
* A restart-proof paginator. Each nav button's customId encodes its full target page, so clicks are
|
|
827
|
+
* idempotent and survive a restart. A persistent `@ButtonRoute` on `Handler` dispatches the clicks.
|
|
828
|
+
*
|
|
829
|
+
* @typeParam Item - The item type, inferred from the source.
|
|
830
|
+
* @typeParam Prefix - The route prefix, inferred from `config.prefix`.
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* ```ts
|
|
834
|
+
* export const Bans = new Paginator({
|
|
835
|
+
* prefix: 'bans',
|
|
836
|
+
* source: new ArraySource((ctx) => loadBans(ctx.guildId), { perPage: 10 }),
|
|
837
|
+
* renderItem: (ban) => ban.user.username
|
|
838
|
+
* });
|
|
839
|
+
*
|
|
840
|
+
* \@ButtonRoute(Bans.cursor)
|
|
841
|
+
* export class BansNav extends Bans.Handler {}
|
|
842
|
+
* ```
|
|
843
|
+
*/
|
|
844
|
+
declare class Paginator<Item, const Prefix extends string> extends PaginatorBase<Item, Prefix, PageContext> {
|
|
845
|
+
/** The nav handler base. Extend it with an empty body and decorate it, `@ButtonRoute(p.cursor)`. */
|
|
846
|
+
readonly Handler: PaginatorHandlerCtor<Prefix>;
|
|
847
|
+
constructor(config: PaginatorConfig<Item, Prefix, PageContext>);
|
|
848
|
+
/**
|
|
849
|
+
* Render a page as a {@link ReplyResponse} without sending anything.
|
|
850
|
+
*
|
|
851
|
+
* @param handler - The handler rendering the page, normally `this`.
|
|
852
|
+
* @param n - The zero-based page.
|
|
853
|
+
*/
|
|
854
|
+
page(handler: RepliableHandler$1<Repliables>, n: number): Promise<ReplyResponse>;
|
|
855
|
+
/**
|
|
856
|
+
* Send a page through the handler's sender. The sender picks reply, edit, or followUp from its ack state.
|
|
857
|
+
*
|
|
858
|
+
* @param handler - The handler starting the paginator, normally `this`.
|
|
859
|
+
* @param n - The zero-based page to open on.
|
|
860
|
+
*/
|
|
861
|
+
start(handler: RepliableHandler$1<Repliables>, n?: number): Promise<SentMessage>;
|
|
862
|
+
}
|
|
863
|
+
//#endregion
|
|
864
|
+
//#region src/pagination/sources.d.ts
|
|
865
|
+
/**
|
|
866
|
+
* The one method a paginator calls on a source, once per click. Implement it for a source neither shipped
|
|
867
|
+
* one covers.
|
|
868
|
+
*
|
|
869
|
+
* @typeParam Item - The item type the source pages over.
|
|
870
|
+
*/
|
|
871
|
+
type PageSource<Item> = PageSourceBase<Item, PageContext>;
|
|
872
|
+
/**
|
|
873
|
+
* A source for a bounded list you can load whole. It loads the full list on every click, then slices the
|
|
874
|
+
* page, so the real total is known (a real last button, "Page X of Y"). Cache inside your loader if the
|
|
875
|
+
* load is expensive.
|
|
876
|
+
*
|
|
877
|
+
* @typeParam Item - The item type, inferred from the loader's return.
|
|
878
|
+
*/
|
|
879
|
+
declare class ArraySource<Item> extends ArraySourceBase<Item, PageContext> {}
|
|
880
|
+
/**
|
|
881
|
+
* A source for a large or unknown-length set you fetch one page at a time (SQL LIMIT/OFFSET, a paged API).
|
|
882
|
+
* The fetcher receives the page index and the page size and reports whether a next page exists. A cursor
|
|
883
|
+
* source has no cheap total, so `totalPages` is undefined, the last button is omitted, and the indicator
|
|
884
|
+
* reads "Page X".
|
|
885
|
+
*
|
|
886
|
+
* @typeParam Item - The item type, inferred from the fetcher's slice.
|
|
887
|
+
*/
|
|
888
|
+
declare class CursorSource<Item> extends CursorSourceBase<Item, PageContext> {}
|
|
889
|
+
//#endregion
|
|
890
|
+
//#region src/gates/Gate.d.ts
|
|
891
|
+
/**
|
|
892
|
+
* The interaction gate context on the HTTP transport. It extends the scalar {@link GateContextBase} with the
|
|
893
|
+
* raw interaction payload and the user and member the payload carries. A gate reading button fields, inferred
|
|
894
|
+
* from its `ctx` annotation, is rejected on a slash handler.
|
|
895
|
+
*
|
|
896
|
+
* The http transport delivers no role-derived permission sets, so `memberGuildPermissions` and
|
|
897
|
+
* `appGuildPermissions` are absent. A gate requiring `GuildPermissionsContext` (a permission gate with
|
|
898
|
+
* `in: 'guild'`) is a compile error on an http handler.
|
|
899
|
+
*
|
|
900
|
+
* @typeParam Repliable - The interaction type the gate reads, narrowing which handlers accept it.
|
|
901
|
+
*
|
|
902
|
+
* @example
|
|
903
|
+
* ```ts
|
|
904
|
+
* import type { APIMessageComponentButtonInteraction } from 'discord-api-types/v10';
|
|
905
|
+
*
|
|
906
|
+
* // a button-only gate: the Repliable generic narrows which handlers accept it
|
|
907
|
+
* const ButtonGate = defineGate('btn', (ctx: InteractionGateContext<APIMessageComponentButtonInteraction>) => {
|
|
908
|
+
* void ctx.interaction; // APIMessageComponentButtonInteraction
|
|
909
|
+
* });
|
|
910
|
+
* ```
|
|
911
|
+
*/
|
|
912
|
+
interface InteractionGateContext<Repliable extends Repliables = Repliables> extends GateContextBase {
|
|
913
|
+
/** Narrow on this before reading `interaction`. */
|
|
914
|
+
readonly kind: 'interaction';
|
|
915
|
+
readonly core: Core;
|
|
916
|
+
/** The raw interaction payload, which is the reply target. */
|
|
917
|
+
readonly interaction: Repliable;
|
|
918
|
+
/** Every repliable interaction contains a user. */
|
|
919
|
+
readonly user: APIUser;
|
|
920
|
+
/** The invoking member, or null in a DM. */
|
|
921
|
+
readonly member: APIInteractionGuildMember | null;
|
|
922
|
+
}
|
|
923
|
+
//#endregion
|
|
924
|
+
//#region src/gates/matching.d.ts
|
|
925
|
+
type AnyHandlerCtor = abstract new (...args: never[]) => {
|
|
926
|
+
execute(): Promise<void>;
|
|
927
|
+
};
|
|
928
|
+
declare const UngateableBrand: unique symbol;
|
|
929
|
+
interface Ungateable {
|
|
930
|
+
readonly [UngateableBrand]: true;
|
|
931
|
+
}
|
|
932
|
+
type ProvidedContext<TCtor extends AnyHandlerCtor> = InstanceType<TCtor> extends RepliableHandler$1<infer Event> ? InteractionGateContext<Event> : Ungateable;
|
|
933
|
+
type SelectData<Repliable> = Repliable extends APIMessageComponentSelectMenuInteraction ? Repliable['data'] : never;
|
|
934
|
+
type SelectKindName<Data> = Data extends APIMessageStringSelectInteractionData ? 'StringMenu' : Data extends APIMessageUserSelectInteractionData ? 'UserMenu' : Data extends APIMessageRoleSelectInteractionData ? 'RoleMenu' : Data extends APIMessageChannelSelectInteractionData ? 'ChannelMenu' : Data extends APIMessageMentionableSelectInteractionData ? 'MentionableMenu' : 'an interaction';
|
|
935
|
+
type KindName<Ctx> = Ctx extends Ungateable ? 'autocomplete' : Ctx extends GuildPermissionsContext ? 'gateway (guild permissions)' : Ctx extends InteractionGateContext<infer Repliable> ? Repliable extends APIChatInputApplicationCommandInteraction ? 'Slash' : Repliable extends APIMessageApplicationCommandInteraction ? 'MessageContextMenu' : Repliable extends APIUserApplicationCommandInteraction ? 'UserContextMenu' : Repliable extends APIMessageComponentSelectMenuInteraction ? SelectKindName<SelectData<Repliable>> : Repliable extends APIMessageComponentButtonInteraction ? 'Button' : Repliable extends APIModalSubmitInteraction ? 'Modal' : 'an interaction' : 'an agnostic';
|
|
936
|
+
type FitAll<TCtor extends AnyHandlerCtor, Gates extends readonly Gate<GateContextBase>[]> = { [Index in keyof Gates]: GateFitsWith<ProvidedContext<TCtor>, KindName<ProvidedContext<TCtor>>, Gates[Index], KindName<RequiredOf<Gates[Index]>>>; };
|
|
937
|
+
//#endregion
|
|
938
|
+
//#region src/gates/Gated.d.ts
|
|
939
|
+
/**
|
|
940
|
+
* Attaches gates to an HTTP interaction handler. The gates run before `execute`, and a gate refusing stops
|
|
941
|
+
* the handler with the reply or drop the gate threw. Multiple gates are ANDed. A gate
|
|
942
|
+
* that requires a context the handler does not provide (a button gate on a slash handler, a gate on an
|
|
943
|
+
* autocomplete handler, or a `RequirePermissions([...], { in: 'guild' })` gate the http transport cannot
|
|
944
|
+
* satisfy) is a compile error at this line, and the error names the gate and the handler kind. Place it
|
|
945
|
+
* above the route decorator.
|
|
946
|
+
*
|
|
947
|
+
* Combine gates with {@link and} or {@link or} to build a single gate from multiple arms.
|
|
948
|
+
*
|
|
949
|
+
* @example
|
|
950
|
+
* ```ts
|
|
951
|
+
* import { PermissionFlagsBits } from 'discord-api-types/v10';
|
|
952
|
+
*
|
|
953
|
+
* \@Gated(GuildOnly(), RequirePermissions([PermissionFlagsBits.ManageMessages]))
|
|
954
|
+
* \@SlashRoute('purge')
|
|
955
|
+
* class Purge extends SlashHandler<'purge'> {
|
|
956
|
+
* async execute() {
|
|
957
|
+
* // both gates passed, so this runs in a guild with a caller who can moderate this channel
|
|
958
|
+
* }
|
|
959
|
+
* }
|
|
960
|
+
* ```
|
|
961
|
+
*
|
|
962
|
+
* @typeParam Gates - The non-empty tuple of gates to run, in order, against the handler's context.
|
|
963
|
+
* @typeParam TCtor - The decorated handler's constructor, checked against every gate's required context.
|
|
964
|
+
* @param gates - One or more gates to attach, each ANDed so the handler runs only when all pass.
|
|
965
|
+
* @param ctor - The handler class being decorated, rejected at compile time when a gate requires a context it lacks.
|
|
966
|
+
*
|
|
967
|
+
* @see {@link defineGate}
|
|
968
|
+
* @see {@link defineEffectGate}
|
|
969
|
+
* @decorator
|
|
970
|
+
*/
|
|
971
|
+
declare function Gated<const Gates extends NonEmptyTuple<Gate<GateContextBase>>>(...gates: Gates): <TCtor extends AnyHandlerCtor>(ctor: FitAll<TCtor, Gates> extends Gates ? TCtor : FitAll<TCtor, Gates>) => void;
|
|
972
|
+
//#endregion
|
|
973
|
+
//#region src/version.d.ts
|
|
974
|
+
declare const version: string;
|
|
975
|
+
//#endregion
|
|
976
|
+
export { RoleMenuHandler as A, AutocompleteHandler as B, Plugin$1 as C, InteractionMiddleware as D, EngineContext as E, InteractionHandler as F, HttpConfig as H, RepliableHandler$1 as I, InteractionRef as L, StringMenuHandler as M, UserMenuHandler as N, ChannelMenuHandler as O, ComponentHandler as P, ReplySender as R, HttpPluginOptions as S, PluginOptions$1 as T, HttpEdgeConfig as U, Core as V, HttpServerConfig as W, Emojis as _, ArraySource as a, SelectedMentionables as b, Paginator as c, WebhookLog$1 as d, ModalHandler as f, SlashHandler as g, UserContextMenuHandler as h, InteractionGateContext as i, SelectMenuHandler as j, MentionableMenuHandler as k, PageContext as l, MessageContextMenuHandler as m, version as n, CursorSource as o, ButtonHandler as p, Gated as r, PageSource as s, HmrModuleHandler$1 as t, Subscriber$1 as u, InjectedEmojiMap as v, PluginLifecycleSpec as w, SlashOptions$1 as x, ModalFields as y, SentMessage as z };
|
|
977
|
+
//# sourceMappingURL=shared-vsj1uwIH.d.mts.map
|