Skip to content

Commit

Permalink
refactor(discordx): discordjs builders support (#1065)
Browse files Browse the repository at this point in the history
* refactor(discordx): discordjs builders support

* refactor: add doc example

* refactor: bump version
  • Loading branch information
vijayymmeena authored Jun 29, 2024
1 parent 86a29fd commit c7c1759
Show file tree
Hide file tree
Showing 18 changed files with 494 additions and 60 deletions.
48 changes: 41 additions & 7 deletions docs/docs/discordx/decorators/command/slash-option.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@ class Example {
}
```

## Create option using discord.js builders

```ts
import {
SlashCommandBuilder,
SlashCommandMentionableOption,
User,
type CommandInteraction,
} from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("hello")
.setDescription("Say hello!");

const user_option = new SlashCommandMentionableOption()
.setName("user")
.setDescription("Mention user to say hello to.")
.setRequired(true);

@Discord()
export class Example {
@Slash(cmd)
async hello(
@SlashOption(user_option) user: User,
interaction: CommandInteraction,
): Promise<void> {
await interaction.reply(`:wave: ${user}`);
}
}
```

## Transformer

Act as middleware for your parameters. Take a look at the following example to see how useful it is.
Expand Down Expand Up @@ -81,13 +113,15 @@ function DocumentTransformer(
export class Example {
@Slash({ description: "Save input into database", name: "save-input" })
async withTransformer(
@SlashOption({
description: "input",
name: "input",
required: true,
transformer: DocumentTransformer,
type: ApplicationCommandOptionType.String,
})
@SlashOption(
{
description: "input",
name: "input",
required: true,
type: ApplicationCommandOptionType.String,
},
DocumentTransformer,
)
doc: Document,
interaction: ChatInputCommandInteraction,
): Promise<void> {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions packages/discordx/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# discordx

## 11.12.0

### Minor Changes

- added support for slash command builder

## 11.11.3

### Patch Changes
Expand Down
41 changes: 41 additions & 0 deletions packages/discordx/examples/builders/commands/autocomplete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* -------------------------------------------------------------------------------------------------------
* Copyright (c) Vijay Meena <[email protected]> (https://github.com/samarmeena). All rights reserved.
* Licensed under the Apache License. See License.txt in the project root for license information.
* -------------------------------------------------------------------------------------------------------
*/
import {
AutocompleteInteraction,
SlashCommandBuilder,
SlashCommandStringOption,
type CommandInteraction,
} from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("planet-auto")
.setDescription("Select a planet");

const planet_option = new SlashCommandStringOption()
.setName("planet")
.setDescription("Choose a planet")
.setRequired(true)
.setAutocomplete(true);

@Discord()
export class Example {
@Slash(cmd)
async hello(
@SlashOption(planet_option) planet: string,
interaction: CommandInteraction | AutocompleteInteraction,
): Promise<void> {
if (interaction.isAutocomplete()) {
interaction.respond([
{ name: "Earth", value: "Earth" },
{ name: "Mars", value: "Mars" },
]);
} else {
await interaction.reply(`:rocket: going to ${planet}`);
}
}
}
36 changes: 36 additions & 0 deletions packages/discordx/examples/builders/commands/choice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* -------------------------------------------------------------------------------------------------------
* Copyright (c) Vijay Meena <[email protected]> (https://github.com/samarmeena). All rights reserved.
* Licensed under the Apache License. See License.txt in the project root for license information.
* -------------------------------------------------------------------------------------------------------
*/
import {
SlashCommandBuilder,
SlashCommandStringOption,
type CommandInteraction,
} from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("planet")
.setDescription("Select a planet");

const planet_option = new SlashCommandStringOption()
.setName("planet")
.setDescription("Choose a planet")
.setRequired(true)
.addChoices([
{ name: "Earth", value: "Earth" },
{ name: "Mars", value: "Mars" },
]);

@Discord()
export class Example {
@Slash(cmd)
async hello(
@SlashOption(planet_option) planet: string,
interaction: CommandInteraction,
): Promise<void> {
await interaction.reply(`:rocket: going to ${planet}`);
}
}
33 changes: 33 additions & 0 deletions packages/discordx/examples/builders/commands/hello.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* -------------------------------------------------------------------------------------------------------
* Copyright (c) Vijay Meena <[email protected]> (https://github.com/samarmeena). All rights reserved.
* Licensed under the Apache License. See License.txt in the project root for license information.
* -------------------------------------------------------------------------------------------------------
*/
import {
SlashCommandBuilder,
SlashCommandMentionableOption,
User,
type CommandInteraction,
} from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("hello")
.setDescription("Say hello!");

const user_option = new SlashCommandMentionableOption()
.setName("user")
.setDescription("Mention user to say hello to.")
.setRequired(true);

@Discord()
export class Example {
@Slash(cmd)
async hello(
@SlashOption(user_option) user: User,
interaction: CommandInteraction,
): Promise<void> {
await interaction.reply(`:wave: ${user}`);
}
}
20 changes: 20 additions & 0 deletions packages/discordx/examples/builders/commands/ping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* -------------------------------------------------------------------------------------------------------
* Copyright (c) Vijay Meena <[email protected]> (https://github.com/samarmeena). All rights reserved.
* Licensed under the Apache License. See License.txt in the project root for license information.
* -------------------------------------------------------------------------------------------------------
*/
import { SlashCommandBuilder, type CommandInteraction } from "discord.js";
import { Discord, Slash } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("ping")
.setDescription("Reply with pong!");

@Discord()
export class Example {
@Slash(cmd)
async ping(interaction: CommandInteraction): Promise<void> {
await interaction.reply("Pong");
}
}
55 changes: 55 additions & 0 deletions packages/discordx/examples/builders/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* -------------------------------------------------------------------------------------------------------
* Copyright (c) Vijay Meena <[email protected]> (https://github.com/samarmeena). All rights reserved.
* Licensed under the Apache License. See License.txt in the project root for license information.
* -------------------------------------------------------------------------------------------------------
*/
import { dirname, importx } from "@discordx/importer";
import { IntentsBitField } from "discord.js";
import { Client } from "discordx";

export class Main {
private static _client: Client;

static get Client(): Client {
return this._client;
}

static async start(): Promise<void> {
this._client = new Client({
// botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)],
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.GuildMembers,
],
silent: false,
});

this._client.once("ready", () => {
// An example of how guild commands can be cleared
//
// await this._client.clearApplicationCommands(
// ...this._client.guilds.cache.map((guild) => guild.id)
// );

void this._client.initApplicationCommands();

console.log(">> Bot started");
});

this._client.on("interactionCreate", (interaction) => {
this._client.executeInteraction(interaction);
});

await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`);

// let's start the bot
if (!process.env.BOT_TOKEN) {
throw Error("Could not find BOT_TOKEN in your environment");
}
await this._client.login(process.env.BOT_TOKEN);
}
}

void Main.start();
17 changes: 17 additions & 0 deletions packages/discordx/examples/builders/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"strict": true,
"noImplicitAny": true,
"outDir": "dist",
"emitDecoratorMetadata": false,
"experimentalDecorators": true,
"strictNullChecks": true,
"noUncheckedIndexedAccess": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Bundler",
"esModuleInterop": true
},
"exclude": ["node_modules", "tests", "examples"]
}
16 changes: 9 additions & 7 deletions packages/discordx/examples/slash/commands/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ function DocumentTransformer(
export class Example {
@Slash({ description: "Save input into database", name: "save-input" })
async withTransformer(
@SlashOption({
description: "input",
name: "input",
required: true,
transformer: DocumentTransformer,
type: ApplicationCommandOptionType.String,
})
@SlashOption(
{
description: "input",
name: "input",
required: true,
type: ApplicationCommandOptionType.String,
},
DocumentTransformer,
)
doc: Document,
interaction: ChatInputCommandInteraction,
): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion packages/discordx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "discordx",
"version": "11.11.3",
"version": "11.12.0",
"private": false,
"description": "Create a discord bot with TypeScript and Decorators!",
"keywords": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Method } from "./Method.js";

interface CreateStructure {
botIds?: string[];
defaultMemberPermissions?: PermissionResolvable | null;
defaultMemberPermissions?: PermissionResolvable | string | null;
description: string;
descriptionLocalizations?: LocalizationMap | null;
dmPermission?: boolean;
Expand All @@ -38,7 +38,7 @@ export class DApplicationCommand extends Method {
private _nameLocalizations: LocalizationMap | null;
private _description: string;
private _descriptionLocalizations: LocalizationMap | null;
private _defaultMemberPermissions: PermissionResolvable | null;
private _defaultMemberPermissions: PermissionResolvable | string | null;
private _dmPermission: boolean;
private _guilds: IGuild[];
private _group?: string;
Expand All @@ -61,7 +61,7 @@ export class DApplicationCommand extends Method {
this._description = value;
}

get defaultMemberPermissions(): PermissionResolvable | null {
get defaultMemberPermissions(): PermissionResolvable | string | null {
return this._defaultMemberPermissions;
}
set defaultMemberPermissions(value: PermissionResolvable | null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
interface CreateStructure {
autocomplete?: SlashAutoCompleteOption;
channelType?: ChannelType[];
choices?: DApplicationCommandOptionChoice[];
description: string;
descriptionLocalizations?: LocalizationMap | null;
index?: number;
Expand Down Expand Up @@ -168,6 +169,7 @@ export class DApplicationCommandOption extends Decorator {
this._name = data.name;
this._autocomplete = data.autocomplete;
this._channelTypes = data.channelType?.sort();
this._choices = data.choices ?? [];
this._description = data.description;
this._index = data.index;
this._maxValue = data.maxValue;
Expand Down
Loading

0 comments on commit c7c1759

Please sign in to comment.