From b54a793002c95cae9d1eefb796b201c6759452dc Mon Sep 17 00:00:00 2001 From: Slincnik Date: Sat, 8 Mar 2025 15:44:06 +0300 Subject: [PATCH] refactor: generateFields func --- src/commands/Administration/config.ts | 80 ++--------------- src/utils/config-fields.ts | 125 ++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 src/utils/config-fields.ts diff --git a/src/commands/Administration/config.ts b/src/commands/Administration/config.ts index a58efecc..6e9d70ae 100644 --- a/src/commands/Administration/config.ts +++ b/src/commands/Administration/config.ts @@ -2,7 +2,9 @@ import { getLocalizedDesc, replyError, translateContext } from "@/helpers/extend import { CommandData, SlashCommandProps } from "@/types.js"; import { createEmbed } from "@/utils/create-embed.js"; import useClient from "@/utils/use-client.js"; -import { ApplicationCommandOptionType, ApplicationIntegrationType, ChannelType, ChatInputCommandInteraction, InteractionContextType, MessageFlags, PermissionsBitField } from "discord.js"; +import { ApplicationCommandOptionType, ApplicationIntegrationType, Channel, ChannelType, ChatInputCommandInteraction, InteractionContextType, MessageFlags, PermissionsBitField } from "discord.js"; +import GuildModel from "@/models/GuildModel.js"; +import { generateFields } from "@/utils/config-fields.js"; const client = useClient(); @@ -74,9 +76,6 @@ export const run = async ({ interaction }: SlashCommandProps) => { name: interaction.guild.name, iconURL: interaction.guild.iconURL() || "", }, - // TODO: тс даёт ошибку но работает ( я ещё учу тс ;( ) - // Тип "({ name: string; value: string; inline: boolean; } | undefined)[]" не может быть назначен для типа "readonly APIEmbedField[]". - // @ts-ignore Type not assignable (for now) fields, }); @@ -85,84 +84,19 @@ export const run = async ({ interaction }: SlashCommandProps) => { const parameter = interaction.options.getString("parameter", true); const state = interaction.options.getBoolean("state", true); - const channel = interaction.options.getChannel("channel"); + const channel = interaction.options.getChannel("channel") as Channel; await changeSetting(interaction, guildData, parameter, state, channel); }; -async function generateFields(interaction: ChatInputCommandInteraction, guildData: any) { - const fieldsConfig = [ - { - nameKey: "administration/config:WELCOME_TITLE", - valueKey: "administration/config:WELCOME_CONTENT", - plugin: guildData.plugins.welcome, - }, - { - nameKey: "administration/config:GOODBYE_TITLE", - valueKey: "administration/config:GOODBYE_CONTENT", - plugin: guildData.plugins.goodbye, - }, - { - nameKey: "administration/config:MONITORING_CHANNELS", - values: [ - { key: "administration/config:MESSAGEUPDATE", value: guildData.plugins?.monitoring?.messageUpdate }, - { key: "administration/config:MESSAGEDELETE", value: guildData.plugins?.monitoring?.messageDelete }, - ], - }, - { - nameKey: "administration/config:SPECIAL_CHANNELS", - values: [ - { key: "administration/config:BIRTHDAYS", value: guildData.plugins?.birthdays }, - { key: "administration/config:MODLOGS", value: guildData.plugins?.modlogs }, - { key: "administration/config:REPORTS", value: guildData.plugins?.reports }, - { key: "administration/config:SUGGESTIONS", value: guildData.plugins?.suggestions }, - { key: "administration/config:TICKETSCATEGORY", value: guildData.plugins?.tickets?.ticketsCategory }, - { key: "administration/config:TICKETLOGS", value: guildData.plugins?.tickets?.ticketLogs }, - { key: "administration/config:TRANSCRIPTIONLOGS", value: guildData.plugins?.tickets?.transcriptionLogs }, - ], - }, - ]; - - const fields = await Promise.all( - fieldsConfig.map(async field => { - const name = await translateContext(interaction, field.nameKey); - - if (field.plugin) { - const value = field.plugin.enabled - ? await translateContext(interaction, field.valueKey!, { - channel: `<#${field.plugin.channel}>`, - }) - : await translateContext(interaction, "common:DISABLED"); - - return { name, value, inline: true }; - } - - if (field.values) { - const value = await Promise.all( - field.values.map(async ({ key, value }) => { - const translatedKey = await translateContext(interaction, key); - const translatedValue = value ? `<#${value}>` : `*${await translateContext(interaction, "common:NOT_DEFINED")}*`; - - return `${translatedKey}: ${translatedValue}`; - }), - ); - - return { name, value: value.join("\n"), inline: false }; - } - }), - ); - - return fields; -} - -async function saveSettings(guildData: any, parameter: string, value: any) { // TODO: Proper type for `any` +async function saveSettings(guildData: InstanceType, parameter: string, value: unknown) { guildData.plugins[parameter] = value; guildData.markModified(`plugins.${parameter}`); await guildData.save(); } -async function generateReply(interaction: ChatInputCommandInteraction, guildData: any, parameter: string, state: boolean, channel?: any) { +async function generateReply(interaction: ChatInputCommandInteraction, guildData: InstanceType, parameter: string, state: boolean, channel?: Channel | null) { const translatedParam = await translateContext(interaction, `administration/config:${parameter.toUpperCase()}`); const enabledText = await translateContext(interaction, "common:ENABLED"); const disabledText = await translateContext(interaction, "common:DISABLED"); @@ -172,7 +106,7 @@ async function generateReply(interaction: ChatInputCommandInteraction, guildData return `${translatedParam}: ${state ? `**${enabledText}** (<#${guildData.plugins[parameter]}>)` : `**${disabledText}**`}`; } -async function changeSetting(interaction: ChatInputCommandInteraction, guildData: any, parameter: string, state: boolean, channel?: any) { +async function changeSetting(interaction: ChatInputCommandInteraction, guildData: any, parameter: string, state: boolean, channel?: Channel | null) { const parameterSplitted = parameter.split("."); const isNested = parameterSplitted.length === 2; diff --git a/src/utils/config-fields.ts b/src/utils/config-fields.ts new file mode 100644 index 00000000..5da5849c --- /dev/null +++ b/src/utils/config-fields.ts @@ -0,0 +1,125 @@ +import { translateContext } from "@/helpers/extenders.js"; +import GuildModel from "@/models/GuildModel.js"; +import { APIEmbedField, ChatInputCommandInteraction } from "discord.js"; + +enum ConfigFieldsType { + plugin = "plugin", + group = "group", +} + +type ConfigPluginField = { + type: ConfigFieldsType.plugin; + nameKey: string; + valueKey: string; + enabled: boolean; + data: { + channel: string; + }; +}; + +type ConfigGroupField = { + type: ConfigFieldsType.group; + nameKey: string; + items: Array<{ + key: string; + path: string; + format: string; + }>; +}; + +type ConfigField = ConfigPluginField | ConfigGroupField; + +const processPluginField = async (interaction: ChatInputCommandInteraction, field: ConfigPluginField) => { + const name = await translateContext(interaction, field.nameKey); + + const value = field.enabled + ? await translateContext(interaction, field.valueKey, { + ...field.data, + channel: `<#${field.data.channel}>`, + }) + : await translateContext(interaction, "common:DISABLED"); + return { name, value, inline: true }; +}; + +const processGroupField = async (interaction: ChatInputCommandInteraction, field: ConfigGroupField) => { + const name = await translateContext(interaction, field.nameKey); + const lines = await Promise.all( + field.items.map(async item => { + const translatedKey = await translateContext(interaction, item.key); + const rawValue = item.path; + + let formattedValue; + switch (item.format) { + case "channel": + formattedValue = rawValue ? `<#${rawValue}>` : `*${await translateContext(interaction, "common:NOT_DEFINED")}*`; + break; + default: + formattedValue = rawValue?.toString() || "N/A"; + } + + return `${translatedKey}: ${formattedValue}`; + }), + ); + + return { name, value: lines.join("\n"), inline: false }; +}; + +export const generateFields = async (interaction: ChatInputCommandInteraction, guildData: InstanceType) => { + const fieldsConfig: ConfigField[] = [ + { + type: ConfigFieldsType.plugin, + nameKey: "administration/config:WELCOME_TITLE", + valueKey: "administration/config:WELCOME_CONTENT", + enabled: guildData.plugins.welcome.enabled, + data: { channel: guildData.plugins.welcome.channel }, + }, + { + type: ConfigFieldsType.plugin, + nameKey: "administration/config:GOODBYE_TITLE", + valueKey: "administration/config:GOODBYE_CONTENT", + enabled: guildData.plugins.goodbye.enabled, + data: { channel: guildData.plugins.goodbye.channel }, + }, + { + type: ConfigFieldsType.group, + nameKey: "administration/config:MONITORING_CHANNELS", + items: [ + { + key: "administration/config:MESSAGEUPDATE", + path: guildData.plugins.monitoring.messageUpdate, + format: "channel", + }, + { + key: "administration/config:MESSAGEDELETE", + path: guildData.plugins.monitoring.messageDelete, + format: "channel", + }, + ], + }, + { + type: ConfigFieldsType.group, + nameKey: "administration/config:SPECIAL_CHANNELS", + items: [ + { key: "administration/config:BIRTHDAYS", path: guildData.plugins.birthdays, format: "channel" }, + { key: "administration/config:MODLOGS", path: guildData.plugins.modlogs, format: "channel" }, + { key: "administration/config:REPORTS", path: guildData.plugins.reports, format: "channel" }, + { key: "administration/config:SUGGESTIONS", path: guildData.plugins.suggestions, format: "channel" }, + { key: "administration/config:TICKETSCATEGORY", path: guildData.plugins.tickets.ticketsCategory, format: "channel" }, + { key: "administration/config:TICKETLOGS", path: guildData.plugins.tickets.ticketLogs, format: "channel" }, + { key: "administration/config:TRANSCRIPTIONLOGS", path: guildData.plugins.tickets.transcriptionLogs, format: "channel" }, + ], + }, + ]; + + const fields: readonly APIEmbedField[] = await Promise.all( + fieldsConfig.map(async field => { + switch (field.type) { + case ConfigFieldsType.plugin: + return processPluginField(interaction, field); + case ConfigFieldsType.group: + return processGroupField(interaction, field); + } + }), + ); + return fields; +};