mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 19:13:31 +01:00
feat(Interactions): add InteractionWebhook for better internals (#5712)
This commit is contained in:
@@ -24,6 +24,19 @@ class WebhookClient extends BaseClient {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
|
Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are here only for documentation purposes - they are implemented by Webhook
|
||||||
|
/* eslint-disable no-empty-function */
|
||||||
|
send() {}
|
||||||
|
sendSlackMessage() {}
|
||||||
|
fetchMessage() {}
|
||||||
|
edit() {}
|
||||||
|
editMessage() {}
|
||||||
|
delete() {}
|
||||||
|
deleteMessage() {}
|
||||||
|
get createdTimestamp() {}
|
||||||
|
get createdAt() {}
|
||||||
|
get url() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Webhook.applyToClass(WebhookClient);
|
Webhook.applyToClass(WebhookClient);
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ module.exports = {
|
|||||||
Integration: require('./structures/Integration'),
|
Integration: require('./structures/Integration'),
|
||||||
IntegrationApplication: require('./structures/IntegrationApplication'),
|
IntegrationApplication: require('./structures/IntegrationApplication'),
|
||||||
Interaction: require('./structures/Interaction'),
|
Interaction: require('./structures/Interaction'),
|
||||||
|
InteractionWebhook: require('./structures/InteractionWebhook'),
|
||||||
Invite: require('./structures/Invite'),
|
Invite: require('./structures/Invite'),
|
||||||
Message: require('./structures/Message'),
|
Message: require('./structures/Message'),
|
||||||
MessageActionRow: require('./structures/MessageActionRow'),
|
MessageActionRow: require('./structures/MessageActionRow'),
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ class APIMessage {
|
|||||||
*/
|
*/
|
||||||
get isInteraction() {
|
get isInteraction() {
|
||||||
const Interaction = require('./Interaction');
|
const Interaction = require('./Interaction');
|
||||||
return this.target instanceof Interaction;
|
const InteractionWebhook = require('./InteractionWebhook');
|
||||||
|
return this.target instanceof Interaction || this.target instanceof InteractionWebhook;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -372,10 +373,15 @@ class APIMessage {
|
|||||||
*/
|
*/
|
||||||
static create(target, content, options, extra = {}) {
|
static create(target, content, options, extra = {}) {
|
||||||
const Interaction = require('./Interaction');
|
const Interaction = require('./Interaction');
|
||||||
|
const InteractionWebhook = require('./InteractionWebhook');
|
||||||
const Webhook = require('./Webhook');
|
const Webhook = require('./Webhook');
|
||||||
const WebhookClient = require('../client/WebhookClient');
|
const WebhookClient = require('../client/WebhookClient');
|
||||||
|
|
||||||
const isWebhook = target instanceof Interaction || target instanceof Webhook || target instanceof WebhookClient;
|
const isWebhook =
|
||||||
|
target instanceof Interaction ||
|
||||||
|
target instanceof InteractionWebhook ||
|
||||||
|
target instanceof Webhook ||
|
||||||
|
target instanceof WebhookClient;
|
||||||
const transformed = this.transformOptions(content, options, extra, isWebhook);
|
const transformed = this.transformOptions(content, options, extra, isWebhook);
|
||||||
return new this(target, transformed);
|
return new this(target, transformed);
|
||||||
}
|
}
|
||||||
@@ -385,7 +391,7 @@ module.exports = APIMessage;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A target for a message.
|
* A target for a message.
|
||||||
* @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient|Interaction} MessageTarget
|
* @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient|Interaction|InteractionWebhook} MessageTarget
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Interaction = require('./Interaction');
|
const Interaction = require('./Interaction');
|
||||||
|
const InteractionWebhook = require('./InteractionWebhook');
|
||||||
const InteractionResponses = require('./interfaces/InteractionResponses');
|
const InteractionResponses = require('./interfaces/InteractionResponses');
|
||||||
const WebhookClient = require('../client/WebhookClient');
|
|
||||||
const Collection = require('../util/Collection');
|
const Collection = require('../util/Collection');
|
||||||
const { ApplicationCommandOptionTypes } = require('../util/Constants');
|
const { ApplicationCommandOptionTypes } = require('../util/Constants');
|
||||||
|
|
||||||
@@ -53,10 +53,10 @@ class CommandInteraction extends Interaction {
|
|||||||
this.replied = false;
|
this.replied = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An associated webhook client, can be used to create deferred replies
|
* An associated interaction webhook, can be used to further interact with this interaction
|
||||||
* @type {WebhookClient}
|
* @type {InteractionWebhook}
|
||||||
*/
|
*/
|
||||||
this.webhook = new WebhookClient(this.applicationID, this.token, this.client.options);
|
this.webhook = new InteractionWebhook(this.client, this.applicationID, this.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
44
src/structures/InteractionWebhook.js
Normal file
44
src/structures/InteractionWebhook.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Webhook = require('./Webhook');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a webhook for an Interaction
|
||||||
|
* @implements {Webhook}
|
||||||
|
*/
|
||||||
|
class InteractionWebhook {
|
||||||
|
/**
|
||||||
|
* @param {Client} client The instantiating client
|
||||||
|
* @param {Snowflake} id ID of the application
|
||||||
|
* @param {string} token Token of the interaction
|
||||||
|
*/
|
||||||
|
constructor(client, id, token) {
|
||||||
|
/**
|
||||||
|
* The client that instantiated the interaction webhook
|
||||||
|
* @name InteractionWebhook#client
|
||||||
|
* @type {Client}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
Object.defineProperty(this, 'client', { value: client });
|
||||||
|
this.id = id;
|
||||||
|
Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are here only for documentation purposes - they are implemented by Webhook
|
||||||
|
/* eslint-disable no-empty-function, valid-jsdoc */
|
||||||
|
/**
|
||||||
|
* Sends a message with this webhook.
|
||||||
|
* @param {string|APIMessage|MessageAdditions} content The content for the reply
|
||||||
|
* @param {InteractionReplyOptions} [options] Additional options for the reply
|
||||||
|
* @returns {Promise<Message|Object>}
|
||||||
|
*/
|
||||||
|
send() {}
|
||||||
|
fetchMessage() {}
|
||||||
|
editMessage() {}
|
||||||
|
deleteMessage() {}
|
||||||
|
get url() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Webhook.applyToClass(InteractionWebhook, ['sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt']);
|
||||||
|
|
||||||
|
module.exports = InteractionWebhook;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Interaction = require('./Interaction');
|
const Interaction = require('./Interaction');
|
||||||
|
const InteractionWebhook = require('./InteractionWebhook');
|
||||||
const InteractionResponses = require('./interfaces/InteractionResponses');
|
const InteractionResponses = require('./interfaces/InteractionResponses');
|
||||||
const WebhookClient = require('../client/WebhookClient');
|
|
||||||
const { MessageComponentTypes } = require('../util/Constants');
|
const { MessageComponentTypes } = require('../util/Constants');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,10 +45,10 @@ class MessageComponentInteraction extends Interaction {
|
|||||||
this.replied = false;
|
this.replied = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An associated webhook client, can be used to create deferred replies
|
* An associated interaction webhook, can be used to further interact with this interaction
|
||||||
* @type {WebhookClient}
|
* @type {InteractionWebhook}
|
||||||
*/
|
*/
|
||||||
this.webhook = new WebhookClient(this.applicationID, this.token, this.client.options);
|
this.webhook = new InteractionWebhook(this.client, this.applicationID, this.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ class Webhook {
|
|||||||
return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size);
|
return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static applyToClass(structure) {
|
static applyToClass(structure, ignore = []) {
|
||||||
for (const prop of [
|
for (const prop of [
|
||||||
'send',
|
'send',
|
||||||
'sendSlackMessage',
|
'sendSlackMessage',
|
||||||
@@ -338,6 +338,7 @@ class Webhook {
|
|||||||
'createdAt',
|
'createdAt',
|
||||||
'url',
|
'url',
|
||||||
]) {
|
]) {
|
||||||
|
if (ignore.includes(prop)) continue;
|
||||||
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop));
|
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,9 +93,8 @@ class InteractionResponses {
|
|||||||
* .then(reply => console.log(`Replied with ${reply.content}`))
|
* .then(reply => console.log(`Replied with ${reply.content}`))
|
||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
async fetchReply() {
|
fetchReply() {
|
||||||
const raw = await this.webhook.fetchMessage('@original');
|
return this.webhook.fetchMessage('@original');
|
||||||
return this.channel?.messages.add(raw) ?? raw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,9 +109,8 @@ class InteractionResponses {
|
|||||||
* .then(console.log)
|
* .then(console.log)
|
||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
async editReply(content, options) {
|
editReply(content, options) {
|
||||||
const raw = await this.webhook.editMessage('@original', content, options);
|
return this.webhook.editMessage('@original', content, options);
|
||||||
return this.channel?.messages.add(raw) ?? raw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,16 +133,8 @@ class InteractionResponses {
|
|||||||
* @param {InteractionReplyOptions} [options] Additional options for the reply
|
* @param {InteractionReplyOptions} [options] Additional options for the reply
|
||||||
* @returns {Promise<Message|Object>}
|
* @returns {Promise<Message|Object>}
|
||||||
*/
|
*/
|
||||||
async followUp(content, options) {
|
followUp(content, options) {
|
||||||
const apiMessage = content instanceof APIMessage ? content : APIMessage.create(this, content, options);
|
return this.webhook.send(content, options);
|
||||||
const { data, files } = await apiMessage.resolveData().resolveFiles();
|
|
||||||
|
|
||||||
const raw = await this.client.api.webhooks(this.applicationID, this.token).post({
|
|
||||||
data,
|
|
||||||
files,
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.channel?.messages.add(raw) ?? raw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
45
typings/index.d.ts
vendored
45
typings/index.d.ts
vendored
@@ -467,7 +467,7 @@ declare module 'discord.js' {
|
|||||||
public deferred: boolean;
|
public deferred: boolean;
|
||||||
public options: Collection<string, CommandInteractionOption>;
|
public options: Collection<string, CommandInteractionOption>;
|
||||||
public replied: boolean;
|
public replied: boolean;
|
||||||
public webhook: WebhookClient;
|
public webhook: InteractionWebhook;
|
||||||
public defer(options?: InteractionDeferOptions): Promise<void>;
|
public defer(options?: InteractionDeferOptions): Promise<void>;
|
||||||
public deleteReply(): Promise<void>;
|
public deleteReply(): Promise<void>;
|
||||||
public editReply(
|
public editReply(
|
||||||
@@ -1139,6 +1139,30 @@ declare module 'discord.js' {
|
|||||||
public isMessageComponent(): this is MessageComponentInteraction;
|
public isMessageComponent(): this is MessageComponentInteraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class InteractionWebhook extends PartialWebhookMixin() {
|
||||||
|
constructor(client: Client, id: Snowflake, token: string);
|
||||||
|
public token: string;
|
||||||
|
public send(
|
||||||
|
content: string | (InteractionReplyOptions & { split?: false }) | MessageAdditions,
|
||||||
|
): Promise<Message | RawMessage>;
|
||||||
|
public send(options: InteractionReplyOptions & { split: true | SplitOptions }): Promise<(Message | RawMessage)[]>;
|
||||||
|
public send(
|
||||||
|
options: InteractionReplyOptions | APIMessage,
|
||||||
|
): Promise<Message | RawMessage | (Message | RawMessage)[]>;
|
||||||
|
public send(
|
||||||
|
content: string | null,
|
||||||
|
options: (InteractionReplyOptions & { split?: false }) | MessageAdditions,
|
||||||
|
): Promise<Message | RawMessage>;
|
||||||
|
public send(
|
||||||
|
content: string | null,
|
||||||
|
options: InteractionReplyOptions & { split: true | SplitOptions },
|
||||||
|
): Promise<(Message | RawMessage)[]>;
|
||||||
|
public send(
|
||||||
|
content: string | null,
|
||||||
|
options: InteractionReplyOptions,
|
||||||
|
): Promise<Message | RawMessage | (Message | RawMessage)[]>;
|
||||||
|
}
|
||||||
|
|
||||||
export class Invite extends Base {
|
export class Invite extends Base {
|
||||||
constructor(client: Client, data: unknown);
|
constructor(client: Client, data: unknown);
|
||||||
public channel: GuildChannel | PartialGroupDMChannel;
|
public channel: GuildChannel | PartialGroupDMChannel;
|
||||||
@@ -1333,7 +1357,7 @@ declare module 'discord.js' {
|
|||||||
public deferred: boolean;
|
public deferred: boolean;
|
||||||
public message: Message | RawMessage;
|
public message: Message | RawMessage;
|
||||||
public replied: boolean;
|
public replied: boolean;
|
||||||
public webhook: WebhookClient;
|
public webhook: InteractionWebhook;
|
||||||
public defer(options?: InteractionDeferOptions): Promise<void>;
|
public defer(options?: InteractionDeferOptions): Promise<void>;
|
||||||
public deferUpdate(): Promise<void>;
|
public deferUpdate(): Promise<void>;
|
||||||
public deleteReply(): Promise<void>;
|
public deleteReply(): Promise<void>;
|
||||||
@@ -2498,18 +2522,15 @@ declare module 'discord.js' {
|
|||||||
stopTyping(force?: boolean): void;
|
stopTyping(force?: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function PartialWebhookMixin<T>(Base?: Constructable<T>): Constructable<T & PartialWebhookFields>;
|
||||||
function WebhookMixin<T>(Base?: Constructable<T>): Constructable<T & WebhookFields>;
|
function WebhookMixin<T>(Base?: Constructable<T>): Constructable<T & WebhookFields>;
|
||||||
|
|
||||||
function VolumeMixin<T>(base: Constructable<T>): Constructable<T & VolumeInterface>;
|
function VolumeMixin<T>(base: Constructable<T>): Constructable<T & VolumeInterface>;
|
||||||
|
|
||||||
interface WebhookFields {
|
interface PartialWebhookFields {
|
||||||
id: Snowflake;
|
id: Snowflake;
|
||||||
readonly createdAt: Date;
|
|
||||||
readonly createdTimestamp: number;
|
|
||||||
readonly url: string;
|
readonly url: string;
|
||||||
delete(reason?: string): Promise<void>;
|
|
||||||
deleteMessage(message: MessageResolvable | '@original'): Promise<void>;
|
deleteMessage(message: MessageResolvable | '@original'): Promise<void>;
|
||||||
edit(options: WebhookEditData): Promise<Webhook>;
|
|
||||||
editMessage(
|
editMessage(
|
||||||
message: MessageResolvable | '@original',
|
message: MessageResolvable | '@original',
|
||||||
content: string | null | APIMessage | MessageAdditions,
|
content: string | null | APIMessage | MessageAdditions,
|
||||||
@@ -2537,7 +2558,14 @@ declare module 'discord.js' {
|
|||||||
content: string | null,
|
content: string | null,
|
||||||
options: WebhookMessageOptions,
|
options: WebhookMessageOptions,
|
||||||
): Promise<Message | RawMessage | (Message | RawMessage)[]>;
|
): Promise<Message | RawMessage | (Message | RawMessage)[]>;
|
||||||
sendSlackMessage(body: unknown): Promise<boolean>;
|
}
|
||||||
|
|
||||||
|
interface WebhookFields extends PartialWebhookFields {
|
||||||
|
readonly createdAt: Date;
|
||||||
|
readonly createdTimestamp: number;
|
||||||
|
delete(reason?: string): Promise<void>;
|
||||||
|
edit(options: WebhookEditData): Promise<Webhook>;
|
||||||
|
sendSlackMessage(body: object): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
@@ -3532,6 +3560,7 @@ declare module 'discord.js' {
|
|||||||
|
|
||||||
type MessageTarget =
|
type MessageTarget =
|
||||||
| Interaction
|
| Interaction
|
||||||
|
| InteractionWebhook
|
||||||
| TextChannel
|
| TextChannel
|
||||||
| NewsChannel
|
| NewsChannel
|
||||||
| DMChannel
|
| DMChannel
|
||||||
|
|||||||
Reference in New Issue
Block a user