From ac2099ad174a28fd68b2fb256bf91c378dc24808 Mon Sep 17 00:00:00 2001 From: "ryzenbeast\\Ioannis Tsiakkas" Date: Tue, 5 Nov 2024 20:18:25 +0200 Subject: [PATCH] Fix voice joining and other commands --- package-lock.json | 31 ++++- package.json | 1 + src/app.ts | 3 +- src/blueprints/attribute.blueprint.ts | 4 +- src/commands/auth/delete_messages.ts | 4 +- src/commands/auth/invite.ts | 10 +- src/commands/auth/url.ts | 141 ++++++++--------------- src/commands/noAuth/join.ts | 24 +++- src/commands/noAuth/leave.ts | 20 ++-- src/events/voiceStateUpdate.event.ts | 24 ++-- src/handlers/event.handler.ts | 1 + src/handlers/mongo.handler.ts | 5 +- src/libraries/adapter.library.ts | 4 +- src/libraries/help.library.ts | 49 ++++---- src/libraries/localisation.library.ts | 115 ++++++++++++------ src/libraries/mongo.library.ts | 2 +- src/types/classes/PVoiceChannel.class.ts | 5 +- 17 files changed, 241 insertions(+), 202 deletions(-) diff --git a/package-lock.json b/package-lock.json index 750159df..6cf79fe4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "portal", - "version": "0.4.0", + "version": "0.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "portal", - "version": "0.4.0", + "version": "0.7.0", "dependencies": { "@discordjs/opus": "0.9.0", "@discordjs/voice": "0.17.0", @@ -20,6 +20,7 @@ "eslint-config-prettier": "9.1.0", "ffmpeg-static": "5.2.0", "jsonfile": "6.1.0", + "libsodium-wrappers": "^0.7.15", "lodash": "4.17.21", "mongoose": "8.8.0", "optionator": "0.9.4", @@ -5267,6 +5268,19 @@ "node": ">= 0.8.0" } }, + "node_modules/libsodium": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.15.tgz", + "integrity": "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz", + "integrity": "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==", + "dependencies": { + "libsodium": "^0.7.15" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -11838,6 +11852,19 @@ "type-check": "~0.4.0" } }, + "libsodium": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.15.tgz", + "integrity": "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==" + }, + "libsodium-wrappers": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz", + "integrity": "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==", + "requires": { + "libsodium": "^0.7.15" + } + }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", diff --git a/package.json b/package.json index ad2f4b8b..de97f260 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "eslint-config-prettier": "9.1.0", "ffmpeg-static": "5.2.0", "jsonfile": "6.1.0", + "libsodium-wrappers": "^0.7.15", "lodash": "4.17.21", "mongoose": "8.8.0", "optionator": "0.9.4", diff --git a/src/app.ts b/src/app.ts index 4047e035..7b55ca1e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -3,13 +3,14 @@ import { Routes } from 'discord-api-types/v9'; import { Client } from 'discord.js'; import dotenv from 'dotenv'; import { transports } from 'winston'; + import * as auth from './commands/auth'; import * as noAuth from './commands/noAuth'; import { clientHandler, connectToDiscord } from './handlers/discord.handler'; import { eventHandler } from './handlers/event.handler'; import { mongoHandler } from './handlers/mongo.handler'; -import logger from './utilities/log.utility'; import { ActiveCooldowns } from './types/classes/PTypes.interface'; +import logger from './utilities/log.utility'; dotenv.config(); diff --git a/src/blueprints/attribute.blueprint.ts b/src/blueprints/attribute.blueprint.ts index 4114cd8b..8085ac78 100644 --- a/src/blueprints/attribute.blueprint.ts +++ b/src/blueprints/attribute.blueprint.ts @@ -41,7 +41,7 @@ async function updateVoiceChannelAttribute(pGuildId: PGuild['id'], pChannelId: P return getResponse(response, category, attribute, value); } -async function updateGuildAttribute(pGuildId: PGuild['id'], category: string[], attribute: string, value: string | number) { +async function updateGuildAttribute(pGuildId: PGuild['id'], category: string[], attribute: keyof PGuild, value: string | number) { const response = await updateGuild(pGuildId, attribute, value); return getResponse(response, category, attribute, value); @@ -53,8 +53,6 @@ async function updateMemberAttribute(pGuildId: PGuild['id'], pMemberId: PMember[ return getResponse(response, category, attribute, value); } -// - export const AttributeBlueprints: Blueprint[] = [ { name: 'p.annAnnounce', diff --git a/src/commands/auth/delete_messages.ts b/src/commands/auth/delete_messages.ts index 972f83a1..3d965ab2 100644 --- a/src/commands/auth/delete_messages.ts +++ b/src/commands/auth/delete_messages.ts @@ -46,7 +46,7 @@ export = { }; } - const result = askForApproval( + const result = await askForApproval( interaction, `*${interaction.user}, are you sure you want to delete **${bulkDeleteLength}** messages*?`, ButtonStyle.Success @@ -59,7 +59,7 @@ export = { }; } - const messages = await (interaction.channel).bulkDelete(bulkDeleteLength); + const messages = await (interaction.channel).bulkDelete(bulkDeleteLength + 1); if (!messages) { return { diff --git a/src/commands/auth/invite.ts b/src/commands/auth/invite.ts index 0f2d724a..5e461562 100644 --- a/src/commands/auth/invite.ts +++ b/src/commands/auth/invite.ts @@ -20,27 +20,27 @@ export = { option .setName('temporary') .setDescription('should invite be temporary') - .setRequired(true)) + .setRequired(false)) .addNumberOption(option => option .setName('max_age') .setDescription('what the maximum age of the invitee shall be') - .setRequired(true)) + .setRequired(false)) .addNumberOption(option => option .setName('max_uses') .setDescription('maximum usages') - .setRequired(true)) + .setRequired(false)) .addBooleanOption(option => option .setName('unique') .setDescription('should invite be unique') - .setRequired(true)) + .setRequired(false)) .addStringOption(option => option .setName('reason') .setDescription('the reason for the invite') - .setRequired(true)) + .setRequired(false)) .setContexts(InteractionContextType.Guild), async execute(interaction: ChatInputCommandInteraction): Promise { const member = interaction.member as GuildMember; diff --git a/src/commands/auth/url.ts b/src/commands/auth/url.ts index 93631575..3d530f5d 100644 --- a/src/commands/auth/url.ts +++ b/src/commands/auth/url.ts @@ -1,5 +1,11 @@ import { SlashCommandBuilder } from '@discordjs/builders'; +import { ChatInputCommandInteraction, InteractionContextType, NewsChannel } from 'discord.js'; + +import { doesChannelHaveUsage } from '../../libraries/guild.library'; +import { messageHelp } from '../../libraries/help.library'; +import { insertURL } from '../../libraries/mongo.library'; import { Command } from '../../types/Command'; +import { PGuild } from '../../types/classes/PGuild.class'; import { ReturnPromise, ScopeLimit } from '../../types/classes/PTypes.interface'; const COMMAND_NAME = 'url'; @@ -13,105 +19,52 @@ export = { scopeLimit: ScopeLimit.NONE, slashCommand: new SlashCommandBuilder() .setName(COMMAND_NAME) - .setDescription(DESCRIPTION), - async execute(/* interaction: ChatInputCommandInteraction, pGuild: PGuild */): Promise { - return { - result: false, - value: 'not yet implemented', - }; + .setDescription(DESCRIPTION) + .addChannelOption((option) => + option + .setName('url_channel') + .setDescription('the channel you want to make the url channel') + .setRequired(true)) + .setContexts(InteractionContextType.Guild), + async execute(interaction: ChatInputCommandInteraction, pGuild: PGuild): Promise { + const urlChannel = interaction.options.getChannel('url_channel'); - // if (!interaction.guild) { - // return { - // result: false, - // value: 'guild could not be fetched', - // }; - // } + if (!urlChannel) { + return { + result: false, + value: messageHelp('commands', 'url'), + }; + } - // if (!interaction.channel) { - // return { - // result: false, - // value: 'channel could not be fetched', - // }; - // } + if (!(urlChannel instanceof NewsChannel)) { + return { + result: false, + value: messageHelp('commands', 'url', 'channel must be news channel'), + }; + } - // if (args.length === 0) { - // if (isUrlOnlyChannel(interaction.channel.id, pGuild)) { - // removeURL(pGuild.id, interaction.channel.id) - // .then((r: boolean) => { - // return { - // result: r, - // value: r ? 'successfully removed url channel' : 'failed to remove url channel', - // }; - // }) - // .catch((e: string) => { - // return { - // result: false, - // value: `failed to remove url channel: ${e}`, - // }; - // }); - // } else if (isAnnouncementChannel(interaction.channel.id, pGuild)) { - // return { - // result: false, - // value: "this can't be set as a URL channel for it is the Announcement channel", - // }; - // } else if (isMusicChannel(interaction.channel.id, pGuild)) { - // return { - // result: true, - // value: "this can't be set as a URL channel for it is the Music channel", - // }; - // } else { - // insertURL(pGuild.id, interaction.channel.id) - // .then((r) => { - // return { - // result: r, - // value: r ? 'set as an url channel successfully' : 'failed to set as an url channel', - // }; - // }) - // .catch((e) => { - // return { - // result: false, - // value: `failed to set as an url channel: ${e}`, - // }; - // }); - // } - // } else if (args.length > 0) { - // let urlChannel: string = args.join(' ').substring(0, args.join(' ').indexOf('|') - 1); - // let urlCategory: string | null = args.join(' ').substring(args.join(' ').indexOf('|')); + if (!urlChannel.isTextBased()) { + return { + result: false, + value: messageHelp('commands', 'url', 'channel must be text channel'), + }; + } - // if (urlChannel === '' && urlCategory !== '') { - // urlChannel = urlCategory; - // urlCategory = null; - // } + const channelHasUsage = await doesChannelHaveUsage(urlChannel.id, pGuild); + if (channelHasUsage.result) { + return { + result: false, + value: channelHasUsage.value, + }; + } - // const urlOptions = getOptions(interaction.guild, 'url only channel'); + const response = await insertURL(pGuild.id, urlChannel.id); - // createChannel(interaction.guild, urlChannel, urlOptions, urlCategory) - // .then((rCreate) => { - // insertURL(pGuild.id, rCreate) - // .then((rUrl) => { - // return { - // result: rUrl, - // value: rUrl ? 'created url channel and category successfully' : 'failed to create a url channel', - // }; - // }) - // .catch((e) => { - // return { - // result: false, - // value: `failed to create a url channel: ${e}`, - // }; - // }); - // }) - // .catch((e) => { - // return { - // result: false, - // value: `failed to create a url channel: ${e}`, - // }; - // }); - // } - - // return { - // result: false, - // value: messageHelp('commands', 'url'), - // }; + return { + result: response, + value: response + ? 'new url channel set successfully' + : 'failed to set new url channel', + }; }, } as Command; diff --git a/src/commands/noAuth/join.ts b/src/commands/noAuth/join.ts index d6734b17..1de19907 100644 --- a/src/commands/noAuth/join.ts +++ b/src/commands/noAuth/join.ts @@ -1,9 +1,12 @@ import { SlashCommandBuilder } from '@discordjs/builders'; -import { ChatInputCommandInteraction, Client } from 'discord.js'; +import { ChatInputCommandInteraction } from 'discord.js'; +import logger from '../../utilities/log.utility'; + import { joinUserVoiceChannelByInteraction, messageHelp } from '../../libraries/help.library'; +import { clientTalk } from '../../libraries/localisation.library'; import { Command } from '../../types/Command'; import { PGuild } from '../../types/classes/PGuild.class'; -import { ReturnPromise, ScopeLimit } from '../../types/classes/PTypes.interface'; +import { AnnouncementAction, ReturnPromise, ScopeLimit } from '../../types/classes/PTypes.interface'; const COMMAND_NAME = 'join'; const DESCRIPTION = 'makes portal join your voice channel' @@ -17,18 +20,29 @@ export = { slashCommand: new SlashCommandBuilder() .setName(COMMAND_NAME) .setDescription(DESCRIPTION), - async execute(interaction: ChatInputCommandInteraction, pGuild: PGuild, client: Client): Promise { + async execute(interaction: ChatInputCommandInteraction, pGuild: PGuild): Promise { try { - await joinUserVoiceChannelByInteraction(client, interaction, pGuild /*, true*/); + const voiceChannel = await joinUserVoiceChannelByInteraction(interaction, pGuild); + + if(!voiceChannel) { + return { + result: false, + value: 'failed to join voice channel', + }; + } + + clientTalk(interaction, pGuild, AnnouncementAction.join); return { result: true, value: 'successfully joined voice channel', }; }catch (error) { + logger.error(`commands.join.error: ${error}`); + return { result: false, - value: messageHelp('commands', 'join', String(error)), + value: messageHelp('commands', 'join', 'failed to join voice channel'), }; } }, diff --git a/src/commands/noAuth/leave.ts b/src/commands/noAuth/leave.ts index 92fa3aed..e1316c6e 100644 --- a/src/commands/noAuth/leave.ts +++ b/src/commands/noAuth/leave.ts @@ -1,7 +1,7 @@ import { SlashCommandBuilder } from '@discordjs/builders'; -import { getVoiceConnection } from '@discordjs/voice'; +import { getVoiceConnection, VoiceConnectionStatus } from '@discordjs/voice'; import { ChatInputCommandInteraction } from 'discord.js'; -import { clientWrite } from '../../libraries/localisation.library'; +import { clientTalk, clientWrite } from '../../libraries/localisation.library'; import { Command } from '../../types/Command'; import { PGuild } from '../../types/classes/PGuild.class'; import { AnnouncementAction, ReturnPromise, ScopeLimit } from '../../types/classes/PTypes.interface'; @@ -35,20 +35,18 @@ export = { }; } - if (!voiceConnection.disconnect()) { + if (voiceConnection.state.status !== VoiceConnectionStatus.Ready) { + // await voiceConnection.destroy(); return { result: false, - value: 'failed to disconnect from voice channel', + value: 'failed to destroy voice connection', }; } - // clientTalk(client, pGuild, 'leave'); - // setTimeout( - // function () { - // voiceConnection.disconnect(); - // }, - // 4000 - // ); + clientTalk(interaction, pGuild, AnnouncementAction.leave); + setTimeout(function () { + voiceConnection.disconnect(); + }, 4000); return { result: true, diff --git a/src/events/voiceStateUpdate.event.ts b/src/events/voiceStateUpdate.event.ts index d4c8032f..6184f364 100644 --- a/src/events/voiceStateUpdate.event.ts +++ b/src/events/voiceStateUpdate.event.ts @@ -79,21 +79,21 @@ export default async function (args: { client: Client; newState: VoiceState; old } // if (args.client.voice && args.newState.member) { - // const newVoiceConnection = args.client.voice.connections - // .find((connection: VoiceConnection) => - // !!newChannel && connection.channel.id === newChannel.id); + // const newVoiceConnection = args.client.voice.connections + // .find((connection: VoiceConnection) => + // !!newChannel && connection.channel.id === newChannel.id); - // if (newVoiceConnection && !args.newState.member.user.bot) { - // clientTalk(args.client, pGuild, 'userConnected'); - // } + // if (newVoiceConnection && !args.newState.member.user.bot) { + // clientTalk(args.client, pGuild, 'userConnected'); + // } - // const oldVoiceConnection = args.client.voice.connections - // .find((connection: VoiceConnection) => - // !!oldChannel && connection.channel.id === oldChannel.id); + // const oldVoiceConnection = args.client.voice.connections + // .find((connection: VoiceConnection) => + // !!oldChannel && connection.channel.id === oldChannel.id); - // if (oldVoiceConnection && !args.newState.member.user.bot) { - // clientTalk(args.client, pGuild, 'userDisconnected'); - // } + // if (oldVoiceConnection && !args.newState.member.user.bot) { + // clientTalk(args.client, pGuild, 'userDisconnected'); + // } // } if (!oldChannel) { diff --git a/src/handlers/event.handler.ts b/src/handlers/event.handler.ts index 366d6ff0..9778b00a 100644 --- a/src/handlers/event.handler.ts +++ b/src/handlers/event.handler.ts @@ -1,4 +1,5 @@ import { Channel, ChannelType, ChatInputCommandInteraction, Client, EmbedBuilder, Guild, GuildMember, Message, MessageReaction, PartialDMChannel, PartialGuildMember, PartialMessage, PartialMessageReaction, PartialUser, User, VoiceState } from 'discord.js'; + import * as EventFunctions from '../events'; import { isUserAuthorised } from '../libraries/help.library'; import { fetchGuildPreData, fetchGuildRest, insertMember } from '../libraries/mongo.library'; diff --git a/src/handlers/mongo.handler.ts b/src/handlers/mongo.handler.ts index 8f9531a5..4b8e116d 100644 --- a/src/handlers/mongo.handler.ts +++ b/src/handlers/mongo.handler.ts @@ -1,4 +1,4 @@ -import mongoose from 'mongoose'; +import mongoose, { ConnectOptions } from 'mongoose'; import logger from '../utilities/log.utility'; export async function mongoHandler(mongoUrl: string) { @@ -10,12 +10,11 @@ export async function mongoHandler(mongoUrl: string) { logger.info('connected to mongo', { service: 'mongse' }); }); - const connectOptions = { + const connectOptions: ConnectOptions = { dbName: 'portal', compressors: 'zlib', maxPoolSize: 50, wtimeoutMS: 2500, - useNewUrlParser: true, }; // { // dbName: 'portal', diff --git a/src/libraries/adapter.library.ts b/src/libraries/adapter.library.ts index 860c6a06..879e1a95 100644 --- a/src/libraries/adapter.library.ts +++ b/src/libraries/adapter.library.ts @@ -1,6 +1,6 @@ import { DiscordGatewayAdapterCreator, DiscordGatewayAdapterLibraryMethods } from '@discordjs/voice'; // import { GatewayVoiceServerUpdateDispatchData } from 'discord-api-types/v9'; -import { Client, Events, GatewayDispatchEvents, Guild, Snowflake, Status, VoiceChannel } from 'discord.js'; +import { Client, Events, GatewayDispatchEvents, Guild, Snowflake, Status, VoiceBasedChannel, VoiceChannel } from 'discord.js'; const adapters = new Map(); const trackedClients = new Set(); @@ -48,7 +48,7 @@ function trackGuild(guild: Guild) { * * @param channel - The channel to create the adapter for */ -export function createDiscordJSAdapter(channel: VoiceChannel): DiscordGatewayAdapterCreator { +export function createDiscordJSAdapter(channel: VoiceBasedChannel): DiscordGatewayAdapterCreator { return (methods) => { adapters.set(channel.guild.id, methods); trackClient(channel.client); diff --git a/src/libraries/help.library.ts b/src/libraries/help.library.ts index c1f94e86..efc84928 100644 --- a/src/libraries/help.library.ts +++ b/src/libraries/help.library.ts @@ -7,7 +7,6 @@ import { ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, - Client, Collection, ColorResolvable, EmbedAuthorOptions, @@ -19,8 +18,7 @@ import { MessageComponentInteraction, PermissionResolvable, TextBasedChannel, - TextChannel, - VoiceChannel + TextChannel } from 'discord.js'; import { VideoSearchResult } from 'yt-search'; @@ -320,54 +318,55 @@ export async function updateMusicLyricsMessage(guild: Guild, pGuild: PGuild, lyr } export async function joinUserVoiceChannelByInteraction( - client: Client, interaction: ChatInputCommandInteraction, pGuild: PGuild ): Promise { - const member = interaction.member as GuildMember; + const member = interaction.member; if (!member) { - throw('user could not be fetched for message'); + return undefined; // throw('user could not be fetched for message'); } - if (!member.voice) { - throw('voice could not be fetched for member'); + if (!(member instanceof GuildMember)) { + return undefined; // throw('member is not a guild member instance'); } - if (!member.voice.channel) { - throw('you aren\'t in a voice channel'); + if (!member.voice) { + return undefined; // throw('voice could not be fetched for member'); } - if (!interaction.guild) { - throw('guild could not be fetched for message'); + const voiceChannel = member.voice.channel; + if (!voiceChannel) { + return undefined; // throw('you aren\'t in a voice channel'); } - if (!interaction.guild.voiceAdapterCreator) { - throw('voiceAdapterCreator could not be fetched for guild'); + const guild = interaction.guild; + if (!guild) { + return undefined; // throw('guild could not be fetched for message'); } - if (!pGuild) { - throw('could not find guild of message'); + if (!guild.voiceAdapterCreator) { + return undefined; // throw('voiceAdapterCreator could not be fetched for guild'); } - if (!client.voice) { - throw('could not fetch portal\'s voice connections'); + if (!pGuild) { + return undefined; // throw('could not find guild of message'); } - let voiceConnection = getVoiceConnection(member.voice.channel.id); - const clientVoiceState = interaction.guild.voiceStates.cache.get(interaction.guild.client.user.id); + let voiceConnection = getVoiceConnection(voiceChannel.id); + const clientVoiceState = guild.voiceStates.cache.get(guild.client.user.id); - if (voiceConnection && clientVoiceState?.channelId === member.voice.channel?.id) { + if (voiceConnection && clientVoiceState?.channelId === voiceChannel?.id) { clientVoiceState.setDeaf(true); } else { voiceConnection = joinVoiceChannel({ - channelId: member.voice.channel.id, - guildId: interaction.guild.id, - adapterCreator: createDiscordJSAdapter(member.voice.channel as VoiceChannel), + channelId: voiceChannel.id, + guildId: guild.id, + adapterCreator: createDiscordJSAdapter(voiceChannel), }); if (!voiceConnection) { - throw('could not join voice channel'); + return undefined; // throw('could not join voice channel'); } if (clientVoiceState) { diff --git a/src/libraries/localisation.library.ts b/src/libraries/localisation.library.ts index a4251c43..252b65d7 100644 --- a/src/libraries/localisation.library.ts +++ b/src/libraries/localisation.library.ts @@ -1,3 +1,4 @@ +import { createAudioPlayer, createAudioResource, getVoiceConnection } from '@discordjs/voice'; import { ChatInputCommandInteraction, GuildMember, User } from 'discord.js'; import { PGuild } from '../types/classes/PGuild.class'; import { @@ -12,6 +13,7 @@ import { StatusArguments } from '../types/classes/PTypes.interface'; import { Locale } from '../types/enums/Locales.enum'; +import logger from '../utilities/log.utility'; export const portal: LocalisationPortalOption[] = [ { @@ -228,40 +230,85 @@ export const consoleText: LocalisationConsoleOption[] = [ }, ]; -// export function clientTalk( -// client: Client, pGuild: GuildPrtl, context: string -// ): boolean { -// const voiceConnection = client?.voice?.connections -// .find(connection => connection.channel.guild.id === pGuild.id); - -// if (voiceConnection) { -// if (!voiceConnection.dispatcher) { -// return pGuild.portalList.some(p => -// p.voiceList.some(v => { - -// if (typeOfAnnouncement.includes(context) && v.annAnnounce) { -// const locale = v.locale; -// const random = Math.floor(Math.random() * Math.floor(3)); - -// voiceConnection.play(`src/assets/mp3s/${locale}/${context}/${context}${random}.mp3`); -// return true; -// } -// else if (typeOfAction.includes(context) && v.annUser) { -// const locale = v.locale; -// const random = Math.floor(Math.random() * Math.floor(3)); - -// voiceConnection.play(`src/assets/mp3s/${locale}/${context}/${context}${random}.mp3`); -// return true; -// } - -// return v.id === voiceConnection.channel.id; -// }) -// ); -// } -// } - -// return false; -// } +function isAnnouncementAction(value: AnnouncementAction | string): value is AnnouncementAction { + return Object.values(AnnouncementAction).includes(value); +} + +function isEventAction(value: EventAction | string): value is EventAction { + return Object.values(EventAction).includes(value); +} + +export function clientTalk( + interaction: ChatInputCommandInteraction, + pGuild: PGuild, + context: AnnouncementAction | EventAction +): boolean { + if (!interaction.guild) { + return false; + } + + const voiceConnection = getVoiceConnection(interaction.guild.id); + + if (!voiceConnection) { + return false; + } + + const player = createAudioPlayer(); + + const localeToString: Record = { + [Locale.gr]: 'gr', + [Locale.en]: 'en', + [Locale.de]: 'de', + }; + + const AnnouncementActionToString: Record = { + [AnnouncementAction.fail]: 'fail', + [AnnouncementAction.announce]: 'announce', + [AnnouncementAction.spotify]: 'spotify', + [AnnouncementAction.url]: 'url', + [AnnouncementAction.readOnly]: 'readOnly', + [AnnouncementAction.join]: 'join', + [AnnouncementAction.leave]: 'leave', + }; + + const EventActionToString: Record = { + [EventAction.userConnected]: 'user_connected', + [EventAction.userDisconnected]: 'user_disconnected', + }; + + for (const p of pGuild.pChannels) { + for (const v of p.pVoiceChannels) { + if (isAnnouncementAction(context.toString())&& !isEventAction(context.toString()) && v.annAnnounce) { + const locale = localeToString[v.locale]; + const contextAsAction = AnnouncementActionToString[context]; + const random = Math.floor(Math.random() * 3); + + const resource = createAudioResource(`src/assets/mp3s/${locale}/${contextAsAction}/${contextAsAction}${random}.mp3`); + logger.info(`src/assets/mp3s/${locale}/${contextAsAction}/${contextAsAction}${random}.mp3, ${!!resource}`); + + player.play(resource); + voiceConnection.subscribe(player); + + return true; + } else if (!isAnnouncementAction(context.toString()) && isEventAction(context.toString()) && v.annUser) { + const locale = localeToString[v.locale]; + const contextAsAction = EventActionToString[context as EventAction]; + + const random = Math.floor(Math.random() * 3); + + const resource = createAudioResource(`src/assets/mp3s/${locale}/${contextAsAction}/${contextAsAction}${random}.mp3`); + logger.info(`src/assets/mp3s/${locale}/${contextAsAction}/${contextAsAction}${random}.mp3, ${!!resource}`); + + player.play(resource); + voiceConnection.subscribe(player); + + return true; + } + } + } + + return false; +} export function getFunction(output: string, locale: number, context: EventAction | AnnouncementAction | LogActions) { let func; diff --git a/src/libraries/mongo.library.ts b/src/libraries/mongo.library.ts index 35cc1c57..35675db2 100644 --- a/src/libraries/mongo.library.ts +++ b/src/libraries/mongo.library.ts @@ -171,7 +171,7 @@ export async function memberExists(guildId: PGuild['id'], memberId: string): Pro ); } -export async function updateGuild(guildId: PGuild['id'], key: string, value: unknown): Promise { +export async function updateGuild(guildId: PGuild['id'], key: keyof PGuild, value: unknown): Promise { const updateWriteOpResult = await PGuildModel.updateOne( { id: guildId, diff --git a/src/types/classes/PVoiceChannel.class.ts b/src/types/classes/PVoiceChannel.class.ts index dd0bd00c..c66e5587 100644 --- a/src/types/classes/PVoiceChannel.class.ts +++ b/src/types/classes/PVoiceChannel.class.ts @@ -1,4 +1,5 @@ import { Document } from 'mongoose'; +import { Locale } from '../enums/Locales.enum'; export class PVoiceChannel { public id: string; @@ -6,7 +7,7 @@ export class PVoiceChannel { public render: boolean; public regex: string; public noBots: boolean; - public locale: number; + public locale: Locale; public annAnnounce: boolean; public annUser: boolean; @@ -16,7 +17,7 @@ export class PVoiceChannel { render: boolean, regex: string, noBots: boolean, - locale: number, + locale: Locale, annAnnounce: boolean, annUser: boolean ) {