How to use sapphire framework decoraters plugin

I saw a youtube tutorial for making a discord bot using sapphire framework in which the person used decoraters to make command but when i tried i am getting this weird error.
Solution:
Are you using "@sapphire/ts-config/decorators" in your tsconfig.json? Else, please show the aforementioned file. This error comes from using ES decorators rather than the legacy ones.
Jump to solution
29 Replies
Munish
MunishOP12mo ago
Unable to resolve signature of class decorator when called as an expression.
The runtime will invoke the decorator with 2 arguments, but the decorator expects 1.ts(1238)
Unable to resolve signature of class decorator when called as an expression.
The runtime will invoke the decorator with 2 arguments, but the decorator expects 1.ts(1238)
import { Command ,type ApplicationCommandRegistry} from "@sapphire/framework";
import { Message , ChatInputCommandInteraction} from "discord.js";
import {ApplyOptions} from "@sapphire/decorators"


@ApplyOptions<Command.Options>({
name: "ping",
description : "Get Client ws latency."
})

export default class PingCommand extends Command {

public override registerApplicationCommands(registry : ApplicationCommandRegistry) {
registry.registerChatInputCommand(command => {
command.setName(this.name).setDescription(this.description);})
}

public async chatInputRun(interaction : Command.ChatInputCommandInteraction) {
await interaction.deferReply();
await interaction.editReply(`My ping is ${this.container.client.ws.ping} ms`)
}

}
import { Command ,type ApplicationCommandRegistry} from "@sapphire/framework";
import { Message , ChatInputCommandInteraction} from "discord.js";
import {ApplyOptions} from "@sapphire/decorators"


@ApplyOptions<Command.Options>({
name: "ping",
description : "Get Client ws latency."
})

export default class PingCommand extends Command {

public override registerApplicationCommands(registry : ApplicationCommandRegistry) {
registry.registerChatInputCommand(command => {
command.setName(this.name).setDescription(this.description);})
}

public async chatInputRun(interaction : Command.ChatInputCommandInteraction) {
await interaction.deferReply();
await interaction.editReply(`My ping is ${this.container.client.ws.ping} ms`)
}

}
how i can remove this helper role I am just a beginner <a:Panda_Thinking:1090180303399690240>
Solution
kyra
kyra12mo ago
Are you using "@sapphire/ts-config/decorators" in your tsconfig.json? Else, please show the aforementioned file. This error comes from using ES decorators rather than the legacy ones.
Munish
MunishOP12mo ago
Yeah I fixed that now I am having an issue no command or event is registering on the bot . I tried to create ping command or a ready event but nothing working .
Munish
MunishOP12mo ago
I am beginner in typescript can you explain me what I am doing wrong ? <a:Panda_Thinking:1090180303399690240>
kyra
kyra12mo ago
Please recreate that token @Manish And don't push it on GitHub
Munish
MunishOP12mo ago
Yes I resetted that token already before publishing it to github Do you figured out any issue in this code ?<a:Panda_Thinking:1090180303399690240>
kyra
kyra12mo ago
Ah, yes You're missing the main field in your package.json node ./dist/index.js runs the script with the CWD at the root, not at ./dist So simply add "main": "./dist/index.js" in your package.json and then run it with node ., the problem with be solved
Munish
MunishOP12mo ago
like this ?
No description
kyra
kyra12mo ago
Outside scripts, it's a property at the root object, alongside dependencies and scripts
Munish
MunishOP12mo ago
actaully the problem is that netiher the clientready event working nor the ping command . Bot comes online but doesn't respond anything
No description
Munish
MunishOP12mo ago
ok <:sunshine_ok_yaar:1182078172003581962>
kyra
kyra12mo ago
Once you place it where it should be and run it with node ., it'll just work
Munish
MunishOP12mo ago
thanks it worked now
kyra
kyra12mo ago
The reason why you need the main field, is because Sapphire reads your package.json using the CWD (accessible with process.cwd(), which is where your package.json is always at) and then read the main field if it exists. Then it joins the CWD with main's directory, which makes it look like /root/dist (being /root the root directory of your project), and then Sapphire can use that root to determine where the other directories are at, so /root/dist/commands for commands, /root/dist/listeners for listeners, etc. Without main, Sapphire cannot determine this correctly and the above fails, which is why Sapphire was trying to read /root/commands and /root/listeners, which in your case don't exist.
Munish
MunishOP12mo ago
ohh nice . Can I use dokdo with sapphire ?
Munish
MunishOP12mo ago
GitHub
GitHub - wonderlandpark/dokdo: Dokdo. Easy Discord bot debuging tool.
Dokdo. Easy Discord bot debuging tool. Contribute to wonderlandpark/dokdo development by creating an account on GitHub.
kyra
kyra12mo ago
That's a separate issue, but to answer it quickly, Sapphire doesn't change Discord.js's behaviour, so if it works with Discord.js, it works with Sapphire.
Munish
MunishOP12mo ago
ok so I have to create a messagecreate to add dokdo . <:humanity_cutepika:1152474497878851676>
kyra
kyra12mo ago
If that's what you want, sure
Favna
Favna12mo ago
snip, i misread last night
Munish
MunishOP12mo ago
export class Dart extends SapphireClient {
public moon : MoonlinkManager;
public constructor() {

super( {
intents: [
"Guilds",
"GuildMessages",
"GuildVoiceStates",
"GuildMembers",
"MessageContent",
"GuildEmojisAndStickers"
],
caseInsensitiveCommands: true,
caseInsensitivePrefixes:true,
defaultPrefix: BOT_PREFIX,
shards:'auto',
logger:{'level': LogLevel.Info},
presence : {'status':'idle',activities:[{'type':ActivityType.Listening ,'name':`/help`}]},
loadMessageCommandListeners:true,
allowedMentions : {'parse':['users'],repliedUser:true},





})
this.moon = new MoonlinkManager([{'host':'78.46.65.243','identifier':'optiklink','password':'manish2004',port:3965 ,'secure':false}] , {'movePlayersToNextNode':true , 'WebSocketDebug':false , 'autoResume':true}, (guild :any , sPayload:any) => {this.guilds.cache.get(guild)?.shard.send(JSON.parse(sPayload))})
}
public override login(token?: string): Promise<string> {
ApplicationCommandRegistries.setDefaultBehaviorWhenNotIdentical(RegisterBehavior.BulkOverwrite);

return super.login(token);

}


}
export class Dart extends SapphireClient {
public moon : MoonlinkManager;
public constructor() {

super( {
intents: [
"Guilds",
"GuildMessages",
"GuildVoiceStates",
"GuildMembers",
"MessageContent",
"GuildEmojisAndStickers"
],
caseInsensitiveCommands: true,
caseInsensitivePrefixes:true,
defaultPrefix: BOT_PREFIX,
shards:'auto',
logger:{'level': LogLevel.Info},
presence : {'status':'idle',activities:[{'type':ActivityType.Listening ,'name':`/help`}]},
loadMessageCommandListeners:true,
allowedMentions : {'parse':['users'],repliedUser:true},





})
this.moon = new MoonlinkManager([{'host':'78.46.65.243','identifier':'optiklink','password':'manish2004',port:3965 ,'secure':false}] , {'movePlayersToNextNode':true , 'WebSocketDebug':false , 'autoResume':true}, (guild :any , sPayload:any) => {this.guilds.cache.get(guild)?.shard.send(JSON.parse(sPayload))})
}
public override login(token?: string): Promise<string> {
ApplicationCommandRegistries.setDefaultBehaviorWhenNotIdentical(RegisterBehavior.BulkOverwrite);

return super.login(token);

}


}
I assigned moonlinkManager to the client . now how to access it in other files sorry I forgot to turn off mention . <:humanity_cutepika:1152474497878851676>
Favna
Favna12mo ago
container.client.moonlinkManager Or just assign it to the container instead of the client so it's a property higher. https://www.sapphirejs.dev/docs/Guide/additional-information/accessing-the-client-in-pieces
Sapphire Framework
Accessing the client in pieces | Sapphire
There are multiple ways to access the client in pieces:
Munish
MunishOP12mo ago
import { Listener , Events , container } from "@sapphire/framework";
import { ApplyOptions } from "@sapphire/decorators";
import { MoonlinkNode } from "moonlink.js";

export class NodeConnectEvent extends Listener {
public constructor(context : Listener.LoaderContext , options: Listener.Options){
super(context , {
...options,
emitter : container.client.moon,
event: 'nodeCreate',
})
}
public run(node : MoonlinkNode) {
container.client.logger.info(`Node with ${node.identifier} is connected `)
}
}
import { Listener , Events , container } from "@sapphire/framework";
import { ApplyOptions } from "@sapphire/decorators";
import { MoonlinkNode } from "moonlink.js";

export class NodeConnectEvent extends Listener {
public constructor(context : Listener.LoaderContext , options: Listener.Options){
super(context , {
...options,
emitter : container.client.moon,
event: 'nodeCreate',
})
}
public run(node : MoonlinkNode) {
container.client.logger.info(`Node with ${node.identifier} is connected `)
}
}
PS C:\Users\Administrator\Documents\GitHub\Dart-Music> tsc
src/listeners/moonlink/nodeCreate.ts:9:40 - error TS2339: Property 'moon' does not exist on type 'SapphireClient<boolean>'.

9 emitter : container.client.moon,
~~~~


Found 1 error in src/listeners/moonlink/nodeCreate.ts:9
PS C:\Users\Administrator\Documents\GitHub\Dart-Music> tsc
src/listeners/moonlink/nodeCreate.ts:9:40 - error TS2339: Property 'moon' does not exist on type 'SapphireClient<boolean>'.

9 emitter : container.client.moon,
~~~~


Found 1 error in src/listeners/moonlink/nodeCreate.ts:9
I tried but getting this error <:humanity_cutepika:1152474497878851676>
Spinel
Spinel12mo ago
If you're adding custom properties to your Client class and you want them to be accessible when accessing the client through something like this.container.client you'll have to add module augmentation: https://gist.github.com/Favna/26ed5b2df82d424203b71b9ffbce85c4 For more information on module augmentation see: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
Munish
MunishOP12mo ago
Thanks, this is fixed. Do you have any examples for a basic command which takes arguments? The example present in the docs for the ping command doesn't take any arguments. I want to make a play command for my bot which takes a query as a required argument. I earlier used discord.py, so I have no idea how to do it in discord.js.
Spinel
Spinel12mo ago
Discord Bots using @sapphire/framework v5.x - Gemboard ᴱ ᴰ - Skyra ᴱ ᴬ ᴰ - Dragonite ᴱ ᴰ - Archangel ᴱ ᴰ - Official Bot Examples ᴱ ᴰ ᴶˢ - KBot ᴱ ᴬ ᴰ v4.x - Radon ᴱ ᴬ - Sapphire Application Commands Examples ᴱ - Zeyr ᴰ ᴬ - Birthdayy ᴰ - RTByte ᴱ ᴬ Legend for the identifiers : Uses ESM (if not specified then uses CJS) : Advanced bot (if not specified it is a simple bot, or not graded) : Uses Docker in production ᴶˢ: Written in JavaScript. If not specified then the bot is written in TypeScript.
Favna
Favna12mo ago
have a look at some of those
Munish
MunishOP12mo ago
Ok let me try.
Want results from more Discord servers?
Add your server