Message commands help

Hey I started my journey with sapphire today and can't seem to make message command's work This is my code so far
//index.ts
import "@sapphire/plugin-i18next/register";
import { LogLevel } from "@sapphire/framework";
import { GatewayIntentBits } from "discord.js";
import { config } from "./export.js";
import Client from "./structures/client.js";
export const client = new Client({
intents: [
GatewayIntentBits.MessageContent,
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
],
fetchPrefix: async () => {
return config.PREFIX;
},
i18n: {
fetchLanguage: async () => {
return "en-US";
},
},
loadMessageCommandListeners: true,
logger: {
level: LogLevel.Debug,
},
});
client.login(config.TOKEN);
//index.ts
import "@sapphire/plugin-i18next/register";
import { LogLevel } from "@sapphire/framework";
import { GatewayIntentBits } from "discord.js";
import { config } from "./export.js";
import Client from "./structures/client.js";
export const client = new Client({
intents: [
GatewayIntentBits.MessageContent,
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
],
fetchPrefix: async () => {
return config.PREFIX;
},
i18n: {
fetchLanguage: async () => {
return "en-US";
},
},
loadMessageCommandListeners: true,
logger: {
level: LogLevel.Debug,
},
});
client.login(config.TOKEN);
//ping.ts
import { Command } from "@sapphire/framework";
import { i18next } from "@sapphire/plugin-i18next";
import type { Message } from "discord.js";

export class PingCommand extends Command {
constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, {
...options,
name: "ping",
aliases: ["p"],
description: "Shows the latency of the bot.",
});
}
public registerApplicationCommands(registry: Command.Registry) {
//redacted to save writing space
}

public async messageRun(message: Message) {
const time = Date.now();
const msg = await message.reply({ content: "Pinging..." });

const roundTripTime = Date.now() - time;
const wsPing = this.container.client.ws.ping;

return msg.edit(
i18next.t("commands:ping", {
roundTime: roundTripTime,
ping: wsPing.toFixed(),
})
);
}
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
//redacted to save writing space
}
}
//ping.ts
import { Command } from "@sapphire/framework";
import { i18next } from "@sapphire/plugin-i18next";
import type { Message } from "discord.js";

export class PingCommand extends Command {
constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, {
...options,
name: "ping",
aliases: ["p"],
description: "Shows the latency of the bot.",
});
}
public registerApplicationCommands(registry: Command.Registry) {
//redacted to save writing space
}

public async messageRun(message: Message) {
const time = Date.now();
const msg = await message.reply({ content: "Pinging..." });

const roundTripTime = Date.now() - time;
const wsPing = this.container.client.ws.ping;

return msg.edit(
i18next.t("commands:ping", {
roundTime: roundTripTime,
ping: wsPing.toFixed(),
})
);
}
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
//redacted to save writing space
}
}
Slash command's work but message commands doesnt seem to work
Solution:
Okay I fixed it, the problem was indeed very silly I found out the code wasn't running after the canRunInChannel function, I checked what's the function was doing and it was a perms error ```ts async canRunInChannel(message) {...
No description
Jump to solution
31 Replies
Tenjaou
TenjaouOP6mo ago
No description
Spinel
Spinel6mo ago
1. Which version of @sapphire/framework are you using? 2. What's your file/folder structure? 3. Did you use the CLI to generate your bot? 4. What's your main (CJS) or module (ESM) property in package.json 5. Are you using TypeScript? And if so, how are you compiling and running your code? That is to say, what are your build and startup scripts? - Did you remove your output folder and rebuild then try again? 6. Is your problem related to message commands? Did you add loadMessageCommandListeners to your SapphireClient options Remember that if you are new to @sapphire/framework it is important that you read the user guide.
Favna
Favna6mo ago
1, 2, 3, 4, 5 :this:
Tenjaou
TenjaouOP6mo ago
1. 5.2.1 2. Image attached 3. No 4. "module": "src/index.ts" 5. Am using Bun 6. Yes I did add loadMessageCommandListeners to my SapphireClient options
No description
Favna
Favna6mo ago
do you also have "type": "module" in the package.json?
Tenjaou
TenjaouOP6mo ago
Yes I do
No description
Favna
Favna6mo ago
can you compare your own setup to this repo? this is a confirmed working setup https://github.com/sapphiredev/node-bun-example
GitHub
GitHub - sapphiredev/node-bun-example: A bot starting point with bu...
A bot starting point with bun for dev and node for prod - sapphiredev/node-bun-example
Tenjaou
TenjaouOP6mo ago
Yes my setup is identical
UndiedGFX
UndiedGFX6mo ago
just curious, is the bot receiving message, i.e do you have message intent enabled?
Tenjaou
TenjaouOP6mo ago
I have enabled intents; the bot will not run unless I have enabled them in the portal and also defined them while defining the Client.
No description
Tenjaou
TenjaouOP6mo ago
No description
UndiedGFX
UndiedGFX6mo ago
can you try creating a listener to see if your bot is getting those messages
Tenjaou
TenjaouOP6mo ago
// listeners/messageCreate.ts
import { Listener } from "@sapphire/framework";
import type { Message } from "discord.js";

export class MessageCreateListener extends Listener {
public constructor(
context: Listener.LoaderContext,
options: Listener.Options
) {
super(context, {
...options,
event: "messageCreate",
});
}
public run(message: Message) {
this.container.logger.info(message.content);
}
}
// listeners/messageCreate.ts
import { Listener } from "@sapphire/framework";
import type { Message } from "discord.js";

export class MessageCreateListener extends Listener {
public constructor(
context: Listener.LoaderContext,
options: Listener.Options
) {
super(context, {
...options,
event: "messageCreate",
});
}
public run(message: Message) {
this.container.logger.info(message.content);
}
}
No description
No description
Tenjaou
TenjaouOP6mo ago
Anymore suggestions?
UndiedGFX
UndiedGFX6mo ago
can i actually see the ping command? and are you sure the prefix is !
Tenjaou
TenjaouOP6mo ago
//ping.ts
import { Command } from "@sapphire/framework";
import { i18next } from "@sapphire/plugin-i18next";
import type { Message } from "discord.js";

export class PingCommand extends Command {
constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, {
...options,
name: "ping",
aliases: ["p"],
description: "Shows the latency of the bot.",
});
}
public registerApplicationCommands(registry: Command.Registry) {
//redacted to save writing space
}

public async messageRun(message: Message) {
const time = Date.now();
const msg = await message.reply({ content: "Pinging..." });

const roundTripTime = Date.now() - time;
const wsPing = this.container.client.ws.ping;

return msg.edit(
i18next.t("commands:ping", {
roundTime: roundTripTime,
ping: wsPing.toFixed(),
})
);
}
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
//redacted to save writing space
}
}
//ping.ts
import { Command } from "@sapphire/framework";
import { i18next } from "@sapphire/plugin-i18next";
import type { Message } from "discord.js";

export class PingCommand extends Command {
constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, {
...options,
name: "ping",
aliases: ["p"],
description: "Shows the latency of the bot.",
});
}
public registerApplicationCommands(registry: Command.Registry) {
//redacted to save writing space
}

public async messageRun(message: Message) {
const time = Date.now();
const msg = await message.reply({ content: "Pinging..." });

const roundTripTime = Date.now() - time;
const wsPing = this.container.client.ws.ping;

return msg.edit(
i18next.t("commands:ping", {
roundTime: roundTripTime,
ping: wsPing.toFixed(),
})
);
}
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
//redacted to save writing space
}
}
Yes prefix is "!"
//export.ts
import { z } from "zod";

export const config = z
.object({ TOKEN: z.string(), PREFIX: z.string() })
.parse(process.env);
//export.ts
import { z } from "zod";

export const config = z
.object({ TOKEN: z.string(), PREFIX: z.string() })
.parse(process.env);
//.env
TOKEN="{redacted}"
PREFIX="!"
//.env
TOKEN="{redacted}"
PREFIX="!"
Favna
Favna6mo ago
to your listener can you add console.log(this.container.stores.get('commands')) to see if the command gets loaded at all? s!ev this.container.stores.get('commands')
Skyra
Skyra6mo ago
Output: ⏱ 805.93μs
Favna
Favna6mo ago
should give something like that
Tenjaou
TenjaouOP6mo ago
lemme try
Tenjaou
TenjaouOP6mo ago
command is loaded
Favna
Favna6mo ago
can you do the same for listeners to check that the following are all there: - CoreMessageCommandAccepted - CoreMessageCommandTyping - CoreMessageCreate - CorePrefixedMessage - CorePreMessageCommandRun - CorePreMessageParser can you can also try logging this.container.client.fetchPrefix(message) (with the message being from the listener) to see if that actually returns ! not sure what your problem is. It's probably something silly somewhere. Trying to find out what...
Tenjaou
TenjaouOP6mo ago
this.container.logger.info(
this.container.stores
.get("listeners")
.map((listener) => listener.name)
.join(", ")
)
this.container.logger.info(
this.container.stores
.get("listeners")
.map((listener) => listener.name)
.join(", ")
)
Yes every listener is there [INFO] CoreInteractionCreate, CorePossibleAutocompleteInteraction, CoreChatInputCommandAccepted, CorePossibleChatInputCommand, CorePreChatInputCommandRun, CoreContextMenuCommandAccepted, CorePossibleContextMenuCommand, CorePreContextMenuCommandRun, CoreChatInputCommandError, CoreCommandApplicationCommandRegistryError, CoreCommandAutocompleteInteractionError, CoreContextMenuCommandError, CoreInteractionHandlerError, CoreInteractionHandlerParseError, CoreListenerError, CoreMessageCommandError, CoreMessageCommandAccepted, CoreMessageCreate, CorePrefixedMessage, CorePreMessageCommandRun, CorePreMessageParser, messageCreate
Tenjaou
TenjaouOP6mo ago
Prefex exists
public async run(message: Message) {
this.container.logger.info(
await this.container.client.fetchPrefix(message)
);
}
public async run(message: Message) {
this.container.logger.info(
await this.container.client.fetchPrefix(message)
);
}
No description
Favna
Favna6mo ago
okay in that case, can you try to debug to see how far sapphire code executes? Either with console logs or vscode debugger endpoints (the latter will be easier if you know how it works). The code will be in node_modules/@sapphire/framework/dist/esm/optional-listeners/message-command-listeners and then the .mjs files starting with CoreMessageCreate and from there you should be able to reason which event comes next by what gets emitted. Some if check somewhere must be going wrong I suspect
Tenjaou
TenjaouOP6mo ago
Alright lemme see
UndiedGFX
UndiedGFX6mo ago
favna you should write a page on the guide on how to use vscode debugger, would help a lot
Favna
Favna6mo ago
true tbh, though with the insistance (junior) devs have with using console logs I'm not sure how much it'll help ;-;
UndiedGFX
UndiedGFX6mo ago
many use console.log because they dont understand how debugger works :kekw:
Solution
Tenjaou
Tenjaou6mo ago
Okay I fixed it, the problem was indeed very silly I found out the code wasn't running after the canRunInChannel function, I checked what's the function was doing and it was a perms error
async canRunInChannel(message) {
if (isDMChannel(message.channel))
return true;
const me = await message.guild?.members.fetchMe();
if (!me)
return false;
const { channel } = message;
const permissionsFor = channel.permissionsFor(me);
if (!permissionsFor)
return false;
return permissionsFor.has(this.requiredPermissions, true);
}
async canRunInChannel(message) {
if (isDMChannel(message.channel))
return true;
const me = await message.guild?.members.fetchMe();
if (!me)
return false;
const { channel } = message;
const permissionsFor = channel.permissionsFor(me);
if (!permissionsFor)
return false;
return permissionsFor.has(this.requiredPermissions, true);
}
No description
Favna
Favna6mo ago
perfect! good to hear
Want results from more Discord servers?
Add your server