Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions packages/bot/src/functions/music/commands/autoplay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ describe('autoplay command', () => {
interaction,
} as any)

expect(interaction.deferReply).toHaveBeenCalledTimes(1)
expect(resolveGuildQueueMock).toHaveBeenCalledWith(client, 'guild-1')
expect(requireQueueMock).toHaveBeenCalledWith(queue, interaction)
expect(queue.setRepeatMode).toHaveBeenCalledWith(
Expand Down Expand Up @@ -151,7 +150,6 @@ describe('autoplay command', () => {
interaction,
} as any)

expect(interaction.deferReply).toHaveBeenCalledTimes(1)
expect(queue.setRepeatMode).toHaveBeenCalledWith(QueueRepeatMode.OFF)
expect(replenishQueueMock).not.toHaveBeenCalled()
expect(interactionReplyMock).toHaveBeenCalled()
Expand Down Expand Up @@ -185,7 +183,6 @@ describe('autoplay command', () => {
interaction,
} as any)

expect(interaction.deferReply).toHaveBeenCalledTimes(1)
expect(requireQueueMock).toHaveBeenCalledWith(null, interaction)
expect(interactionReplyMock).not.toHaveBeenCalled()
})
Expand All @@ -211,7 +208,6 @@ describe('autoplay command', () => {
interaction,
} as any)

expect(interaction.deferReply).toHaveBeenCalledTimes(1)
expect(requireQueueMock).toHaveBeenCalledWith(null, interaction)
expect(interactionReplyMock).not.toHaveBeenCalled()
})
Expand Down
4 changes: 0 additions & 4 deletions packages/bot/src/functions/music/commands/autoplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,6 @@ export default new Command({
const guildId = interaction.guildId
if (!guildId) return

if (!interaction.deferred && !interaction.replied) {
await interaction.deferReply()
}

const { queue, source, diagnostics } = resolveGuildQueue(
client,
guildId,
Expand Down
22 changes: 19 additions & 3 deletions packages/bot/src/handlers/interactionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,20 @@
await reactionRolesService.handleButtonInteraction(interaction)
}
} catch (error) {
errorLog({ message: 'Error handling interaction:', error })
const commandName = interaction.isChatInputCommand()
? interaction.commandName
: interaction.isButton()
? interaction.customId
: 'unknown'

Check warning on line 113 in packages/bot/src/handlers/interactionHandler.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=LucasSantana-Dev_NexusBot&issues=AZ08tOzfRnJvyhKaOosN&open=AZ08tOzfRnJvyhKaOosN&pullRequest=377
errorLog({
message: 'Error handling interaction:',
error,
data: {
commandName,
userId: interaction.user.id,
guildId: interaction.guild?.id,
},
})

try {
if (
Expand All @@ -123,8 +136,11 @@
},
})
}
} catch (error) {
errorLog({ message: 'Error sending error message:', error })
} catch (replyError) {
errorLog({
message: 'Error sending error message:',
error: replyError,
})
}
}
}
72 changes: 49 additions & 23 deletions packages/bot/src/utils/command/commandValidations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import type { ChatInputCommandInteraction, GuildMember } from 'discord.js'
import type { GuildQueue } from 'discord-player'
import { errorEmbed } from '../general/embeds'
import { interactionReply } from '../general/interactionReply'
import { handleError, createUserErrorMessage } from '@lucky/shared/utils'
import {
handleError,
createUserErrorMessage,
warnLog,
} from '@lucky/shared/utils'

export async function requireGuild(
interaction: ChatInputCommandInteraction,
Expand Down Expand Up @@ -32,18 +36,22 @@ export async function requireVoiceChannel(
): Promise<boolean> {
const member = interaction.member as GuildMember
if (!member?.voice?.channel) {
const error = handleError(
new Error('User must be in a voice channel'),
{
guildId: interaction.guildId ?? undefined,
warnLog({
message: 'requireVoiceChannel: user not in voice channel',
data: {
commandName: interaction.commandName,
userId: interaction.user.id,
guildId: interaction.guildId ?? undefined,
},
)
})

await interactionReply({
interaction,
content: {
embeds: [errorEmbed('Error', createUserErrorMessage(error))],
embeds: [
errorEmbed('Not in Voice', 'Join a voice channel first.'),
],
ephemeral: true,
},
})
return false
Expand All @@ -56,20 +64,24 @@ export async function requireQueue(
interaction: ChatInputCommandInteraction,
): Promise<boolean> {
if (!queue) {
const error = handleError(
new Error(
'No active music queue found. The player may have restarted. Use /play to start a new queue.',
),
{
guildId: interaction.guildId ?? undefined,
warnLog({
message: 'requireQueue: no active queue',
data: {
commandName: interaction.commandName,
userId: interaction.user.id,
guildId: interaction.guildId ?? undefined,
},
)
})

await interactionReply({
interaction,
content: {
embeds: [errorEmbed('Error', createUserErrorMessage(error))],
embeds: [
errorEmbed(
'No Queue',
'No music is playing. Use /play to start.',
),
],
},
Comment on lines 76 to 85

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make the requireQueue validation reply ephemeral for consistency.

Other expected validation failures here are ephemeral; this one is public and can add avoidable channel noise.

🎯 Suggested fix
         await interactionReply({
             interaction,
             content: {
                 embeds: [
                     errorEmbed(
                         'No Queue',
                         'No music is playing. Use /play to start.',
                     ),
                 ],
+                ephemeral: true,
             },
         })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await interactionReply({
interaction,
content: {
embeds: [errorEmbed('Error', createUserErrorMessage(error))],
embeds: [
errorEmbed(
'No Queue',
'No music is playing. Use /play to start.',
),
],
},
await interactionReply({
interaction,
content: {
embeds: [
errorEmbed(
'No Queue',
'No music is playing. Use /play to start.',
),
],
ephemeral: true,
},
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bot/src/utils/command/commandValidations.ts` around lines 76 - 85,
The "No Queue" validation reply in requireQueue is currently public; update the
interactionReply call inside the requireQueue validation to send the response as
ephemeral (e.g., pass ephemeral: true in the interactionReply options) so this
validation failure matches other ephemeral validation messages; locate the call
to interactionReply that sends the errorEmbed('No Queue', ...) and add the
ephemeral flag to its options.

})
return false
Expand All @@ -82,15 +94,22 @@ export async function requireCurrentTrack(
interaction: ChatInputCommandInteraction,
): Promise<boolean> {
if (!queue?.currentTrack) {
const error = handleError(new Error('No track is currently playing'), {
guildId: interaction.guildId ?? undefined,
userId: interaction.user.id,
warnLog({
message: 'requireCurrentTrack: no current track',
data: {
commandName: interaction.commandName,
userId: interaction.user.id,
guildId: interaction.guildId ?? undefined,
},
})

await interactionReply({
interaction,
content: {
embeds: [errorEmbed('Error', createUserErrorMessage(error))],
embeds: [
errorEmbed('Not Playing', 'No track is currently playing.'),
],
ephemeral: true,
},
})
return false
Expand All @@ -103,15 +122,22 @@ export async function requireIsPlaying(
interaction: ChatInputCommandInteraction,
): Promise<boolean> {
if (!queue?.isPlaying()) {
const error = handleError(new Error('No music is currently playing'), {
guildId: interaction.guildId ?? undefined,
userId: interaction.user.id,
warnLog({
message: 'requireIsPlaying: not playing',
data: {
commandName: interaction.commandName,
userId: interaction.user.id,
guildId: interaction.guildId ?? undefined,
},
})

await interactionReply({
interaction,
content: {
embeds: [errorEmbed('Error', createUserErrorMessage(error))],
embeds: [
errorEmbed('Not Playing', 'No music is currently playing.'),
],
ephemeral: true,
},
})
return false
Expand Down
Loading
Loading