Skip to content

Commit

Permalink
fix: component registering
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilloftheshadow committed Sep 10, 2024
1 parent 306d50a commit 6239590
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
"ignore": ["website"]
}
5 changes: 5 additions & 0 deletions .changeset/small-paws-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@buape/carbon": patch
---

fix: component registering
2 changes: 1 addition & 1 deletion apps/cloudo/src/commands/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class PingCommand extends Command {

async run(interaction: CommandInteraction) {
return interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>"
content: "Pong!"
})
}
}
4 changes: 3 additions & 1 deletion apps/cloudo/src/commands/testing/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export default class ButtonCommand extends Command {
description = "A simple command with a button!"
defer = true

components = [PingButton]

async run(interaction: CommandInteraction) {
await interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>",
content: "Pong!",
components: [new Row([new PingButton(), new Link()])]
})
}
Expand Down
25 changes: 17 additions & 8 deletions apps/cloudo/src/commands/testing/every_select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,25 @@ export default class SelectCommand extends Command {
description = "Send every select menu"
defer = true

components = [
StringSelect,
RoleSelect,
MentionableSelect,
ChannelSelect,
UserSelect
]

async run(interaction: CommandInteraction) {
const row = new Row()
row.addComponent(new StringSelect())
row.addComponent(new RoleSelect())
row.addComponent(new MentionableSelect())
row.addComponent(new ChannelSelect())
row.addComponent(new UserSelect())

interaction.reply({
content: "Select menus! <:caughtIn4k:1145473115703496816>",
components: [
new Row([new StringSelect()]),
new Row([new RoleSelect()]),
new Row([new MentionableSelect()]),
new Row([new ChannelSelect()]),
new Row([new UserSelect()])
]
content: "Select menus!!",
components: [row]
})
}
}
Expand Down
16 changes: 16 additions & 0 deletions apps/cloudo/src/commands/testing/message_command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {
ApplicationCommandType,
Command,
type CommandInteraction
} from "@buape/carbon"

export default class MessageCommand extends Command {
name = "Message Command"
description = "Message command test"
defer = true
type = ApplicationCommandType.Message

async run(interaction: CommandInteraction) {
interaction.reply({ content: "Message command" })
}
}
66 changes: 66 additions & 0 deletions apps/cloudo/src/commands/testing/modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
Command,
type CommandInteraction,
Modal,
type ModalInteraction,
Row,
TextInput,
TextInputStyle
} from "@buape/carbon"

export default class ModalCommand extends Command {
name = "modal"
description = "Modal test"

modals = [TestModal]

async run(interaction: CommandInteraction) {
await interaction.showModal(new TestModal())
}
}

class TestModal extends Modal {
title = "Test Modal"
customId = "test-modal"

components = [
new Row([new TextInputHi()]),
new Row([new TextInputName()]),
new Row([new TextInputAge()]),
new Row([new TextInputColor()]),
new Row([new TextInputHeight()])
]

run(interaction: ModalInteraction) {
return interaction.reply({
content: `Hi ${interaction.fields.getText("name")}, you are ${interaction.fields.getText("age")} years old, and your favorite color is ${interaction.fields.getText("color")}. You are ${interaction.fields.getText("height") || "not"} tall.`
})
}
}

class TextInputHi extends TextInput {
label = "Hi, how are you?"
customId = "hi"
style = TextInputStyle.Paragraph
}

class TextInputColor extends TextInput {
label = "What is your favorite color?"
customId = "color"
}

class TextInputAge extends TextInput {
label = "How old are you?"
customId = "age"
}

class TextInputName extends TextInput {
label = "What is your name?"
customId = "name"
}

class TextInputHeight extends TextInput {
label = "How tall are you?"
customId = "height"
required = false
}
4 changes: 3 additions & 1 deletion apps/cloudo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SelectCommand from "./commands/testing/every_select.js"
import Options from "./commands/testing/options.js"
import Subc from "./commands/testing/subcommand.js"
import SubcG from "./commands/testing/subcommandgroup.js"
import ModalCommand from "./commands/testing/modal.js"

type Env = {
CLIENT_ID: string
Expand All @@ -29,7 +30,8 @@ export default {
new PingCommand(),
new SelectCommand(),
new Subc(),
new SubcG()
new SubcG(),
new ModalCommand()
]
)
if (request.url.endsWith("/deploy")) {
Expand Down
2 changes: 1 addition & 1 deletion apps/rocko/src/commands/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class PingCommand extends Command {

async run(interaction: CommandInteraction) {
return interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>"
content: "Pong!"
})
}
}
4 changes: 3 additions & 1 deletion apps/rocko/src/commands/testing/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export default class ButtonCommand extends Command {
description = "A simple command with a button!"
defer = true

components = [PingButton]

async run(interaction: CommandInteraction) {
await interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>",
content: "Pong!",
components: [new Row([new PingButton(), new Link()])]
})
}
Expand Down
10 changes: 9 additions & 1 deletion apps/rocko/src/commands/testing/every_select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ export default class SelectCommand extends Command {
description = "Send every select menu"
defer = true

components = [
StringSelect,
RoleSelect,
MentionableSelect,
ChannelSelect,
UserSelect
]

async run(interaction: CommandInteraction) {
const row = new Row()
row.addComponent(new StringSelect())
Expand All @@ -28,7 +36,7 @@ export default class SelectCommand extends Command {
row.addComponent(new UserSelect())

interaction.reply({
content: "Select menus! <:caughtIn4k:1145473115703496816>",
content: "Select menus!!",
components: [row]
})
}
Expand Down
2 changes: 2 additions & 0 deletions apps/rocko/src/commands/testing/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export default class ModalCommand extends Command {
name = "modal"
description = "Modal test"

modals = [TestModal]

async run(interaction: CommandInteraction) {
await interaction.showModal(new TestModal())
}
Expand Down
19 changes: 15 additions & 4 deletions packages/carbon/src/abstracts/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import {
ApplicationCommandType,
type RESTPostAPIApplicationCommandsJSONBody
} from "discord-api-types/v10"
import { ApplicationIntegrationType, InteractionContextType } from "../index.js"
import {
ApplicationIntegrationType,
type BaseComponent,
InteractionContextType,
type Modal
} from "../index.js"

/**
* Represents the base data of a command that the user creates
Expand Down Expand Up @@ -47,10 +52,16 @@ export abstract class BaseCommand {
]

/**
* All the paginators that the command is able to use.
* You mount these here so the handler can access them
* The components that the command is able to use.
* You pass these here so the handler can listen for them..
*/
components: (new () => BaseComponent)[] = []

/**
* All the modals that the command is able to use.
* You pass these here so the handler can listen for them.
*/
// paginators?: Paginator[] = []
modals: (new () => Modal)[] = []

/**
* Serializes the command into a JSON object that can be sent to Discord
Expand Down
6 changes: 0 additions & 6 deletions packages/carbon/src/abstracts/BaseInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,6 @@ export abstract class BaseInteraction<T extends APIInteraction> extends Base {
data: InteractionReplyData,
options: InteractionReplyOptions = {}
) {
data.components?.map((row) => {
row.components.map((component) => {
this.client.componentHandler.registerComponent(component)
})
})
if (this._deferred) {
await this.client.rest.patch(
Routes.webhookMessage(
Expand Down Expand Up @@ -214,7 +209,6 @@ export abstract class BaseInteraction<T extends APIInteraction> extends Base {
async showModal(modal: Modal) {
if (this._deferred)
throw new Error("You cannot defer an interaction that shows a modal")
this.client.modalHandler.registerModal(modal)
await this.client.rest.post(
Routes.interactionCallback(this.rawData.id, this.rawData.token),
{
Expand Down
15 changes: 15 additions & 0 deletions packages/carbon/src/classes/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export type ClientOptions = {
* Whether the commands should be deployed to Discord automatically.
*/
autoDeploy?: boolean
/**
* Whether components and modals should be registered automatically.
* If you don't want to do this (e.g. you are changing them at runtime), you can manually call {@link ComponentHandler#registerComponent} and {@link ModalHandler#registerModal} on the client.
*/
autoRegister?: boolean
}

/**
Expand Down Expand Up @@ -125,6 +130,16 @@ export class Client {
if (!options.token) throw new Error("Missing token")
this.options = options
this.commands = commands
if (this.options.autoRegister) {
this.commands.map((command) => {
command.components.map((component) => {
this.componentHandler.registerComponent(new component())
})
command.modals.map((modal) => {
this.modalHandler.registerModal(new modal())
})
})
}
const routerData =
this.options.mode === ClientMode.Bun && this.options.port
? { port: this.options.port }
Expand Down
1 change: 0 additions & 1 deletion packages/carbon/src/internals/AutocompleteInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export class AutocompleteInteraction extends BaseInteraction<APIApplicationComma
value: string
}[]
) {
console.log(choices)
await this.client.rest.post(
Routes.interactionCallback(this.rawData.id, this.rawData.token),
{
Expand Down
2 changes: 1 addition & 1 deletion website/content/carbon/classes/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class PingCommand extends Command {

async run(interaction: CommandInteraction) {
return interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>"
content: "Pong!"
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion website/content/carbon/classes/components/buttons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class PingButton extends Button {

async run(interaction: ButtonInteraction) {
return interaction.reply({
content: "Pong <:caughtIn4k:1145473115703496816>"
content: "Pong!"
})
}
}
Expand Down
35 changes: 34 additions & 1 deletion website/content/carbon/classes/components/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,37 @@ index: true

Components are used to create interactive elements in your bot, such as buttons, select menus, and text inputs.

When you create a component, you will need to pass it to the [`components` property of the `Command` class](/carbon/api/classes/CommandInteraction#properties). This will allow it to be registered with the bot as a handler.
When you create a component, you will need to pass it to the [`components` property of the `Command` class](/carbon/api/classes/CommandInteraction#properties). This will allow it to be registered with the bot as a handler.
When you pass it, make sure you aren't instantiating it, but rather just passing the class itself.

```ts title="src/commands/ping.ts"
import { Command, type CommandInteraction } from "@buape/carbon"

export default class PingCommand extends Command {
name = "ping"
description = "A simple ping command"
defer = false

components = [PingButton]

async run(interaction: CommandInteraction) {
return interaction.reply({
content: "Pong!"
})
}
}

class PingButton extends Button {
customId = "ping"
label = "Ping"
style = ButtonStyle.Primary

async run(interaction: ButtonInteraction) {
return interaction.reply({
content: "OMG YOU CLICKED THE BUTTON"
})
}
}
```

If you don't want to automatically register the components, you can do so manually by setting the `autoRegister` option to `false` in the client options.

0 comments on commit 6239590

Please sign in to comment.