From 27b6e74d16ce4329e7a172da0364c769171153a0 Mon Sep 17 00:00:00 2001 From: Vermium Sifell Date: Wed, 13 Apr 2022 21:32:06 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20slash=20command=20builder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/settings/guild/addons/credits.ts | 99 ------------- src/plugins/settings/guild/addons/points.ts | 83 ----------- .../settings/guild/addons/pterodactyl.ts | 51 ------- src/plugins/settings/guild/index.ts | 98 +++++++------ src/plugins/settings/guild/modules/credits.ts | 134 ++++++++++++++++++ src/plugins/settings/guild/modules/points.ts | 107 ++++++++++++++ .../settings/guild/modules/pterodactyl.ts | 68 +++++++++ src/plugins/settings/index.ts | 112 +-------------- src/plugins/settings/user/index.ts | 48 +++++-- 9 files changed, 403 insertions(+), 397 deletions(-) delete mode 100644 src/plugins/settings/guild/addons/credits.ts delete mode 100644 src/plugins/settings/guild/addons/points.ts delete mode 100644 src/plugins/settings/guild/addons/pterodactyl.ts create mode 100644 src/plugins/settings/guild/modules/credits.ts create mode 100644 src/plugins/settings/guild/modules/points.ts create mode 100644 src/plugins/settings/guild/modules/pterodactyl.ts diff --git a/src/plugins/settings/guild/addons/credits.ts b/src/plugins/settings/guild/addons/credits.ts deleted file mode 100644 index fd0ad60..0000000 --- a/src/plugins/settings/guild/addons/credits.ts +++ /dev/null @@ -1,99 +0,0 @@ -// Dependencies -import { CommandInteraction } from "discord.js"; - -// Configurations -import { successColor, footerText, footerIcon } from "@config/embed"; - -//Handlers -import logger from "@logger"; - -// Models -import guildSchema from "@schemas/guild"; - -// Function -export default async (interaction: CommandInteraction) => { - // Destructure member - const { guild, user, options } = interaction; - - // Get options - const status = options?.getBoolean("status"); - const rate = options?.getNumber("rate"); - const timeout = options?.getNumber("timeout"); - const minimumLength = options?.getNumber("minimum-length"); - const workRate = options?.getNumber("work-rate"); - const workTimeout = options?.getNumber("work-timeout"); - - // Get guild object - const guildDB = await guildSchema?.findOne({ - guildId: guild?.id, - }); - - if (guildDB === null) return; - - // Modify values - guildDB.credits.status = status !== null ? status : guildDB?.credits?.status; - guildDB.credits.rate = rate !== null ? rate : guildDB?.credits?.rate; - guildDB.credits.timeout = - timeout !== null ? timeout : guildDB?.credits?.timeout; - guildDB.credits.workRate = - workRate !== null ? workRate : guildDB?.credits?.workRate; - guildDB.credits.workTimeout = - workTimeout !== null ? workTimeout : guildDB?.credits?.workTimeout; - guildDB.credits.minimumLength = - minimumLength !== null ? minimumLength : guildDB?.credits?.minimumLength; - - // Save guild - await guildDB?.save()?.then(async () => { - // Embed object - const embed = { - title: ":tools: Settings - Guild [Credits]", - description: "Following settings is set!", - color: successColor, - fields: [ - { - name: "🤖 Status", - value: `${guildDB?.credits?.status}`, - inline: true, - }, - { - name: "📈 Rate", - value: `${guildDB?.credits?.rate}`, - inline: true, - }, - { - name: "📈 Work Rate", - value: `${guildDB?.credits?.workRate}`, - inline: true, - }, - { - name: "🔨 Minimum Length", - value: `${guildDB?.credits?.minimumLength}`, - inline: true, - }, - { - name: "⏰ Timeout", - value: `${guildDB?.credits?.timeout}`, - inline: true, - }, - { - name: "⏰ Work Timeout", - value: `${guildDB?.credits?.workTimeout}`, - inline: true, - }, - ], - timestamp: new Date(), - footer: { - iconURL: footerIcon, - text: footerText, - }, - }; - - // Send debug message - logger?.debug( - `Guild: ${guild?.id} User: ${user.id} has changed credit details.` - ); - - // Return interaction reply - return interaction?.editReply({ embeds: [embed] }); - }); -}; diff --git a/src/plugins/settings/guild/addons/points.ts b/src/plugins/settings/guild/addons/points.ts deleted file mode 100644 index 1221dea..0000000 --- a/src/plugins/settings/guild/addons/points.ts +++ /dev/null @@ -1,83 +0,0 @@ -// Dependencies -import { CommandInteraction } from "discord.js"; - -// Configurations -import { successColor, footerText, footerIcon } from "@config/embed"; - -// Handlers -import logger from "../../../../logger"; - -// Models -import guildSchema from "../../../../database/schemas/guild"; - -// Function -export default async (interaction: CommandInteraction) => { - // Destructure member - const { options, guild, user } = interaction; - - // Get options - const status = options?.getBoolean("status"); - const rate = options?.getNumber("rate"); - const timeout = options?.getNumber("timeout"); - const minimumLength = options?.getNumber("minimum-length"); - - // Get guild object - const guildDB = await guildSchema?.findOne({ - guildId: guild?.id, - }); - - if (guildDB === null) return; - - // Modify values - guildDB.points.status = status !== null ? status : guildDB?.points?.status; - guildDB.points.rate = rate !== null ? rate : guildDB?.points?.rate; - guildDB.points.timeout = - timeout !== null ? timeout : guildDB?.points?.timeout; - guildDB.points.minimumLength = - minimumLength !== null ? minimumLength : guildDB?.points?.minimumLength; - - // Save guild - await guildDB?.save()?.then(async () => { - // Create embed object - const embed = { - title: ":hammer: Settings - Guild [Points]", - description: "Following settings is set!", - color: successColor, - fields: [ - { - name: "🤖 Status", - value: `${guildDB?.points?.status}`, - inline: true, - }, - { - name: "📈 Rate", - value: `${guildDB?.points?.rate}`, - inline: true, - }, - { - name: "🔨 Minimum Length", - value: `${guildDB?.points?.minimumLength}`, - inline: true, - }, - { - name: "⏰ Timeout", - value: `${guildDB?.points?.timeout}`, - inline: true, - }, - ], - timestamp: new Date(), - footer: { - iconURL: footerIcon, - text: footerText, - }, - }; - - // Send debug message - logger?.debug( - `Guild: ${guild?.id} User: ${user?.id} has changed credit details.` - ); - - // Return interaction reply - return interaction?.editReply({ embeds: [embed] }); - }); -}; diff --git a/src/plugins/settings/guild/addons/pterodactyl.ts b/src/plugins/settings/guild/addons/pterodactyl.ts deleted file mode 100644 index caa1dfd..0000000 --- a/src/plugins/settings/guild/addons/pterodactyl.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Dependencies -import { CommandInteraction } from "discord.js"; - -// Configurations -import { successColor, footerText, footerIcon } from "@config/embed"; - -// Handlers -import logger from "../../../../logger"; - -// Models -import apiSchema from "../../../../database/schemas/api"; -import encryption from "../../../../handlers/encryption"; - -// Function -export default async (interaction: CommandInteraction) => { - // Destructure member - const { options, guild, user } = interaction; - - // Get options - const url = options?.getString("url"); - const token = encryption.encrypt(options?.getString("token")); - - // Update API credentials - await apiSchema - ?.findOneAndUpdate( - { guildId: guild?.id }, - { url, token }, - { new: true, upsert: true } - ) - .then(async () => { - // Embed object - const embed = { - title: ":hammer: Settings - Guild [Pterodactyl]", - color: successColor, - description: "Pterodactyl settings is saved!", - timestamp: new Date(), - footer: { - iconURL: footerIcon as string, - text: footerText as string, - }, - }; - - // Send debug message - logger?.debug( - `Guild: ${guild?.id} User: ${user?.id} has changed api credentials.` - ); - - // Return interaction reply - return interaction?.editReply({ embeds: [embed] }); - }); -}; diff --git a/src/plugins/settings/guild/index.ts b/src/plugins/settings/guild/index.ts index 9c5b1ba..8beecfd 100644 --- a/src/plugins/settings/guild/index.ts +++ b/src/plugins/settings/guild/index.ts @@ -8,55 +8,67 @@ import { errorColor, footerText, footerIcon } from "@config/embed"; import logger from "../../../logger"; // Modules -import pterodactyl from "./addons/pterodactyl"; -import credits from "./addons/credits"; -import points from "./addons/points"; +import pterodactyl from "./modules/pterodactyl"; +import credits from "./modules/credits"; +import points from "./modules/points"; +import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders"; // Function -export default async (interaction: CommandInteraction) => { - // Destructure member - const { memberPermissions, options, commandName, user, guild } = interaction; +export default { + data: (group: SlashCommandSubcommandGroupBuilder) => { + return group + .setName("guild") + .setDescription("Manage guild settings.") + .addSubcommand(pterodactyl.data) + .addSubcommand(credits.data) + .addSubcommand(points.data); + }, + execute: async (interaction: CommandInteraction) => { + // Destructure member + const { memberPermissions, options, commandName, user, guild } = + interaction; - // Check permission - if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) { - // Create embed object - const embed = { - title: ":tools: Settings - Guild", - color: errorColor, - description: "You do not have permission to manage this!", - timestamp: new Date(), - footer: { - iconURL: footerIcon as string, - text: footerText as string, - }, - }; + // Check permission + if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) { + // Create embed object + const embed = { + title: ":tools: Settings - Guild", + color: errorColor, + description: "You do not have permission to manage this!", + timestamp: new Date(), + footer: { + iconURL: footerIcon as string, + text: footerText as string, + }, + }; - // Return interaction reply - return interaction?.editReply({ embeds: [embed] }); - } + // Return interaction reply + return interaction?.editReply({ embeds: [embed] }); + } - // Module - Pterodactyl - if (options?.getSubcommand() === "pterodactyl") { - // Execute Module - Pterodactyl - return pterodactyl(interaction); - } + // Module - Pterodactyl + if (options?.getSubcommand() === "pterodactyl") { + // Execute Module - Pterodactyl + return pterodactyl.execute(interaction); + } - // Module - Credits - else if (options?.getSubcommand() === "credits") { - // Execute Module - Credits - return credits(interaction); - } + // Module - Credits + else if (options?.getSubcommand() === "credits") { + // Execute Module - Credits + return credits.execute(interaction); + } - // Module - Points - else if (options?.getSubcommand() === "points") { - // Execute Module - Points - return points(interaction); - } + // Module - Points + else if (options?.getSubcommand() === "points") { + // Execute Module - Points + return points.execute(interaction); + } - // Send debug message - return logger?.debug( - `Guild: ${guild?.id} User: ${ - user?.id - } executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}` - ); + // Send debug message + return logger?.debug( + `Guild: ${guild?.id} User: ${ + user?.id + } executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}` + ); + }, }; diff --git a/src/plugins/settings/guild/modules/credits.ts b/src/plugins/settings/guild/modules/credits.ts new file mode 100644 index 0000000..dd38971 --- /dev/null +++ b/src/plugins/settings/guild/modules/credits.ts @@ -0,0 +1,134 @@ +// Dependencies +import { CommandInteraction } from "discord.js"; + +// Configurations +import { successColor, footerText, footerIcon } from "@config/embed"; + +//Handlers +import logger from "@logger"; + +// Models +import guildSchema from "@schemas/guild"; +import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; + +// Function +export default { + data: (command: SlashCommandSubcommandBuilder) => { + return command + .setName("credits") + .setDescription("Credits") + .addBooleanOption((option) => + option.setName("status").setDescription("Should credits be enabled?") + ) + .addNumberOption((option) => + option.setName("rate").setDescription("Amount of credits per message.") + ) + .addNumberOption((option) => + option + .setName("minimum-length") + .setDescription("Minimum length of message to earn credits.") + ) + .addNumberOption((option) => + option + .setName("work-rate") + .setDescription("Maximum amount of credits on work.") + ) + .addNumberOption((option) => + option + .setName("work-timeout") + .setDescription("Timeout between work schedules (milliseconds).") + ) + .addNumberOption((option) => + option + .setName("timeout") + .setDescription("Timeout between earning credits (milliseconds).") + ); + }, + execute: async (interaction: CommandInteraction) => { + // Destructure member + const { guild, user, options } = interaction; + + // Get options + const status = options?.getBoolean("status"); + const rate = options?.getNumber("rate"); + const timeout = options?.getNumber("timeout"); + const minimumLength = options?.getNumber("minimum-length"); + const workRate = options?.getNumber("work-rate"); + const workTimeout = options?.getNumber("work-timeout"); + + // Get guild object + const guildDB = await guildSchema?.findOne({ + guildId: guild?.id, + }); + + if (guildDB === null) return; + + // Modify values + guildDB.credits.status = + status !== null ? status : guildDB?.credits?.status; + guildDB.credits.rate = rate !== null ? rate : guildDB?.credits?.rate; + guildDB.credits.timeout = + timeout !== null ? timeout : guildDB?.credits?.timeout; + guildDB.credits.workRate = + workRate !== null ? workRate : guildDB?.credits?.workRate; + guildDB.credits.workTimeout = + workTimeout !== null ? workTimeout : guildDB?.credits?.workTimeout; + guildDB.credits.minimumLength = + minimumLength !== null ? minimumLength : guildDB?.credits?.minimumLength; + + // Save guild + await guildDB?.save()?.then(async () => { + // Embed object + const embed = { + title: ":tools: Settings - Guild [Credits]", + description: "Following settings is set!", + color: successColor, + fields: [ + { + name: "🤖 Status", + value: `${guildDB?.credits?.status}`, + inline: true, + }, + { + name: "📈 Rate", + value: `${guildDB?.credits?.rate}`, + inline: true, + }, + { + name: "📈 Work Rate", + value: `${guildDB?.credits?.workRate}`, + inline: true, + }, + { + name: "🔨 Minimum Length", + value: `${guildDB?.credits?.minimumLength}`, + inline: true, + }, + { + name: "⏰ Timeout", + value: `${guildDB?.credits?.timeout}`, + inline: true, + }, + { + name: "⏰ Work Timeout", + value: `${guildDB?.credits?.workTimeout}`, + inline: true, + }, + ], + timestamp: new Date(), + footer: { + iconURL: footerIcon, + text: footerText, + }, + }; + + // Send debug message + logger?.debug( + `Guild: ${guild?.id} User: ${user.id} has changed credit details.` + ); + + // Return interaction reply + return interaction?.editReply({ embeds: [embed] }); + }); + }, +}; diff --git a/src/plugins/settings/guild/modules/points.ts b/src/plugins/settings/guild/modules/points.ts new file mode 100644 index 0000000..b9ef0b1 --- /dev/null +++ b/src/plugins/settings/guild/modules/points.ts @@ -0,0 +1,107 @@ +// Dependencies +import { CommandInteraction } from "discord.js"; + +// Configurations +import { successColor, footerText, footerIcon } from "@config/embed"; + +// Handlers +import logger from "../../../../logger"; + +// Models +import guildSchema from "../../../../database/schemas/guild"; +import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; + +// Function +export default { + data: (command: SlashCommandSubcommandBuilder) => { + return command + .setName("points") + .setDescription("Points") + .addBooleanOption((option) => + option.setName("status").setDescription("Should credits be enabled?") + ) + .addNumberOption((option) => + option.setName("rate").setDescription("Amount of credits per message.") + ) + .addNumberOption((option) => + option + .setName("minimum-length") + .setDescription("Minimum length of message to earn credits.") + ) + .addNumberOption((option) => + option + .setName("timeout") + .setDescription("Timeout between earning credits (milliseconds).") + ); + }, + execute: async (interaction: CommandInteraction) => { + // Destructure member + const { options, guild, user } = interaction; + + // Get options + const status = options?.getBoolean("status"); + const rate = options?.getNumber("rate"); + const timeout = options?.getNumber("timeout"); + const minimumLength = options?.getNumber("minimum-length"); + + // Get guild object + const guildDB = await guildSchema?.findOne({ + guildId: guild?.id, + }); + + if (guildDB === null) return; + + // Modify values + guildDB.points.status = status !== null ? status : guildDB?.points?.status; + guildDB.points.rate = rate !== null ? rate : guildDB?.points?.rate; + guildDB.points.timeout = + timeout !== null ? timeout : guildDB?.points?.timeout; + guildDB.points.minimumLength = + minimumLength !== null ? minimumLength : guildDB?.points?.minimumLength; + + // Save guild + await guildDB?.save()?.then(async () => { + // Create embed object + const embed = { + title: ":hammer: Settings - Guild [Points]", + description: "Following settings is set!", + color: successColor, + fields: [ + { + name: "🤖 Status", + value: `${guildDB?.points?.status}`, + inline: true, + }, + { + name: "📈 Rate", + value: `${guildDB?.points?.rate}`, + inline: true, + }, + { + name: "🔨 Minimum Length", + value: `${guildDB?.points?.minimumLength}`, + inline: true, + }, + { + name: "⏰ Timeout", + value: `${guildDB?.points?.timeout}`, + inline: true, + }, + ], + timestamp: new Date(), + footer: { + iconURL: footerIcon, + text: footerText, + }, + }; + + // Send debug message + logger?.debug( + `Guild: ${guild?.id} User: ${user?.id} has changed credit details.` + ); + + // Return interaction reply + return interaction?.editReply({ embeds: [embed] }); + }); + }, +}; diff --git a/src/plugins/settings/guild/modules/pterodactyl.ts b/src/plugins/settings/guild/modules/pterodactyl.ts new file mode 100644 index 0000000..d25bfe3 --- /dev/null +++ b/src/plugins/settings/guild/modules/pterodactyl.ts @@ -0,0 +1,68 @@ +// Dependencies +import { CommandInteraction } from "discord.js"; + +// Configurations +import { successColor, footerText, footerIcon } from "@config/embed"; + +// Handlers +import logger from "../../../../logger"; + +// Models +import apiSchema from "../../../../database/schemas/api"; +import encryption from "../../../../handlers/encryption"; +import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; + +// Function +export default { + data: (command: SlashCommandSubcommandBuilder) => { + return command + .setName("pterodactyl") + .setDescription("Controlpanel.gg") + .addStringOption((option) => + option.setName("url").setDescription("The api url").setRequired(true) + ) + .addStringOption((option) => + option + .setName("token") + .setDescription("The api token") + .setRequired(true) + ); + }, + execute: async (interaction: CommandInteraction) => { + // Destructure member + const { options, guild, user } = interaction; + + // Get options + const url = options?.getString("url"); + const token = encryption.encrypt(options?.getString("token")); + + // Update API credentials + await apiSchema + ?.findOneAndUpdate( + { guildId: guild?.id }, + { url, token }, + { new: true, upsert: true } + ) + .then(async () => { + // Embed object + const embed = { + title: ":hammer: Settings - Guild [Pterodactyl]", + color: successColor, + description: "Pterodactyl settings is saved!", + timestamp: new Date(), + footer: { + iconURL: footerIcon as string, + text: footerText as string, + }, + }; + + // Send debug message + logger?.debug( + `Guild: ${guild?.id} User: ${user?.id} has changed api credentials.` + ); + + // Return interaction reply + return interaction?.editReply({ embeds: [embed] }); + }); + }, +}; diff --git a/src/plugins/settings/index.ts b/src/plugins/settings/index.ts index 8b7435b..0ccb54d 100644 --- a/src/plugins/settings/index.ts +++ b/src/plugins/settings/index.ts @@ -15,111 +15,9 @@ export default { data: new SlashCommandBuilder() .setName("settings") .setDescription("Manage settings.") - .addSubcommandGroup((group) => - group - .setName("guild") - .setDescription("Manage guild settings.") - .addSubcommand((command) => - command - .setName("pterodactyl") - .setDescription("Controlpanel.gg") - .addStringOption((option) => - option - .setName("url") - .setDescription("The api url") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("token") - .setDescription("The api token") - .setRequired(true) - ) - ) - .addSubcommand((command) => - command - .setName("credits") - .setDescription("Credits") - .addBooleanOption((option) => - option - .setName("status") - .setDescription("Should credits be enabled?") - ) - .addNumberOption((option) => - option - .setName("rate") - .setDescription("Amount of credits per message.") - ) - .addNumberOption((option) => - option - .setName("minimum-length") - .setDescription("Minimum length of message to earn credits.") - ) - .addNumberOption((option) => - option - .setName("work-rate") - .setDescription("Maximum amount of credits on work.") - ) - .addNumberOption((option) => - option - .setName("work-timeout") - .setDescription( - "Timeout between work schedules (milliseconds)." - ) - ) - .addNumberOption((option) => - option - .setName("timeout") - .setDescription( - "Timeout between earning credits (milliseconds)." - ) - ) - ) - .addSubcommand((command) => - command - .setName("points") - .setDescription("Points") - .addBooleanOption((option) => - option - .setName("status") - .setDescription("Should credits be enabled?") - ) - .addNumberOption((option) => - option - .setName("rate") - .setDescription("Amount of credits per message.") - ) - .addNumberOption((option) => - option - .setName("minimum-length") - .setDescription("Minimum length of message to earn credits.") - ) - .addNumberOption((option) => - option - .setName("timeout") - .setDescription( - "Timeout between earning credits (milliseconds)." - ) - ) - ) - ) - .addSubcommandGroup((group) => - group - .setName("user") - .setDescription("Manage user settings.") - .addSubcommand((command) => - command - .setName("appearance") - .setDescription("Manage your appearance") - .addStringOption((option) => - option - .setName("language") - .setDescription("Configure your language") - .addChoice("English", "en") - .addChoice("Swedish", "sv") - ) - ) - ), + .addSubcommandGroup(guildGroup.data) + .addSubcommandGroup(userGroup.data), + async execute(interaction: CommandInteraction) { // Destructure const { options, commandName, user, guild } = interaction; @@ -127,12 +25,12 @@ export default { // Group - Guild if (options.getSubcommandGroup() === "guild") { // Execute Group - Guild - await guildGroup(interaction); + await guildGroup.execute(interaction); } // Group - User else if (options.getSubcommandGroup() === "user") { // Execute Group - User - await userGroup(interaction); + await userGroup.execute(interaction); } // Send debug message diff --git a/src/plugins/settings/user/index.ts b/src/plugins/settings/user/index.ts index fad1442..e325780 100644 --- a/src/plugins/settings/user/index.ts +++ b/src/plugins/settings/user/index.ts @@ -1,4 +1,5 @@ // Dependencies +import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders"; import { CommandInteraction } from "discord.js"; // Handlers @@ -8,20 +9,39 @@ import logger from "../../../logger"; import appearance from "./modules/appearance"; // Function -export default async (interaction: CommandInteraction) => { - // Destructure member - const { guild, user, options, commandName } = interaction; +export default { + data: (group: SlashCommandSubcommandGroupBuilder) => { + return group + .setName("user") + .setDescription("Manage user settings.") + .addSubcommand((command) => + command + .setName("appearance") + .setDescription("Manage your appearance") + .addStringOption((option) => + option + .setName("language") + .setDescription("Configure your language") + .addChoice("English", "en") + .addChoice("Swedish", "sv") + ) + ); + }, + execute: async (interaction: CommandInteraction) => { + // Destructure member + const { guild, user, options, commandName } = interaction; - // Module - Appearance - if (options?.getSubcommand() === "appearance") { - // Execute Module - Appearance - await appearance(interaction); - } + // Module - Appearance + if (options?.getSubcommand() === "appearance") { + // Execute Module - Appearance + await appearance(interaction); + } - // Send debug message - return logger?.debug( - `Guild: ${guild?.id} User: ${ - user?.id - } executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}` - ); + // Send debug message + return logger?.debug( + `Guild: ${guild?.id} User: ${ + user?.id + } executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}` + ); + }, };