From 51b1d71e9a9053372191a0751017c0ca13eea8e2 Mon Sep 17 00:00:00 2001 From: Helloyunho Date: Wed, 31 Mar 2021 02:18:24 +0900 Subject: [PATCH] :sparkles: Add guild channel voice states manager --- src/managers/guildChannelVoiceStates.ts | 39 +++++++++++++++++++++++++ src/structures/guildVoiceChannel.ts | 6 ++++ src/test/cmds/kickFromSpecificVoice.ts | 28 ++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/managers/guildChannelVoiceStates.ts create mode 100644 src/test/cmds/kickFromSpecificVoice.ts diff --git a/src/managers/guildChannelVoiceStates.ts b/src/managers/guildChannelVoiceStates.ts new file mode 100644 index 0000000..2dc9ac5 --- /dev/null +++ b/src/managers/guildChannelVoiceStates.ts @@ -0,0 +1,39 @@ +import { Client } from '../models/client.ts' +import { BaseChildManager } from './baseChild.ts' +import { VoiceStatePayload } from '../types/voice.ts' +import { VoiceState } from '../structures/voiceState.ts' +import { GuildVoiceStatesManager } from './guildVoiceStates.ts' +import { VoiceChannel } from '../structures/guildVoiceChannel.ts' + +export class GuildChannelVoiceStatesManager extends BaseChildManager< + VoiceStatePayload, + VoiceState +> { + channel: VoiceChannel + + constructor( + client: Client, + parent: GuildVoiceStatesManager, + channel: VoiceChannel + ) { + super(client, parent as any) + this.channel = channel + } + + async get(id: string): Promise { + const res = await this.parent.get(id) + if (res !== undefined && res.channel?.id === this.channel.id) return res + else return undefined + } + + async array(): Promise { + const arr = (await this.parent.array()) as VoiceState[] + return arr.filter((c: any) => c.channel?.id === this.channel.id) as any + } + + async fromPayload(d: VoiceStatePayload[]): Promise { + for (const data of d) { + await this.set(data.user_id, data) + } + } +} diff --git a/src/structures/guildVoiceChannel.ts b/src/structures/guildVoiceChannel.ts index d1dc287..0f2764a 100644 --- a/src/structures/guildVoiceChannel.ts +++ b/src/structures/guildVoiceChannel.ts @@ -10,6 +10,7 @@ import { CHANNEL } from '../types/endpoint.ts' import { GuildChannel } from './channel.ts' import { Guild } from './guild.ts' import { VoiceState } from './voiceState.ts' +import { GuildChannelVoiceStatesManager } from '../managers/guildChannelVoiceStates.ts' export interface VoiceServerData extends VoiceServerUpdateData { sessionID: string @@ -18,6 +19,11 @@ export interface VoiceServerData extends VoiceServerUpdateData { export class VoiceChannel extends GuildChannel { bitrate: string userLimit: number + voiceStates = new GuildChannelVoiceStatesManager( + this.client, + this.guild.voiceStates, + this + ) constructor(client: Client, data: GuildVoiceChannelPayload, guild: Guild) { super(client, data, guild) diff --git a/src/test/cmds/kickFromSpecificVoice.ts b/src/test/cmds/kickFromSpecificVoice.ts new file mode 100644 index 0000000..5fb8499 --- /dev/null +++ b/src/test/cmds/kickFromSpecificVoice.ts @@ -0,0 +1,28 @@ +import { Command, VoiceChannel } from '../../../mod.ts' +import { CommandContext } from '../../models/command.ts' +import { ChannelTypes } from '../../types/channel.ts' + +export default class KickFromSpecificVoiceCommand extends Command { + name = 'kickFromSpecificVoice' + + async execute(ctx: CommandContext): Promise { + if (ctx.guild !== undefined) { + const channel = await ctx.guild.channels.get('YOUR VOICE CHANNEL ID') + if (channel === undefined || channel.type !== ChannelTypes.GUILD_VOICE) { + ctx.channel.send('The channel is either not a voice or not available.') + return + } + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const voiceStates = await (channel as VoiceChannel).voiceStates.array() + if (voiceStates !== undefined) { + voiceStates.forEach(async (voiceState) => { + const member = await voiceState.disconnect() + if (member !== undefined) { + ctx.channel.send(`Kicked member ${member.id}`) + } + }) + } + } + } +}