Giter VIP home page Giter VIP logo

necord's People

Contributors

antonygarand avatar dependabot[bot] avatar eliasgcf avatar forfalt avatar nedcloarbr avatar renovate[bot] avatar socketsomeone avatar wolffparkinson avatar ystneris 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

necord's Issues

Support native guards

Feature

When doing server management feature, such as changing the prefix or whitelisted channels, the command must be restricted to elevated users.
Instead of making a custom guard or decorator, I believe this would be a good feature to integrate within necord itself.

Currently, this must be done in a guard, and using a "manual" way to specify the required permissions.
Ex:

// command
@UseGuards(ServerAdminGuard)
// guard
interaction.memberPermissions.has(Permissions.FLAGS.MANAGE_GUILD)

It would be much cleaner to have this within its own @GuildPermission decorator, or within arguments to the Command decorator.

Ideal solution or implementation

@SlashCommand('name', 'desc', { defaultPermission: true, guildPermission: [Permissions.FLAGS.MANAGE_GUILD] } )
// or
@SlashCommand('name','desc')
@GuildPermissions(Permissions.FLAGS.MANAGE_GUILD)

Alternative solutions or implementations

No response

Other context

No response

how to use send message to channels

What is your question?

`
@Injectable()
export class GeneralLogger implements LoggerService {
private readonly logger = new Logger(GeneralLogger.name);

public constructor(
private readonly client: Client,
private readonly configServer: ConfigService,
) {}

@once('ready')
public onReady(@context() [client]: ContextOf<'ready'>) {
this.logger.log(Bot logged in as ${client.user.username});
}

@on('warn')
public onWarn(@context() [message]: ContextOf<'warn'>) {
this.logger.warn(message);
}

log(message: string): void {
this.logger.log('info', message);
}

error(message: string): void {
this.logger.log('error', message);
}

warn(message: string): void {
this.logger.log('warn', message);
}

debug(message: string): void {
this.logger.log('debug', message);
}

verbose(message: string): void {
this.logger.log('debug', message);
}

sendToMessage(message: string) {
const channel = this.client.channels.cache.get('1131273538611982538') as any;
channel.send(message);
}
}
`
necord version 6.1

error 'TypeError: undefined is not an object (evaluating 'this.client.channels.cache.get("1131273538611982538").send')
at sendToMessage (/home/tuan-dd/repos/project_mentor/src/global/services/logger-general.service.ts:49:24)
at getHello (/home/tuan-dd/repos/project_mentor/src/app.service.ts:9:11)
at (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/router/router-execution-context.js:37:48)
at intercept (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/interceptors/interceptors-consumer.js:10:16)
at (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/router/router-execution-context.js:46:51)
at (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/router/router-execution-context.js:40:30)
at (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/router/router-proxy.js:10:12)
at (/home/tuan-dd/repos/project_mentor/node_modules/@nestjs/core/router/router-proxy.js:7:16)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/route.js:146:11)
at dispatch (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/route.js:115:21)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:283:43)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at (node:domain:34:22)
at runInContextMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/request-context/lib/index.js:136:28)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at urlencodedParser (/home/tuan-dd/repos/project_mentor/node_modules/body-parser/lib/types/urlencoded.js:91:6)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at jsonParser (/home/tuan-dd/repos/project_mentor/node_modules/body-parser/lib/types/json.js:113:6)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:518:6)
at xXssProtectionMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:294:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xPoweredByMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:287:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xPermittedCrossDomainPoliciesMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:280:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xFrameOptionsMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:264:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xDownloadOptionsMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:244:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xDnsPrefetchControlMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:237:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at xContentTypeOptionsMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:229:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at strictTransportSecurityMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:222:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at referrerPolicyMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:190:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at originAgentClusterMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:165:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at crossOriginResourcePolicyMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:158:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at crossOriginOpenerPolicyMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:142:7)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at contentSecurityPolicyMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:107:8)
at internalNext (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:514:46)
at helmetMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/helmet/index.mjs:518:6)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at compression (/home/tuan-dd/repos/project_mentor/node_modules/compression/index.js:219:9)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at logger (/home/tuan-dd/repos/project_mentor/node_modules/morgan/index.js:143:9)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at cors (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:187:11)
at (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:225:13)
at originCallback (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:213:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:219:27)
at optionsCallback (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:198:18)
at corsMiddleware (/home/tuan-dd/repos/project_mentor/node_modules/cors/lib/index.js:204:12)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at expressInit (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/middleware/init.js:39:9)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
at process_params (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:349:6)
at next (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:280:10)
at query (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/middleware/query.js:44:9)
at handle (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/layer.js:94:21)
at trim_prefix (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:327:41)
at (/home/tuan-dd/repos/project_mentor/node_modules/express/lib/router/index.js:288:13)
localhost - - [25/Sep/2023:18:11:01 +0000] "GET / HTTP/1.1" - - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"'

Guards: Provide event handler context

Feature

When an event is captured by multiple event handlers, such as by having a @On('interactionCreate') decorator, a new context will be created and sent to the various receiving parties.
While this is not bad or wrong it itself, it can cause an issue with global guards: If your guard replies or interacts to the interaction, as the guard will be executed multiple times, it can cause the message to be sent multiple times, or the second+ guard to trigger a discord error "Unknown interaction".
Note that even in the following code, as both interactions are technically a new context, interaction.replied is false in both of them.
image

Ideal solution or implementation

  1. Provide the execution context within NecordExecutionContext.getInfo(), with the entity on which the decorator is applied.
    This will allow us to avoid answering or replying to the guard if the execution is not on an ApplicationCommand, but on the generic InteractionCreate handler instead for example.
  2. Provide the same discord context within the different components: The interaction itself should be shared, making it so interaction.replied is properly populated.
  3. Provide the index of the interaction within the necord context, so we know to only block it once for example.

Alternative solutions or implementations

No response

Other context

No response

Options from slash command are undefined if you use TypeORM

Issue description

Steps to reproduce:

  1. Create Nest project using following command nest new necord_issue
  2. Remove unnecessary files (leave only app.module.ts and main.ts under src folder)
  3. Install Necord and discordjs npm install necord discord.js
  4. Under src create folder discord which will represent discord module of nest application
  5. Under discord folder create discord.module.ts file with following content and register this module inside app.module:
import { GatewayIntentBits } from 'discord.js';
import { NecordModule } from 'necord';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot(),
    NecordModule.forRoot({
      token: process.env.DISCORD_BOT_TOKEN,
      intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent,
        GatewayIntentBits.GuildMessageReactions,
      ],
      development: [process.env.DISCORD_DEVELOPMENT_GUILD_ID],
    }),
  ],
  providers: [],
})
export class DiscordModule {}
  1. Create discord.service.ts with following content (to create slash command) and define it in discord.module.ts inside providers array
import {
  Context,
  Options,
  SlashCommand,
  SlashCommandContext,
  StringOption,
} from 'necord';
import { Injectable } from '@nestjs/common';

class TextDto {
  @StringOption({
    name: 'text',
    description: 'Your text',
    required: true,
  })
  text: string;
}

@Injectable()
export class DiscordService {
  @SlashCommand({
    name: 'length',
    description: 'Get length of text',
  })
  public async onLength(
    @Context() [interaction]: SlashCommandContext,
    @Options() { text }: TextDto,
  ) {
    return interaction.reply({ content: `Length of your text ${text.length}` });
  }
}
  1. If you run the bot and try to use command then everything is okay. But let's install typeorm
  2. Install TypeOrm npm i @nestjs/typeorm typeorm pg config @nestjs/config
  3. In the app.module.ts configure TypeOrmModule
@Module({
  imports: [
    DiscordModule,
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.PG_HOST,
      username: process.env.PG_USER,
      password: process.env.PG_PASS,
      database: process.env.PG_DATABASE,
      ssl: true,
      autoLoadEntities: true,
      synchronize: true,
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
  1. If you run the bot and try to use command then you will get an error
E:\Learning\necord_issue\src\discord\discord.service.ts:29
    return interaction.reply({ content: `Length of your text ${text.length}` });
                                                                    ^
TypeError: Cannot read properties of undefined (reading 'length')
    at DiscordService.onLength (E:\Learning\necord_issue\src\discord\discord.service.ts:29:69)
    at E:\Learning\necord_issue\node_modules\@nestjs\core\helpers\external-context-creator.js:69:29
    at InterceptorsConsumer.intercept (E:\Learning\necord_issue\node_modules\@nestjs\core\interceptors\interceptors-consumer.js:12:20)
    at target (E:\Learning\necord_issue\node_modules\@nestjs\core\helpers\external-context-creator.js:74:60)
    at SlashCommandDiscovery.contextCallback (E:\Learning\necord_issue\node_modules\@nestjs\core\helpers\external-proxy.js:9:30)
    at SlashCommandDiscovery.execute (E:\Learning\necord_issue\node_modules\necord\dist\context\necord-base.discovery.js:25:21)
    at SlashCommandDiscovery.execute (E:\Learning\necord_issue\node_modules\necord\dist\commands\slash-commands\slash-command.discovery.js:45:22)
    at Client.<anonymous> (E:\Learning\necord_issue\node_modules\necord\dist\commands\slash-commands\slash-commands.module.js:37:112)
    at Client.emit (node:events:526:35)
    at InteractionCreateAction.handle (E:\Learning\necord_issue\node_modules\discord.js\src\client\actions\InteractionCreate.js:97:12)

Code sample

Link to repo with reproduction - https://github.com/iAmArbuzik/necord_issue

discord.js version

14.14.1

nest.js version

10.3.2

Node.js version

nodejs version - v20.10.0 typescript version - v5.3.3

Operating system

OS Windows 11 (Version 10.0.22621)

Priority this issue should have

High (immediate attention needed)

Which partials do you have configured?

No Partials

Which gateway intents are you subscribing to?

GUILDS, GUILD_MESSAGES, GUILD_MESSAGE_REACTIONS

Modals

  • Wait for the feature to be released in Discord

The `guilds` property is broken at all commands

Issue description

After v5.7.0, the commands that receive guilds property are not registering this commands as Guild Application Commands, but as Global Application Commands.

At v5.6.1 it works fine.

Code sample

No response

discord.js version

14.11.0

nest.js version

9.4.0

Node.js version

16.19.1

Operating system

macOS

Priority this issue should have

High (immediate attention needed)

Which partials do you have configured?

No Partials

Which gateway intents are you subscribing to?

GUILDS, GUILD_MEMBERS, GUILD_MESSAGES

How to test ?

What is your question?

How to test the spec files ?

Guide to use with Fastify adapter?

What is your question?

Looking for a guide that how to set this up with NestJs using Fastify. The simple configuration as mentioned in docs doesn't seem to work and raising errors.

C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\platform-fastify\adapters\fastify-adapter.js:242
        return !('status' in response);
                          ^

TypeError: Cannot use 'in' operator to search for 'status' in undefined
    at FastifyAdapter.isNativeResponse (C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\platform-fastify\adapters\fastify-adapter.js:242:27)
    at FastifyAdapter.reply (C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\platform-fastify\adapters\fastify-adapter.js:117:35)
    at ExceptionsFilter.catch (C:\Users\Priyam\Documents\api-next\dist\main.js:844:21)
    at ExternalExceptionsHandler.invokeCustomFilters (C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\core\exceptions\external-exceptions-handler.js:34:32)
    at ExternalExceptionsHandler.next (C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\core\exceptions\external-exceptions-handler.js:13:29)
    at Object.execute (C:\Users\Priyam\Documents\api-next\node_modules\@nestjs\core\helpers\external-proxy.js:14:42)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

Node.js v17.1.0

Interaction Decorators

  • On
  • Button Component
  • Select Component
  • Message Command (Context Menu)
  • User Command (Context Menu)
  • Slash Command
  • Groups and SubGroups

Registry

  • Message Components
  • Application Commands
  • (Optional) Listeners

Permissions v2

Feature

.

Ideal solution or implementation

.

Alternative solutions or implementations

No response

Other context

No response

Collectors

Feature

DJS collectors for :

  • Message Collector
  • Interaction Collector
  • Reaction Collector

Ideal solution or implementation

abstract class :

  • InteractionCollector
  • MessageCollector
  • ReactionCollector

methods on these classes

  • onCollect
  • onFilter

using interceptors, intercept the interactions/events and pass them to relevant contexts and methods

Alternative solutions or implementations

decorators based approach :

  • InteractionCollector
  • MessageCollector
  • ReactionCollector

Other context

No response

Dynamic matching for Modals

Feature

Dynamic matching for customId of modals, similar to what is there for Components

Ideal solution or implementation

pattern matching in ModalInteraction service

Alternative solutions or implementations

No response

Other context

No response

Update the documentation to include sharding.

What is your question?

I didn't know this package existed until @jmcdo29 told me about it on the nestjs discord. It seems you support more than the @discord-nestjs/core package. I made a recommendation to them about adding documentation for sharding, I created a simple explanation here.

I think adding something similar to your documentation would be extremely beneficial. It would also be worth your time to add examples using discord-hybrid-sharding and discord-cross-hosting packages I mentioned in the explanation above as this is super important for bots that require scale.

I would be more than happy to contribute to the documentation if this suits you!

User and Emoji Providers is null or empty

Issue description

So it's embarrassing to say this, but the PR #1117 I did yesterday has a bug...
I've been trying to find some way to fix this for 3h but I haven't found it
I did the PR on emotion and forgot to test before opening it ๐Ÿ˜ฅ
In short, the client.user only stores the client user after it emits the Ready event, and the same goes for client.emojis , but seeing by this logic the GuildProvider(client.guilds) was not supposed to work but works
image
image

Code sample

import { BaseGuildEmojiManager, Client, ClientUser } from "discord.js";
import { Module, OnApplicationBootstrap } from "@nestjs/common";

@Module({})
export class IssueModule implements OnApplicationBootstrap {
  public constructor(
    private readonly emojis: BaseGuildEmojiManager,
    private readonly user: ClientUser,
    private readonly client: Client
  ) {}

  public onApplicationBootstrap () {
    console.log(this.client.user)
    console.log(this.user)
    console.log(this.emojis.cache)
    console.log(this.client.emojis.cache)
  }
}

discord.js version

14.14.1

nest.js version

10.3.3

Node.js version

NodeJS v20.6.1 | TypeScript v5.4.2

Operating system

Linux 5.15 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

USER, CHANNEL, GUILD_MEMBER, MESSAGE, REACTION

Which gateway intents are you subscribing to?

GUILDS, GUILD_MEMBERS, GUILD_BANS, GUILD_EMOJIS_AND_STICKERS, GUILD_INTEGRATIONS, GUILD_WEBHOOKS, GUILD_INVITES, GUILD_VOICE_STATES, GUILD_PRESENCES, GUILD_MESSAGES, GUILD_MESSAGE_REACTIONS, GUILD_MESSAGE_TYPING, DIRECT_MESSAGES, DIRECT_MESSAGE_REACTIONS, DIRECT_MESSAGE_TYPING

Support for NestJS v9

Feature

A good addition would be to not have warning messages on newly scaffolded NestJS projects after adding Necord.

Ideal solution or implementation

Add @nestjs/common and @nestjs/core ^9.0.0 as optional peer dependency

Alternative solutions or implementations

No response

Other context

No response

Clean up non-existing guild commands when using `guilds` property

Feature

When using command guilds property, then changing name after command has been registered doesn't remove the old one.

Ideal solution or implementation

Maybe remove all guild commands and re-register all current one?

Alternative solutions or implementations

No response

Other context

No response

Get the discordjs client instance

What is your question?

It is possible to get the discordjs client as a provider in others classes constructor? I didn't find about in documentation.

Apply SlashGroup decorator only once

Feature

  • Current implementation of subcommand groups with subcommands requires @SlashGroup(name,description) decorator on every subcommand method implementation. It would be really useful to minimize code repeatability while developing bots, also reduced source of developer related typo bugs.
  • Also current implementation of subcommand group naming is kinda counter-intuitive with Discord's naming.

Discord

slash-command
  |-subcommand-1
  |-subcommand-2
  |-subcommand-group-1
  |   |-subcommand-1
  |   |-subcommand-2 
  |   |-subcommand-3
  |-subcommand-group-2
      |-subcommand-1
      |-subcommand-2 
      |-subcommand-3 

Current implementation

@SlashCommand
  |--@SlashCommand-1
  |--@SlashCommand-2
  |--@SlashGroup-1
  |  @SlashCommand-1
  |--@SlashGroup-1
  |  @SlashCommand-2
  |--@SlashGroup-1
  |  @SlashCommand-3
  |--@SlashGroup-2
  |  @SlashCommand-1
  |--@SlashGroup-2
  |  @SlashCommand-2
  |--@SlashGroup-2
  |  @SlashCommand-3

Ideal solution or implementation

  • Seperate Decorators for Subcommands
  • Combine Subcommands under a Subcommand group into a single class, which also makes it easier to implement guards and other lifecycle events on a group.
import {
  Ctx,
  SlashCommand,
  SlashCommandContext,
  SlashWithGroups,
  Subcommand,
  SubCommandGroup
} from 'necord';

@SubCommandGroup('utility', 'Basic utilities')
export class Utility {
  @Subcommand('ping', 'Utility for checking network latency')
  ping(@Ctx() [interaction]: SlashCommandContext) {
    return interaction.reply('pong from subcommand in subcommand group');
  }
}

@SlashCommand('help', 'Helpful information regarding bot')
export class SlashCommandWithSubcommands implements SlashWithGroups {
  groups = [new Utility()];

  @Subcommand('ping', 'pongs you !')
  pingMe(@Ctx() [interaction]: SlashCommandContext) {
    return interaction.reply('pong from subcommand');
  }
}

Alternative solutions or implementations

No response

Other context

I am willing to submit a PR, I have a branch ready

defaultMemberPermissions does not work on Subcommand but is typed

Issue description

defaultMemberPermissions is allowed as configuration option for the @subcommand decorator, but does nothing when set.

Code sample

import {
    PermissionFlagsBits,
} from 'discord.js';
import {
    Context,
    SlashCommandContext,
    Subcommand,
} from 'necord';

@Subcommand({
        name: 'command',
        description: 'Bla',
        defaultMemberPermissions: [PermissionFlagsBits.Administrator],
    })
    public async onCommand(
        @Context() [interaction]: SlashCommandContext,
    ): Promise<InteractionResponse<boolean>> {
        // func
    }

discord.js version

14.13.0

nest.js version

10.2.7

Node.js version

18.17.1

Operating system

MacOS but running in docker with official alpine node image

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

No Partials

Which gateway intents are you subscribing to?

GUILDS

Regex and dynamic matching support for Button

Feature

The current @Button decorator only accepts strings, which is limiting if we want to support dynamic button id's.
To store a bit of metadata within buttons, as they do not have a value property, we need to store it within the id.
For example, if we want to have a button to approve or decline an event, they have the id approve:1234, where approve is the action, and 1234 the id of the even which we want to approve.
This is loosely equivalent to a route for /approve/:id if it were a controller.

The idea behind this feature is to add support for dynamic matching.

Ideal solution or implementation

The easiest solution would be to support string | regex and to use buttonId.test(regex) to match the routes.
The user can then access the id and find his own arguments using button.id.

An enhancement would be to support named captures: @Button(/^approve:(?<id>\d+/), and add the captures or the match as a whole as an argument similarly to @Options for @SlashCommands.

Alternative solutions or implementations

To get a simpler solution not involving regex, there could be a matching system similar to routes in controllers, where the named arguments would be described within the string: approve/:id to match ^approve/(?<id>.*)
Finally this could be accessed via a decorator such as @Param('id') in the event listener.

This would require more work to convert strings to regexes to matches, but could be a simple approach compared to having users do their own regexes, and be similar to routes for controllers.

Other context

No response

Add samples

  • Preview of Module register, Discord Events & Message Components
  • Preview of Slash Commands
  • Preview of Context Menus

Development mode - Set all commands to a specific guild

Feature

As guild commands and global commands have a different timeout, the global ones being cached for up to an hour, development is best done with guild commands when possible.
For this purpose, I suggest a way to pass a development guild id to necord, which would do the same as adding the @Guilds decorator on all commands, applying it globally.

Ideal solution or implementation

I believe this would be best applied within the necord module configuration:

    NecordModule.forRoot({
      token: "token",
      intents: [],
      isDevelopment: false | "guild" | "guilds"[]
    }),

Alternative solutions or implementations

No response

Other context

No response

Centralising errors catching

What is your question?

Hello,

First and foremost thanks for releasing this, much appreciated!

I am building a new version of a bot I previously created with discord.js. One of the features I previously used was a centralised error catching for all my slash commands. This includes old commands that I removed, but are still pending in the guild.

Is there a place where to create this catchall for errors?

Thanks

Autocomplete: Support multiple `@Autocomplete` on a single command

Feature

Add support for multiple @Autocomplete on a single command.
At the moment, to support multiple autocomplete fields, one must add this feature within the autocompleter itself, by using focused.name to find out which component it needs to autocomplete.

switch(focused.name) {
  case 'color':
    ...
  case 'meal'
    ...
  default:
    []
}

This makes it hard to reuse the same autocomplete logic across components: If many commands rely on the colorAutocomplete, but only one of them needs to also autocomplete the meal, you would need to manually merge both of them for this one command.

Ideal solution or implementation

I would like to add support for autocomplete chaining:

@Autocomplete(colorAutocomplete, mealAutocomplete)

This would run all of the autocompletes until one returns data, allowing them to return a falsy value if the autocomplete is not made for this input.

This would also open the way for a Global autocomplete, filtering itself from of the input.name, to reduce boilerplate:

NecordModule.forRoot({
  // ...
  globalAutocomplete: [ colorAutocomplete ]
}),

Alternative solutions or implementations

No response

Other context

No response

Ordering command arguments

Feature

Slash command arguments are currently sorted in the order they are in the class, and can't be reordered within necord.

I'd recommend to have an index: number property added to the various command options (StringOption, BooleanOption, etc.) to specify the order in which we want them to appear.

image

Ideal solution or implementation

Adding an index property on the various comand options:

  @StringOption({
    name: "option",
    description:
      "The rsn for one of your accounts (defaults to all accounts if no rsn is provided)",
    required: false,
    autocomplete: true,
    index: 2,
  })

Alternative solutions or implementations

No response

Other context

No response

Support websocket events

Feature

Hey! Currently NecordEvents has quite a lot of events that are really helpful, but most of ws-events are missing, and they are really useful for debugging and other stuff.

Ideal solution or implementation

Allow the @on decorator to handle the missing ws-events.

Alternative solutions or implementations

No response

Other context

No response

Params Decorators

  • Context
  • String Option
  • Integer Option
  • Boolean Option
  • User Option
  • Channel Option
  • Role Option
  • Mentionable Option
  • Number Option

Not resolving /interactions route

What is your question?

Hi, do I need to manually set up /interactions route and direct requests to discord service? From reading documentation I was under the impression that it'd be done automatically by NecordModule during setup. Could you please clarify, many thanks.

Group commands overwriting instead of grouping

Issue description

After v6.1.0 released, sub-commands weren't appearing as application commands. Downgrading to v6.0.0 fixed that.

Code sample

import { Injectable } from '@nestjs/common';
import { Subcommand, createCommandGroupDecorator } from 'necord';

const DemoCommands = createCommandGroupDecorator({
  name: 'demo',
  description: 'Just a demo command group',
});

@Injectable()
@DemoCommands()
export class TestCommands {
  @Subcommand({ name: 'first', description: 'First demo command' })
  async demoFirst() {}

  @Subcommand({ name: 'second', description: 'Second demo command' })
  async demoSecond() {}
}

discord.js version

14.13.0

nest.js version

10.2.1

Node.js version

18.17.1

Operating system

Ubuntu 22.04.3 LTS

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

No Partials

Which gateway intents are you subscribing to?

GUILDS, GUILD_MEMBERS, GUILD_VOICE_STATES, GUILD_PRESENCES, GUILD_MESSAGES

Github

  • Labels
  • Templates
  • Contributing
  • Security
  • Funding
  • Autodeploy

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.