Giter Site home page Giter Site logo

owengombas / discord.ts Goto Github PK

View Code? Open in Web Editor NEW
322.0 7.0 41.0 1.03 MB

🤖 Create your discord bot by using TypeScript and decorators!

Home Page: https://owencalvin.github.io/discord.ts/

TypeScript 99.62% JavaScript 0.18% Shell 0.20%
discord discord-bot typescript decorators bot type command slash slash-commands

discord.ts's Introduction

🎓 Master's student in Computer Science at University of Bern

discord.ts's People

Contributors

adondriel avatar andyclausen avatar dbrxnds avatar feixuruins avatar hnrklssn avatar keanu73 avatar owengombas avatar russjr08 avatar samarmeena avatar steeledslagle13 avatar stijnstroeve avatar tonyeung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

discord.ts's Issues

getInteractionGroupTree TypeError

Whenever I try to tun a simple slash command, I get a TypeError in the getInteractionGroupTree(interaction) method.

Error Stack

(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)
    ...

Debug screenshot

image

Node version

I'm actually using nvm to manage my node versions. But both my default and debug versions are 16.9.0.

My 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"
  }

CommandMessage converts args to number without regards to whether it is safe to do so. (and ignores argtypes property)

For an example:
Discord_2020-07-17_223
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.
image

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

image

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.

Can't use @Permission on class

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

Support ButtonInteraction

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.

Proposal 1 - Split interaction event in two

For 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);
  });

Proposal 2 - Create a decorator @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
    ) {
        //...
    }
}

Add support for slash commands

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 🙂

Info and Description decorators not working on commands

// 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'
  }
]

bigint support

Simple example:

@Command("find :search")
async execute(command: CommandMessage) {
    const search = command.args.search;
    console.log("test " + search);
}

find 76561198007433923 would yield test 76561198007433920

Support for Context Menu (User and Message) Interactions

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:

  • There is no description
  • There are no options (the Interaction includes the user/message that the menu was used on)

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.

On READY event return null for ClientUser property

Problem:

on_ready_user_null
image
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.

Expectation:

We should be able to use it the way the native discord.js module do
bot.on('ready', () => { bot.user.setActivity(...) })

My workaround solution for now:

workaround_solution

Much appreciate if you can fix it in the near feature :)

[Question] How to to send a MessageEmbed?

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})

"messageReactionAdd" listener is not triggered in old messages

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.

function required to read command arguments separately

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']

[Question/bug] The @CommandNotFound decorator seems to not function for me

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.

Multiple bots support

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.

Steps to reproduce

  1. create a bot with a event like onready.
  2. create another bot with a event like onready but different output.
  3. turn on both bots, and when your bots ready, you will see 4 outputs, but you were expecting only two outputs.

Reason of problem

Metadata does not differentiate between multiple Client objects, because it's scope is globally initialized.

Guards TypeError: undefined is not a function

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);
    }
  }
}

guildMemberAdd and guildMemberRemove events seem to not work somehow

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);
  }
}

[FEATURE] Option to mention bot

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.

Add brackets when calling empty Discord decorator

Problem

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

Solution

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.

Command alias working without a prefix

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) {...}

@Command breaks @On('message')

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.

[Feature Request] Globally apply a guard

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.

cannot use dynamic prefix with Mysql

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)

Can't use @Option as a required option

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.

API v8

Discord API version 8 has been released and versions 6 and 7 are deprecated

Customize @On Decorator

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.

commandName bug

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

Args as array

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).

Cannot use import statement outside a module

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

How to unban a user?

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.

Speaking event not triggering

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)
                })
                

Utilizing @Command causes an UnhandledPromiseRejectionWarning

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.

Fetching Prefix dynamically from mongoDB

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

The slash command does not execute correctly

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.

Analysis:

  1. I run my command on my discord server
    1

  2. The interaction arrived successfully and get the interaction group tree
    2

  3. 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
    3
    3bis

  4. And finally the getInteractionGroupTree method ends up returning the following
    4

  5. 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
    5

  6. And consequently, it ends up returning slash undefined
    6

This causes the command to fail by not executing the slash
7

Try to be as detailed as possible so that I can share my analysis.

Thanks for your time
Regards ✌🏻

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.