VoiceState.js (6015B)
1 'use strict'; 2 3 const Base = require('./Base'); 4 const { Error, TypeError } = require('../errors'); 5 const { browser } = require('../util/Constants'); 6 7 /** 8 * Represents the voice state for a Guild Member. 9 */ 10 class VoiceState extends Base { 11 /** 12 * @param {Guild} guild The guild the voice state is part of 13 * @param {Object} data The data for the voice state 14 */ 15 constructor(guild, data) { 16 super(guild.client); 17 /** 18 * The guild of this voice state 19 * @type {Guild} 20 */ 21 this.guild = guild; 22 /** 23 * The ID of the member of this voice state 24 * @type {Snowflake} 25 */ 26 this.id = data.user_id; 27 this._patch(data); 28 } 29 30 _patch(data) { 31 /** 32 * Whether this member is deafened server-wide 33 * @type {?boolean} 34 */ 35 this.serverDeaf = data.deaf; 36 /** 37 * Whether this member is muted server-wide 38 * @type {?boolean} 39 */ 40 this.serverMute = data.mute; 41 /** 42 * Whether this member is self-deafened 43 * @type {?boolean} 44 */ 45 this.selfDeaf = data.self_deaf; 46 /** 47 * Whether this member is self-muted 48 * @type {?boolean} 49 */ 50 this.selfMute = data.self_mute; 51 /** 52 * The session ID of this member's connection 53 * @type {?string} 54 */ 55 this.sessionID = data.session_id; 56 /** 57 * Whether this member is streaming using "Go Live" 58 * @type {boolean} 59 */ 60 this.streaming = data.self_stream || false; 61 /** 62 * The ID of the voice channel that this member is in 63 * @type {?Snowflake} 64 */ 65 this.channelID = data.channel_id; 66 return this; 67 } 68 69 /** 70 * The member that this voice state belongs to 71 * @type {?GuildMember} 72 * @readonly 73 */ 74 get member() { 75 return this.guild.members.cache.get(this.id) || null; 76 } 77 78 /** 79 * The channel that the member is connected to 80 * @type {?VoiceChannel} 81 * @readonly 82 */ 83 get channel() { 84 return this.guild.channels.cache.get(this.channelID) || null; 85 } 86 87 /** 88 * If this is a voice state of the client user, then this will refer to the active VoiceConnection for this guild 89 * @type {?VoiceConnection} 90 * @readonly 91 */ 92 get connection() { 93 if (browser || this.id !== this.client.user.id) return null; 94 return this.client.voice.connections.get(this.guild.id) || null; 95 } 96 97 /** 98 * Whether this member is either self-deafened or server-deafened 99 * @type {?boolean} 100 * @readonly 101 */ 102 get deaf() { 103 return this.serverDeaf || this.selfDeaf; 104 } 105 106 /** 107 * Whether this member is either self-muted or server-muted 108 * @type {?boolean} 109 * @readonly 110 */ 111 get mute() { 112 return this.serverMute || this.selfMute; 113 } 114 115 /** 116 * Whether this member is currently speaking. A boolean if the information is available (aka 117 * the bot is connected to any voice channel in the guild), otherwise this is null 118 * @type {?boolean} 119 * @readonly 120 */ 121 get speaking() { 122 return this.channel && this.channel.connection ? Boolean(this.channel.connection._speaking.get(this.id)) : null; 123 } 124 125 /** 126 * Mutes/unmutes the member of this voice state. 127 * @param {boolean} mute Whether or not the member should be muted 128 * @param {string} [reason] Reason for muting or unmuting 129 * @returns {Promise<GuildMember>} 130 */ 131 setMute(mute, reason) { 132 return this.member ? this.member.edit({ mute }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); 133 } 134 135 /** 136 * Deafens/undeafens the member of this voice state. 137 * @param {boolean} deaf Whether or not the member should be deafened 138 * @param {string} [reason] Reason for deafening or undeafening 139 * @returns {Promise<GuildMember>} 140 */ 141 setDeaf(deaf, reason) { 142 return this.member ? this.member.edit({ deaf }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); 143 } 144 145 /** 146 * Kicks the member from the voice channel. 147 * @param {string} [reason] Reason for kicking member from the channel 148 * @returns {Promise<GuildMember>} 149 */ 150 kick(reason) { 151 return this.setChannel(null, reason); 152 } 153 154 /** 155 * Moves the member to a different channel, or disconnects them from the one they're in. 156 * @param {ChannelResolvable|null} [channel] Channel to move the member to, or `null` if you want to disconnect them 157 * from voice. Requires the `MOVE_MEMBERS` permission. 158 * @param {string} [reason] Reason for moving member to another channel or disconnecting 159 * @returns {Promise<GuildMember>} 160 */ 161 setChannel(channel, reason) { 162 return this.member 163 ? this.member.edit({ channel }, reason) 164 : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); 165 } 166 167 /** 168 * Self-mutes/unmutes the bot for this voice state. 169 * @param {boolean} mute Whether or not the bot should be self-muted 170 * @returns {Promise<boolean>} true if the voice state was successfully updated, otherwise false 171 */ 172 async setSelfMute(mute) { 173 if (this.id !== this.client.user.id) throw new Error('VOICE_STATE_NOT_OWN'); 174 if (typeof mute !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'mute'); 175 if (!this.connection) return false; 176 this.selfMute = mute; 177 await this.connection.sendVoiceStateUpdate(); 178 return true; 179 } 180 181 /** 182 * Self-deafens/undeafens the bot for this voice state. 183 * @param {boolean} deaf Whether or not the bot should be self-deafened 184 * @returns {Promise<boolean>} true if the voice state was successfully updated, otherwise false 185 */ 186 async setSelfDeaf(deaf) { 187 if (this.id !== this.client.user.id) return new Error('VOICE_STATE_NOT_OWN'); 188 if (typeof deaf !== 'boolean') return new TypeError('VOICE_STATE_INVALID_TYPE', 'deaf'); 189 if (!this.connection) return false; 190 this.selfDeaf = deaf; 191 await this.connection.sendVoiceStateUpdate(); 192 return true; 193 } 194 195 toJSON() { 196 return super.toJSON({ 197 id: true, 198 serverDeaf: true, 199 serverMute: true, 200 selfDeaf: true, 201 selfMute: true, 202 sessionID: true, 203 channelID: 'channel', 204 }); 205 } 206 } 207 208 module.exports = VoiceState;