commit
5fa5b32e49
@ -204,6 +204,8 @@ class Client extends BaseClient {
|
|||||||
this.token = null;
|
this.token = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._interactionCache = new Collection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User that the client is logged in as
|
* User that the client is logged in as
|
||||||
* @type {?ClientUser}
|
* @type {?ClientUser}
|
||||||
@ -340,7 +342,7 @@ class Client extends BaseClient {
|
|||||||
this.emit(Events.DEBUG, `Added Fingerprint: ${res.data.fingerprint}`);
|
this.emit(Events.DEBUG, `Added Fingerprint: ${res.data.fingerprint}`);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
this.emit(Events.DEBUG, `Finding Cookie and Fingerprint failed: ${err.message}`);
|
this.emit(Events.DEBUG, `Update Cookie and Fingerprint failed: ${err.message}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +12,6 @@ module.exports = (client, { d: data }) => {
|
|||||||
status: false,
|
status: false,
|
||||||
metadata: data,
|
metadata: data,
|
||||||
});
|
});
|
||||||
|
// Delete cache
|
||||||
|
client._interactionCache.delete(data.nonce);
|
||||||
};
|
};
|
||||||
|
@ -8,8 +8,21 @@ module.exports = (client, { d: data }) => {
|
|||||||
* @param {InteractionResponseBody} data data
|
* @param {InteractionResponseBody} data data
|
||||||
*/
|
*/
|
||||||
client.emit(Events.INTERACTION_SUCCESS, data);
|
client.emit(Events.INTERACTION_SUCCESS, data);
|
||||||
|
// Get channel data
|
||||||
|
const cache = client._interactionCache.get(data.nonce);
|
||||||
|
const channel = cache.guildId
|
||||||
|
? client.guilds.cache.get(cache.guildId)?.channels.cache.get(cache.channelId)
|
||||||
|
: client.channels.cache.get(cache.channelId);
|
||||||
|
// Set data
|
||||||
|
const interaction = {
|
||||||
|
...cache,
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
const data_ = channel.interactions._add(interaction);
|
||||||
client.emit('interactionResponse', {
|
client.emit('interactionResponse', {
|
||||||
status: true,
|
status: true,
|
||||||
metadata: data,
|
metadata: data_,
|
||||||
});
|
});
|
||||||
|
// Delete cache
|
||||||
|
// client._interactionCache.delete(data.nonce);
|
||||||
};
|
};
|
||||||
|
39
src/managers/InteractionManager.js
Normal file
39
src/managers/InteractionManager.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const CachedManager = require('./CachedManager');
|
||||||
|
const InteractionResponse = require('../structures/InteractionResponse');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages API methods for InteractionResponse and holds their cache.
|
||||||
|
* @extends {CachedManager}
|
||||||
|
*/
|
||||||
|
class InteractionManager extends CachedManager {
|
||||||
|
constructor(channel, iterable) {
|
||||||
|
super(channel.client, InteractionResponse, iterable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The channel that the messages belong to
|
||||||
|
* @type {TextBasedChannels}
|
||||||
|
*/
|
||||||
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache of InteractionResponse
|
||||||
|
* @type {Collection<Snowflake, InteractionResponse>}
|
||||||
|
* @name InteractionManager#cache
|
||||||
|
*/
|
||||||
|
|
||||||
|
_add(data, cache) {
|
||||||
|
data = {
|
||||||
|
...data,
|
||||||
|
channelId: this.channel.id,
|
||||||
|
guildId: this.channel.guild?.id,
|
||||||
|
};
|
||||||
|
if (!data.id) return;
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
|
return super._add(data, cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = InteractionManager;
|
@ -597,7 +597,7 @@ class ApplicationCommand extends Base {
|
|||||||
* @param {Message} message Discord Message
|
* @param {Message} message Discord Message
|
||||||
* @param {Array<string>} subCommandArray SubCommand Array
|
* @param {Array<string>} subCommandArray SubCommand Array
|
||||||
* @param {Array<string>} options The options to Slash Command
|
* @param {Array<string>} options The options to Slash Command
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line consistent-return
|
// eslint-disable-next-line consistent-return
|
||||||
async sendSlashCommand(message, subCommandArray = [], options = []) {
|
async sendSlashCommand(message, subCommandArray = [], options = []) {
|
||||||
@ -861,6 +861,11 @@ class ApplicationCommand extends Base {
|
|||||||
body: data,
|
body: data,
|
||||||
files: attachmentsBuffer,
|
files: attachmentsBuffer,
|
||||||
});
|
});
|
||||||
|
this.client._interactionCache.set(nonce, {
|
||||||
|
channelId: message.channelId,
|
||||||
|
guildId: message.guildId,
|
||||||
|
metadata: data,
|
||||||
|
});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handler = data => {
|
const handler = data => {
|
||||||
timeout.refresh();
|
timeout.refresh();
|
||||||
@ -911,7 +916,7 @@ class ApplicationCommand extends Base {
|
|||||||
/**
|
/**
|
||||||
* Message Context Menu
|
* Message Context Menu
|
||||||
* @param {Message} message Discord Message
|
* @param {Message} message Discord Message
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
async sendContextMenu(message) {
|
async sendContextMenu(message) {
|
||||||
if (!(message instanceof Message())) {
|
if (!(message instanceof Message())) {
|
||||||
@ -941,6 +946,11 @@ class ApplicationCommand extends Base {
|
|||||||
await this.client.api.interactions.post({
|
await this.client.api.interactions.post({
|
||||||
body: data,
|
body: data,
|
||||||
});
|
});
|
||||||
|
this.client._interactionCache.set(nonce, {
|
||||||
|
channelId: message.channelId,
|
||||||
|
guildId: message.guildId,
|
||||||
|
metadata: data,
|
||||||
|
});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handler = data => {
|
const handler = data => {
|
||||||
timeout.refresh();
|
timeout.refresh();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const GuildChannel = require('./GuildChannel');
|
const GuildChannel = require('./GuildChannel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const GuildTextThreadManager = require('../managers/GuildTextThreadManager');
|
const GuildTextThreadManager = require('../managers/GuildTextThreadManager');
|
||||||
|
const InteractionManager = require('../managers/InteractionManager');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,6 +21,12 @@ class BaseGuildTextChannel extends GuildChannel {
|
|||||||
*/
|
*/
|
||||||
this.messages = new MessageManager(this);
|
this.messages = new MessageManager(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the interactions sent to this channel
|
||||||
|
* @type {InteractionManager}
|
||||||
|
*/
|
||||||
|
this.interactions = new InteractionManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager of the threads belonging to this channel
|
* A manager of the threads belonging to this channel
|
||||||
* @type {GuildTextThreadManager}
|
* @type {GuildTextThreadManager}
|
||||||
|
@ -4,6 +4,7 @@ const { Collection } = require('@discordjs/collection');
|
|||||||
const { joinVoiceChannel, entersState, VoiceConnectionStatus } = require('@discordjs/voice');
|
const { joinVoiceChannel, entersState, VoiceConnectionStatus } = require('@discordjs/voice');
|
||||||
const { Channel } = require('./Channel');
|
const { Channel } = require('./Channel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
|
const InteractionManager = require('../managers/InteractionManager');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
const { Status, Opcodes } = require('../util/Constants');
|
const { Status, Opcodes } = require('../util/Constants');
|
||||||
|
|
||||||
@ -24,6 +25,12 @@ class DMChannel extends Channel {
|
|||||||
* @type {MessageManager}
|
* @type {MessageManager}
|
||||||
*/
|
*/
|
||||||
this.messages = new MessageManager(this);
|
this.messages = new MessageManager(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the interactions sent to this channel
|
||||||
|
* @type {InteractionManager}
|
||||||
|
*/
|
||||||
|
this.interactions = new InteractionManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_patch(data) {
|
_patch(data) {
|
||||||
|
113
src/structures/InteractionResponse.js
Normal file
113
src/structures/InteractionResponse.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { setTimeout } = require('node:timers');
|
||||||
|
const Base = require('./Base');
|
||||||
|
const { Events } = require('../util/Constants');
|
||||||
|
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a interaction on Discord.
|
||||||
|
* @extends {Base}
|
||||||
|
*/
|
||||||
|
class InteractionResponse extends Base {
|
||||||
|
constructor(client, data) {
|
||||||
|
super(client);
|
||||||
|
/**
|
||||||
|
* The id of the channel the interaction was sent in
|
||||||
|
* @type {Snowflake}
|
||||||
|
*/
|
||||||
|
this.channelId = data.channelId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the guild the interaction was sent in, if any
|
||||||
|
* @type {?Snowflake}
|
||||||
|
*/
|
||||||
|
this.guildId = data.guildId ?? this.channel?.guild?.id ?? null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interaction data was sent in
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
this.sendData = data.metadata;
|
||||||
|
this._patch(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_patch(data) {
|
||||||
|
if ('id' in data) {
|
||||||
|
/**
|
||||||
|
* The interaction response's ID
|
||||||
|
* @type {Snowflake}
|
||||||
|
*/
|
||||||
|
this.id = data.id;
|
||||||
|
}
|
||||||
|
if ('nonce' in data) {
|
||||||
|
/**
|
||||||
|
* The interaction response's nonce
|
||||||
|
* @type {Snowflake}
|
||||||
|
*/
|
||||||
|
this.nonce = data.nonce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The timestamp the interaction response was created at
|
||||||
|
* @type {number}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get createdTimestamp() {
|
||||||
|
return SnowflakeUtil.timestampFrom(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time the interaction response was created at
|
||||||
|
* @type {Date}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get createdAt() {
|
||||||
|
return new Date(this.createdTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The channel that the interaction was sent in
|
||||||
|
* @type {TextBasedChannels}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get channel() {
|
||||||
|
return this.client.channels.resolve(this.channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The guild the inteaaction was sent in (if in a guild channel)
|
||||||
|
* @type {?Guild}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get guild() {
|
||||||
|
return this.client.guilds.resolve(this.guildId) ?? this.channel?.guild ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Modal send from interaction
|
||||||
|
* @param {?number} time Time to wait for modal (Default: 120000)
|
||||||
|
* @returns {Modal}
|
||||||
|
*/
|
||||||
|
awaitModal(time = 120_000) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const handler = modal => {
|
||||||
|
timeout.refresh();
|
||||||
|
if (modal.nonce != this.nonce || modal.id != this.id) return;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
|
this.client.decrementMaxListeners();
|
||||||
|
resolve(modal);
|
||||||
|
};
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
|
this.client.decrementMaxListeners();
|
||||||
|
reject(new Error('MODAL_TIMEOUT'));
|
||||||
|
}, time || 120_000).unref();
|
||||||
|
this.client.incrementMaxListeners();
|
||||||
|
this.client.on(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = InteractionResponse;
|
@ -1043,7 +1043,7 @@ class Message extends Base {
|
|||||||
/**
|
/**
|
||||||
* Click specific button
|
* Click specific button
|
||||||
* @param {MessageButton|string} button Button ID
|
* @param {MessageButton|string} button Button ID
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
clickButton(button) {
|
clickButton(button) {
|
||||||
let buttonID;
|
let buttonID;
|
||||||
@ -1066,7 +1066,7 @@ class Message extends Base {
|
|||||||
* Select specific menu or First Menu
|
* Select specific menu or First Menu
|
||||||
* @param {string|Array<string>} menuID Select Menu specific id or auto select first Menu
|
* @param {string|Array<string>} menuID Select Menu specific id or auto select first Menu
|
||||||
* @param {Array<string>} options Menu Options
|
* @param {Array<string>} options Menu Options
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
async selectMenu(menuID, options = []) {
|
async selectMenu(menuID, options = []) {
|
||||||
if (!this.components[0]) throw new TypeError('MESSAGE_NO_COMPONENTS');
|
if (!this.components[0]) throw new TypeError('MESSAGE_NO_COMPONENTS');
|
||||||
@ -1100,7 +1100,7 @@ class Message extends Base {
|
|||||||
* Send context Menu v2
|
* Send context Menu v2
|
||||||
* @param {Snowflake} botId Bot id
|
* @param {Snowflake} botId Bot id
|
||||||
* @param {string} commandName Command name in Context Menu
|
* @param {string} commandName Command name in Context Menu
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
async contextMenu(botId, commandName) {
|
async contextMenu(botId, commandName) {
|
||||||
if (!botId) throw new Error('Bot ID is required');
|
if (!botId) throw new Error('Bot ID is required');
|
||||||
|
@ -168,14 +168,13 @@ class MessageButton extends BaseMessageComponent {
|
|||||||
/**
|
/**
|
||||||
* Click the button
|
* Click the button
|
||||||
* @param {Message} message Discord Message
|
* @param {Message} message Discord Message
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
async click(message) {
|
async click(message) {
|
||||||
const nonce = SnowflakeUtil.generate();
|
const nonce = SnowflakeUtil.generate();
|
||||||
if (!(message instanceof Message())) throw new Error('[UNKNOWN_MESSAGE] Please pass a valid Message');
|
if (!(message instanceof Message())) throw new Error('[UNKNOWN_MESSAGE] Please pass a valid Message');
|
||||||
if (!this.customId || this.style == 5 || this.disabled) return false; // Button URL, Disabled
|
if (!this.customId || this.style == 5 || this.disabled) return false; // Button URL, Disabled
|
||||||
await message.client.api.interactions.post({
|
const data = {
|
||||||
data: {
|
|
||||||
type: 3, // ?
|
type: 3, // ?
|
||||||
nonce,
|
nonce,
|
||||||
guild_id: message.guild?.id ?? null, // In DMs
|
guild_id: message.guild?.id ?? null, // In DMs
|
||||||
@ -188,7 +187,14 @@ class MessageButton extends BaseMessageComponent {
|
|||||||
component_type: 2, // Button
|
component_type: 2, // Button
|
||||||
custom_id: this.customId,
|
custom_id: this.customId,
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
|
await message.client.api.interactions.post({
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
message.client._interactionCache.set(nonce, {
|
||||||
|
channelId: message.channelId,
|
||||||
|
guildId: message.guildId,
|
||||||
|
metadata: data,
|
||||||
});
|
});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handler = data => {
|
const handler = data => {
|
||||||
|
@ -215,7 +215,7 @@ class MessageSelectMenu extends BaseMessageComponent {
|
|||||||
* Mesage select menu
|
* Mesage select menu
|
||||||
* @param {Message} message The message this select menu is for
|
* @param {Message} message The message this select menu is for
|
||||||
* @param {Array<string>} values The values of the select menu
|
* @param {Array<string>} values The values of the select menu
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
*/
|
*/
|
||||||
async select(message, values = []) {
|
async select(message, values = []) {
|
||||||
// Github copilot is the best :))
|
// Github copilot is the best :))
|
||||||
@ -242,8 +242,7 @@ class MessageSelectMenu extends BaseMessageComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const nonce = SnowflakeUtil.generate();
|
const nonce = SnowflakeUtil.generate();
|
||||||
await message.client.api.interactions.post({
|
const data = {
|
||||||
data: {
|
|
||||||
type: 3, // ?
|
type: 3, // ?
|
||||||
guild_id: message.guild?.id ?? null, // In DMs
|
guild_id: message.guild?.id ?? null, // In DMs
|
||||||
channel_id: message.channel.id,
|
channel_id: message.channel.id,
|
||||||
@ -258,7 +257,14 @@ class MessageSelectMenu extends BaseMessageComponent {
|
|||||||
values,
|
values,
|
||||||
},
|
},
|
||||||
nonce,
|
nonce,
|
||||||
},
|
};
|
||||||
|
await message.client.api.interactions.post({
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
message.client._interactionCache.set(nonce, {
|
||||||
|
channelId: message.channelId,
|
||||||
|
guildId: message.guildId,
|
||||||
|
metadata: data,
|
||||||
});
|
});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handler = data => {
|
const handler = data => {
|
||||||
|
@ -59,13 +59,29 @@ class Modal {
|
|||||||
this.application = data.application
|
this.application = data.application
|
||||||
? {
|
? {
|
||||||
...data.application,
|
...data.application,
|
||||||
bot: data.application.bot ? new User(client, data.application.bot) : null,
|
bot: data.application.bot ? new User(client, data.application.bot, data.application) : null,
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Interaction Response
|
||||||
|
* @type {?InteractionResponse}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get sendFromInteraction() {
|
||||||
|
if (this.id && this.nonce && this.client) {
|
||||||
|
const cache = this.client._interactionCache.get(this.nonce);
|
||||||
|
const channel = cache.guildId
|
||||||
|
? this.client.guilds.cache.get(cache.guildId)?.channels.cache.get(cache.channelId)
|
||||||
|
: this.client.channels.cache.get(cache.channelId);
|
||||||
|
return channel.interactions.cache.get(this.id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds components to the modal.
|
* Adds components to the modal.
|
||||||
* @param {...MessageActionRowResolvable[]} components The components to add
|
* @param {...MessageActionRowResolvable[]} components The components to add
|
||||||
@ -135,24 +151,27 @@ class Modal {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} ModalReplyData
|
* @typedef {Object} ModalReplyData
|
||||||
* @property {GuildResolvable} [guild] Guild to send the modal to
|
* @property {?GuildResolvable} [guild] Guild to send the modal to
|
||||||
* @property {TextChannelResolvable} [channel] User to send the modal to
|
* @property {?TextChannelResolvable} [channel] User to send the modal to
|
||||||
* @property {TextInputComponentReplyData[]} [data] Reply data
|
* @property {TextInputComponentReplyData[]} [data] Reply data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reply to this modal with data. (Event only)
|
* Reply to this modal with data. (Event only)
|
||||||
* @param {ModalReplyData} data Data to send with the modal
|
* @param {ModalReplyData} data Data to send with the modal
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
* @example
|
* @example
|
||||||
* // With Event
|
|
||||||
* client.on('interactionModalCreate', modal => {
|
* client.on('interactionModalCreate', modal => {
|
||||||
* modal.reply('guildId', 'channelId', {
|
* modal.reply({
|
||||||
|
* data: [
|
||||||
|
* {
|
||||||
* customId: 'code',
|
* customId: 'code',
|
||||||
* value: '1+1'
|
* value: '1+1'
|
||||||
* }, {
|
* }, {
|
||||||
* customId: 'message',
|
* customId: 'message',
|
||||||
* value: 'hello'
|
* value: 'hello'
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
* })
|
* })
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
@ -160,8 +179,9 @@ class Modal {
|
|||||||
if (typeof data !== 'object') throw new TypeError('ModalReplyData must be an object');
|
if (typeof data !== 'object') throw new TypeError('ModalReplyData must be an object');
|
||||||
if (!Array.isArray(data.data)) throw new TypeError('ModalReplyData.data must be an array');
|
if (!Array.isArray(data.data)) throw new TypeError('ModalReplyData.data must be an array');
|
||||||
if (!this.application) throw new Error('Modal cannot reply (Missing Application)');
|
if (!this.application) throw new Error('Modal cannot reply (Missing Application)');
|
||||||
const guild = this.client.guilds.resolveId(data.guild);
|
const data_cache = this.sendFromInteraction;
|
||||||
const channel = this.client.channels.resolveId(data.channel);
|
const guild = this.client.guilds.resolveId(data.guild) || data_cache.guildId || null;
|
||||||
|
const channel = this.client.channels.resolveId(data.channel) || data_cache.channelId;
|
||||||
// Add data to components
|
// Add data to components
|
||||||
// this.components = [ MessageActionRow.components = [ TextInputComponent ] ]
|
// this.components = [ MessageActionRow.components = [ TextInputComponent ] ]
|
||||||
// 5 MessageActionRow / Modal, 1 TextInputComponent / 1 MessageActionRow
|
// 5 MessageActionRow / Modal, 1 TextInputComponent / 1 MessageActionRow
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const { Channel } = require('./Channel');
|
const { Channel } = require('./Channel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const { RangeError } = require('../errors');
|
const { RangeError } = require('../errors');
|
||||||
|
const InteractionManager = require('../managers/InteractionManager');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
const ThreadMemberManager = require('../managers/ThreadMemberManager');
|
const ThreadMemberManager = require('../managers/ThreadMemberManager');
|
||||||
const Permissions = require('../util/Permissions');
|
const Permissions = require('../util/Permissions');
|
||||||
@ -35,6 +36,12 @@ class ThreadChannel extends Channel {
|
|||||||
*/
|
*/
|
||||||
this.messages = new MessageManager(this);
|
this.messages = new MessageManager(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the interactions sent to this channel
|
||||||
|
* @type {InteractionManager}
|
||||||
|
*/
|
||||||
|
this.interactions = new InteractionManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager of the members that are part of this thread
|
* A manager of the members that are part of this thread
|
||||||
* @type {ThreadMemberManager}
|
* @type {ThreadMemberManager}
|
||||||
|
@ -16,7 +16,7 @@ const UserFlags = require('../util/UserFlags');
|
|||||||
* @extends {Base}
|
* @extends {Base}
|
||||||
*/
|
*/
|
||||||
class User extends Base {
|
class User extends Base {
|
||||||
constructor(client, data) {
|
constructor(client, data, application) {
|
||||||
super(client);
|
super(client);
|
||||||
/**
|
/**
|
||||||
* The user's id
|
* The user's id
|
||||||
@ -78,7 +78,7 @@ class User extends Base {
|
|||||||
* @type {?ClientApplication}
|
* @type {?ClientApplication}
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
this.application = null;
|
this.application = application ? new ClientApplication(this.client, application, this) : null;
|
||||||
this._partial = true;
|
this._partial = true;
|
||||||
this._patch(data);
|
this._patch(data);
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ class User extends Base {
|
|||||||
* @type {?boolean}
|
* @type {?boolean}
|
||||||
*/
|
*/
|
||||||
this.bot = Boolean(data.bot);
|
this.bot = Boolean(data.bot);
|
||||||
if (this.bot === true) {
|
if (this.bot === true && !this.application) {
|
||||||
this.application = new ClientApplication(this.client, { id: this.id }, this);
|
this.application = new ClientApplication(this.client, { id: this.id }, this);
|
||||||
this.botInGuildsCount = null;
|
this.botInGuildsCount = null;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const process = require('node:process');
|
const process = require('node:process');
|
||||||
const BaseGuildVoiceChannel = require('./BaseGuildVoiceChannel');
|
const BaseGuildVoiceChannel = require('./BaseGuildVoiceChannel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
|
const InteractionManager = require('../managers/InteractionManager');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
const { VideoQualityModes } = require('../util/Constants');
|
const { VideoQualityModes } = require('../util/Constants');
|
||||||
const Permissions = require('../util/Permissions');
|
const Permissions = require('../util/Permissions');
|
||||||
@ -24,6 +25,12 @@ class VoiceChannel extends BaseGuildVoiceChannel {
|
|||||||
*/
|
*/
|
||||||
this.messages = new MessageManager(this);
|
this.messages = new MessageManager(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the interactions sent to this channel
|
||||||
|
* @type {InteractionManager}
|
||||||
|
*/
|
||||||
|
this.interactions = new InteractionManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the guild considers this channel NSFW
|
* If the guild considers this channel NSFW
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* eslint-disable import/order */
|
/* eslint-disable import/order */
|
||||||
|
const InteractionManager = require('../../managers/InteractionManager');
|
||||||
const MessageCollector = require('../MessageCollector');
|
const MessageCollector = require('../MessageCollector');
|
||||||
const MessagePayload = require('../MessagePayload');
|
const MessagePayload = require('../MessagePayload');
|
||||||
const SnowflakeUtil = require('../../util/SnowflakeUtil');
|
const SnowflakeUtil = require('../../util/SnowflakeUtil');
|
||||||
@ -31,6 +32,12 @@ class TextBasedChannel {
|
|||||||
*/
|
*/
|
||||||
this.messages = new MessageManager(this);
|
this.messages = new MessageManager(this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the interactions sent to this channel
|
||||||
|
* @type {InteractionManager}
|
||||||
|
*/
|
||||||
|
this.interactions = new InteractionManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The channel's last message id, if one was sent
|
* The channel's last message id, if one was sent
|
||||||
* @type {?Snowflake}
|
* @type {?Snowflake}
|
||||||
@ -405,7 +412,7 @@ class TextBasedChannel {
|
|||||||
* @param {UserResolvable} bot Bot user
|
* @param {UserResolvable} bot Bot user
|
||||||
* @param {string} commandString Command name (and sub / group formats)
|
* @param {string} commandString Command name (and sub / group formats)
|
||||||
* @param {...?string|string[]} args Command arguments
|
* @param {...?string|string[]} args Command arguments
|
||||||
* @returns {Promise<InteractionResponseBody>}
|
* @returns {Promise<InteractionResponse>}
|
||||||
* @example
|
* @example
|
||||||
* // Send Slash to this channel
|
* // Send Slash to this channel
|
||||||
* // Demo:
|
* // Demo:
|
||||||
|
48
typings/index.d.ts
vendored
48
typings/index.d.ts
vendored
@ -509,8 +509,8 @@ export class ApplicationCommand<PermissionsFetchType = {}> extends Base {
|
|||||||
message: Message,
|
message: Message,
|
||||||
subCommandArray?: string[],
|
subCommandArray?: string[],
|
||||||
options?: string[],
|
options?: string[],
|
||||||
): Promise<InteractionResponseBody>;
|
): Promise<InteractionResponse>;
|
||||||
public static sendContextMenu(message: Message): Promise<InteractionResponseBody>;
|
public static sendContextMenu(message: Message): Promise<InteractionResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ApplicationResolvable = Application | Activity | Snowflake;
|
export type ApplicationResolvable = Application | Activity | Snowflake;
|
||||||
@ -1934,10 +1934,10 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
|||||||
// Added
|
// Added
|
||||||
public markUnread(): Promise<boolean>;
|
public markUnread(): Promise<boolean>;
|
||||||
public markRead(): Promise<boolean>;
|
public markRead(): Promise<boolean>;
|
||||||
public clickButton(button: MessageButton | string): Promise<InteractionResponseBody>;
|
public clickButton(button: MessageButton | string): Promise<InteractionResponse>;
|
||||||
public selectMenu(menuID: string, options: string[]): Promise<InteractionResponseBody>;
|
public selectMenu(menuID: string, options: string[]): Promise<InteractionResponse>;
|
||||||
public selectMenu(options: string[]): Promise<InteractionResponseBody>;
|
public selectMenu(options: string[]): Promise<InteractionResponse>;
|
||||||
public contextMenu(botID: Snowflake, commandName: string): Promise<InteractionResponseBody>;
|
public contextMenu(botID: Snowflake, commandName: string): Promise<InteractionResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MessageActionRow<
|
export class MessageActionRow<
|
||||||
@ -2001,7 +2001,7 @@ export class MessageButton extends BaseMessageComponent {
|
|||||||
public setStyle(style: MessageButtonStyleResolvable): this;
|
public setStyle(style: MessageButtonStyleResolvable): this;
|
||||||
public setURL(url: string): this;
|
public setURL(url: string): this;
|
||||||
public toJSON(): APIButtonComponent;
|
public toJSON(): APIButtonComponent;
|
||||||
public click(message: Message): Promise<InteractionResponseBody>;
|
public click(message: Message): Promise<InteractionResponse>;
|
||||||
private static resolveStyle(style: MessageButtonStyleResolvable): MessageButtonStyle;
|
private static resolveStyle(style: MessageButtonStyleResolvable): MessageButtonStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2241,7 +2241,7 @@ export class MessageSelectMenu extends BaseMessageComponent {
|
|||||||
...options: MessageSelectOptionData[] | MessageSelectOptionData[][]
|
...options: MessageSelectOptionData[] | MessageSelectOptionData[][]
|
||||||
): this;
|
): this;
|
||||||
public toJSON(): APISelectMenuComponent;
|
public toJSON(): APISelectMenuComponent;
|
||||||
public select(message: Message, values: string[]): Promise<InteractionResponseBody>;
|
public select(message: Message, values: string[]): Promise<InteractionResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo
|
// Todo
|
||||||
@ -2253,6 +2253,7 @@ export class Modal {
|
|||||||
public application: object | null;
|
public application: object | null;
|
||||||
public client: Client | null;
|
public client: Client | null;
|
||||||
public nonce: Snowflake | null;
|
public nonce: Snowflake | null;
|
||||||
|
public readonly sendFromInteraction: InteractionResponse | null;
|
||||||
public addComponents(
|
public addComponents(
|
||||||
...components: (
|
...components: (
|
||||||
| MessageActionRow<ModalActionRowComponent>
|
| MessageActionRow<ModalActionRowComponent>
|
||||||
@ -2276,12 +2277,12 @@ export class Modal {
|
|||||||
): this;
|
): this;
|
||||||
public setTitle(title: string): this;
|
public setTitle(title: string): this;
|
||||||
public toJSON(): RawModalSubmitInteractionData;
|
public toJSON(): RawModalSubmitInteractionData;
|
||||||
public reply(data: ModalReplyData): Promise<InteractionResponseBody>;
|
public reply(data: ModalReplyData): Promise<InteractionResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModalReplyData {
|
export interface ModalReplyData {
|
||||||
guild: GuildResolvable;
|
guild?: GuildResolvable;
|
||||||
channel: TextChannelResolvable;
|
channel?: TextChannelResolvable;
|
||||||
data: TextInputComponentReplyData[];
|
data: TextInputComponentReplyData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3901,6 +3902,26 @@ export class MessageManager extends CachedManager<Snowflake, Message, MessageRes
|
|||||||
public search(options: MessageSearchOptions): Promise<MessageSearchResult>;
|
public search(options: MessageSearchOptions): Promise<MessageSearchResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class InteractionManager extends CachedManager<Snowflake, Message, MessageResolvable> {
|
||||||
|
private constructor(channel: TextBasedChannel, iterable?: Iterable<RawMessageData>);
|
||||||
|
public channel: TextBasedChannel;
|
||||||
|
public cache: Collection<Snowflake, Message>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InteractionResponse extends Base {
|
||||||
|
private constructor(client: Client, data: Object);
|
||||||
|
public readonly channel: GuildTextBasedChannel | TextBasedChannel;
|
||||||
|
public channelId: Snowflake;
|
||||||
|
public readonly createdAt: Date;
|
||||||
|
public createdTimestamp: number;
|
||||||
|
public guildId: Snowflake | null;
|
||||||
|
public readonly guild: Snowflake | null;
|
||||||
|
public id: Snowflake;
|
||||||
|
public nonce: Snowflake;
|
||||||
|
public sendData: Object;
|
||||||
|
public awaitModal(time?: number): Modal;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MessageSearchOptions {
|
export interface MessageSearchOptions {
|
||||||
author: Snowflake[];
|
author: Snowflake[];
|
||||||
content: string;
|
content: string;
|
||||||
@ -4069,6 +4090,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
|
|||||||
lastPinTimestamp: number | null;
|
lastPinTimestamp: number | null;
|
||||||
readonly lastPinAt: Date | null;
|
readonly lastPinAt: Date | null;
|
||||||
messages: MessageManager;
|
messages: MessageManager;
|
||||||
|
interactions: InteractionManager;
|
||||||
awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ACTION_ROW'>(
|
awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ACTION_ROW'>(
|
||||||
options?: AwaitMessageCollectorOptionsParams<T, true>,
|
options?: AwaitMessageCollectorOptionsParams<T, true>,
|
||||||
): Promise<MappedInteractionTypes[T]>;
|
): Promise<MappedInteractionTypes[T]>;
|
||||||
@ -4086,7 +4108,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
|
|||||||
setNSFW(nsfw?: boolean, reason?: string): Promise<this>;
|
setNSFW(nsfw?: boolean, reason?: string): Promise<this>;
|
||||||
fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
||||||
sendTyping(): Promise<void>;
|
sendTyping(): Promise<void>;
|
||||||
sendSlash(bot: UserResolvable, commandName: string, ...args: any): Promise<InteractionResponseBody>;
|
sendSlash(bot: UserResolvable, commandName: string, ...args: any): Promise<InteractionResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PartialWebhookMixin<T>(Base?: Constructable<T>): Constructable<T & PartialWebhookFields>;
|
export function PartialWebhookMixin<T>(Base?: Constructable<T>): Constructable<T & PartialWebhookFields>;
|
||||||
@ -6616,7 +6638,7 @@ export type AnyChannel =
|
|||||||
| VoiceChannel
|
| VoiceChannel
|
||||||
| ForumChannel;
|
| ForumChannel;
|
||||||
|
|
||||||
export type TextBasedChannel = Exclude<Extract<AnyChannel, { messages: MessageManager }>, ForumChannel>;
|
export type TextBasedChannel = Exclude<Extract<AnyChannel, { messages: MessageManager, interactions: InteractionManager }>, ForumChannel>;
|
||||||
|
|
||||||
export type TextBasedChannelTypes = TextBasedChannel['type'];
|
export type TextBasedChannelTypes = TextBasedChannel['type'];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user