diff --git a/src/features/core/internal/Voice/internal/Voice.class.ts b/src/features/core/internal/Voice/internal/Voice.class.ts index 1f7b8f01..b40ebab4 100644 --- a/src/features/core/internal/Voice/internal/Voice.class.ts +++ b/src/features/core/internal/Voice/internal/Voice.class.ts @@ -1,7 +1,6 @@ import type { VoiceConnection, ChatInputCommandInteraction, - InteractionReplyOptions, VoiceBasedChannel, } from '@/features/library/index.js'; import { @@ -9,6 +8,7 @@ import { isNil, joinVoiceChannel, } from '@/features/library/index.js'; +import { LogicException } from '@/features/others/Error/LogicException.js'; import { getInteractionMemberId } from '@/features/others/discord/index.js'; import { JOINABLE_TYPE_MAP } from './Voice.constants.js'; @@ -24,26 +24,55 @@ export class Voice { }: { interaction: Readonly; }) { - const member = await getInteractionMemberId(interaction); - const checkJoinableResult = this.checkJoinable({ - channel: member.voice.channel, + const { + voice: { channel }, + } = await getInteractionMemberId(interaction); + const joinable = this.checkJoinable({ + channel, }); - if (checkJoinableResult.joinableType !== JOINABLE_TYPE_MAP.JOINABLE) - return false; + switch (joinable) { + case JOINABLE_TYPE_MAP.NOT_FOUND: + interaction.reply({ + content: '接続先のVCが見つかりません。', + ephemeral: false, + }); + return false; - const connection = joinVoiceChannel({ - channelId: checkJoinableResult.channel.id, - guildId: checkJoinableResult.channel.guild.id, - adapterCreator: checkJoinableResult.channel.guild.voiceAdapterCreator, - }); + case JOINABLE_TYPE_MAP.NOT_JOINABLE: + interaction.reply({ + content: '接続先のVCに参加できません。権限の見直しをしてください。', + ephemeral: true, + }); + return false; - this.#connection.push({ - guildId: checkJoinableResult.channel.guild.id, - connection, - }); + case JOINABLE_TYPE_MAP.NOT_VIEWABLE: + interaction.reply({ + content: '接続先のVCに参加できません。権限の見直しをしてください。', + ephemeral: true, + }); + return false; - return true; + case JOINABLE_TYPE_MAP.JOINABLE: + if (isNil(channel)) + throw new LogicException( + 'Channel is null. Please check checkJoinable()' + ); + const connection = joinVoiceChannel({ + channelId: channel.id, + guildId: channel.guild.id, + adapterCreator: channel.guild.voiceAdapterCreator, + }); + + this.#connection.push({ + guildId: channel.guild.id, + connection, + }); + return true; + + default: + throw new LogicException('Unknown joinable type.'); + } } public async leave({ @@ -76,37 +105,19 @@ export class Voice { } } - checkJoinable({ channel }: { channel: VoiceBasedChannel | null }): - | (Pick & { - joinableType: Exclude< - (typeof JOINABLE_TYPE_MAP)[keyof typeof JOINABLE_TYPE_MAP], - typeof JOINABLE_TYPE_MAP.JOINABLE - >; - }) - | { - joinableType: typeof JOINABLE_TYPE_MAP.JOINABLE; - channel: VoiceBasedChannel; - } { + checkJoinable({ + channel, + }: { + channel: VoiceBasedChannel | null; + }): (typeof JOINABLE_TYPE_MAP)[keyof typeof JOINABLE_TYPE_MAP] { if (isNil(channel)) { - return { - joinableType: JOINABLE_TYPE_MAP.NOT_FOUND, - content: '接続先のVCが見つかりません。', - ephemeral: false, - }; + return JOINABLE_TYPE_MAP.NOT_FOUND; } else if (!channel.joinable) { - return { - joinableType: JOINABLE_TYPE_MAP.NOT_JOINABLE, - content: '接続先のVCに参加できません。権限の見直しをしてください。', - ephemeral: true, - }; + return JOINABLE_TYPE_MAP.NOT_JOINABLE; } else if (!channel.viewable) { - return { - joinableType: JOINABLE_TYPE_MAP.NOT_VIEWABLE, - content: '接続先のVCに参加できません。権限の見直しをしてください。', - ephemeral: true, - }; + return JOINABLE_TYPE_MAP.NOT_VIEWABLE; } else { - return { joinableType: JOINABLE_TYPE_MAP.JOINABLE, channel }; + return JOINABLE_TYPE_MAP.JOINABLE; } } }