owengombas / discord.ts Goto Github PK
View Code? Open in Web Editor NEW🤖 Create your discord bot by using TypeScript and decorators!
Home Page: https://owencalvin.github.io/discord.ts/
🤖 Create your discord bot by using TypeScript and decorators!
Home Page: https://owencalvin.github.io/discord.ts/
I don't know if this is specific to discord.ts or discordjs, but I've seen people manage to do it using the latter.
My issue with this, is no matter how I try to detect a user speaking, it doesn't work.
Here's a snippet of an example of what I've tried
const connection = await command.member!.voice.channel
connection
.then(conn => {
command.channel.send('ready!')
//Create our voice receiver
const receiver = conn.receiver
conn.on('speaking', (user, speaking) => {
command.channel.send(`Channel ${user}'s speaking`)
if (speaking) {
command.channel.send(`I'm listening to ${user}`)
const audioStream = receiver.createStream(user)
const outputStream = generateOutputFile(VoiceChannel, user)
audioStream.pipe(outputStream)
outputStream.on("data", console.log)
audioStream.on('end', () => {
command.channel.send(`I'm no longer listening to ${user}`)
conn.play(audioStream, { type: 'opus' })
})
}
})
})
.catch((err) => {
console.log(err)
})
this is example of command
-cmd hello there
I know we can read the parameters by slug
cmd :text :text2
but I wish to read full text
hello there
I can replace -cmd
but is there any alternative solution?
By Harry
I couldn't find a way to send embed message,
i created an embed using discord.js but couldn't send it cause
channel.send()
didn't have an embed
parameter
the client is undefined when injected in the ready event. I'm trying to create a channel if it doesn't exist when my bot startup.
If use some command alias like in example without a prefix, command will running.
protected static _aliases = [
"alias1",
"alias2",
"alias3",
];
@Command("help")
@Rules(Rule(_aliases.join("|")).end())
async runCommand(command: CommandMessage) {...}
On message event works properly but i tested both add and remove events and they seem to not trigger.
import {ArgsOf, Discord, On, Command, CommandMessage, Client} from '@typeit/discord';
import * as Events from './events';
import {prefix, welcomeChannelID, guestRoleID} from './data';
@Discord(prefix)
export abstract class DiscordBot{
@Command("ping")
ping(command: CommandMessage): void {
command.reply("pong!");
}
@On('guildMemberAdd')
private async onGulidMemberAdd([member]: ArgsOf<"guildMemberAdd">){
member.roles.add(member.guild.roles.cache.get(guestRoleID));
const welcomeChannel = member.guild.channels.cache.get(welcomeChannelID);
if(welcomeChannel.isText()) welcomeChannel.send(`Witaj na serwerze discord Partii Technokratycznej ${member.user.username}!`);
}
@On("message")
onMessage(
[message]: ArgsOf<"message">,
client: Client
) {
console.log(message.content);
}
}
Hi,
I would love to have a feature, where you can mention the bot (i,e, @ Bot help) and avoiding the prefix. I have tried to implement this using Guards or Rules and it simply does not work.
I know you can implement this in the on("Message") handler, but then you lose all modularity of the command/event structure, as you cannot forward or close.
Hi, i'm trying to use @Permission decoration to make a Group Slash with a role permission but it always throw me this error
D:\depotsGit\Bot-Discord-IUT-Nancy-Charlemagne\node_modules\reflect-metadata\Reflect.js:544
throw new TypeError();
^
TypeError:
at DecorateConstructor (D:\depotsGit\Bot-Discord-IUT-Nancy-Charlemagne\node_modules\reflect-metadata\Reflect.js:544:31)
at Reflect.decorate (D:\depotsGit\Bot-Discord-IUT-Nancy-Charlemagne\node_modules\reflect-metadata\Reflect.js:130:24)
at Object.__decorate (D:\depotsGit\Bot-Discord-IUT-Nancy-Charlemagne\node_modules\tslib\tslib.js:98:96)
at Object.<anonymous> (D:\depotsGit\Bot-Discord-IUT-Nancy-Charlemagne\commands\Test.ts:6:17)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Module.m._compile (C:\Users\hugob\AppData\Roaming\npm\node_modules\ts-node\src\index.ts:1295:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Object.require.extensions.<computed> [as .ts] (C:\Users\hugob\AppData\Roaming\npm\node_modules\ts-node\src\index.ts:1298:12)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
import { Discord, Slash, Group, Description, Permission } from "@typeit/discord";
import { CommandInteraction, TextChannel } from "discord.js";
@Discord()
@Permission("753182939352793138", 'ROLE')
@Group("maintenance", "Commandes de maintenance réservées aux Admins")
abstract class maintenance {
@Slash('purgeChannel')
@Description("Clone et supprime le salon afin de supprimer son contenu")
private purgeChannel(interaction: CommandInteraction) {
const channel = <TextChannel>interaction.channel;
channel.clone({ reason: `Purge du salon demandé par ${interaction.user.username}` });
channel.delete(`Purge du salon demandé par ${interaction.user.username}`);
}
}
I also tried with the doc example
import { Discord, Permission, Slash } from '@typeit/discord';
@Discord()
@Permission("227882902031958016", "USER") // Only the role that has this USER_ID can use this command
@Permission("753182939352793138", "ROLE") // Only the role that has this ROLE_ID can use this command
class DiscordBot {
@Slash("hello") // Only the role that has this ROLE_ID can use this command
private hello(
) {
// ...
}
@Slash("hello2") // Only the role that has this ROLE_ID can use this command
private hello2(
) {
// ...
}
}
But it throw the same error.
Thx in advance <3
PS: Idk if it's linked but i can't use multiple @Permission, it only take the last, maybe i will create a different issue for that
When using the following code from the repository documentation:
import { Discord } from '@typeit/discord';
@Discord() // Decorate the class
abstract class AppDiscord {}
My application crashes with the following error:
\node_modules\@typeit\src\Decorators\Discord.ts:1
TypeError: Cannot read property 'importCommands' of undefined
at \node_modules\@typeit\src\Decorators\Discord.ts:24:16
at DecorateConstructor (\node_modules\reflect-metadata\Reflect.js:541:33)
at Object.decorate (\node_modules\reflect-metadata\Reflect.js:130:24)
at Object.__decorate (\node_modules\tslib\tslib.js:92:96)
at Object.<anonymous> (\src\main.ts:9:22)
at Generator.next (<anonymous>)
My tool configuration is:
Node v12.16.1
TypeScript 3.8.2
ts-node 8.9.1
According to Judge user from the discord channel, I fixed this by adding brackets in the parentheses when calling Discord decorator in this way:
import { Discord } from '@typeit/discord';
@Discord({}) // Decorate the class with brackets in parentheses
abstract class AppDiscord {}
Maybe it'll be useful for someone with the same versions of configuration tools.
Discord API version 8 has been released and versions 6 and 7 are deprecated
he's buzzing and i can't concentrate.
If a command prefix is found anywhere within a message (not just the beginning) the command still executes.
Hi, this is a proposal to use MessageComponents like Buttons easier like Slash commands are easier with decorators.
I'm not a English native, sorry if some explanation are weird or something like that.
interaction
event in twoFor now interaction are handle like this
client.on("interaction", (interaction) => {
client.executeSlash(interaction);
});
But interaction
can be CommandInteraction or ButtonInteraction.
I think it's could be nice to split this event in two like (feel free to change event's name)
client.on("interaction", (interaction) => {
//Switch statement with interaction.type or things like that
});
client.on("command", (interaction: CommandInteraction) => {
client.executeSlash(interaction);
});
client.on("button", (interaction: ButtonInteraction) => {
client.executeButton(interaction);
});
@Button('customID')
Like @slash, it could be nice to create a decorator to handle ButtonInterraction
@Discord()
abstract class ButtonExample{
//param is customID, see https://discord.js.org/#/docs/main/master/class/ButtonInteraction?scrollTo=customID
@Button('buttonExample-1')
//@Guard(...)
private buttonExample1(
interaction: ButtonInteraction
) {
//...
}
}
git clone https://github.com/owencalvin/discord.js-template
Isn't avaiable anymore.
I have tried to find the method to do it but I cannot find it. In discord.js it is easy to find because the method is message.guild.members.unban(id)
but in discord.ts I can't find the "unban" method anywhere.
Could you tell me where I can find the method? I have tried and got 0 results.
Is there an easy way to just get the args as one array? Adding an actual :args only gets the first or however many, but I'm looking for an indeterminant amount of inputs (well up to 5).
Hello,
Thank you for your library, I like TS.
When I run Main.js, this error occur (I try on your example) :
command line : node Main.js
discord.ts-master/examples/commandsDir/build/discords/DiscordApp.d.ts:1
import { CommandMessage } from '@typeit/discord';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:983:16)
at Module._compile (internal/modules/cjs/loader.js:1033:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1103:10)
at Module.load (internal/modules/cjs/loader.js:914:32)
at Function.Module._load (internal/modules/cjs/loader.js:822:14)
at Module.require (internal/modules/cjs/loader.js:956:19)
at require (internal/modules/cjs/helpers.js:74:18)
at ~/discord.ts-master/examples/commandsDir/node_modules/@typeit/discord/Client.js:81:25
at Array.map ()
at ~/discord.ts-master/examples/commandsDir/node_modules/@typeit/discord/Client.js:80:27
For an example:
The value being passed in, in this case is a roleid, roleid is supposed to be a string.
So, I told commandmessage that roleid should be a string.
It still parsed it as a number.
I fixed this locally as a test, in public/CommandMessage.js, in the parseArgs() function, by adding a check for
|| !Number.isSafeInteger(value)
to the existing conditional
This fixed the issue locally.
However there seems to be a bigger issue here. It seems like it's not even checking the ArgsType interface that is passed in to the CommandMessage object... or I may not have found the proper documentation for this, as I can't find any docs on how to use CommandMessage with both ArgsType AND InfosType.
Simple example:
@Command("find :search")
async execute(command: CommandMessage) {
const search = command.args.search;
console.log("test " + search);
}
find 76561198007433923
would yield test 76561198007433920
When i try to use the "ready" event, the value for user (UserClient) is null and i cannot use any of the ClientUser instance or method.
We should be able to use it the way the native discord.js module do
bot.on('ready', () => { bot.user.setActivity(...) })
Much appreciate if you can fix it in the near feature :)
Version 4.0.6
Adding a message
event listener works as expected:
@Discord('<')
export abstract class AppDiscord {
@On("message")
private async onMessage(
[message]: ArgsOf<"message">,
client: Client
) {
console.log(message.content);
}
}
But when a Command
is defined, all message
event listeners break
@Discord('<')
export abstract class AppDiscord {
@On("message")
private async onMessage(
[message]: ArgsOf<"message">,
client: Client
) {
console.log(message.content);
}
@Command('command')
private async command(message: CommandMessage, client: Client) {
console.log('command');
}
}
Expected: message.content
and 'command'
logged when <command
typed in chat and message.content
logged for other messages
Actual: onMessage
is never called and message.content
is never logged
The command doesn't need to be defined in the same class; @Command
annotations anywhere immediately break all other @On('message')
annotations in the project.
I am testing the forward slash commands with the following example project: https://github.com/OwenCalvin/discord.ts-starter.git
Also update the
@typeit/discord
dependency to its latest available version: 5.0.11
{
"dependencies": {
"@typeit/discord": "^5.0.11",
"discord.js": "github:discordjs/discord.js",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
"@types/node": "^15.6.0",
"ts-node": "^9.1.1",
"tslib": "^2.2.0",
"typescript": "^4.2.4"
}
}
The problem I found is when executing a command within a group. It seems that the command tree cannot be calculated correctly and returns undefined.
For better understanding I provide screenshots of debugging.
The interaction arrived successfully and get the interaction group tree
At this point, when trying to execute the getOptionsTree method on line 223, the variable _a takes the value of undefined in its second iteration
And finally the getInteractionGroupTree method ends up returning the following
Then it tries to retrieve slash from tree, accessing by case 1, but the conditions are never met because it tries to compare the group name with the command name, which is wrong
This causes the command to fail by not executing the slash
Try to be as detailed as possible so that I can share my analysis.
Thanks for your time
Regards ✌🏻
Adding the ability to further narrow down the On decorator.
Example:
@On('message','begins','!Foo') // Message begins with !Foo
private onCommandFoo(message: Message){
// ...
}
@On('message','equals','!help') // Message equals !help
private onCommandHelp(message: Message){
// ...
}
@On('message','contains','#bar') // Message contains #bar
private onHashtagBar(message: Message){
// ...
}
This way instead of having one onMessage
method which has to handle all commands that a user could send, there could be multiple methods for different commands.
Thank you for this great framework :D its very pleasant to work with.
Unfortunately I can't seem to manage to get the CommandNotFound decorator to work. Can you help me?
I have the following code for my commandnotfound function.
import {
CommandNotFound,
ArgsOf,
Guard,
} from "@typeit/discord";
import {ShouldRespond} from "../Guard/ShouldRespond";
export abstract class CommandNotFoundEvent {
@CommandNotFound()
@Guard(ShouldRespond)
async notFound([message]: ArgsOf<"commandMessage">) {
// Do something when a command is not found
message.reply("Command not found check `--list for commands`");
}
}
the ShouldRespond guard looks like this:
import {
Client,
GuardFunction,
} from "@typeit/discord";
export const ShouldRespond: GuardFunction<"message"> = async (
[message],
client: Client,
next,
guardDatas
) => {
if (message.content.startsWith(globalThis.settings.prefix) && message.author.bot === false) {
await next();
}
}
With the above code I run into this issue where whenever this event would fire it gives me this error in the console.
(node:17460) TypeError: undefined is not a function
at CommandNotFoundEvent.notFound (C:**\build\src\Event\CommandNotFound.js:8:19)
It throws this error 2 times with different errors:
UnhandledPromiseRejectionWarning:
TypeError
and also gives a DepreciationWarning:
Unhandled promise rejections are deprecated. In the future, promis rejections that are not handled will terminate the node.js process
Any help would be highly appreciated.
When we import discord.ts and create new client, it initialize MetaStorage once, https://github.com/OwenCalvin/discord.ts/blob/slash/src/logic/metadatas/MetadataStorage.ts
.
so when a event or command triggered from bot a
it will also execute bot b
events. Cause of this issue, only one bot can be used under one deployment.
Metadata does not differentiate between multiple Client objects, because it's scope is globally initialized.
Hi.
with mysql I have to return the results of a query througth a callback, but the Discord decorator doesn't accept that.
I dont know how can i get the value that is passed to callback out of its scope in order to use it in the Discord decorator.
const getPrefix = (callback: (result: string) => void) => {
connection.query("SELECT prefix FROM config", (err, rows) => {
if (err) throw err
if (rows[0]?.prefix !== undefined) {
callback(rows[0].prefix)
} else {
callback("!")
}
})
}
@Discord(getPrefix)
Version 4.0.8
(discord.js 12.3.1)
Utilizing the given tsconfig.json
from the README
Not sure what exactly is causing this exception I'm running into... However whenever I add a function with a @Command
decorator, I appear to lose functionality of my @On
event as well. Whenever the bot picks up a message, the following is thrown into stdout:
(node:4477) UnhandledPromiseRejectionWarning: TypeError: (intermediate value).flatMap is not a function
at Promise.all.events.map (/home/russjr08/discord-bot/node_modules/@typeit/src/logic/metadatas/MetadataStorage.ts:155:14)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:4477) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:4477) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Here is my class that is being used with @Discord
import { Discord, Command, CommandMessage, On, ArgsOf } from "@typeit/discord";
@Discord("&")
abstract class Bot {
@On("message")
private onMessage([message]: ArgsOf<"message">) {
console.log(`Received message from ${message.author.username} with contents ${message.content}`)
}
@Command("ping")
private onPingRequest(message: CommandMessage) {
console.log("ping received!")
}
}
If I comment out the on message event, I still get the exception. If I even send a message that does not have the & prefix, the exception is still printed. If I comment out the @Command
event, then all is fine.
I'll definitely admit I am newer to TypeScript, so it could be something I am doing wrong myself but... I've stuck with pretty much everything from README at this point.
Love the framework 🎉
I was hoping someone might be able to help me out in figuring out how to send a rich text or embedded message.
This appears to be the most up-to-date guide: https://discordjs.guide/popular-topics/embeds.html#embed-preview
Problem 1
I just discovered that even though I am installing "discord.js": "^12.1.1"
, I could see my type definition file was from 11.6.4 for some reason. I manually grabbed the updated one from GitHub.
That resolved my issues creating my MessageEmbed
.
Problem 2
CommandMessage.reply would only accept a string as far as I understand, so post this MessageEmbed
I believe we have to call CommandMessage.channel.send()
, in there I sent my MessageEmbed
.
When I test this, a post is made in the channel but it is a string, not an embedded message, and I am receiving this error:
DiscordAPIError: Cannot send an empty message
at /<my_project>/node_modules/@typeit/discord/node_modules/discord.js/src/client/rest/RequestHandlers/Sequential.js:85:15
at /<my_project>/node_modules/snekfetch/src/index.js:215:21
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
name: 'DiscordAPIError',
message: 'Cannot send an empty message',
path: '/api/v7/channels/xxxxxxxxxxxxxxxx/messages',
code: 50006,
method: 'POST'
}
Answer: send({embed: MessageEmbed})
this is example of command
when we define command name without slug like
@command("cmd")
// and then we retrieve it with ```command.commandName``, it returns
cmd
but when we do the same thing with arguments
@command("cmd :slug")
and then we retrieve it with ```command.commandName``, it returns
cmd :slug
in runtime command name is cmd
. There should be solution to get command name and arguments separately
Suggested solution: return command name with command.commandName
but make another function command.commandArguments
which returns the arguments in array format.
//command.commandName
cmd//command.commandArguments
['slug']
Discord recently shipped context menu commands for users and messages. It would be great if these can be supported as additional decorators.
They are, for the most part, registered and handled the same way as slash commands, with the only differences being:
An example usage would be something like:
@ContextMenu('Mute', 'USER')
@Guild(GUILD_ID)
@Permission(ROLE_ID, "ROLE")
private async mute(interaction: ContextMenuInteraction) {
const user = await interaction.guild.members.fetch(interaction.targetId);
await do_some_thing_with(message);
interaction.reply("done with message");
}
An alternative is to have separate @MessageContextMenu
and @UserContextMenu
decorators instead of a single one where the type can be toggled. This does not make a practical difference, since discord.js does not distinguish between the two types of responses and the function signature remains the same.
I'm trying to create a required option in a Slash Command, but it shows as a non-required option for some reason.
How to reproduce:
@Discord()
@Guild("<redacted>")
@Group("test", "Testing command sub-groups with options")
export default abstract class TestCommand {
@Slash("brega", { description: "test sub-command" })
async runCommand(
@Option("randomOption", "STRING", {
description: "This option is required.",
required: true,
})
categoryTicketID: string,
interaction: CommandInteraction
) {
interaction.reply("Certa noite em campo grande.");
}
}
The slash command is created and the option appears, but not as a required option.
No errors are showing in logs.
I am using Mikro ORM in my bot, which requires the use of a RequestContext
to ensure that it's identity map updates, and doing this with a Guard was the easiest way to make it work. Unfortunately this means that every command I create will need to be decorated with that guard, and it would be helpful to be able to globally apply this guard, either through the Client
create, or the @Discord
decorator.
This has not yet been implemented (properly) in discord.js, but it is on its way. I'm creating this issue to start a discussion and make sure there is some attention on it.
I think this is a great opportunity to utilize the @Infos
/@Description
decorators 🙂
Whenever I try to tun a simple slash command, I get a TypeError
in the getInteractionGroupTree(interaction)
method.
(node:13002) DeprecationWarning: The interaction event is deprecated. Use interactionCreate instead
(Use `node --trace-deprecation ...` to show where the warning was created)
internal/process/warning:50
TypeError: _a.values is not a function
at getOptionsTree (/home/marantesss/Documents/marantilhas/node_modules/@typeit/src/Client.ts:296:58)
at Client.getInteractionGroupTree (/home/marantesss/Documents/marantilhas/node_modules/@typeit/src/Client.ts:300:5)
at Client.executeSlash (/home/marantesss/Documents/marantilhas/node_modules/@typeit/src/Client.ts:362:23)
at Client.<anonymous> (/home/marantesss/Documents/marantilhas/src/App.ts:41:12)
...
I'm actually using nvm
to manage my node versions. But both my default and debug versions are 16.9.0
.
package.json
"scripts": {
"dev": "nodemon --config nodemon.json src/App.ts",
"build": "tsc",
"start": "node dist/App.js",
"lint": "eslint src/.",
"test": "echo 'Your tests are in another castle 🏰'"
},
"dependencies": {
"@typeit/discord": "^5.0.13",
"discord.js": "^13.1.0",
"dotenv": "^10.0.0",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^4.31.0",
"@typescript-eslint/parser": "^4.31.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"nodemon": "^2.0.12",
"prettier": "^2.3.2",
"ts-node": "^10.2.1",
"tslib": "^2.3.1",
"typescript": "^4.4.2"
}
command.commandName
return last command name inside a class. This happens when you define multiple commands under single class using decorator. Below this the example code of this issue
export abstract class Fun {
@Command("cats")
async catfaces(command: CommandMessage, client: Client) {
}
@Command("joke")
async joke(command: CommandMessage, client: Client) {
}
@Command("qr")
async qr(command: CommandMessage, client: Client) {
}
@Command("comic")
async comic(command: CommandMessage, client: Client) {
}
}
it returns comic
for all commandName for defined commands in this class such as for qr
it will return commandName comic
.
https://discordapp.com/channels/693401527494377482/693401527494377485/718265975283122216
Hello, I encountered an issue when I tried to listen to user reactions on messages :
A messageReactionAdd
listener won't trigger if the message the reaction was added on was sent before the bot started.
Code where I ran my tests :
import {ArgsOf, On} from "@typeit/discord";
export abstract class Reaction {
@On("messageReactionAdd")
private async processEvent([reaction, user]: ArgsOf<"messageReactionAdd">) {
console.log("**REACTION**", reaction.emoji.name);
}
}
The console.log()
is triggered on messages sent after the bot started, but not before.
// src/bot/bot.ts
import { ArgsOf, Discord, Client } from "@typeit/discord";
import config from "../core/config";
import * as Path from 'path';
@Discord(config.bot.prefix, {
import: [
Path.join(__dirname, "commands", "*/*command.ts")
]
})
export class Bot extends Client {}
// src/bot/commands/help.command.ts
import { Command, CommandMessage, Client, Description, Infos } from "@typeit/discord";
export abstract class HelpCommand {
@Description('Show available commands')
@Infos({ type: 'help' })
@Command('help')
async showCommands(message: CommandMessage) {
const commands = Client.getCommands();
const commandNames = [];
commands.forEach(command => {
commandNames.push(command.commandName);
})
message.channel.send(commandNames);
}
}
However, as you can see, it doesnt really add any of the metadata to the command
//console.log(Client.getCommands())
[
{
description: undefined,
infos: {},
argsRules: [ [AsyncFunction (anonymous)] ],
prefix: '\\.',
commandName: 'help'
}
]
Hi,
I'm saving the prefix set by a guild in a MongoDB and want to fetch that prefix and forward that to @Discord
.
I followed the example in the Readme and passed an async function as the first arg that queries the db and returns the correct string for the quild, or a default when no db record was found.
When I do this tho, the bot goes wild.
It will start triggering on every message (with and without prefix, or with any prefix) and execute a command mulitple times in a row, even when it was only called once.
Adding something like if (message.content[0] !== myPrefix) return;
would not stop the bot from triggering multiple times for every message sent in the channel and DMs.
Removing the async fn getPrefix
again fixes this behavior of the bot and it stops spamming.
Example:
async function getPrefix(message: Message) {
try {
const prefix: string = await getGuildPrefix(message); // gets findById(message.guild.id) with mongoose and returns the prefix field
return prefix || '$'; // '$' is the default here
} catch (err) {
return '$';
}
}
@Discord(getPrefix, {
import: [
join(__dirname, '../commands', '*.ts'),
join(__dirname, '../events', '*.ts'),
],
})
export class DiscordApp { ... }
Am I missing something?
This is probably also not the best way to go about this, since I would query the DB on every command/message/event. Where should I do this instead to persist the data and only query for the prefix once on startup? Should I not set a global prefix with @Discord
but rather add a Guard or Rule to check for the prefix?
Thanks for your help
Unhandled rejection TypeError: undefined is not a function
at DGuard.guard [as _fn] (/config/workspace/plumeware/src/guards/SlashCommandPermission.ts:5:55)
at next (/config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:83:37)
at /config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:97:34
at DSlash.<anonymous> (/config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:29:43)
at Bot.executeSlash (/config/workspace/plumeware/node_modules/@typeit/src/Client.ts:368:24)
at AppDiscord.onMessage (/config/workspace/plumeware/src/events/interaction.ts:8:12)
at next (/config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:74:37)
at /config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:97:34
at DOn.<anonymous> (/config/workspace/plumeware/node_modules/@typeit/src/decorators/classes/Method.ts:29:43)
at Bot.<anonymous> (/config/workspace/plumeware/node_modules/@typeit/src/logic/metadatas/MetadataStorage.ts:301:30)
SlashCommandPermission.ts
import { GuardFunction, ArgsOf } from '@typeit/discord';
import { PermissionResolvable } from 'discord.js';
export function SlashCommandPermission(permissions: PermissionResolvable[] | PermissionResolvable) {
const guard: GuardFunction<ArgsOf<'interaction'>> = async ([interaction], client, next, guardDatas) => {
const perms = Array.isArray(permissions) ? permissions : [permissions];
const guildMember = interaction.guild.members.cache.get(interaction.member.user.id);
const hasPermissions = perms.every((perm) => guildMember.permissions.has(perm));
if (!hasPermissions) {
guardDatas.error = 'You have no access to this command';
}
await next();
};
return guard;
}
Some controller:
@Discord()
@Group('channel', 'Add or remove channel to bot watching list')
@Guard(SlashCommandPermission('MANAGE_CHANNELS'))
export abstract class AppDiscord {
@Slash('add')
async add(
@Option('channelId', { description: 'id of the channel for listening on join', required: true })
channelId: string,
interaction: CommandInteraction,
guardDatas: Record<string, string>,
) {
if (guardDatas.error) {
interaction.reply(guardDatas.erorr);
} else {
const result = await add(interaction, channelId);
interaction.reply(result);
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.