From 263405141bbe05d338186d351b5d056fc09d5277 Mon Sep 17 00:00:00 2001 From: Bradley Bickford Date: Tue, 2 Jan 2024 20:39:23 -0500 Subject: [PATCH] A number of changes to address issues and missing pieces from the voice call monitoring components of Breadbot --- breadbot.js | 122 +++++++++---------------------------------- utilities/sqlutil.js | 35 ++++++++++++- 2 files changed, 60 insertions(+), 97 deletions(-) diff --git a/breadbot.js b/breadbot.js index c815a27..e5478b5 100644 --- a/breadbot.js +++ b/breadbot.js @@ -30,8 +30,6 @@ const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBit client.commands = new Collection(); -//const commandFiles = allFiles.filter(file => file.endsWith('.js')); - var activeCalls = [] getAllFiles('.' + path.sep + 'commands', []) @@ -48,19 +46,6 @@ getAllFiles('.' + path.sep + 'commands', []) } }); -/* -for (const file of commandFiles) { - const command = require(file); - - if ('enabled' in command && command.enabled && 'data' in command && 'execute' in command) { - client.commands.set(command.data.name, command); - console.log(`[INFO] Loaded command at ${file}`); - } - else { - console.log(`[WARNING] The command at ${file} is missing a required "data" or "execute" property or is not enabled.`); - } -} -*/ client.on(Events.InteractionCreate, async interaction => { if (!interaction.isChatInputCommand()) return; @@ -101,6 +86,10 @@ client.on(Events.VoiceStateUpdate, async (oldState, newState) => { console.log("Voice State Update Fired") if (oldState.channel == null && newState.channel != null) { + if (newState.member.id == client.user.id) { + return //If the user is breadbot, ignore and exit + } + console.log(`\tChannel Join Detected ${newState.guild.id} - ${newState.channelId} - ${newState.member.id}`) var existingCallID = await sqlutil.inCall(newState.guild.id, newState.channelId) @@ -152,102 +141,43 @@ client.on(Events.VoiceStateUpdate, async (oldState, newState) => { } catch (error) { console.warn(error) } - - /*console.log(newState.guild.channels.cache) - - const voiceChannel = newState.guild.channels.cache - .filter(c => c.type === "voice" || c.type === "stage") - .find(c => c.id === newState.channelId) - - if(!voiceChannel) { - console.log("\tVOICE CHANNEL LOOKUP FAILED") - - return - }*/ - - /* - connection = newState.channel.join().then(conn => { - const receiver = conn.receiver - - conn.on("speaking", (user, speaking) => { - if (speaking) { - console.log(`User is speaking ${user.username}`) - - const audioStream = receiver.createStream(user, { mode: "pcm"}) - - const pathToFile = "." + path.sep + "media" + path.sep + "voice_audio" + path.sep + newCallID + `${user.id}-${Date.now()}.pcm` - - audioStream.pipe(fs.createWriteStream(pathToFile)) - audioStream.on("end", () => { - console.log(`User stopped speaking ${user.username}`) - }) - } - }) - }).catch(error => { - console.log(error) - })*/ - } - } else if (oldState.channel != null && newState.channel == null ) { - - } - /*if (oldState.channel== null && newState.channel != null) { - console.log(`User ${newState.member.user.username} joined channel ${newState.channel.name} in guild ${newState.guild.name}`) - - var last_voice_active_users = await sqlutil.getVoiceActiveUsers(newState.guild.id, newState.channelId) - - var did_update = await sqlutil.updateVoiceActiveUsers(newState.guild.id, newState.channelId, true) - - if (did_update) { - console.log("\t Registered another user as participating in this voice channel") - } else { - console.log("\t Failed to register this user as participating in this voice channel") } - var voice_active_users = await sqlutil.getVoiceActiveUsers(newState.guild.id, newState.channelId) + var userRegistered = await sqlutil.registerUserIfMissing(newState.member.id, newState.member.username, newState.member.displayName) - if (last_voice_active_users <= 0 && voice_active_users > 0) { - console.log("New call detected, getting set up") - var new_call_id = await sqlutil.registerNewCall(newState.guild.id, newState.channelId, new Date()) + if (userRegistered) { + var markedUserInCall = await sqlutil.registerUserInCall(existingCallID, newState.member.id) - if (new_call_id != -1) { - console.log("New call successfully registered") - activeCalls[newState.guild.id.concat("|", newState.channelId)] = new_call_id - - // Setup call connection for BreadBot and configure events here - } else { - console.log("Failed to generate a new call ID") + if (!markedUserInCall) { + console.log(`Something went wrong when marking user in voice call: ${newState.member.id} - ${newState.member.channelId}`) } + } else { + console.log(`Something went wrong when registering user for call: ${newState.member.id} - ${newState.member.username}`) } } else if (oldState.channel != null && newState.channel == null) { - console.log(`User ${oldState.member.user.username} left channel ${oldState.channel.name} in guild ${oldState.guild.name}`) - - var last_voice_active_users = await sqlutil.getVoiceActiveUsers(oldState.guild.id, oldState.channelId) - - var did_update = await sqlutil.updateVoiceActiveUsers(oldState.guild.id, oldState.channelId, false) - - if (did_update) { - console.log("\t Removed registered user as participating in this voice channel") - } else { - console.log("\t Failed to remove registered user as participating in this voice channel") + if (oldState.member.id == client.user.id) { + return //If the user is breadbot, ignore and exit } - var voice_active_users = await sqlutil.getVoiceActiveUsers(oldState.guild.id, oldState.channelId) + console.log(`Channel Exit Detected ${oldState.guild.id} - ${oldState.channelId} - ${oldState.member.id}`) - if (last_voice_active_users > 0 && voice_active_users <= 0) { - console.log("End of call detected, tearing down") - var end_time_set = await sqlutil.updateCallEndTime(activeCalls[oldState.guild.id.concat("|", oldState.channelId)], new Date()) + var existingCallID = await sqlutil.inCall(oldState.guild.id, newState.channelId) - if (end_time_set) { - console.log("Call is ending, disconnecting BreadBot") + console.log(`Existing call ID: ${existingCallID}`) - // Disconnect BreadBot and end connection here + if (existingCallID != -1) { + await sqlutil.deregisterUserInCall(existingCallID, oldState.member.id) - delete activeCalls[oldState.guild.id.concat("|", oldState.channelId)] - } else { - console.log("Failed to properly set the end time of the call") + var usersInCall = await sqlutil.getNumberUsersInCall(existingCallID) + + if (usersInCall == 0) { + const connection = getVoiceConnection(oldState.guild.id) + connection.disconnect() } + } else { + console.log("Couldn't find a call ID based on the guild and channel info, was Breadbot in the call?") } - }*/ + } }) client.on(Events.MessageCreate, async message => { diff --git a/utilities/sqlutil.js b/utilities/sqlutil.js index 1425bdf..9de0afa 100644 --- a/utilities/sqlutil.js +++ b/utilities/sqlutil.js @@ -237,6 +237,36 @@ async function registerNewCall(server_snowflake, channel_snowflake, call_start_t }) } +async function registerUserInCall(call_id, user_snowflake) { + return connection_pool.query("INSERT INTO call_users (call_id, user_snowflake) VALUES (?, ?)", [call_id, user_snowflake]).then(([rows, fields]) => { + return true + }).catch((error) => { + console.log(error) + + return false + }) +} + +async function deregisterUserInCall(call_id, user_snowflake) { + return connection_pool.query("DELETE FROM call_users WHERE call_id = ? AND user_snowflake = ?", [call_id, user_snowflake]).then(([rows, field]) => { + return true + }).catch((error) => { + console.log(error) + + return false + }) +} + +async function getNumberUsersInCall(call_id) { + return connection_pool.query("SELECT COUNT(call_users_id) AS users_in_call FROM call_users WHERE call_id = ?", [call_id]).then(([rows, fields]) => { + return rows[0].users_in_call + }).catch((error) => { + console.log(error) + + return -1 + }) +} + async function updateCallEndTime(call_id, call_end_time) { return await connection_pool.query("UPDATE call_states SET call_end_time = ? WHERE call_id = ?", [call_end_time, call_id]).then(async ([rows, fields]) => { return true @@ -261,5 +291,8 @@ module.exports = { inCall, updateMessageContentIfPresent, markMessageDeletedIfPresent, - registerAttachmentIfMissing + registerAttachmentIfMissing, + registerUserInCall, + deregisterUserInCall, + getNumberUsersInCall } \ No newline at end of file