Melhore esse código. Eu quero que além dessas funções, seja possível ele importar e exportar o json da embed, mas tome cuidado ao importar para o usuário n colocar um codigo malicioso, ent verifique tudo.
Um exemplo de json é esse:
{
  "author": {
    "name": "Info",
    "url": "https://example.com"
  },
  "title": "Example Title",
  "url": "https://example.com",
  "description": "This is an example description. Markdown works too!\n\nhttps://automatic.links\n> Block Quotes\n```\nCode Blocks\n```\n*Emphasis* or _emphasis_\n`Inline code` or ``inline code``\n[Links](https://example.com)\n<@123>, <@!123>, <#123>, <@&123>, @here, @everyone mentions\n||Spoilers||\n~~Strikethrough~~\n**Strong**\n__Underline__",
  "fields": [
    {
      "name": "Field Name",
      "value": "This is the field value."
    },
    {
      "name": "The first inline field.",
      "value": "This field is inline.",
      "inline": true
    },
    {
      "name": "The second inline field.",
      "value": "Inline fields are stacked next to each other.",
      "inline": true
    },
    {
      "name": "The third inline field.",
      "value": "You can have up to 3 inline fields in a row.",
      "inline": true
    },
    {
      "name": "Even if the next field is inline...",
      "value": "It won't stack with the previous inline fields.",
      "inline": true
    }
  ],
  "image": {
    "url": "https://cubedhuang.com/images/alex-knight-unsplash.webp"
  },
  "thumbnail": {
    "url": "https://dan.onl/images/emptysong.jpg"
  },
  "color": "#00b0f4",
  "footer": {
    "text": "Example Footer",
    "icon_url": "https://slate.dan.onl/slate.png"
  },
  "timestamp": 1727188546999
}



codigo (ME ENVIE A RESPOSTA COMPLETA<<<, SEM CORTAR OU ABREVIAR):

// src/modules/EmbedManager.js
const wio = require("wio.db");


const { EmbedBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, ButtonBuilder, ButtonStyle, PermissionsBitField } = require("discord.js");
const ticketsBotao = new wio.JsonDatabase({ databasePath: "src/database/ticketsBotao.json" });
const ticketsPainel = new wio.JsonDatabase({ databasePath: "src/database/ticketsPainel.json" });
const { sanitizeInput, isValidURL, isValidColor } = require("../utils/validation"); // Funções de validação que vamos criar
const { capitalizeFirstLetter } = require("../utils/functions"); // Função utilitária existente

class EmbedManager {
    constructor(client) {
        this.client = client;
    }

    /**
     * Exibe o menu de configuração de embed para o ticket especificado.
     * @param {Interaction} interaction - A interação do Discord.
     * @param {String} ticketId - O ID do ticket.
     * @param {String} type - O tipo de ticket ('Painel' ou 'Botao').
     */
    async showEmbedConfigMenu(interaction, ticketId, type) {
        try {
            const db = this.getDatabase(type);
            const embedConfig = db.get(`${ticketId}.configs`) || {};

            const embed = new EmbedBuilder()
                .setTitle(embedConfig.titulo || "Não configurado ainda...")
                .setDescription(embedConfig.descricao || "Não configurado ainda...")
                .setColor(embedConfig.embedColor || "Navy")
                .setFooter({ text: embedConfig.footer || "Sem rodapé" });

            if (embedConfig.banner) {
                if (isValidURL(embedConfig.banner)) {
                    embed.setImage(embedConfig.banner);
                } else {
                    embedConfig.banner = null;
                    db.set(`${ticketId}.configs.banner`, null);
                }
            }

            if (embedConfig.miniatura) {
                if (isValidURL(embedConfig.miniatura)) {
                    embed.setThumbnail(embedConfig.miniatura);
                } else {
                    embedConfig.miniatura = null;
                    db.set(`${ticketId}.configs.miniatura`, null);
                }
            }

            const menu = new StringSelectMenuBuilder()
                .setCustomId(`embedConfigMenu-${ticketId}-${type}`)
                .setPlaceholder("Selecione uma opção para editar");

            const options = [
                {
                    label: "Título",
                    description: "Editar o título da embed",
                    emoji: "🏷️",
                    value: "titulo",
                },
                {
                    label: "Descrição",
                    description: "Editar a descrição da embed",
                    emoji: "✏️",
                    value: "descricao",
                },
                {
                    label: "Rodapé",
                    description: "Editar o rodapé da embed",
                    emoji: "🔍",
                    value: "footer",
                },
                {
                    label: "Cor",
                    description: "Editar a cor da embed",
                    emoji: "🎨",
                    value: "embedColor",
                },
                {
                    label: "Banner",
                    description: "Editar o banner da embed",
                    emoji: "🖼️",
                    value: "banner",
                },
                {
                    label: "Miniatura",
                    description: "Editar a miniatura da embed",
                    emoji: "🖼️",
                    value: "miniatura",
                },
                type === 'Painel' ? {
                    label: "Placeholder",
                    description: "Editar o texto placeholder",
                    emoji: "🔡",
                    value: "placeholder",
                } : null,
            ].filter(option => option !== null); // Remover opções nulas

            options.forEach(opt => {
                menu.addOptions(
                    new StringSelectMenuOptionBuilder()
                        .setLabel(opt.label)
                        .setDescription(opt.description)
                        .setEmoji(opt.emoji)
                        .setValue(opt.value)
                );
            });

            const row = new ActionRowBuilder().addComponents(menu);

            await interaction.editReply({
                embeds: [embed],
                components: [row],
            });
        } catch (error) {
            console.error("Erro ao exibir o menu de configuração de embed:", error);
            await interaction.reply({
                content: "❌ | Ocorreu um erro ao exibir o menu de configuração. Por favor, tente novamente mais tarde.",
                ephemeral: true,
            });
        }
    }

    /**
     * Lida com a seleção de uma opção de configuração de embed e exibe o modal correspondente.
     * @param {Interaction} interaction - A interação do Discord.
     * @param {String} ticketId - O ID do ticket.
     * @param {String} type - O tipo de ticket ('Painel' ou 'Botao').
     * @param {String} field - O campo do embed a ser editado.
     */
    async handleEmbedConfigSelection(interaction, ticketId, type, field) {
        try {
            // Verificar permissões
            if (!interaction.member.permissions.has(PermissionsBitField.Flags.Administrator)) {
                return interaction.reply({
                    content: "❌ | Você não tem permissão para editar o embed deste ticket.",
                    ephemeral: true,
                });
            }

            const modal = new ModalBuilder()
                .setTitle(`Editar ${capitalizeFirstLetter(field)}`)
                .setCustomId(`editEmbedModal-${field}-${ticketId}-${type}`);

            let inputLabel = `Novo ${capitalizeFirstLetter(field)}:`;
            let placeholder = `Digite o novo ${field} aqui`;
            let style = TextInputStyle.Short;
            let required = true;

            if (field === 'descricao') {
                style = TextInputStyle.Paragraph;
            }

            const input = new TextInputBuilder()
                .setCustomId("embedInput")
                .setLabel(inputLabel)
                .setPlaceholder(placeholder)
                .setStyle(style)
                .setRequired(required);

            const actionRow = new ActionRowBuilder().addComponents(input);
            modal.addComponents(actionRow);

            await interaction.showModal(modal);
        } catch (error) {
            console.error("Erro ao lidar com a seleção de configuração de embed:", error);
            await interaction.reply({
                content: "❌ | Ocorreu um erro ao processar sua solicitação. Por favor, tente novamente mais tarde.",
                ephemeral: true,
            });
        }
    }

    /**
     * Processa a submissão do modal e atualiza o embed.
     * @param {Interaction} interaction - A interação do Discord.
     */
    async handleEmbedModalSubmit(interaction) {
        const customId = interaction.customId;

        // Estrutura esperada: editEmbedModal-${field}-${ticketId}-${type}
        const parts = customId.split('-');
        console.log(customId, parts)
        if (parts.length !== 4) return; // Invalid customId

        const [, field, ticketId, type] = parts.slice(0, 4); // Ignorar 'editEmbedModal'

        try {
            // Sanitizar e validar a entrada do usuário
            let newValue = sanitizeInput(interaction.fields.getTextInputValue('embedInput'));

            if (['banner', 'miniatura'].includes(field)) {
                if (!isValidURL(newValue)) {
                    return interaction.reply({
                        content: "❌ | Por favor, insira um URL válido.",
                        ephemeral: true,
                    });
                }
            }

            if (field === 'embedColor') {
                if (!isValidColor(newValue)) {
                    return interaction.reply({
                        content: "❌ | Por favor, insira uma cor válida (nome ou código hexadecimal).",
                        ephemeral: true,
                    });
                }
                newValue = this.normalizeColor(newValue); // Transformar nome da cor em código hexadecimal, se necessário
            }

            const db = this.getDatabase(type);
            db.set(`${ticketId}.configs.${field}`, newValue);

            // Atualizar a embed no canal do painel ou do botão
            const channelId = db.get(`${ticketId}.channelId`); // Supondo que você tenha um campo channelId
            const channel = await this.client.channels.fetch(channelId).catch(() => null);
            if (!channel) {
                return interaction.reply({
                    content: "❌ | Não foi possível encontrar o canal para atualizar o embed.",
                    ephemeral: true,
                });
            }

            const msgId = db.get(`${ticketId}.msgId`); // Supondo que você tenha um campo msgId
            const message = await channel.messages.fetch(msgId).catch(() => null);
            if (!message) {
                return interaction.reply({
                    content: "❌ | Não foi possível encontrar a mensagem do embed para atualizar.",
                    ephemeral: true,
                });
            }

            const embedConfig = db.get(`${ticketId}.configs`) || {};

            const embed = new EmbedBuilder()
                .setTitle(embedConfig.titulo || "Não configurado ainda...")
                .setDescription(embedConfig.descricao || "Não configurado ainda...")
                .setColor(embedConfig.embedColor || "Navy")
                .setFooter({ text: embedConfig.footer || "Sem rodapé" });

            if (embedConfig.banner) {
                if (isValidURL(embedConfig.banner)) {
                    embed.setImage(embedConfig.banner);
                } else {
                    embedConfig.banner = null;
                    db.set(`${ticketId}.configs.banner`, null);
                }
            }

            if (embedConfig.miniatura) {
                if (isValidURL(embedConfig.miniatura)) {
                    embed.setThumbnail(embedConfig.miniatura);
                } else {
                    embedConfig.miniatura = null;
                    db.set(`${ticketId}.configs.miniatura`, null);
                }
            }

            // Se for um tipo de painel que possui placeholder
            if (type === 'Painel' && embedConfig.placeholder) {
                embed.setFooter({ text: embedConfig.footer || "Sem rodapé", iconURL: null }).setDescription(`${embedConfig.descricao || "Não configurado ainda..."}\n\n${embedConfig.placeholder}`);
            }

            await message.edit({ embeds: [embed] });

            await interaction.update({content: ''})
            await interaction.followUp({
                content: `✅ | **${capitalizeFirstLetter(field)}** atualizado com sucesso.`,
                ephemeral: true,
            });

            // Reexibir o menu de configuração
            await this.showEmbedConfigMenu(interaction, ticketId, type);
        } catch (error) {
            console.error("Erro ao processar a submissão do modal de embed:", error);
            await interaction.channel.send({
                content: "❌ | Ocorreu um erro ao atualizar o embed. Por favor, tente novamente mais tarde.",
                ephemeral: true,
            });
        }
    }

    /**
     * Seleciona o banco de dados correto baseado no tipo de ticket.
     * @param {String} type - O tipo de ticket ('Painel' ou 'Botao').
     * @returns {JsonDatabase} - O banco de dados correspondente.
     */
    getDatabase(type) {
        if (type === 'Painel') {
            return ticketsPainel;
        } else if (type === 'Botao') {
            return ticketsBotao;
        } else {
            throw new Error("Tipo de ticket inválido. Deve ser 'Painel' ou 'Botao'.");
        }
    }

    /**
     * Normaliza a cor para um formato hexadecimal se um nome de cor for fornecido.
     * @param {String} color - Nome da cor ou código hexadecimal.
     * @returns {String} - Código hexadecimal da cor.
     */
    normalizeColor(color) {
        // Aqui você pode adicionar mapeamentos de nomes de cores para códigos hexadecimais
        const colorMap = {
            "azul": "#0000FF",
            "verde": "#00FF00",
            "vermelho": "#FF0000",
            "cinza": "#808080",
            // Adicione mais mapeamentos conforme necessário
        };

        const lowerColor = color.toLowerCase();
        return colorMap[lowerColor] || color; // Retorna a cor original se não houver mapeamento
    }
}

module.exports = EmbedManager;