mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 02:23:31 +01:00
feat: stage instances (#5749)
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com> Co-authored-by: SpaceEEC <spaceeec@yahoo.com> Co-authored-by: Antonio Román <kyradiscord@gmail.com>
This commit is contained in:
@@ -15,6 +15,7 @@ const GuildEmojiManager = require('../managers/GuildEmojiManager');
|
||||
const GuildMemberManager = require('../managers/GuildMemberManager');
|
||||
const PresenceManager = require('../managers/PresenceManager');
|
||||
const RoleManager = require('../managers/RoleManager');
|
||||
const StageInstanceManager = require('../managers/StageInstanceManager');
|
||||
const VoiceStateManager = require('../managers/VoiceStateManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const {
|
||||
@@ -83,6 +84,12 @@ class Guild extends BaseGuild {
|
||||
*/
|
||||
this.voiceStates = new VoiceStateManager(this);
|
||||
|
||||
/**
|
||||
* A manager of the stage instances of this guild
|
||||
* @type {StageInstanceManager}
|
||||
*/
|
||||
this.stageInstances = new StageInstanceManager(this);
|
||||
|
||||
/**
|
||||
* Whether the bot has been removed from the guild
|
||||
* @type {boolean}
|
||||
@@ -402,6 +409,13 @@ class Guild extends BaseGuild {
|
||||
}
|
||||
}
|
||||
|
||||
if (data.stage_instances) {
|
||||
this.stageInstances.cache.clear();
|
||||
for (const stageInstance of data.stage_instances) {
|
||||
this.stageInstances.add(stageInstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.voice_states) {
|
||||
this.voiceStates.cache.clear();
|
||||
for (const voiceState of data.voice_states) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Integration = require('./Integration');
|
||||
const StageInstance = require('./StageInstance');
|
||||
const Webhook = require('./Webhook');
|
||||
const Collection = require('../util/Collection');
|
||||
const { OverwriteTypes, PartialTypes } = require('../util/Constants');
|
||||
@@ -19,6 +20,7 @@ const Util = require('../util/Util');
|
||||
* * EMOJI
|
||||
* * MESSAGE
|
||||
* * INTEGRATION
|
||||
* * STAGE_INSTANCE
|
||||
* @typedef {string} AuditLogTargetType
|
||||
*/
|
||||
|
||||
@@ -38,6 +40,7 @@ const Targets = {
|
||||
EMOJI: 'EMOJI',
|
||||
MESSAGE: 'MESSAGE',
|
||||
INTEGRATION: 'INTEGRATION',
|
||||
STAGE_INSTANCE: 'STAGE_INSTANCE',
|
||||
UNKNOWN: 'UNKNOWN',
|
||||
};
|
||||
|
||||
@@ -79,6 +82,9 @@ const Targets = {
|
||||
* * INTEGRATION_CREATE: 80
|
||||
* * INTEGRATION_UPDATE: 81
|
||||
* * INTEGRATION_DELETE: 82
|
||||
* * STAGE_INSTANCE_CREATE: 83
|
||||
* * STAGE_INSTANCE_UPDATE: 84
|
||||
* * STAGE_INSTANCE_DELETE: 85
|
||||
* @typedef {?(number|string)} AuditLogAction
|
||||
*/
|
||||
|
||||
@@ -124,6 +130,9 @@ const Actions = {
|
||||
INTEGRATION_CREATE: 80,
|
||||
INTEGRATION_UPDATE: 81,
|
||||
INTEGRATION_DELETE: 82,
|
||||
STAGE_INSTANCE_CREATE: 83,
|
||||
STAGE_INSTANCE_UPDATE: 84,
|
||||
STAGE_INSTANCE_DELETE: 85,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -187,9 +196,11 @@ class GuildAuditLogs {
|
||||
* * An emoji
|
||||
* * A message
|
||||
* * An integration
|
||||
* * A stage instance
|
||||
* * An object with an id key if target was deleted
|
||||
* * An object where the keys represent either the new value or the old value
|
||||
* @typedef {?(Object|Guild|Channel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration)} AuditLogEntryTarget
|
||||
* @typedef {?(Object|Guild|Channel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance)}
|
||||
* AuditLogEntryTarget
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -206,7 +217,8 @@ class GuildAuditLogs {
|
||||
if (target < 60) return Targets.WEBHOOK;
|
||||
if (target < 70) return Targets.EMOJI;
|
||||
if (target < 80) return Targets.MESSAGE;
|
||||
if (target < 90) return Targets.INTEGRATION;
|
||||
if (target < 83) return Targets.INTEGRATION;
|
||||
if (target < 86) return Targets.STAGE_INSTANCE;
|
||||
return Targets.UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -237,6 +249,7 @@ class GuildAuditLogs {
|
||||
Actions.EMOJI_CREATE,
|
||||
Actions.MESSAGE_PIN,
|
||||
Actions.INTEGRATION_CREATE,
|
||||
Actions.STAGE_INSTANCE_CREATE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'CREATE';
|
||||
@@ -258,6 +271,7 @@ class GuildAuditLogs {
|
||||
Actions.MESSAGE_BULK_DELETE,
|
||||
Actions.MESSAGE_UNPIN,
|
||||
Actions.INTEGRATION_DELETE,
|
||||
Actions.STAGE_INSTANCE_DELETE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'DELETE';
|
||||
@@ -276,6 +290,7 @@ class GuildAuditLogs {
|
||||
Actions.WEBHOOK_UPDATE,
|
||||
Actions.EMOJI_UPDATE,
|
||||
Actions.INTEGRATION_UPDATE,
|
||||
Actions.STAGE_INSTANCE_UPDATE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'UPDATE';
|
||||
@@ -366,7 +381,7 @@ class GuildAuditLogsEntry {
|
||||
case Actions.MESSAGE_DELETE:
|
||||
case Actions.MESSAGE_BULK_DELETE:
|
||||
this.extra = {
|
||||
channel: guild.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id },
|
||||
channel: guild.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id },
|
||||
count: Number(data.options.count),
|
||||
};
|
||||
break;
|
||||
@@ -374,7 +389,7 @@ class GuildAuditLogsEntry {
|
||||
case Actions.MESSAGE_PIN:
|
||||
case Actions.MESSAGE_UNPIN:
|
||||
this.extra = {
|
||||
channel: guild.client.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id },
|
||||
channel: guild.client.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id },
|
||||
messageID: data.options.message_id,
|
||||
};
|
||||
break;
|
||||
@@ -390,7 +405,7 @@ class GuildAuditLogsEntry {
|
||||
case Actions.CHANNEL_OVERWRITE_DELETE:
|
||||
switch (Number(data.options.type)) {
|
||||
case OverwriteTypes.role:
|
||||
this.extra = guild.roles.cache.get(data.options.id) || {
|
||||
this.extra = guild.roles.cache.get(data.options.id) ?? {
|
||||
id: data.options.id,
|
||||
name: data.options.role_name,
|
||||
type: OverwriteTypes[OverwriteTypes.role],
|
||||
@@ -398,7 +413,7 @@ class GuildAuditLogsEntry {
|
||||
break;
|
||||
|
||||
case OverwriteTypes.member:
|
||||
this.extra = guild.members.cache.get(data.options.id) || {
|
||||
this.extra = guild.members.cache.get(data.options.id) ?? {
|
||||
id: data.options.id,
|
||||
type: OverwriteTypes[OverwriteTypes.member],
|
||||
};
|
||||
@@ -409,6 +424,14 @@ class GuildAuditLogsEntry {
|
||||
}
|
||||
break;
|
||||
|
||||
case Actions.STAGE_INSTANCE_CREATE:
|
||||
case Actions.STAGE_INSTANCE_DELETE:
|
||||
case Actions.STAGE_INSTANCE_UPDATE:
|
||||
this.extra = {
|
||||
channel: guild.client.channels.cache.get(data.options?.channel_id) ?? { id: data.options?.channel_id },
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -492,6 +515,23 @@ class GuildAuditLogsEntry {
|
||||
},
|
||||
{ id: data.target_id },
|
||||
);
|
||||
} else if (targetType === Targets.STAGE_INSTANCE) {
|
||||
this.target =
|
||||
guild.stageInstances.cache.get(data.target_id) ??
|
||||
new StageInstance(
|
||||
guild.client,
|
||||
this.changes.reduce(
|
||||
(o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
},
|
||||
{
|
||||
id: data.target_id,
|
||||
channel_id: data.options?.channel_id,
|
||||
guild_id: guild.id,
|
||||
},
|
||||
),
|
||||
);
|
||||
} else if (data.target_id) {
|
||||
this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) || { id: data.target_id };
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@ class StageChannel extends BaseGuildVoiceChannel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The instance of this stage channel, if it exists
|
||||
* @type {?StageInstance}
|
||||
* @readonly
|
||||
*/
|
||||
get instance() {
|
||||
return this.guild.stageInstances.cache.find(stageInstance => stageInstance.channelID === this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RTC region of the channel.
|
||||
* @name StageChannel#setRTCRegion
|
||||
|
||||
143
src/structures/StageInstance.js
Normal file
143
src/structures/StageInstance.js
Normal file
@@ -0,0 +1,143 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { PrivacyLevels } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents a stage instance.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class StageInstance extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The ID of this stage instance
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* Whether the stage instance has been deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The guild ID of the associated stage channel
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildID = data.guild_id;
|
||||
|
||||
/**
|
||||
* The ID of the associated stage channel
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.channelID = data.channel_id;
|
||||
|
||||
/**
|
||||
* The topic of the stage instance
|
||||
* @type {string}
|
||||
*/
|
||||
this.topic = data.topic;
|
||||
|
||||
/**
|
||||
* The privacy level of the stage instance
|
||||
* @type {PrivacyLevel}
|
||||
*/
|
||||
this.privacyLevel = PrivacyLevels[data.privacy_level];
|
||||
|
||||
/**
|
||||
* Whether or not stage discovery is disabled
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.discoverableDisabled = data.discoverable_disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stage channel associated with this instance
|
||||
* @type {?StageChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get channel() {
|
||||
return this.client.channels.resolve(this.channelID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this stage instance belongs to
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.resolve(this.guildID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this stage instance.
|
||||
* @param {StageInstanceEditOptions} options The options to edit the stage instance
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Edit a stage instance
|
||||
* stageInstance.edit({ topic: 'new topic' })
|
||||
* .then(stageInstance => console.log(stageInstance))
|
||||
* .catch(console.error)
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.stageInstances.edit(this.channelID, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this stage instance.
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Delete a stage instance
|
||||
* stageInstance.delete()
|
||||
* .then(stageInstance => console.log(stageInstance))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete() {
|
||||
await this.guild.stageInstances.delete(this.channelID);
|
||||
const clone = this._clone();
|
||||
clone.deleted = true;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the topic of this stage instance.
|
||||
* @param {string} topic The topic for the stage instance
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Set topic of a stage instance
|
||||
* stageInstance.setTopic('new topic')
|
||||
* .then(stageInstance => console.log(`Set the topic to: ${stageInstance.topic}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setTopic(topic) {
|
||||
return this.guild.stageInstances.edit(this.channelID, { topic });
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this stage instances was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this stage instance was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StageInstance;
|
||||
Reference in New Issue
Block a user