Rhys - ^Sort of related to above, does inheritance...

^Sort of related to above, does inheritance work with commands? I've got a few commands for opening menus, i.e /server-settings, /channel-settings, and originally I was going to make a base class and extend from that from those, but when trying to do that it seemed to only register the abstract class and not the inherited classes which I found odd
2 Replies
Lioness100
Lioness100•2y ago
Can you show your code?
Rhys
Rhys•2y ago
Sorry I should have included that in the original message I went to rewrite it to recreate the issue and it's working now 😅 not sure about that one Here's the working code Parent:
import type { SettingsMenuView } from "@primitives/views/settings-view";
import { Command } from "@sapphire/framework";
import { findRootChannel } from "@utils/add-to-parse-data";
import type { GuildRootChannel, SettingsInteractionHandlerTypes } from "@utils/types";

export abstract class OpenSettingsMenuCommand<
T extends SettingsInteractionHandlerTypes
> extends Command {
// Register slash and context menu command
public override registerApplicationCommands(registry: Command.Registry) {
// Register slash command
registry.registerChatInputCommand({
name: this.name,
description: this.description,
});
}

// eslint-disable-next-line no-unused-vars
public abstract getMenu(root_channel: GuildRootChannel): Promise<SettingsMenuView<T>>;

public async chatInputRun(interaction: Command.ChatInputInteraction) {
const channel_settings = await this.container.answer_overflow.channel_settings.get({
where: {
channel_id: interaction.channelId,
},
});
if (channel_settings?.bitfield == null) {
await interaction.reply({ content: "Channel settings not found", ephemeral: true });
return;
}
const root_channel = findRootChannel(interaction);
if (root_channel == null) {
await interaction.reply({
content: "Could not find a channel to update settings for",
ephemeral: true,
});
return;
}
const menu = await this.getMenu(root_channel);
const view = await menu.getView();
await interaction.reply({ ...view, ephemeral: true });
}
}
import type { SettingsMenuView } from "@primitives/views/settings-view";
import { Command } from "@sapphire/framework";
import { findRootChannel } from "@utils/add-to-parse-data";
import type { GuildRootChannel, SettingsInteractionHandlerTypes } from "@utils/types";

export abstract class OpenSettingsMenuCommand<
T extends SettingsInteractionHandlerTypes
> extends Command {
// Register slash and context menu command
public override registerApplicationCommands(registry: Command.Registry) {
// Register slash command
registry.registerChatInputCommand({
name: this.name,
description: this.description,
});
}

// eslint-disable-next-line no-unused-vars
public abstract getMenu(root_channel: GuildRootChannel): Promise<SettingsMenuView<T>>;

public async chatInputRun(interaction: Command.ChatInputInteraction) {
const channel_settings = await this.container.answer_overflow.channel_settings.get({
where: {
channel_id: interaction.channelId,
},
});
if (channel_settings?.bitfield == null) {
await interaction.reply({ content: "Channel settings not found", ephemeral: true });
return;
}
const root_channel = findRootChannel(interaction);
if (root_channel == null) {
await interaction.reply({
content: "Could not find a channel to update settings for",
ephemeral: true,
});
return;
}
const menu = await this.getMenu(root_channel);
const view = await menu.getView();
await interaction.reply({ ...view, ephemeral: true });
}
}
Child:
import type { ChannelSettingsWithBitfield } from "@answeroverflow/core";
import { getDefaultChannelSettings } from "@answeroverflow/core/dist/structures/channel-settings";
import { OpenSettingsMenuCommand } from "@primitives/commands/settings/open-settings-menu";
import { ChannelSettingsMenuView } from "@primitives/views/channel-settings-view";
import type { SettingsMenuView } from "@primitives/views/settings-view";
import { ApplyOptions } from "@sapphire/decorators";
import type { Command } from "@sapphire/framework";
import type { GuildRootChannel } from "@utils/types";

@ApplyOptions<Command.Options>({
name: "channel-settings",
description:
"Adjust settings for the current channel. Allows you to enable indexing, mark as solution, etc.",
})
export class ChannelSettings extends OpenSettingsMenuCommand<ChannelSettingsWithBitfield> {
public async getMenu(
root_channel: GuildRootChannel
): Promise<SettingsMenuView<ChannelSettingsWithBitfield>> {
let settings = await this.container.answer_overflow.channel_settings.get({
where: {
channel_id: root_channel.id,
},
});
if (settings == null) {
settings = getDefaultChannelSettings(root_channel.id);
}
return new ChannelSettingsMenuView(settings, root_channel);
}
}
import type { ChannelSettingsWithBitfield } from "@answeroverflow/core";
import { getDefaultChannelSettings } from "@answeroverflow/core/dist/structures/channel-settings";
import { OpenSettingsMenuCommand } from "@primitives/commands/settings/open-settings-menu";
import { ChannelSettingsMenuView } from "@primitives/views/channel-settings-view";
import type { SettingsMenuView } from "@primitives/views/settings-view";
import { ApplyOptions } from "@sapphire/decorators";
import type { Command } from "@sapphire/framework";
import type { GuildRootChannel } from "@utils/types";

@ApplyOptions<Command.Options>({
name: "channel-settings",
description:
"Adjust settings for the current channel. Allows you to enable indexing, mark as solution, etc.",
})
export class ChannelSettings extends OpenSettingsMenuCommand<ChannelSettingsWithBitfield> {
public async getMenu(
root_channel: GuildRootChannel
): Promise<SettingsMenuView<ChannelSettingsWithBitfield>> {
let settings = await this.container.answer_overflow.channel_settings.get({
where: {
channel_id: root_channel.id,
},
});
if (settings == null) {
settings = getDefaultChannelSettings(root_channel.id);
}
return new ChannelSettingsMenuView(settings, root_channel);
}
}
Trying to decide if it's overcomplicating it abstracting it this way but I'm just playing around with the setup atm to see how it feels