Duck
SIASapphire - Imagine a framework
•Created by Duck on 12/16/2023 in #discordjs-support
Encountered error while handling an interaction handler run method for interaction-handler
Been trying to debug an interaction error and haven't been able to figure out why it's erroring. There isn't a single method on the interaction which is allowing me to edit a reply or send a new one and I am confused. The code I am using is code I'm using on other interactions and it works perfectly fine, so I'm confused.
GroupButton.ts button for groups
replyToInteraction.ts Interaction util for my help command
interactionReplyUtil General utils for interactions
public run(interaction: ButtonInteraction) {
// If the group is undefined then we should not run
if (!this.group) return;
// We can now run the command
return replyWithCommands(interaction, this.group.name);
}
public run(interaction: ButtonInteraction) {
// If the group is undefined then we should not run
if (!this.group) return;
// We can now run the command
return replyWithCommands(interaction, this.group.name);
}
export async function replyWithCommands(
interaction: ChatInputCommandInteraction | MessageComponentInteraction,
groupName: string
) {
await autoDeferReply(interaction);
// Check the group exists
const group = await getGroup(interaction.client, interaction, groupName);
if (!group) {
return sendDeferredEphermeralResponse(interaction, {
content: `The group \`${groupName}\` does not exist.`,
});
}
// Get all the commands for the group
const commands = await getCommandsForGroup(
interaction.client,
interaction,
group.name
);
// Create a button for going back to the groups
const backButton = new ButtonBuilder() //
.setCustomId(GroupButtonIDs.BackToGroup)
.setEmoji(":back:")
.setStyle(ButtonStyle.Primary);
// Add the button to a action row
const row = new ActionRowBuilder<ButtonBuilder>();
row.addComponents(backButton);
// Embed builder
const embed = new EmbedBuilder() //
.setColor(0x2095ab)
.setAuthor({
name: interaction.user.username,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields([
{
name: "Information",
value: `Click on the 🔙 button to go back to the groups.`,
},
{
name: `${group.name} Commands`,
value:
commands
.map(
(command) =>
`\`/${command.name}\` ${command.description}`
)
.join("\n") || "No commands found",
},
]);
return sendDeferredResponse(interaction, {
embeds: [embed],
components: [row],
});
}
export async function replyWithCommands(
interaction: ChatInputCommandInteraction | MessageComponentInteraction,
groupName: string
) {
await autoDeferReply(interaction);
// Check the group exists
const group = await getGroup(interaction.client, interaction, groupName);
if (!group) {
return sendDeferredEphermeralResponse(interaction, {
content: `The group \`${groupName}\` does not exist.`,
});
}
// Get all the commands for the group
const commands = await getCommandsForGroup(
interaction.client,
interaction,
group.name
);
// Create a button for going back to the groups
const backButton = new ButtonBuilder() //
.setCustomId(GroupButtonIDs.BackToGroup)
.setEmoji(":back:")
.setStyle(ButtonStyle.Primary);
// Add the button to a action row
const row = new ActionRowBuilder<ButtonBuilder>();
row.addComponents(backButton);
// Embed builder
const embed = new EmbedBuilder() //
.setColor(0x2095ab)
.setAuthor({
name: interaction.user.username,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields([
{
name: "Information",
value: `Click on the 🔙 button to go back to the groups.`,
},
{
name: `${group.name} Commands`,
value:
commands
.map(
(command) =>
`\`/${command.name}\` ${command.description}`
)
.join("\n") || "No commands found",
},
]);
return sendDeferredResponse(interaction, {
embeds: [embed],
components: [row],
});
}
/**
* This util will defer the reply only when it is able to.
*
* @param interaction
*/
export async function autoDeferReply(
interaction: ChatInputCommandInteraction | MessageComponentInteraction
) {
const fromMessageComponent = isMessageComponentInteraction(interaction);
// Defer the interaction if it hasn't already been (command interaction)
if (
!fromMessageComponent &&
!interaction.deferred &&
!interaction.replied
) {
await interaction.deferReply();
}
}
export async function sendDeferredResponse(
interaction: ChatInputCommandInteraction | MessageComponentInteraction,
options?: BaseMessageOptions
): Promise<InteractionResponse<boolean> | Message<boolean>> {
const { content, embeds, components } = options ?? {};
// Response to the interaction
const responseObj: BaseMessageOptions = {
content: content ?? "",
embeds,
components,
};
const fromMessageComponent = isMessageComponentInteraction(interaction);
// A button interaction cause this function to be called
if (fromMessageComponent && !interaction.replied) {
return interaction.update(responseObj);
}
// A command interaction cause this function to be called
return interaction.editReply(responseObj);
}
/**
* This util will defer the reply only when it is able to.
*
* @param interaction
*/
export async function autoDeferReply(
interaction: ChatInputCommandInteraction | MessageComponentInteraction
) {
const fromMessageComponent = isMessageComponentInteraction(interaction);
// Defer the interaction if it hasn't already been (command interaction)
if (
!fromMessageComponent &&
!interaction.deferred &&
!interaction.replied
) {
await interaction.deferReply();
}
}
export async function sendDeferredResponse(
interaction: ChatInputCommandInteraction | MessageComponentInteraction,
options?: BaseMessageOptions
): Promise<InteractionResponse<boolean> | Message<boolean>> {
const { content, embeds, components } = options ?? {};
// Response to the interaction
const responseObj: BaseMessageOptions = {
content: content ?? "",
embeds,
components,
};
const fromMessageComponent = isMessageComponentInteraction(interaction);
// A button interaction cause this function to be called
if (fromMessageComponent && !interaction.replied) {
return interaction.update(responseObj);
}
// A command interaction cause this function to be called
return interaction.editReply(responseObj);
}
9 replies
SIASapphire - Imagine a framework
•Created by Duck on 4/7/2023 in #sapphire-support
TypeError: Cannot read properties of undefined (reading 'write')
\testing-forbidden\node_modules\@sapphire\framework\dist\lib\utils\logger\Logger.js:27
this.write(ILogger_js.LogLevel.Error, ...values);
^
TypeError: Cannot read properties of undefined (reading 'write')
at error (\testing-forbidden\node_modules\@sapphire\framework\dist\lib\utils\logger\Logger.js:27:10)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Node.js v18.14.1
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
\testing-forbidden\node_modules\@sapphire\framework\dist\lib\utils\logger\Logger.js:27
this.write(ILogger_js.LogLevel.Error, ...values);
^
TypeError: Cannot read properties of undefined (reading 'write')
at error (\testing-forbidden\node_modules\@sapphire\framework\dist\lib\utils\logger\Logger.js:27:10)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Node.js v18.14.1
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@sapphire/plugin-logger
.
I am building a provider to my database that currently uses the logging methods, I assumed it was because the client hadn't logged in yet so I moved my provider instantiation to the ReadyListener
.
This is my ReadyListener
at the moment
import { Listener } from "@sapphire/framework";
import type { Client } from "discord.js";
import { MongoProvider } from "../provider/MongoProvider";
import * as Schemas from "../provider/schemas";
export class ReadyListener extends Listener {
public constructor(context: Listener.Context, options: Listener.Options) {
super(context, {
...options,
event: "ready",
once: true,
});
}
public run(bot: Client) {
if (!bot.user) {
this.container.logger.error(
"Ready: Bot has initialised with no user"
);
return;
}
this.container.logger.info(
`Ready: Bot has initialised as ${bot.user.tag} (${bot.user.id})`
);
// Setup theprovider
bot.provider = new MongoProvider(
{
hostname: process.env.DB_HOSTNAME,
port: process.env.DB_PORT,
auth: {
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
},
},
{ guilds: Schemas.GuildSchema }
);
// Test the that the insert document method works
bot.provider.waitForConnection(() => {
bot.provider.insertDocument("guilds", {
guildID: "1",
prefix: "!",
});
});
}
}
import { Listener } from "@sapphire/framework";
import type { Client } from "discord.js";
import { MongoProvider } from "../provider/MongoProvider";
import * as Schemas from "../provider/schemas";
export class ReadyListener extends Listener {
public constructor(context: Listener.Context, options: Listener.Options) {
super(context, {
...options,
event: "ready",
once: true,
});
}
public run(bot: Client) {
if (!bot.user) {
this.container.logger.error(
"Ready: Bot has initialised with no user"
);
return;
}
this.container.logger.info(
`Ready: Bot has initialised as ${bot.user.tag} (${bot.user.id})`
);
// Setup theprovider
bot.provider = new MongoProvider(
{
hostname: process.env.DB_HOSTNAME,
port: process.env.DB_PORT,
auth: {
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
},
},
{ guilds: Schemas.GuildSchema }
);
// Test the that the insert document method works
bot.provider.waitForConnection(() => {
bot.provider.insertDocument("guilds", {
guildID: "1",
prefix: "!",
});
});
}
}
2023-04-07 22:53:02 - INFO - ApplicationCommandRegistries: Initializing...
2023-04-07 22:53:02 - INFO - Ready: Bot has initialised as testing-forbidden#5339 (1091541627056689242)
2023-04-07 22:53:02 - INFO - MongoProvider: Attempting to connect to the database...
2023-04-07 22:53:02 - INFO - MongoProvider: Connected to database. Initialising provider...
2023-04-07 22:53:02 - INFO - MongoProvider: Provider initialised.
2023-04-07 22:53:02 - INFO - ApplicationCommandRegistries: Initializing...
2023-04-07 22:53:02 - INFO - Ready: Bot has initialised as testing-forbidden#5339 (1091541627056689242)
2023-04-07 22:53:02 - INFO - MongoProvider: Attempting to connect to the database...
2023-04-07 22:53:02 - INFO - MongoProvider: Connected to database. Initialising provider...
2023-04-07 22:53:02 - INFO - MongoProvider: Provider initialised.
10 replies