diff --git a/package-lock.json b/package-lock.json index b24a1a0..b2deb5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "bignumber.js": "^9.0.2", "bufferutil": "^4.0.6", "chalk": "^4.1.2", - "discord-api-types": "^0.33.3", + "discord-api-types": "^0.33.5", "discord-bettermarkdown": "^1.2.0", "discord-rpc-contructor": "^1.1.5", "discord.js": "^13.8.0", @@ -37,7 +37,7 @@ "string_decoder": "^1.3.0", "string-similarity": "^4.0.4", "utf-8-validate": "^5.0.9", - "ws": "^8.7.0" + "ws": "^8.8.0" }, "devDependencies": { "@commitlint/cli": "^16.0.1", diff --git a/package.json b/package.json index 42e42d4..3d8fb93 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "bignumber.js": "^9.0.2", "bufferutil": "^4.0.6", "chalk": "^4.1.2", - "discord-api-types": "^0.33.3", + "discord-api-types": "^0.33.5", "discord-bettermarkdown": "^1.2.0", "discord-rpc-contructor": "^1.1.5", "discord.js": "^13.8.0", @@ -79,7 +79,7 @@ "string_decoder": "^1.3.0", "string-similarity": "^4.0.4", "utf-8-validate": "^5.0.9", - "ws": "^8.7.0" + "ws": "^8.8.0" }, "engines": { "node": ">=16.6.0", diff --git a/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js b/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js index c579315..009f6de 100644 --- a/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +++ b/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js @@ -2,14 +2,10 @@ const { Events } = require('../../../util/Constants'); module.exports = (client, { d: data }) => { - if (!data.application_commands[0]) return; for (const command of data.application_commands) { const user = client.users.cache.get(command.application_id); - if (!user) continue; + if (!user || !user.bot) continue; user.applications._add(command, true); } - client.emit( - Events.GUILD_APPLICATION_COMMANDS_UPDATE, - client.users.cache.get(data.application_commands[0].application_id).applications.cache, - ); + client.emit(Events.GUILD_APPLICATION_COMMANDS_UPDATE, data); }; diff --git a/src/client/websocket/handlers/RELATIONSHIP_ADD.js b/src/client/websocket/handlers/RELATIONSHIP_ADD.js index 06c4afa..d2007de 100644 --- a/src/client/websocket/handlers/RELATIONSHIP_ADD.js +++ b/src/client/websocket/handlers/RELATIONSHIP_ADD.js @@ -11,7 +11,7 @@ module.exports = (client, { d: data }) => { * Emitted whenever a relationship is updated. * @event Client#relationshipAdd * @param {Snowflake} user The userID that was updated - * @param {RelationshipTypes} type The new relationship type (String) + * @param {RelationshipTypes} type The new relationship type */ client.emit(Events.RELATIONSHIP_ADD, data.id, RelationshipTypes[data.type]); }; diff --git a/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js b/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js index 25938a7..3c6b405 100644 --- a/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +++ b/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js @@ -1,13 +1,14 @@ 'use strict'; -const { Events } = require('../../../util/Constants'); +const { Events, RelationshipTypes } = require('../../../util/Constants'); module.exports = (client, { d: data }) => { client.relationships.cache.delete(data.id); /** - * Emitted whenever a relationship is updated. + * Emitted whenever a relationship is delete. * @event Client#relationshipRemove * @param {Snowflake} user The userID that was updated + * @param {RelationshipTypes} type The type of the old relationship */ - client.emit(Events.RELATIONSHIP_REMOVE, data.id); + client.emit(Events.RELATIONSHIP_REMOVE, data.id, RelationshipTypes[data.type]); }; diff --git a/src/errors/Messages.js b/src/errors/Messages.js index d16677a..70f7cde 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -101,6 +101,8 @@ const Messages = { STAGE_CHANNEL_RESOLVE: 'Could not resolve channel to a stage channel.', GUILD_SCHEDULED_EVENT_RESOLVE: 'Could not resolve the guild scheduled event.', + MISSING_VALUE: (where, type) => `Missing value for ${where} (${type})`, + INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, INVALID_ELEMENT: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`, diff --git a/src/managers/ChannelManager.js b/src/managers/ChannelManager.js index 0228e12..d7484d8 100644 --- a/src/managers/ChannelManager.js +++ b/src/managers/ChannelManager.js @@ -129,7 +129,6 @@ class ChannelManager extends CachedManager { // Check if (!recipients || !Array.isArray(recipients)) throw new Error('No recipients || Invalid Type (Array)'); recipients = recipients.filter(r => r instanceof User && r.id && r.friend); - console.log(recipients); if (recipients.length < 2 || recipients.length > 9) throw new Error('Invalid Users length (2 - 9)'); const data = await this.client.api.users['@me'].channels.post({ data: { recipients: recipients.map(r => r.id) }, diff --git a/src/managers/RelationshipsManager.js b/src/managers/RelationshipsManager.js index c174bff..2d371ed 100644 --- a/src/managers/RelationshipsManager.js +++ b/src/managers/RelationshipsManager.js @@ -26,6 +26,14 @@ class RelationshipsManager { this._setup(users); } + /** + * Return array of cache + * @returns {Array<{id: Snowflake, type: RelationshipTypes}>} + */ + toArray() { + return this.cache.map((value, key) => ({ id: key, type: RelationshipTypes[value] })); + } + /** * @private * @param {Array} users An array of users to add to the cache diff --git a/src/structures/ApplicationCommand.js b/src/structures/ApplicationCommand.js index 50afc28..2aad131 100644 --- a/src/structures/ApplicationCommand.js +++ b/src/structures/ApplicationCommand.js @@ -626,9 +626,11 @@ class ApplicationCommand extends Base { // ApplicationCommandData version: this.version, id: this.id, + guild_id: message.guildId, name: this.name, type: ApplicationCommandTypes[this.type], options: option_, + attachments: [], // Todo }, nonce: SnowflakeUtil.generate(), }, @@ -648,7 +650,7 @@ class ApplicationCommand extends Base { * await command.sendContextMenu(messsage); */ async sendContextMenu(message, sendFromMessage = false) { - if (!(message instanceof Message && !sendFromMessage)) { + if (!sendFromMessage && !(message instanceof Message)) { throw new TypeError('The message must be a Discord.Message'); } if (this.type == 'CHAT_INPUT') return false; diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 811d79c..41fc589 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -36,6 +36,7 @@ const { Events, } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); const SystemChannelFlags = require('../util/SystemChannelFlags'); const Util = require('../util/Util'); @@ -615,34 +616,24 @@ class Guild extends AnonymousGuild { /** * Options for guildSearchInteraction * @typedef {Object} GuildSearchInteractionOptions - * @property {?number|string} [type=1] {@link ApplicationCommandTypes} - * @property {?string} [query] Command name - * @property {?number} [limit=1] Maximum number of results + * @property {string} query Command name + * @property {?number} [limit=10] Maximum number of results * @property {?number} [offset=0] Only return entries for actions made by this user - * @property {Snowflake[]} botId Array of bot IDs to filter by + * @property {?Snowflake} [botId] BotID + * @property {?ApplicationCommandType} [type=CHAT_INPUT] Type of command */ /** * Searches for guild interactions * @param {GuildSearchInteractionOptions} options Options for the search - * @returns {Promise} + * @returns {void | Promise} */ searchInteraction(options = {}) { - let { query, type, limit, offset, botId } = Object.assign( - { query: undefined, type: 1, limit: 1, offset: 0, botId: [] }, + let { query, limit, offset, botId, type } = Object.assign( + { query: undefined, limit: 10, offset: 0, botId: undefined, type: 'CHAT_INPUT' }, options, ); - if (typeof type === 'string') { - if (type == 'CHAT_INPUT') type = 1; - else if (type == 'USER') type = 2; - else if (type == 'MESSAGE') type = 3; - // MODAL_SUMMIT :)) - } - if (type < 1 || type > 3) { - throw new RangeError('Type must be 1 (CHAT_INPUT), 2 (USER), 3 (MESSAGE)'); - } - if (typeof type !== 'number') { - throw new TypeError('Type must be a number | string'); - } + if (!query) throw new Error('MISSING_VALUE', 'searchInteraction', 'query'); + const nonce = SnowflakeUtil.generate(); this.shard.send({ op: Opcodes.REQUEST_APPLICATION_COMMANDS, d: { @@ -650,18 +641,21 @@ class Guild extends AnonymousGuild { applications: false, limit, offset, - type, - query: query, - command_ids: Array.isArray(botId) ? botId : undefined, + query, + nonce, }, }); + if (!botId || !type) return undefined; return new Promise((resolve, reject) => { - const handler = application => { + const handler = applications => { timeout.refresh(); + if (applications.nonce !== nonce) return; + const cmd = applications.application_commands.find(app => app.name == query && app.application_id == botId); + if (!cmd) return; clearTimeout(timeout); this.client.removeListener(Events.GUILD_APPLICATION_COMMANDS_UPDATE, handler); this.client.decrementMaxListeners(); - resolve(application.slice(0, limit)); + resolve(this.client.users.cache.get(botId)?.applications?.cache?.find(c => c.name === query && c.type == type)); }; const timeout = setTimeout(() => { this.client.removeListener(Events.GUILD_APPLICATION_COMMANDS_UPDATE, handler); diff --git a/src/structures/interfaces/TextBasedChannel.js b/src/structures/interfaces/TextBasedChannel.js index a26f97c..dcb5e1c 100644 --- a/src/structures/interfaces/TextBasedChannel.js +++ b/src/structures/interfaces/TextBasedChannel.js @@ -1,8 +1,8 @@ 'use strict'; /* eslint-disable import/order */ +const { Message } = require('discord.js'); const MessageCollector = require('../MessageCollector'); -const { Message } = require('../Message'); const MessagePayload = require('../MessagePayload'); const SnowflakeUtil = require('../../util/SnowflakeUtil'); const { Collection } = require('@discordjs/collection'); @@ -404,20 +404,9 @@ class TextBasedChannel { throw new Error('botId is not a bot or does not have an application slash command'); } if (!commandName || typeof commandName !== 'string') throw new Error('Command name is required'); - const commandTarget = ( - user.applications.cache.find(c => c.name === commandName && c.type === 'CHAT_INPUT') - ? this.guild - ? await this.guild.searchInteraction({ - type: 'CHAT_INPUT', - query: commandName, - botId: [botId], - limit: 1, - }) - : await user.applications.fetch() - : user.applications.cache - ).find(application => commandName == application.name && application.type == 'CHAT_INPUT'); + const commandTarget = user.applications.cache.find(c => c.name === commandName && c.type === 'CHAT_INPUT'); if (!commandTarget) { - throw new Error(`Command ${commandName} is not found`); + throw new Error(`Command ${commandName} is not found\nDebug:\n+ botId: ${botId}\n+ args: ${args.join(' | ')}`); } return commandTarget.sendSlashCommand( new Message(this.client, {