update
This commit is contained in:
parent
f19c8e0aa6
commit
924c442ad4
@ -1,115 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const process = require('node:process');
|
|
||||||
const Action = require('./Action');
|
|
||||||
const AutocompleteInteraction = require('../../structures/AutocompleteInteraction');
|
|
||||||
const ButtonInteraction = require('../../structures/ButtonInteraction');
|
|
||||||
const CommandInteraction = require('../../structures/CommandInteraction');
|
|
||||||
const MessageContextMenuInteraction = require('../../structures/MessageContextMenuInteraction');
|
|
||||||
const ModalSubmitInteraction = require('../../structures/ModalSubmitInteraction');
|
|
||||||
const {
|
|
||||||
ChannelSelectInteraction,
|
|
||||||
MentionableSelectInteraction,
|
|
||||||
RoleSelectInteraction,
|
|
||||||
SelectMenuInteraction,
|
|
||||||
UserSelectInteraction,
|
|
||||||
} = require('../../structures/SelectMenuInteraction');
|
|
||||||
const UserContextMenuInteraction = require('../../structures/UserContextMenuInteraction');
|
|
||||||
const { Events, InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../../util/Constants');
|
|
||||||
|
|
||||||
let deprecationEmitted = false;
|
|
||||||
|
|
||||||
class InteractionCreateAction extends Action {
|
|
||||||
handle(data) {
|
|
||||||
const client = this.client;
|
|
||||||
|
|
||||||
// Resolve and cache partial channels for Interaction#channel getter
|
|
||||||
const channel = this.getChannel(data);
|
|
||||||
// Do not emit this for interactions that cache messages that are non-text-based.
|
|
||||||
let InteractionType;
|
|
||||||
switch (data.type) {
|
|
||||||
case InteractionTypes.APPLICATION_COMMAND:
|
|
||||||
switch (data.data.type) {
|
|
||||||
case ApplicationCommandTypes.CHAT_INPUT:
|
|
||||||
InteractionType = CommandInteraction;
|
|
||||||
break;
|
|
||||||
case ApplicationCommandTypes.USER:
|
|
||||||
InteractionType = UserContextMenuInteraction;
|
|
||||||
break;
|
|
||||||
case ApplicationCommandTypes.MESSAGE:
|
|
||||||
InteractionType = MessageContextMenuInteraction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
client.emit(
|
|
||||||
Events.DEBUG,
|
|
||||||
`[INTERACTION] Received application command interaction with unknown type: ${data.data.type}`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InteractionTypes.MESSAGE_COMPONENT:
|
|
||||||
if (channel && !channel.isText()) return;
|
|
||||||
switch (data.data.component_type) {
|
|
||||||
case MessageComponentTypes.BUTTON:
|
|
||||||
InteractionType = ButtonInteraction;
|
|
||||||
break;
|
|
||||||
case MessageComponentTypes.STRING_SELECT:
|
|
||||||
InteractionType = SelectMenuInteraction;
|
|
||||||
break;
|
|
||||||
case MessageComponentTypes.CHANNEL_SELECT:
|
|
||||||
InteractionType = ChannelSelectInteraction;
|
|
||||||
break;
|
|
||||||
case MessageComponentTypes.MENTIONABLE_SELECT:
|
|
||||||
InteractionType = MentionableSelectInteraction;
|
|
||||||
break;
|
|
||||||
case MessageComponentTypes.ROLE_SELECT:
|
|
||||||
InteractionType = RoleSelectInteraction;
|
|
||||||
break;
|
|
||||||
case MessageComponentTypes.USER_SELECT:
|
|
||||||
InteractionType = UserSelectInteraction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
client.emit(
|
|
||||||
Events.DEBUG,
|
|
||||||
`[INTERACTION] Received component interaction with unknown type: ${data.data.component_type}`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE:
|
|
||||||
InteractionType = AutocompleteInteraction;
|
|
||||||
break;
|
|
||||||
case InteractionTypes.MODAL_SUBMIT:
|
|
||||||
InteractionType = ModalSubmitInteraction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
client.emit(
|
|
||||||
Events.DEBUG,
|
|
||||||
`[INTERACTION] Received [BOT] / Send (Selfbot) interactionID ${data.id} with unknown type: ${data.type}`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const interaction = new InteractionType(client, data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when an interaction is created.
|
|
||||||
* @event Client#interactionCreate
|
|
||||||
* @param {InteractionResponseBody | Interaction} interaction The interaction which was created.
|
|
||||||
*/
|
|
||||||
client.emit(Events.INTERACTION_CREATE, interaction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when an interaction is created.
|
|
||||||
* @event Client#interaction
|
|
||||||
* @param {Interaction} interaction The interaction which was created
|
|
||||||
* @deprecated Use {@link Client#event:interactionCreate} instead
|
|
||||||
*/
|
|
||||||
if (client.emit('interaction', interaction) && !deprecationEmitted) {
|
|
||||||
deprecationEmitted = true;
|
|
||||||
process.emitWarning('The interaction event is deprecated. Use interactionCreate instead', 'DeprecationWarning');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = InteractionCreateAction;
|
|
@ -1,16 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Events } = require('../../../util/Constants');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} InteractionResponseBody
|
|
||||||
* @property {Snowflake} id Interaction ID
|
|
||||||
* @property {Snowflake} nonce nonce in POST /interactions
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
|
||||||
if (client.user.bot) {
|
|
||||||
client.actions.InteractionCreate.handle(data);
|
|
||||||
} else {
|
|
||||||
client.emit(Events.INTERACTION_CREATE, data);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,18 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Events } = require('../../../util/Constants');
|
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
|
||||||
/**
|
|
||||||
* Emitted whenever client user send interaction and error
|
|
||||||
* @event Client#interactionFailure
|
|
||||||
* @param {InteractionResponseBody} data data
|
|
||||||
*/
|
|
||||||
client.emit(Events.INTERACTION_FAILURE, data);
|
|
||||||
client.emit('interactionResponse', {
|
|
||||||
status: false,
|
|
||||||
metadata: client._interactionCache.get(data.nonce),
|
|
||||||
error: 'No response from bot',
|
|
||||||
});
|
|
||||||
// Delete cache
|
|
||||||
client._interactionCache.delete(data.nonce);
|
|
||||||
};
|
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const Modal = require('../../../structures/Modal');
|
const Modal = require('../../../structures/Modal');
|
||||||
const { Events } = require('../../../util/Constants');
|
const { Events } = require('../../../util/Constants');
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
module.exports = (client, { d: data }) => {
|
||||||
/**
|
/**
|
||||||
* Emitted whenever client user receive interaction.showModal()
|
* Emitted whenever client user receive interaction.showModal()
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Events } = require('../../../util/Constants');
|
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
|
||||||
/**
|
|
||||||
* Emitted whenever client user send interaction and success
|
|
||||||
* @event Client#interactionSuccess
|
|
||||||
* @param {InteractionResponseBody} data data
|
|
||||||
*/
|
|
||||||
client.emit(Events.INTERACTION_SUCCESS, data);
|
|
||||||
// Get channel data
|
|
||||||
const cache = client._interactionCache.get(data.nonce);
|
|
||||||
if (!cache) return;
|
|
||||||
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', {
|
|
||||||
status: true,
|
|
||||||
metadata: data_,
|
|
||||||
error: 'Success',
|
|
||||||
});
|
|
||||||
// Delete cache
|
|
||||||
// client._interactionCache.delete(data.nonce);
|
|
||||||
};
|
|
@ -1,17 +1,19 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Events, RelationshipTypes } = require('../../../util/Constants');
|
const { Events } = require('../../../util/Constants');
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
module.exports = (client, { d: data }) => {
|
||||||
if (data.user) {
|
if (data.user) {
|
||||||
client.users._add(data.user);
|
client.users._add(data.user);
|
||||||
}
|
}
|
||||||
client.relationships.cache.set(data.id, data.type);
|
client.relationships.cache.set(data.id, data.type);
|
||||||
|
client.relationships.friendNicknames.set(data.id, data.nickname);
|
||||||
|
client.relationships.sinceCache.set(data.id, new Date(data.since || 0));
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a relationship is updated.
|
* Emitted when a relationship is created, relevant to the current user.
|
||||||
* @event Client#relationshipAdd
|
* @event Client#relationshipAdd
|
||||||
* @param {Snowflake} user The userID that was updated
|
* @param {Snowflake} user Target userId
|
||||||
* @param {RelationshipTypes} type The new relationship type
|
* @param {boolean} shouldNotify Whether the client should notify the user of this relationship's creation
|
||||||
*/
|
*/
|
||||||
client.emit(Events.RELATIONSHIP_ADD, data.id, RelationshipTypes[data.type]);
|
client.emit(Events.RELATIONSHIP_ADD, data.id, Boolean(data.should_notify));
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Events, RelationshipTypes } = require('../../../util/Constants');
|
const { Events } = require('../../../util/Constants');
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
module.exports = (client, { d: data }) => {
|
||||||
client.relationships.cache.delete(data.id);
|
client.relationships.cache.delete(data.id);
|
||||||
client.user.friendNicknames.delete(data.id);
|
client.relationships.friendNicknames.delete(data.id);
|
||||||
|
client.relationships.sinceCache.delete(data.id);
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a relationship is delete.
|
* Emitted when a relationship is removed, relevant to the current user.
|
||||||
* @event Client#relationshipRemove
|
* @event Client#relationshipRemove
|
||||||
* @param {Snowflake} user The userID that was updated
|
* @param {Snowflake} user The userID that was updated
|
||||||
* @param {RelationshipTypes} type The type of the old relationship
|
* @param {RelationshipTypes} type The type of the old relationship
|
||||||
|
* @param {string | null} nickname The nickname of the user in this relationship (1-32 characters)
|
||||||
*/
|
*/
|
||||||
client.emit(Events.RELATIONSHIP_REMOVE, data.id, RelationshipTypes[data.type]);
|
client.emit(Events.RELATIONSHIP_REMOVE, data.id, data.type, data.nickname);
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,41 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Events, RelationshipTypes } = require('../../../util/Constants');
|
const { Events } = require('../../../util/Constants');
|
||||||
|
|
||||||
module.exports = (client, { d: data }) => {
|
module.exports = (client, { d: data }) => {
|
||||||
client.relationships.cache.set(data.id, data.type);
|
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a relationship is updated.
|
* @typedef {Object} RelationshipUpdateObject
|
||||||
|
* @property {RelationshipTypes} type The type of relationship
|
||||||
|
* @property {Date} since When the user requested a relationship
|
||||||
|
* @property {string | null} nickname The nickname of the user in this relationship (1-32 characters)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Emitted when a relationship is updated, relevant to the current user (e.g. friend nickname changed).
|
||||||
|
* <info>This is not sent when the type of a relationship changes; see {@link Client#relationshipAdd} and {@link Client#relationshipRemove} for that.</info>
|
||||||
* @event Client#relationshipUpdate
|
* @event Client#relationshipUpdate
|
||||||
* @param {Snowflake} user The userID that was updated
|
* @param {Snowflake} user The userID that was updated
|
||||||
* @param {RelationshipTypes} type The new relationship type
|
* @param {RelationshipUpdateObject} oldData Old data
|
||||||
* @param {Object} data The raw data
|
* @param {RelationshipUpdateObject} newData New data
|
||||||
*/
|
*/
|
||||||
if ('nickname' in data) {
|
const oldType = client.relationships.cache.get(data.id);
|
||||||
client.user.friendNicknames.set(data.id, data.nickname);
|
const oldSince = client.relationships.sinceCache.get(data.id);
|
||||||
}
|
const oldNickname = client.relationships.friendNicknames.get(data.id);
|
||||||
client.emit(Events.RELATIONSHIP_UPDATE, data.id, RelationshipTypes[data.type], data);
|
// Update
|
||||||
|
if (data.type) client.relationships.cache.set(data.id, data.type);
|
||||||
|
if (data.nickname) client.relationships.friendNicknames.set(data.id, data.nickname);
|
||||||
|
if (data.since) client.relationships.sinceCache.set(data.id, new Date(data.since || 0));
|
||||||
|
client.emit(
|
||||||
|
Events.RELATIONSHIP_UPDATE,
|
||||||
|
data.id,
|
||||||
|
{
|
||||||
|
type: oldType,
|
||||||
|
nickname: oldNickname,
|
||||||
|
since: oldSince,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: data.type,
|
||||||
|
nickname: data.nickname,
|
||||||
|
since: new Date(data.since || 0),
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Buffer = require('node:buffer').Buffer;
|
|
||||||
const { Collection } = require('@discordjs/collection');
|
const { Collection } = require('@discordjs/collection');
|
||||||
|
const BaseManager = require('./BaseManager');
|
||||||
const { GuildMember } = require('../structures/GuildMember');
|
const { GuildMember } = require('../structures/GuildMember');
|
||||||
const { Message } = require('../structures/Message');
|
const { Message } = require('../structures/Message');
|
||||||
const ThreadMember = require('../structures/ThreadMember');
|
const ThreadMember = require('../structures/ThreadMember');
|
||||||
@ -11,19 +11,22 @@ const { RelationshipTypes } = require('../util/Constants');
|
|||||||
/**
|
/**
|
||||||
* Manages API methods for Relationships and stores their cache.
|
* Manages API methods for Relationships and stores their cache.
|
||||||
*/
|
*/
|
||||||
class RelationshipManager {
|
class RelationshipManager extends BaseManager {
|
||||||
constructor(client, users) {
|
constructor(client, users) {
|
||||||
/**
|
super(client);
|
||||||
* The client that instantiated this manager.
|
|
||||||
* @type {Client}
|
|
||||||
*/
|
|
||||||
this.client = client;
|
|
||||||
/**
|
/**
|
||||||
* A collection of users this manager is caching. (Type: Number)
|
* A collection of users this manager is caching. (Type: Number)
|
||||||
* @type {Collection<Snowflake, RelationshipTypes>}
|
* @type {Collection<Snowflake, RelationshipTypes>}
|
||||||
* @readonly
|
|
||||||
*/
|
*/
|
||||||
this.cache = new Collection();
|
this.cache = new Collection();
|
||||||
|
/**
|
||||||
|
* @type {Collection<Snowflake, string>}
|
||||||
|
*/
|
||||||
|
this.friendNicknames = new Collection();
|
||||||
|
/**
|
||||||
|
* @type {Collection<Snowflake, Date>}
|
||||||
|
*/
|
||||||
|
this.sinceCache = new Collection();
|
||||||
this._setup(users);
|
this._setup(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +38,7 @@ class RelationshipManager {
|
|||||||
get friendCache() {
|
get friendCache() {
|
||||||
const users = this.cache
|
const users = this.cache
|
||||||
.filter(value => value === RelationshipTypes.FRIEND)
|
.filter(value => value === RelationshipTypes.FRIEND)
|
||||||
.map((value, key) => [key, this.client.users.cache.get(key)]);
|
.map((_, key) => [key, this.client.users.cache.get(key)]);
|
||||||
return new Collection(users);
|
return new Collection(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ class RelationshipManager {
|
|||||||
get blockedCache() {
|
get blockedCache() {
|
||||||
const users = this.cache
|
const users = this.cache
|
||||||
.filter(value => value === RelationshipTypes.BLOCKED)
|
.filter(value => value === RelationshipTypes.BLOCKED)
|
||||||
.map((value, key) => [key, this.client.users.cache.get(key)]);
|
.map((_, key) => [key, this.client.users.cache.get(key)]);
|
||||||
return new Collection(users);
|
return new Collection(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +62,7 @@ class RelationshipManager {
|
|||||||
get incomingCache() {
|
get incomingCache() {
|
||||||
const users = this.cache
|
const users = this.cache
|
||||||
.filter(value => value === RelationshipTypes.PENDING_INCOMING)
|
.filter(value => value === RelationshipTypes.PENDING_INCOMING)
|
||||||
.map((value, key) => [key, this.client.users.cache.get(key)]);
|
.map((_, key) => [key, this.client.users.cache.get(key)]);
|
||||||
return new Collection(users);
|
return new Collection(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,16 +74,29 @@ class RelationshipManager {
|
|||||||
get outgoingCache() {
|
get outgoingCache() {
|
||||||
const users = this.cache
|
const users = this.cache
|
||||||
.filter(value => value === RelationshipTypes.PENDING_OUTGOING)
|
.filter(value => value === RelationshipTypes.PENDING_OUTGOING)
|
||||||
.map((value, key) => [key, this.client.users.cache.get(key)]);
|
.map((_, key) => [key, this.client.users.cache.get(key)]);
|
||||||
return new Collection(users);
|
return new Collection(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return array of cache
|
* @typedef {Object} RelationshipJSONData
|
||||||
* @returns {Array<{id: Snowflake, type: RelationshipTypes}>}
|
* @property {Snowflake} id The ID of the target user
|
||||||
|
* @property {RelationshipTypes} type The type of relationship
|
||||||
|
* @property {string | null} nickname The nickname of the user in this relationship (1-32 characters)
|
||||||
|
* @property {string} since When the user requested a relationship (ISO8601 timestamp)
|
||||||
*/
|
*/
|
||||||
toArray() {
|
|
||||||
return this.cache.map((value, key) => ({ id: key, type: RelationshipTypes[value] }));
|
/**
|
||||||
|
* Return array of cache
|
||||||
|
* @returns {RelationshipJSONData[]}
|
||||||
|
*/
|
||||||
|
toJSON() {
|
||||||
|
return this.cache.map((value, key) => ({
|
||||||
|
id: key,
|
||||||
|
type: RelationshipTypes[value],
|
||||||
|
nickname: this.friendNicknames.get(key),
|
||||||
|
since: this.sinceCache.get(key).toISOString(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,8 +107,9 @@ class RelationshipManager {
|
|||||||
_setup(users) {
|
_setup(users) {
|
||||||
if (!Array.isArray(users)) return;
|
if (!Array.isArray(users)) return;
|
||||||
for (const relationShip of users) {
|
for (const relationShip of users) {
|
||||||
this.client.user.friendNicknames.set(relationShip.id, relationShip.nickname);
|
this.friendNicknames.set(relationShip.id, relationShip.nickname);
|
||||||
this.cache.set(relationShip.id, relationShip.type);
|
this.cache.set(relationShip.id, relationShip.type);
|
||||||
|
this.sinceCache.set(relationShip.id, new Date(relationShip.since || 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,66 +150,55 @@ class RelationshipManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a friend relationship with a client user.
|
* Deletes a friend / blocked relationship with a client user or cancels a friend request.
|
||||||
* @param {UserResolvable} user Target
|
* @param {UserResolvable} user Target
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
deleteFriend(user) {
|
async deleteRelationship(user) {
|
||||||
const id = this.resolveId(user);
|
const id = this.resolveId(user);
|
||||||
// Check if already friends
|
if (
|
||||||
if (this.cache.get(id) !== RelationshipTypes.FRIEND) return false;
|
![RelationshipTypes.FRIEND, RelationshipTypes.BLOCKED, RelationshipTypes.PENDING_OUTGOING].includes(
|
||||||
return this.__cancel(id);
|
this.cache.get(id),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
await this.client.api.users['@me'].relationships[id].delete({
|
||||||
|
DiscordContext: { location: 'Friends' },
|
||||||
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a blocked relationship with a client user.
|
* @typedef {Object} FriendRequestOptions
|
||||||
* @param {UserResolvable} user Target
|
* @property {UserResolvable} [user] Target
|
||||||
* @returns {Promise<boolean>}
|
* @property {string} [username] Discord username
|
||||||
|
* @property {number | null} [discriminator] Discord discriminator
|
||||||
*/
|
*/
|
||||||
deleteBlocked(user) {
|
|
||||||
const id = this.resolveId(user);
|
|
||||||
// Check if already blocked
|
|
||||||
if (this.cache.get(id) !== RelationshipTypes.BLOCKED) return false;
|
|
||||||
return this.__cancel(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a friend request.
|
* Sends a friend request.
|
||||||
* @param {string} username Username of the user to send the request to
|
* @param {FriendRequestOptions} options Target
|
||||||
* @param {?number} discriminator Discriminator of the user to send the request to
|
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
async sendFriendRequest(username, discriminator) {
|
async sendFriendRequest(options) {
|
||||||
await this.client.api.users('@me').relationships.post({
|
if (options?.user) {
|
||||||
data: {
|
const id = this.resolveId(options.user);
|
||||||
username,
|
await this.client.api.users['@me'].relationships[id].put({
|
||||||
discriminator: discriminator == 0 ? null : parseInt(discriminator),
|
data: {},
|
||||||
},
|
DiscordContext: { location: 'ContextMenu' },
|
||||||
headers: {
|
});
|
||||||
'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Add Friend' }), 'utf8').toString('base64'),
|
return true;
|
||||||
},
|
} else {
|
||||||
});
|
await this.client.api.users['@me'].relationships.post({
|
||||||
return true;
|
data: {
|
||||||
}
|
username: options.username,
|
||||||
|
discriminator: options.discriminator,
|
||||||
/**
|
},
|
||||||
* Cancels a friend request.
|
DiscordContext: { location: 'Add Friend' },
|
||||||
* @param {UserResolvable} user the user you want to delete
|
});
|
||||||
* @returns {Promise<boolean>}
|
return true;
|
||||||
*/
|
}
|
||||||
cancelFriendRequest(user) {
|
|
||||||
const id = this.resolveId(user);
|
|
||||||
if (this.cache.get(id) !== RelationshipTypes.PENDING_OUTGOING) return false;
|
|
||||||
return this.__cancel(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async __cancel(id) {
|
|
||||||
await this.client.api.users['@me'].relationships[id].delete({
|
|
||||||
headers: {
|
|
||||||
'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Friends' }), 'utf8').toString('base64'),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,16 +209,14 @@ class RelationshipManager {
|
|||||||
async addFriend(user) {
|
async addFriend(user) {
|
||||||
const id = this.resolveId(user);
|
const id = this.resolveId(user);
|
||||||
// Check if already friends
|
// Check if already friends
|
||||||
if (this.cache.get(id) === RelationshipTypes.FRIEND) return false;
|
if (this.cache.get(id) === RelationshipTypes.FRIEND) return Promise.resolve(false);
|
||||||
// Check if outgoing request
|
// Check if outgoing request
|
||||||
if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING) return false;
|
if (this.cache.get(id) === RelationshipTypes.PENDING_OUTGOING) return Promise.resolve(false);
|
||||||
await this.client.api.users['@me'].relationships[id].put({
|
await this.client.api.users['@me'].relationships[id].put({
|
||||||
data: {
|
data: {
|
||||||
type: RelationshipTypes.FRIEND,
|
type: RelationshipTypes.FRIEND,
|
||||||
},
|
},
|
||||||
headers: {
|
DiscordContext: { location: 'Friends' },
|
||||||
'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'Friends' }), 'utf8').toString('base64'),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -223,14 +227,19 @@ class RelationshipManager {
|
|||||||
* @param {?string} nickname New nickname
|
* @param {?string} nickname New nickname
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
async setNickname(user, nickname) {
|
async setNickname(user, nickname = null) {
|
||||||
const id = this.resolveId(user);
|
const id = this.resolveId(user);
|
||||||
if (this.cache.get(id) !== RelationshipTypes.FRIEND) return false;
|
if (this.cache.get(id) !== RelationshipTypes.FRIEND) return Promise.resolve(false);
|
||||||
await this.client.api.users['@me'].relationships[id].patch({
|
await this.client.api.users['@me'].relationships[id].patch({
|
||||||
data: {
|
data: {
|
||||||
nickname: typeof nickname === 'string' ? nickname : null,
|
nickname: typeof nickname === 'string' ? nickname : null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (nickname) {
|
||||||
|
this.friendNicknames.set(id, nickname);
|
||||||
|
} else {
|
||||||
|
this.friendNicknames.delete(id);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,14 +251,12 @@ class RelationshipManager {
|
|||||||
async addBlocked(user) {
|
async addBlocked(user) {
|
||||||
const id = this.resolveId(user);
|
const id = this.resolveId(user);
|
||||||
// Check
|
// Check
|
||||||
if (this.cache.get(id) === RelationshipTypes.BLOCKED) return false;
|
if (this.cache.get(id) === RelationshipTypes.BLOCKED) return Promise.resolve(false);
|
||||||
await this.client.api.users['@me'].relationships[id].put({
|
await this.client.api.users['@me'].relationships[id].put({
|
||||||
data: {
|
data: {
|
||||||
type: RelationshipTypes.BLOCKED,
|
type: RelationshipTypes.BLOCKED,
|
||||||
},
|
},
|
||||||
headers: {
|
DiscordContext: { location: 'ContextMenu' },
|
||||||
'X-Context-Properties': Buffer.from(JSON.stringify({ location: 'ContextMenu' }), 'utf8').toString('base64'),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
'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
|
|
||||||
* @returns {Modal}
|
|
||||||
*/
|
|
||||||
awaitModal(time) {
|
|
||||||
if (!time || typeof time !== 'number' || time < 0) throw new Error('INVALID_TIME');
|
|
||||||
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).unref();
|
|
||||||
this.client.incrementMaxListeners();
|
|
||||||
this.client.on(Events.INTERACTION_MODAL_CREATE, handler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = InteractionResponse;
|
|
@ -2,24 +2,15 @@
|
|||||||
|
|
||||||
const { setTimeout } = require('node:timers');
|
const { setTimeout } = require('node:timers');
|
||||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||||
const User = require('./User');
|
const { InteractionTypes, Events } = require('../util/Constants');
|
||||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||||
const Util = require('../util/Util');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a modal (form) to be shown in response to an interaction
|
* Represents a modal (form) to be shown in response to an interaction
|
||||||
*/
|
*/
|
||||||
class Modal {
|
class Modal {
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} ModalOptions
|
* @param {Object} data Modal to clone or raw data
|
||||||
* @property {string} [customId] A unique string to be sent in the interaction when clicked
|
|
||||||
* @property {string} [title] The title to be displayed on this modal
|
|
||||||
* @property {Array<(MessageActionRow|MessageActionRowOptions)>} [components]
|
|
||||||
* Action rows containing interactive components for the modal (text input components)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Modal|ModalOptions} data Modal to clone or raw data
|
|
||||||
* @param {Client} client The client constructing this Modal, if provided
|
* @param {Client} client The client constructing this Modal, if provided
|
||||||
*/
|
*/
|
||||||
constructor(data = {}, client = null) {
|
constructor(data = {}, client = null) {
|
||||||
@ -33,106 +24,69 @@ class Modal {
|
|||||||
* A unique string to be sent in the interaction when submitted
|
* A unique string to be sent in the interaction when submitted
|
||||||
* @type {?string}
|
* @type {?string}
|
||||||
*/
|
*/
|
||||||
this.customId = data.custom_id ?? data.customId ?? null;
|
this.customId = data.custom_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The title to be displayed on this modal
|
* The title to be displayed on this modal
|
||||||
* @type {?string}
|
* @type {?string}
|
||||||
*/
|
*/
|
||||||
this.title = data.title ?? null;
|
this.title = data.title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp (Discord epoch) of when this modal was created
|
* Timestamp (Discord epoch) of when this modal was created
|
||||||
* @type {?Snowflake}
|
* @type {Snowflake}
|
||||||
*/
|
*/
|
||||||
this.nonce = data.nonce ?? null;
|
this.nonce = data.nonce;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID slash / button / menu when modal is displayed
|
* ID slash / button / menu when modal is displayed
|
||||||
* @type {?Snowflake}
|
* @type {Snowflake}
|
||||||
*/
|
*/
|
||||||
this.id = data.id ?? null;
|
this.id = data.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application sending the modal
|
* Application sending the modal
|
||||||
* @type {?Object}
|
* @type {Snowflake}
|
||||||
*/
|
*/
|
||||||
this.application = data.application
|
this.applicationId = data.application.id;
|
||||||
? {
|
|
||||||
...data.application,
|
|
||||||
bot: data.application.bot ? new User(client, data.application.bot, data.application) : null,
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
|
|
||||||
this.client = client;
|
/**
|
||||||
|
* The id of the channel the message was sent in
|
||||||
|
* @type {Snowflake}
|
||||||
|
*/
|
||||||
|
this.channelId = data.channel_id;
|
||||||
|
|
||||||
|
Object.defineProperty(this, 'client', {
|
||||||
|
value: client,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Interaction Response
|
* The id of the guild the message was sent in, if any
|
||||||
* @type {?InteractionResponse}
|
* @type {?Snowflake}
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get sendFromInteraction() {
|
get guildId() {
|
||||||
if (this.id && this.nonce && this.client) {
|
return this.client.channels.cache.get(this.channelId)?.guildId || null;
|
||||||
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.
|
* The channel that the message was sent in
|
||||||
* @param {...MessageActionRowResolvable[]} components The components to add
|
* @type {TextBasedChannels}
|
||||||
* @returns {Modal}
|
* @readonly
|
||||||
*/
|
*/
|
||||||
addComponents(...components) {
|
get channel() {
|
||||||
this.components.push(...components.flat(Infinity).map(c => BaseMessageComponent.create(c)));
|
return this.client.channels.resolve(this.channelId);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the components of the modal.
|
* The guild the message was sent in (if in a guild channel)
|
||||||
* @param {...MessageActionRowResolvable[]} components The components to set
|
* @type {?Guild}
|
||||||
* @returns {Modal}
|
* @readonly
|
||||||
*/
|
*/
|
||||||
setComponents(...components) {
|
get guild() {
|
||||||
this.spliceComponents(0, this.components.length, components);
|
return this.client.guilds.resolve(this.guildId) ?? this.channel?.guild ?? null;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the custom id for this modal
|
|
||||||
* @param {string} customId A unique string to be sent in the interaction when submitted
|
|
||||||
* @returns {Modal}
|
|
||||||
*/
|
|
||||||
setCustomId(customId) {
|
|
||||||
this.customId = Util.verifyString(customId, RangeError, 'MODAL_CUSTOM_ID');
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes, replaces, and inserts components in the modal.
|
|
||||||
* @param {number} index The index to start at
|
|
||||||
* @param {number} deleteCount The number of components to remove
|
|
||||||
* @param {...MessageActionRowResolvable[]} [components] The replacing components
|
|
||||||
* @returns {Modal}
|
|
||||||
*/
|
|
||||||
spliceComponents(index, deleteCount, ...components) {
|
|
||||||
this.components.splice(index, deleteCount, ...components.flat(Infinity).map(c => BaseMessageComponent.create(c)));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the title of this modal
|
|
||||||
* @param {string} title The title to be displayed on this modal
|
|
||||||
* @returns {Modal}
|
|
||||||
*/
|
|
||||||
setTitle(title) {
|
|
||||||
this.title = Util.verifyString(title, RangeError, 'MODAL_TITLE');
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
toJSON() {
|
||||||
@ -144,136 +98,77 @@ class Modal {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} TextInputComponentReplyData
|
|
||||||
* @property {string} [customId] TextInputComponent custom id
|
|
||||||
* @property {string} [value] TextInputComponent value
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ModalReplyData
|
|
||||||
* @property {?GuildResolvable} [guild] Guild to send the modal to
|
|
||||||
* @property {?TextChannelResolvable} [channel] User to send the modal to
|
|
||||||
* @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
|
* @returns {Promise<Message|Modal>}
|
||||||
* @returns {Promise<InteractionResponse>}
|
|
||||||
* @example
|
* @example
|
||||||
* client.on('interactionModalCreate', modal => {
|
* client.on('interactionModalCreate', modal => {
|
||||||
* // 1.
|
* // Modal > ActionRow > TextInput
|
||||||
* modal.reply({
|
* modal.components[0].components[0].setValue('1+1');
|
||||||
* data: [
|
* modal.components[1].components[0].setValue('hello');
|
||||||
* {
|
* modal.reply();
|
||||||
* customId: 'code',
|
|
||||||
* value: '1+1'
|
|
||||||
* }, {
|
|
||||||
* customId: 'message',
|
|
||||||
* value: 'hello'
|
|
||||||
* }
|
|
||||||
* ],
|
|
||||||
* channel: 'id', // optional
|
|
||||||
* guild: 'id', // optional
|
|
||||||
* })
|
|
||||||
* // or 2.
|
|
||||||
* modal.components[0].components[0].setValue('1+1');
|
|
||||||
* modal.components[1].components[0].setValue('hello');
|
|
||||||
* modal.reply();
|
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
async reply(data = {}) {
|
reply() {
|
||||||
if (!this.application) throw new Error('Modal cannot reply (Missing Application)');
|
if (!this.applicationId || !this.client || !this.channelId) throw new Error('Modal cannot reply');
|
||||||
const data_cache = this.sendFromInteraction;
|
|
||||||
const guild = this.client.guilds.resolveId(data?.guild) || data_cache.guildId || null;
|
|
||||||
const channel = this.client.channels.resolveId(data?.channel) || data_cache.channelId;
|
|
||||||
if (!channel) throw new Error('Modal cannot reply (Missing data)');
|
|
||||||
// Add data to components
|
|
||||||
// this.components = [ MessageActionRow.components = [ TextInputComponent ] ]
|
|
||||||
// 5 MessageActionRow / Modal, 1 TextInputComponent / 1 MessageActionRow
|
|
||||||
if (Array.isArray(data?.data) && data?.data?.length > 0) {
|
|
||||||
for (let i = 0; i < this.components.length; i++) {
|
|
||||||
const value = data.data.find(d => d.customId == this.components[i].components[0].customId);
|
|
||||||
if (this.components[i].components[0].required == true && !value) {
|
|
||||||
throw new Error(
|
|
||||||
'MODAL_REQUIRED_FIELD_MISSING\n' +
|
|
||||||
`Required fieldId ${this.components[i].components[0].customId} missing value`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
if (value?.value?.includes('\n') && this.components[i].components[0].style == 'SHORT') {
|
|
||||||
throw new Error(
|
|
||||||
'MODAL_REPLY_DATA_INVALID\n' +
|
|
||||||
`value must be a single line, got multiple lines [Custom ID: ${value.customId}]`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.components[i].components[0].setValue(value.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get Object
|
// Get Object
|
||||||
const dataFinal = this.toJSON();
|
const dataFinal = this.toJSON();
|
||||||
dataFinal.components = dataFinal.components
|
dataFinal.components = dataFinal.components
|
||||||
.map(c => {
|
.map(c => {
|
||||||
delete c.components[0].max_length;
|
c.components[0] = {
|
||||||
delete c.components[0].min_length;
|
type: c.components[0].type,
|
||||||
delete c.components[0].required;
|
value: c.components[0].value,
|
||||||
delete c.components[0].placeholder;
|
custom_id: c.components[0].custom_id,
|
||||||
delete c.components[0].label;
|
};
|
||||||
delete c.components[0].style;
|
|
||||||
return c;
|
return c;
|
||||||
})
|
})
|
||||||
.filter(c => c.components[0].value && c.components[0].value !== '');
|
.filter(c => c.components[0].value && c.components[0].value !== '');
|
||||||
delete dataFinal.title;
|
delete dataFinal.title;
|
||||||
const nonce = SnowflakeUtil.generate();
|
const nonce = SnowflakeUtil.generate();
|
||||||
const postData = {
|
const postData = {
|
||||||
type: 5, // Modal
|
type: InteractionTypes.MODAL_SUBMIT, // Modal
|
||||||
application_id: this.application.id,
|
application_id: this.applicationId,
|
||||||
guild_id: guild || null,
|
guild_id: this.guildId,
|
||||||
channel_id: channel,
|
channel_id: this.channelId,
|
||||||
data: dataFinal,
|
data: dataFinal,
|
||||||
nonce,
|
nonce,
|
||||||
session_id: this.client.sessionId,
|
session_id: this.client.ws.shards.first()?.sessionId,
|
||||||
};
|
};
|
||||||
await this.client.api.interactions.post({
|
this.client.api.interactions.post({
|
||||||
data: postData,
|
data: postData,
|
||||||
});
|
});
|
||||||
this.client._interactionCache.set(nonce, {
|
|
||||||
channelId: channel,
|
|
||||||
guildId: guild,
|
|
||||||
metadata: postData,
|
|
||||||
});
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
const timeoutMs = 15_000;
|
||||||
|
// Waiting for MsgCreate / ModalCreate
|
||||||
const handler = data => {
|
const handler = data => {
|
||||||
timeout.refresh();
|
if (data.nonce !== nonce) return;
|
||||||
if (data.metadata?.nonce !== nonce) return;
|
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
this.client.removeListener('interactionResponse', handler);
|
this.client.removeListener(Events.MESSAGE_CREATE, handler);
|
||||||
|
this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
this.client.decrementMaxListeners();
|
this.client.decrementMaxListeners();
|
||||||
if (data.status) {
|
resolve(data);
|
||||||
resolve(data.metadata);
|
|
||||||
} else {
|
|
||||||
reject(
|
|
||||||
new Error('INTERACTION_ERROR', {
|
|
||||||
cause: data,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
this.client.removeListener('interactionResponse', handler);
|
this.client.removeListener(Events.MESSAGE_CREATE, handler);
|
||||||
|
this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
this.client.decrementMaxListeners();
|
this.client.decrementMaxListeners();
|
||||||
reject(
|
reject(new Error('INTERACTION_FAILED'));
|
||||||
new Error('INTERACTION_TIMEOUT', {
|
}, timeoutMs).unref();
|
||||||
cause: postData,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}, this.client.options.interactionTimeout).unref();
|
|
||||||
this.client.incrementMaxListeners();
|
this.client.incrementMaxListeners();
|
||||||
this.client.on('interactionResponse', handler);
|
this.client.on(Events.MESSAGE_CREATE, handler);
|
||||||
|
this.client.on(Events.INTERACTION_MODAL_CREATE, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TypeScript
|
||||||
|
/**
|
||||||
|
* Check data
|
||||||
|
* @type {boolean}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get isMessage() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Modal;
|
module.exports = Modal;
|
||||||
|
Loading…
Reference in New Issue
Block a user