discord.js 15.0.0-dev.1745453588-abc5d99ce → 15.0.0-dev.1745626383-8f375275c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/client/Client.js +14 -0
- package/src/client/actions/Action.js +4 -0
- package/src/client/actions/ActionsManager.js +1 -0
- package/src/client/actions/GuildSoundboardSoundDelete.js +29 -0
- package/src/client/actions/InteractionCreate.js +4 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +24 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +18 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +5 -0
- package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +20 -0
- package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +24 -0
- package/src/client/websocket/handlers/index.js +5 -0
- package/src/errors/ErrorCodes.js +5 -0
- package/src/errors/Messages.js +3 -0
- package/src/index.js +4 -0
- package/src/managers/ApplicationCommandManager.js +1 -0
- package/src/managers/GuildManager.js +67 -1
- package/src/managers/GuildSoundboardSoundManager.js +192 -0
- package/src/structures/ApplicationCommand.js +21 -3
- package/src/structures/BaseInteraction.js +10 -0
- package/src/structures/CommandInteraction.js +1 -0
- package/src/structures/Guild.js +7 -0
- package/src/structures/GuildAuditLogsEntry.js +4 -5
- package/src/structures/MessageComponentInteraction.js +1 -0
- package/src/structures/ModalSubmitInteraction.js +1 -0
- package/src/structures/PrimaryEntryPointCommandInteraction.js +11 -0
- package/src/structures/SoundboardSound.js +204 -0
- package/src/structures/Sticker.js +1 -1
- package/src/structures/VoiceChannel.js +21 -1
- package/src/structures/VoiceChannelEffect.js +9 -0
- package/src/structures/interfaces/InteractionResponses.js +26 -0
- package/src/util/APITypes.js +5 -0
- package/src/util/DataResolver.js +5 -4
- package/src/util/Events.js +10 -0
- package/src/util/Partials.js +2 -0
- package/typings/index.d.mts +152 -19
- package/typings/index.d.ts +152 -19
- package/typings/index.test-d.ts +112 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "discord.js",
|
|
4
|
-
"version": "15.0.0-dev.
|
|
4
|
+
"version": "15.0.0-dev.1745626383-8f375275c",
|
|
5
5
|
"description": "A powerful library for interacting with the Discord API",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./typings/index.d.ts",
|
|
@@ -57,12 +57,13 @@
|
|
|
57
57
|
"discord-api-types": "^0.38.1",
|
|
58
58
|
"fast-deep-equal": "3.1.3",
|
|
59
59
|
"lodash.snakecase": "4.1.1",
|
|
60
|
+
"magic-bytes.js": "^1.10.0",
|
|
60
61
|
"tslib": "^2.8.1",
|
|
61
62
|
"undici": "7.8.0",
|
|
62
|
-
"@discordjs/collection": "^2.1.1",
|
|
63
63
|
"@discordjs/builders": "^1.9.0",
|
|
64
|
-
"@discordjs/rest": "^2.4.0",
|
|
65
64
|
"@discordjs/formatters": "^0.5.0",
|
|
65
|
+
"@discordjs/rest": "^2.4.0",
|
|
66
|
+
"@discordjs/collection": "^2.1.1",
|
|
66
67
|
"@discordjs/util": "^1.1.1",
|
|
67
68
|
"@discordjs/ws": "^2.0.0"
|
|
68
69
|
},
|
package/src/client/Client.js
CHANGED
|
@@ -19,6 +19,7 @@ const { ClientPresence } = require('../structures/ClientPresence.js');
|
|
|
19
19
|
const { GuildPreview } = require('../structures/GuildPreview.js');
|
|
20
20
|
const { GuildTemplate } = require('../structures/GuildTemplate.js');
|
|
21
21
|
const { Invite } = require('../structures/Invite.js');
|
|
22
|
+
const { SoundboardSound } = require('../structures/SoundboardSound.js');
|
|
22
23
|
const { Sticker } = require('../structures/Sticker.js');
|
|
23
24
|
const { StickerPack } = require('../structures/StickerPack.js');
|
|
24
25
|
const { VoiceRegion } = require('../structures/VoiceRegion.js');
|
|
@@ -536,6 +537,19 @@ class Client extends BaseClient {
|
|
|
536
537
|
return new Collection(data.sticker_packs.map(stickerPack => [stickerPack.id, new StickerPack(this, stickerPack)]));
|
|
537
538
|
}
|
|
538
539
|
|
|
540
|
+
/**
|
|
541
|
+
* Obtains the list of default soundboard sounds.
|
|
542
|
+
* @returns {Promise<Collection<string, SoundboardSound>>}
|
|
543
|
+
* @example
|
|
544
|
+
* client.fetchDefaultSoundboardSounds()
|
|
545
|
+
* .then(sounds => console.log(`Available soundboard sounds are: ${sounds.map(sound => sound.name).join(', ')}`))
|
|
546
|
+
* .catch(console.error);
|
|
547
|
+
*/
|
|
548
|
+
async fetchDefaultSoundboardSounds() {
|
|
549
|
+
const data = await this.rest.get(Routes.soundboardDefaultSounds());
|
|
550
|
+
return new Collection(data.map(sound => [sound.sound_id, new SoundboardSound(this, sound)]));
|
|
551
|
+
}
|
|
552
|
+
|
|
539
553
|
/**
|
|
540
554
|
* Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds.
|
|
541
555
|
* @param {GuildResolvable} guild The guild to fetch the preview for
|
|
@@ -131,6 +131,10 @@ class Action {
|
|
|
131
131
|
return this.getPayload({ user_id: id }, manager, id, Partials.ThreadMember, false);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
getSoundboardSound(data, guild) {
|
|
135
|
+
return this.getPayload(data, guild.soundboardSounds, data.sound_id, Partials.SoundboardSound);
|
|
136
|
+
}
|
|
137
|
+
|
|
134
138
|
spreadInjectedData(data) {
|
|
135
139
|
return Object.fromEntries(Object.getOwnPropertySymbols(data).map(symbol => [symbol, data[symbol]]));
|
|
136
140
|
}
|
|
@@ -27,6 +27,7 @@ class ActionsManager {
|
|
|
27
27
|
this.register(require('./GuildScheduledEventDelete.js').GuildScheduledEventDeleteAction);
|
|
28
28
|
this.register(require('./GuildScheduledEventUserAdd.js').GuildScheduledEventUserAddAction);
|
|
29
29
|
this.register(require('./GuildScheduledEventUserRemove.js').GuildScheduledEventUserRemoveAction);
|
|
30
|
+
this.register(require('./GuildSoundboardSoundDelete.js').GuildSoundboardSoundDeleteAction);
|
|
30
31
|
this.register(require('./GuildStickerCreate.js').GuildStickerCreateAction);
|
|
31
32
|
this.register(require('./GuildStickerDelete.js').GuildStickerDeleteAction);
|
|
32
33
|
this.register(require('./GuildStickerUpdate.js').GuildStickerUpdateAction);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Action } = require('./Action.js');
|
|
4
|
+
const { Events } = require('../../util/Events.js');
|
|
5
|
+
|
|
6
|
+
class GuildSoundboardSoundDeleteAction extends Action {
|
|
7
|
+
handle(data) {
|
|
8
|
+
const guild = this.client.guilds.cache.get(data.guild_id);
|
|
9
|
+
|
|
10
|
+
if (!guild) return {};
|
|
11
|
+
|
|
12
|
+
const soundboardSound = this.getSoundboardSound(data, guild);
|
|
13
|
+
|
|
14
|
+
if (soundboardSound) {
|
|
15
|
+
guild.soundboardSounds.cache.delete(soundboardSound.soundId);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Emitted whenever a soundboard sound is deleted in a guild.
|
|
19
|
+
* @event Client#guildSoundboardSoundDelete
|
|
20
|
+
* @param {SoundboardSound} soundboardSound The soundboard sound that was deleted
|
|
21
|
+
*/
|
|
22
|
+
this.client.emit(Events.GuildSoundboardSoundDelete, soundboardSound);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { soundboardSound };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.GuildSoundboardSoundDeleteAction = GuildSoundboardSoundDeleteAction;
|
|
@@ -9,6 +9,7 @@ const { ChatInputCommandInteraction } = require('../../structures/ChatInputComma
|
|
|
9
9
|
const { MentionableSelectMenuInteraction } = require('../../structures/MentionableSelectMenuInteraction.js');
|
|
10
10
|
const { MessageContextMenuCommandInteraction } = require('../../structures/MessageContextMenuCommandInteraction.js');
|
|
11
11
|
const { ModalSubmitInteraction } = require('../../structures/ModalSubmitInteraction.js');
|
|
12
|
+
const { PrimaryEntryPointCommandInteraction } = require('../../structures/PrimaryEntryPointCommandInteraction.js');
|
|
12
13
|
const { RoleSelectMenuInteraction } = require('../../structures/RoleSelectMenuInteraction.js');
|
|
13
14
|
const { StringSelectMenuInteraction } = require('../../structures/StringSelectMenuInteraction.js');
|
|
14
15
|
const { UserContextMenuCommandInteraction } = require('../../structures/UserContextMenuCommandInteraction.js');
|
|
@@ -38,6 +39,9 @@ class InteractionCreateAction extends Action {
|
|
|
38
39
|
if (channel && !channel.isTextBased()) return;
|
|
39
40
|
InteractionClass = MessageContextMenuCommandInteraction;
|
|
40
41
|
break;
|
|
42
|
+
case ApplicationCommandType.PrimaryEntryPoint:
|
|
43
|
+
InteractionClass = PrimaryEntryPointCommandInteraction;
|
|
44
|
+
break;
|
|
41
45
|
default:
|
|
42
46
|
client.emit(
|
|
43
47
|
Events.Debug,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Collection } = require('@discordjs/collection');
|
|
4
|
+
const { Events } = require('../../../util/Events.js');
|
|
5
|
+
|
|
6
|
+
module.exports = (client, { d: data }) => {
|
|
7
|
+
const guild = client.guilds.cache.get(data.guild_id);
|
|
8
|
+
|
|
9
|
+
if (!guild) return;
|
|
10
|
+
|
|
11
|
+
const soundboardSounds = new Collection();
|
|
12
|
+
|
|
13
|
+
for (const soundboardSound of data.soundboard_sounds) {
|
|
14
|
+
soundboardSounds.set(soundboardSound.sound_id, guild.soundboardSounds._add(soundboardSound));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Emitted whenever multiple guild soundboard sounds are updated.
|
|
19
|
+
* @event Client#guildSoundboardSoundsUpdate
|
|
20
|
+
* @param {Collection<Snowflake, SoundboardSound>} soundboardSounds The updated soundboard sounds
|
|
21
|
+
* @param {Guild} guild The guild that the soundboard sounds are from
|
|
22
|
+
*/
|
|
23
|
+
client.emit(Events.GuildSoundboardSoundsUpdate, soundboardSounds, guild);
|
|
24
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Events } = require('../../../util/Events.js');
|
|
4
|
+
|
|
5
|
+
module.exports = (client, { d: data }) => {
|
|
6
|
+
const guild = client.guilds.cache.get(data.guild_id);
|
|
7
|
+
|
|
8
|
+
if (!guild) return;
|
|
9
|
+
|
|
10
|
+
const soundboardSound = guild.soundboardSounds._add(data);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Emitted whenever a guild soundboard sound is created.
|
|
14
|
+
* @event Client#guildSoundboardSoundCreate
|
|
15
|
+
* @param {SoundboardSound} soundboardSound The created guild soundboard sound
|
|
16
|
+
*/
|
|
17
|
+
client.emit(Events.GuildSoundboardSoundCreate, soundboardSound);
|
|
18
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Events } = require('../../../util/Events.js');
|
|
4
|
+
|
|
5
|
+
module.exports = (client, { d: data }) => {
|
|
6
|
+
const guild = client.guilds.cache.get(data.guild_id);
|
|
7
|
+
|
|
8
|
+
if (!guild) return;
|
|
9
|
+
|
|
10
|
+
const oldGuildSoundboardSound = guild.soundboardSounds.cache.get(data.sound_id)?._clone() ?? null;
|
|
11
|
+
const newGuildSoundboardSound = guild.soundboardSounds._add(data);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Emitted whenever a guild soundboard sound is updated.
|
|
15
|
+
* @event Client#guildSoundboardSoundUpdate
|
|
16
|
+
* @param {?SoundboardSound} oldGuildSoundboardSound The guild soundboard sound before the update
|
|
17
|
+
* @param {SoundboardSound} newGuildSoundboardSound The guild soundboard sound after the update
|
|
18
|
+
*/
|
|
19
|
+
client.emit(Events.GuildSoundboardSoundUpdate, oldGuildSoundboardSound, newGuildSoundboardSound);
|
|
20
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Collection } = require('@discordjs/collection');
|
|
4
|
+
const { Events } = require('../../../util/Events.js');
|
|
5
|
+
|
|
6
|
+
module.exports = (client, { d: data }) => {
|
|
7
|
+
const guild = client.guilds.cache.get(data.guild_id);
|
|
8
|
+
|
|
9
|
+
if (!guild) return;
|
|
10
|
+
|
|
11
|
+
const soundboardSounds = new Collection();
|
|
12
|
+
|
|
13
|
+
for (const soundboardSound of data.soundboard_sounds) {
|
|
14
|
+
soundboardSounds.set(soundboardSound.sound_id, guild.soundboardSounds._add(soundboardSound));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Emitted whenever soundboard sounds are received (all soundboard sounds come from the same guild).
|
|
19
|
+
* @event Client#soundboardSounds
|
|
20
|
+
* @param {Collection<Snowflake, SoundboardSound>} soundboardSounds The sounds received
|
|
21
|
+
* @param {Guild} guild The guild that the soundboard sounds are from
|
|
22
|
+
*/
|
|
23
|
+
client.emit(Events.SoundboardSounds, soundboardSounds, guild);
|
|
24
|
+
};
|
|
@@ -32,6 +32,10 @@ const PacketHandlers = Object.fromEntries([
|
|
|
32
32
|
['GUILD_SCHEDULED_EVENT_UPDATE', require('./GUILD_SCHEDULED_EVENT_UPDATE.js')],
|
|
33
33
|
['GUILD_SCHEDULED_EVENT_USER_ADD', require('./GUILD_SCHEDULED_EVENT_USER_ADD.js')],
|
|
34
34
|
['GUILD_SCHEDULED_EVENT_USER_REMOVE', require('./GUILD_SCHEDULED_EVENT_USER_REMOVE.js')],
|
|
35
|
+
['GUILD_SOUNDBOARD_SOUNDS_UPDATE', require('./GUILD_SOUNDBOARD_SOUNDS_UPDATE.js')],
|
|
36
|
+
['GUILD_SOUNDBOARD_SOUND_CREATE', require('./GUILD_SOUNDBOARD_SOUND_CREATE.js')],
|
|
37
|
+
['GUILD_SOUNDBOARD_SOUND_DELETE', require('./GUILD_SOUNDBOARD_SOUND_DELETE.js')],
|
|
38
|
+
['GUILD_SOUNDBOARD_SOUND_UPDATE', require('./GUILD_SOUNDBOARD_SOUND_UPDATE.js')],
|
|
35
39
|
['GUILD_STICKERS_UPDATE', require('./GUILD_STICKERS_UPDATE.js')],
|
|
36
40
|
['GUILD_UPDATE', require('./GUILD_UPDATE.js')],
|
|
37
41
|
['INTERACTION_CREATE', require('./INTERACTION_CREATE.js')],
|
|
@@ -49,6 +53,7 @@ const PacketHandlers = Object.fromEntries([
|
|
|
49
53
|
['MESSAGE_UPDATE', require('./MESSAGE_UPDATE.js')],
|
|
50
54
|
['PRESENCE_UPDATE', require('./PRESENCE_UPDATE.js')],
|
|
51
55
|
['READY', require('./READY.js')],
|
|
56
|
+
['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS.js')],
|
|
52
57
|
['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE.js')],
|
|
53
58
|
['STAGE_INSTANCE_DELETE', require('./STAGE_INSTANCE_DELETE.js')],
|
|
54
59
|
['STAGE_INSTANCE_UPDATE', require('./STAGE_INSTANCE_UPDATE.js')],
|
package/src/errors/ErrorCodes.js
CHANGED
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
* @property {'GuildChannelUnowned'} GuildChannelUnowned
|
|
62
62
|
* @property {'GuildOwned'} GuildOwned
|
|
63
63
|
* @property {'GuildMembersTimeout'} GuildMembersTimeout
|
|
64
|
+
* @property {'GuildSoundboardSoundsTimeout'} GuildSoundboardSoundsTimeout
|
|
64
65
|
* @property {'GuildUncachedMe'} GuildUncachedMe
|
|
65
66
|
* @property {'ChannelNotCached'} ChannelNotCached
|
|
66
67
|
* @property {'StageChannelResolve'} StageChannelResolve
|
|
@@ -85,6 +86,8 @@
|
|
|
85
86
|
* @property {'EmojiManaged'} EmojiManaged
|
|
86
87
|
* @property {'MissingManageGuildExpressionsPermission'} MissingManageGuildExpressionsPermission
|
|
87
88
|
*
|
|
89
|
+
|
|
90
|
+
* @property {'NotGuildSoundboardSound'} NotGuildSoundboardSound
|
|
88
91
|
* @property {'NotGuildSticker'} NotGuildSticker
|
|
89
92
|
|
|
90
93
|
* @property {'ReactionResolveUser'} ReactionResolveUser
|
|
@@ -193,6 +196,7 @@ const keys = [
|
|
|
193
196
|
'GuildChannelUnowned',
|
|
194
197
|
'GuildOwned',
|
|
195
198
|
'GuildMembersTimeout',
|
|
199
|
+
'GuildSoundboardSoundsTimeout',
|
|
196
200
|
'GuildUncachedMe',
|
|
197
201
|
'ChannelNotCached',
|
|
198
202
|
'StageChannelResolve',
|
|
@@ -217,6 +221,7 @@ const keys = [
|
|
|
217
221
|
'EmojiManaged',
|
|
218
222
|
'MissingManageGuildExpressionsPermission',
|
|
219
223
|
|
|
224
|
+
'NotGuildSoundboardSound',
|
|
220
225
|
'NotGuildSticker',
|
|
221
226
|
|
|
222
227
|
'ReactionResolveUser',
|
package/src/errors/Messages.js
CHANGED
|
@@ -66,6 +66,7 @@ const Messages = {
|
|
|
66
66
|
[ErrorCodes.GuildChannelUnowned]: "The fetched channel does not belong to this manager's guild.",
|
|
67
67
|
[ErrorCodes.GuildOwned]: 'Guild is owned by the client.',
|
|
68
68
|
[ErrorCodes.GuildMembersTimeout]: "Members didn't arrive in time.",
|
|
69
|
+
[ErrorCodes.GuildSoundboardSoundsTimeout]: "Soundboard sounds didn't arrive in time.",
|
|
69
70
|
[ErrorCodes.GuildUncachedMe]: 'The client user as a member of this guild is uncached.',
|
|
70
71
|
[ErrorCodes.ChannelNotCached]: 'Could not find the channel where this message came from in the cache!',
|
|
71
72
|
[ErrorCodes.StageChannelResolve]: 'Could not resolve channel to a stage channel.',
|
|
@@ -91,6 +92,8 @@ const Messages = {
|
|
|
91
92
|
[ErrorCodes.MissingManageGuildExpressionsPermission]: guild =>
|
|
92
93
|
`Client must have Manage Guild Expressions permission in guild ${guild} to see emoji authors.`,
|
|
93
94
|
|
|
95
|
+
[ErrorCodes.NotGuildSoundboardSound]: action =>
|
|
96
|
+
`Soundboard sound is a default (non-guild) soundboard sound and can't be ${action}.`,
|
|
94
97
|
[ErrorCodes.NotGuildSticker]: 'Sticker is a standard (non-guild) sticker and has no author.',
|
|
95
98
|
|
|
96
99
|
[ErrorCodes.ReactionResolveUser]: "Couldn't resolve the user id to remove from the reaction.",
|
package/src/index.js
CHANGED
|
@@ -74,6 +74,7 @@ exports.GuildMemberManager = require('./managers/GuildMemberManager.js').GuildMe
|
|
|
74
74
|
exports.GuildMemberRoleManager = require('./managers/GuildMemberRoleManager.js').GuildMemberRoleManager;
|
|
75
75
|
exports.GuildMessageManager = require('./managers/GuildMessageManager.js').GuildMessageManager;
|
|
76
76
|
exports.GuildScheduledEventManager = require('./managers/GuildScheduledEventManager.js').GuildScheduledEventManager;
|
|
77
|
+
exports.GuildSoundboardSoundManager = require('./managers/GuildSoundboardSoundManager.js').GuildSoundboardSoundManager;
|
|
77
78
|
exports.GuildStickerManager = require('./managers/GuildStickerManager.js').GuildStickerManager;
|
|
78
79
|
exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager.js').GuildTextThreadManager;
|
|
79
80
|
exports.MessageManager = require('./managers/MessageManager.js').MessageManager;
|
|
@@ -186,6 +187,8 @@ exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel.js')
|
|
|
186
187
|
exports.PermissionOverwrites = require('./structures/PermissionOverwrites.js').PermissionOverwrites;
|
|
187
188
|
exports.Poll = require('./structures/Poll.js').Poll;
|
|
188
189
|
exports.PollAnswer = require('./structures/PollAnswer.js').PollAnswer;
|
|
190
|
+
exports.PrimaryEntryPointCommandInteraction =
|
|
191
|
+
require('./structures/PrimaryEntryPointCommandInteraction.js').PrimaryEntryPointCommandInteraction;
|
|
189
192
|
exports.Presence = require('./structures/Presence.js').Presence;
|
|
190
193
|
exports.ReactionCollector = require('./structures/ReactionCollector.js').ReactionCollector;
|
|
191
194
|
exports.ReactionEmoji = require('./structures/ReactionEmoji.js').ReactionEmoji;
|
|
@@ -194,6 +197,7 @@ exports.Role = require('./structures/Role.js').Role;
|
|
|
194
197
|
exports.RoleSelectMenuComponent = require('./structures/RoleSelectMenuComponent.js').RoleSelectMenuComponent;
|
|
195
198
|
exports.RoleSelectMenuInteraction = require('./structures/RoleSelectMenuInteraction.js').RoleSelectMenuInteraction;
|
|
196
199
|
exports.SKU = require('./structures/SKU.js').SKU;
|
|
200
|
+
exports.SoundboardSound = require('./structures/SoundboardSound.js').SoundboardSound;
|
|
197
201
|
exports.StageChannel = require('./structures/StageChannel.js').StageChannel;
|
|
198
202
|
exports.StageInstance = require('./structures/StageInstance.js').StageInstance;
|
|
199
203
|
exports.Sticker = require('./structures/Sticker.js').Sticker;
|
|
@@ -4,8 +4,9 @@ const process = require('node:process');
|
|
|
4
4
|
const { setTimeout, clearTimeout } = require('node:timers');
|
|
5
5
|
const { Collection } = require('@discordjs/collection');
|
|
6
6
|
const { makeURLSearchParams } = require('@discordjs/rest');
|
|
7
|
-
const { Routes, RouteBases } = require('discord-api-types/v10');
|
|
7
|
+
const { GatewayOpcodes, Routes, RouteBases } = require('discord-api-types/v10');
|
|
8
8
|
const { CachedManager } = require('./CachedManager.js');
|
|
9
|
+
const { DiscordjsError, ErrorCodes } = require('../errors/index.js');
|
|
9
10
|
const { ShardClientUtil } = require('../sharding/ShardClientUtil.js');
|
|
10
11
|
const { Guild } = require('../structures/Guild.js');
|
|
11
12
|
const { GuildChannel } = require('../structures/GuildChannel.js');
|
|
@@ -282,6 +283,71 @@ class GuildManager extends CachedManager {
|
|
|
282
283
|
return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection());
|
|
283
284
|
}
|
|
284
285
|
|
|
286
|
+
/**
|
|
287
|
+
* @typedef {Object} FetchSoundboardSoundsOptions
|
|
288
|
+
* @param {Snowflake[]} guildIds The ids of the guilds to fetch soundboard sounds for
|
|
289
|
+
* @param {number} [time=10_000] The timeout for receipt of the soundboard sounds
|
|
290
|
+
*/
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Fetches soundboard sounds for the specified guilds.
|
|
294
|
+
* @param {FetchSoundboardSoundsOptions} options The options for fetching soundboard sounds
|
|
295
|
+
* @returns {Promise<Collection<Snowflake, Collection<Snowflake, SoundboardSound>>>}
|
|
296
|
+
* @example
|
|
297
|
+
* // Fetch soundboard sounds for multiple guilds
|
|
298
|
+
* const soundboardSounds = await client.guilds.fetchSoundboardSounds({
|
|
299
|
+
* guildIds: ['123456789012345678', '987654321098765432'],
|
|
300
|
+
* })
|
|
301
|
+
*
|
|
302
|
+
* console.log(soundboardSounds.get('123456789012345678'));
|
|
303
|
+
*/
|
|
304
|
+
async fetchSoundboardSounds({ guildIds, time = 10_000 }) {
|
|
305
|
+
const shardCount = await this.client.ws.getShardCount();
|
|
306
|
+
const shardIds = Map.groupBy(guildIds, guildId => ShardClientUtil.shardIdForGuildId(guildId, shardCount));
|
|
307
|
+
|
|
308
|
+
for (const [shardId, shardGuildIds] of shardIds) {
|
|
309
|
+
this.client.ws.send(shardId, {
|
|
310
|
+
op: GatewayOpcodes.RequestSoundboardSounds,
|
|
311
|
+
d: {
|
|
312
|
+
guild_ids: shardGuildIds,
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return new Promise((resolve, reject) => {
|
|
318
|
+
const remainingGuildIds = new Set(guildIds);
|
|
319
|
+
|
|
320
|
+
const fetchedSoundboardSounds = new Collection();
|
|
321
|
+
|
|
322
|
+
const handler = (soundboardSounds, guild) => {
|
|
323
|
+
timeout.refresh();
|
|
324
|
+
|
|
325
|
+
if (!remainingGuildIds.has(guild.id)) return;
|
|
326
|
+
|
|
327
|
+
fetchedSoundboardSounds.set(guild.id, soundboardSounds);
|
|
328
|
+
|
|
329
|
+
remainingGuildIds.delete(guild.id);
|
|
330
|
+
|
|
331
|
+
if (remainingGuildIds.size === 0) {
|
|
332
|
+
clearTimeout(timeout);
|
|
333
|
+
this.client.removeListener(Events.SoundboardSounds, handler);
|
|
334
|
+
this.client.decrementMaxListeners();
|
|
335
|
+
|
|
336
|
+
resolve(fetchedSoundboardSounds);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const timeout = setTimeout(() => {
|
|
341
|
+
this.client.removeListener(Events.SoundboardSounds, handler);
|
|
342
|
+
this.client.decrementMaxListeners();
|
|
343
|
+
reject(new DiscordjsError(ErrorCodes.GuildSoundboardSoundsTimeout));
|
|
344
|
+
}, time).unref();
|
|
345
|
+
|
|
346
|
+
this.client.incrementMaxListeners();
|
|
347
|
+
this.client.on(Events.SoundboardSounds, handler);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
285
351
|
/**
|
|
286
352
|
* Options used to set incident actions. Supplying `null` to any option will disable the action.
|
|
287
353
|
* @typedef {Object} IncidentActionsEditOptions
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Collection } = require('@discordjs/collection');
|
|
4
|
+
const { lazy } = require('@discordjs/util');
|
|
5
|
+
const { Routes } = require('discord-api-types/v10');
|
|
6
|
+
const { CachedManager } = require('./CachedManager.js');
|
|
7
|
+
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
|
|
8
|
+
const { SoundboardSound } = require('../structures/SoundboardSound.js');
|
|
9
|
+
const { resolveBase64, resolveFile } = require('../util/DataResolver.js');
|
|
10
|
+
|
|
11
|
+
const fileTypeMime = lazy(() => require('magic-bytes.js').filetypemime);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Manages API methods for Soundboard Sounds and stores their cache.
|
|
15
|
+
* @extends {CachedManager}
|
|
16
|
+
*/
|
|
17
|
+
class GuildSoundboardSoundManager extends CachedManager {
|
|
18
|
+
constructor(guild, iterable) {
|
|
19
|
+
super(guild.client, SoundboardSound, iterable);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The guild this manager belongs to
|
|
23
|
+
* @type {Guild}
|
|
24
|
+
*/
|
|
25
|
+
this.guild = guild;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The cache of Soundboard Sounds
|
|
30
|
+
* @type {Collection<Snowflake, SoundboardSound>}
|
|
31
|
+
* @name GuildSoundboardSoundManager#cache
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
_add(data, cache) {
|
|
35
|
+
return super._add(data, cache, { extras: [this.guild], id: data.sound_id });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Data that resolves to give a SoundboardSound object. This can be:
|
|
40
|
+
* * A SoundboardSound object
|
|
41
|
+
* * A Snowflake
|
|
42
|
+
* @typedef {SoundboardSound|Snowflake} SoundboardSoundResolvable
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolves a SoundboardSoundResolvable to a SoundboardSound object.
|
|
47
|
+
* @method resolve
|
|
48
|
+
* @memberof GuildSoundboardSoundManager
|
|
49
|
+
* @instance
|
|
50
|
+
* @param {SoundboardSoundResolvable} soundboardSound The SoundboardSound resolvable to identify
|
|
51
|
+
* @returns {?SoundboardSound}
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a {@link SoundboardSoundResolvable} to a {@link SoundboardSound} id.
|
|
56
|
+
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound resolvable to resolve
|
|
57
|
+
* @returns {?Snowflake}
|
|
58
|
+
*/
|
|
59
|
+
resolveId(soundboardSound) {
|
|
60
|
+
if (soundboardSound instanceof this.holds) return soundboardSound.soundId;
|
|
61
|
+
if (typeof soundboardSound === 'string') return soundboardSound;
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Options used to create a soundboard sound in a guild.
|
|
67
|
+
* @typedef {Object} GuildSoundboardSoundCreateOptions
|
|
68
|
+
* @property {BufferResolvable|Stream} file The file for the soundboard sound
|
|
69
|
+
* @property {string} name The name for the soundboard sound
|
|
70
|
+
* @property {string} [contentType] The content type for the soundboard sound file
|
|
71
|
+
* @property {number} [volume] The volume (a double) for the soundboard sound, from 0 (inclusive) to 1. Defaults to 1
|
|
72
|
+
* @property {Snowflake} [emojiId] The emoji id for the soundboard sound
|
|
73
|
+
* @property {string} [emojiName] The emoji name for the soundboard sound
|
|
74
|
+
* @property {string} [reason] The reason for creating the soundboard sound
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new guild soundboard sound.
|
|
79
|
+
* @param {GuildSoundboardSoundCreateOptions} options Options for creating a guild soundboard sound
|
|
80
|
+
* @returns {Promise<SoundboardSound>} The created soundboard sound
|
|
81
|
+
* @example
|
|
82
|
+
* // Create a new soundboard sound from a file on your computer
|
|
83
|
+
* guild.soundboardSounds.create({ file: './sound.mp3', name: 'sound' })
|
|
84
|
+
* .then(sound => console.log(`Created new soundboard sound with name ${sound.name}!`))
|
|
85
|
+
* .catch(console.error);
|
|
86
|
+
*/
|
|
87
|
+
async create({ contentType, emojiId, emojiName, file, name, reason, volume }) {
|
|
88
|
+
const resolvedFile = await resolveFile(file);
|
|
89
|
+
|
|
90
|
+
const resolvedContentType = contentType ?? resolvedFile.contentType ?? fileTypeMime()(resolvedFile.data)[0];
|
|
91
|
+
|
|
92
|
+
const sound = resolveBase64(resolvedFile.data, resolvedContentType);
|
|
93
|
+
|
|
94
|
+
const body = { emoji_id: emojiId, emoji_name: emojiName, name, sound, volume };
|
|
95
|
+
|
|
96
|
+
const soundboardSound = await this.client.rest.post(Routes.guildSoundboardSounds(this.guild.id), {
|
|
97
|
+
body,
|
|
98
|
+
reason,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return this._add(soundboardSound);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Data for editing a soundboard sound.
|
|
106
|
+
* @typedef {Object} GuildSoundboardSoundEditOptions
|
|
107
|
+
* @property {string} [name] The name of the soundboard sound
|
|
108
|
+
* @property {?number} [volume] The volume of the soundboard sound, from 0 to 1
|
|
109
|
+
* @property {?Snowflake} [emojiId] The emoji id of the soundboard sound
|
|
110
|
+
* @property {?string} [emojiName] The emoji name of the soundboard sound
|
|
111
|
+
* @property {string} [reason] The reason for editing the soundboard sound
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Edits a soundboard sound.
|
|
116
|
+
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound to edit
|
|
117
|
+
* @param {GuildSoundboardSoundEditOptions} [options={}] The new data for the soundboard sound
|
|
118
|
+
* @returns {Promise<SoundboardSound>}
|
|
119
|
+
*/
|
|
120
|
+
async edit(soundboardSound, options = {}) {
|
|
121
|
+
const soundId = this.resolveId(soundboardSound);
|
|
122
|
+
|
|
123
|
+
if (!soundId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'soundboardSound', 'SoundboardSoundResolvable');
|
|
124
|
+
|
|
125
|
+
const { emojiId, emojiName, name, reason, volume } = options;
|
|
126
|
+
|
|
127
|
+
const body = { emoji_id: emojiId, emoji_name: emojiName, name, volume };
|
|
128
|
+
|
|
129
|
+
const data = await this.client.rest.patch(Routes.guildSoundboardSound(this.guild.id, soundId), {
|
|
130
|
+
body,
|
|
131
|
+
reason,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const existing = this.cache.get(soundId);
|
|
135
|
+
|
|
136
|
+
if (existing) {
|
|
137
|
+
const clone = existing._clone();
|
|
138
|
+
|
|
139
|
+
clone._patch(data);
|
|
140
|
+
return clone;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return this._add(data);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Deletes a soundboard sound.
|
|
148
|
+
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound to delete
|
|
149
|
+
* @param {string} [reason] Reason for deleting this soundboard sound
|
|
150
|
+
* @returns {Promise<void>}
|
|
151
|
+
*/
|
|
152
|
+
async delete(soundboardSound, reason) {
|
|
153
|
+
const soundId = this.resolveId(soundboardSound);
|
|
154
|
+
|
|
155
|
+
if (!soundId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'soundboardSound', 'SoundboardSoundResolvable');
|
|
156
|
+
|
|
157
|
+
await this.client.rest.delete(Routes.guildSoundboardSound(this.guild.id, soundId), { reason });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Obtains one or more soundboard sounds from Discord, or the soundboard sound cache if they're already available.
|
|
162
|
+
* @param {Snowflake} [id] The soundboard sound's id
|
|
163
|
+
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
|
164
|
+
* @returns {Promise<SoundboardSound|Collection<Snowflake, SoundboardSound>>}
|
|
165
|
+
* @example
|
|
166
|
+
* // Fetch all soundboard sounds from the guild
|
|
167
|
+
* guild.soundboardSounds.fetch()
|
|
168
|
+
* .then(sounds => console.log(`There are ${sounds.size} soundboard sounds.`))
|
|
169
|
+
* .catch(console.error);
|
|
170
|
+
* @example
|
|
171
|
+
* // Fetch a single soundboard sound
|
|
172
|
+
* guild.soundboardSounds.fetch('222078108977594368')
|
|
173
|
+
* .then(sound => console.log(`The soundboard sound name is: ${sound.name}`))
|
|
174
|
+
* .catch(console.error);
|
|
175
|
+
*/
|
|
176
|
+
async fetch(id, { cache = true, force = false } = {}) {
|
|
177
|
+
if (id) {
|
|
178
|
+
if (!force) {
|
|
179
|
+
const existing = this.cache.get(id);
|
|
180
|
+
if (existing) return existing;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const sound = await this.client.rest.get(Routes.guildSoundboardSound(this.guild.id, id));
|
|
184
|
+
return this._add(sound, cache);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const data = await this.client.rest.get(Routes.guildSoundboardSounds(this.guild.id));
|
|
188
|
+
return new Collection(data.map(sound => [sound.sound_id, this._add(sound, cache)]));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
exports.GuildSoundboardSoundManager = GuildSoundboardSoundManager;
|
|
@@ -162,6 +162,18 @@ class ApplicationCommand extends Base {
|
|
|
162
162
|
this.contexts ??= null;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
if ('handler' in data) {
|
|
166
|
+
/**
|
|
167
|
+
* Determines whether the interaction is handled by the app's interactions handler or by Discord.
|
|
168
|
+
* <info>Only available for {@link ApplicationCommandType.PrimaryEntryPoint} commands on
|
|
169
|
+
* applications with the {@link ApplicationFlags.Embedded} flag (i.e, those that have an Activity)</info>
|
|
170
|
+
* @type {?EntryPointCommandHandlerType}
|
|
171
|
+
*/
|
|
172
|
+
this.handler = data.handler;
|
|
173
|
+
} else {
|
|
174
|
+
this.handler ??= null;
|
|
175
|
+
}
|
|
176
|
+
|
|
165
177
|
if ('version' in data) {
|
|
166
178
|
/**
|
|
167
179
|
* Autoincrementing version identifier updated during substantial record changes
|
|
@@ -204,14 +216,19 @@ class ApplicationCommand extends Base {
|
|
|
204
216
|
* @property {string} name The name of the command, must be in all lowercase if type is
|
|
205
217
|
* {@link ApplicationCommandType.ChatInput}
|
|
206
218
|
* @property {Object<Locale, string>} [nameLocalizations] The localizations for the command name
|
|
207
|
-
* @property {string} description The description of the command,
|
|
219
|
+
* @property {string} description The description of the command,
|
|
220
|
+
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
|
208
221
|
* @property {boolean} [nsfw] Whether the command is age-restricted
|
|
209
222
|
* @property {Object<Locale, string>} [descriptionLocalizations] The localizations for the command description,
|
|
210
|
-
* if type is {@link ApplicationCommandType.ChatInput}
|
|
223
|
+
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
|
211
224
|
* @property {ApplicationCommandType} [type=ApplicationCommandType.ChatInput] The type of the command
|
|
212
225
|
* @property {ApplicationCommandOptionData[]} [options] Options for the command
|
|
213
226
|
* @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions
|
|
214
227
|
* a member needs in order to run the command
|
|
228
|
+
* @property {ApplicationIntegrationType[]} [integrationTypes] Installation contexts where the command is available
|
|
229
|
+
* @property {InteractionContextType[]} [contexts] Interaction contexts where the command can be used
|
|
230
|
+
* @property {EntryPointCommandHandlerType} [handler] Whether the interaction is handled by the app's
|
|
231
|
+
* interactions handler or by Discord.
|
|
215
232
|
*/
|
|
216
233
|
|
|
217
234
|
/**
|
|
@@ -395,7 +412,8 @@ class ApplicationCommand extends Base {
|
|
|
395
412
|
this.descriptionLocalizations ?? {},
|
|
396
413
|
) ||
|
|
397
414
|
!isEqual(command.integrationTypes ?? command.integration_types ?? [], this.integrationTypes ?? []) ||
|
|
398
|
-
!isEqual(command.contexts ?? [], this.contexts ?? [])
|
|
415
|
+
!isEqual(command.contexts ?? [], this.contexts ?? []) ||
|
|
416
|
+
('handler' in command && command.handler !== this.handler)
|
|
399
417
|
) {
|
|
400
418
|
return false;
|
|
401
419
|
}
|