Comando para eliminar y ver los canales agregados al modelo channel alliace

This commit is contained in:
2025-09-20 03:15:16 -05:00
parent 0f18f3a56c
commit f742ab862e
3 changed files with 710 additions and 1 deletions

View File

@@ -0,0 +1,340 @@
import { CommandMessage } from "../../../core/types/commands";
// @ts-ignore
import { EmbedBuilder, ButtonStyle, MessageFlags, ChannelType } from "discord.js";
export const command: CommandMessage = {
name: "listchannels-alliance",
type: "message",
aliases: ["listalchannel", "channelsally", "alliancechannels"],
cooldown: 5,
// @ts-ignore
run: async (message, args, client) => {
// Obtener canales configurados existentes con estadísticas
const existingChannels = await client.prisma.allianceChannel.findMany({
where: { guildId: message.guildId! },
include: {
_count: {
select: {
pointsHistory: true
}
}
},
orderBy: {
createdAt: 'desc'
}
});
// Obtener estadísticas generales
const totalPointsHistory = await client.prisma.pointHistory.count({
where: { guildId: message.guildId! }
});
const availableBlocks = await client.prisma.blockV2Config.count({
where: { guildId: message.guildId! }
});
if (existingChannels.length === 0) {
// Embed cuando no hay canales configurados
const noChannelsEmbed = new EmbedBuilder()
.setTitle("📋 Canales de Alianza Configurados")
.setDescription("```\n🗂 Lista vacía\n```\n\n📭 **No hay canales configurados** para alianzas en este servidor.\n\n🚀 **¿Quieres empezar?**\n• Usa `!setchannel-alliance` para configurar tu primer canal\n• Crea bloques con `!blockcreate <nombre>`")
.setColor(0x36393f)
.addFields([
{
name: "📊 Estadísticas Generales",
value: `🧩 **Bloques disponibles:** ${availableBlocks}\n📈 **Puntos totales otorgados:** ${totalPointsHistory}`,
inline: false
}
])
.setFooter({
text: `📅 ${new Date().toLocaleDateString('es-ES', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}`
})
.setTimestamp();
const helpRow = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Success,
label: " Configurar Canal",
custom_id: "setup_first_channel",
emoji: { name: "🔧" }
},
{
type: 2,
style: ButtonStyle.Secondary,
label: "📖 Ayuda",
custom_id: "show_setup_help",
emoji: { name: "❓" }
}
]
};
const response = await message.reply({
embeds: [noChannelsEmbed],
components: [helpRow]
});
// Collector para botones de ayuda
const collector = response.createMessageComponentCollector({
time: 300000,
filter: (i) => i.user.id === message.author.id
});
collector.on("collect", async (interaction) => {
if (interaction.customId === "setup_first_channel") {
await interaction.reply({
content: "🔧 **Configurar Canal**\n\nUsa el comando: `!setchannel-alliance`\n\nEste comando te guiará paso a paso para configurar tu primer canal de alianzas.",
flags: 64 // Ephemeral
});
} else if (interaction.customId === "show_setup_help") {
await interaction.reply({
content: "📖 **Guía de Configuración**\n\n**Paso 1:** Crear un bloque\n`!blockcreate mi-alianza`\n\n**Paso 2:** Configurar canal\n`!setchannel-alliance`\n\n**Paso 3:** ¡Listo!\nLos usuarios ganarán puntos automáticamente.",
flags: 64 // Ephemeral
});
}
});
return;
}
// Crear descripción detallada de canales
let channelListDescription = "```\n📋 Lista de Canales Configurados\n```\n\n";
const channelDetails = await Promise.all(
existingChannels.map(async (config: any, index: number) => {
const channel = message.guild!.channels.cache.get(config.channelId);
const channelName = channel ? `#${channel.name}` : "❌ *Canal Eliminado*";
const status = config.isActive ? "🟢 **Activo**" : "🔴 **Inactivo**";
const pointsCount = config._count.pointsHistory;
// Obtener información del bloque
const blockInfo = await client.prisma.blockV2Config.findFirst({
where: {
guildId: message.guildId!,
name: config.blockConfigName
},
select: { name: true, id: true }
});
const blockStatus = blockInfo ? "✅ Válido" : "⚠️ Bloque Eliminado";
const createdDate = new Date(config.createdAt).toLocaleDateString('es-ES', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
return {
index: index + 1,
channelName,
status,
pointsCount,
blockName: config.blockConfigName,
blockStatus,
createdDate,
isValid: !!channel && !!blockInfo
};
})
);
// Agrupar por estado
const activeChannels = channelDetails.filter(c => c.status.includes("Activo"));
const inactiveChannels = channelDetails.filter(c => c.status.includes("Inactivo"));
// Construir embed principal
const mainEmbed = new EmbedBuilder()
.setTitle("📋 Canales de Alianza Configurados")
.setDescription(`${channelListDescription}📊 **Resumen:** ${existingChannels.length} canal(es) configurado(s)\n🟢 **Activos:** ${activeChannels.length} • 🔴 **Inactivos:** ${inactiveChannels.length}`)
.setColor(0x5865f2)
.setThumbnail(message.guild!.iconURL({ size: 128 }) || null)
.setFooter({
text: `📅 Actualizado • ${message.guild!.name}`,
iconURL: message.guild!.iconURL({ size: 32 }) || undefined
})
.setTimestamp();
// Añadir campos de canales activos
if (activeChannels.length > 0) {
const activeList = activeChannels.slice(0, 10).map(c =>
`**${c.index}.** ${c.channelName}\n` +
`\`${c.blockName}\`${c.blockStatus}\n` +
`└ 📈 **${c.pointsCount}** puntos otorgados\n` +
`└ 📅 Desde: ${c.createdDate}`
).join('\n\n');
mainEmbed.addFields([
{
name: `🟢 Canales Activos (${activeChannels.length})`,
value: activeList || "Ninguno",
inline: false
}
]);
}
// Añadir campos de canales inactivos (si los hay)
if (inactiveChannels.length > 0) {
const inactiveList = inactiveChannels.slice(0, 5).map(c =>
`**${c.index}.** ${c.channelName}\n` +
`\`${c.blockName}\`${c.blockStatus}`
).join('\n\n');
mainEmbed.addFields([
{
name: `🔴 Canales Inactivos (${inactiveChannels.length})`,
value: inactiveList || "Ninguno",
inline: false
}
]);
}
// Añadir estadísticas generales
mainEmbed.addFields([
{
name: "📊 Estadísticas del Servidor",
value: `🧩 **Bloques disponibles:** ${availableBlocks}\n📈 **Total puntos otorgados:** ${totalPointsHistory}\n⚡ **Canales más activos:** ${channelDetails.sort((a, b) => b.pointsCount - a.pointsCount).slice(0, 3).map((c, i) => `${i + 1}. ${c.channelName.replace(/[#❌*]/g, '').trim()}`).join(', ') || 'N/A'}`,
inline: false
}
]);
// Botones de acción
const actionRow1 = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Success,
label: " Añadir Canal",
custom_id: "add_channel",
emoji: { name: "🔧" }
},
{
type: 2,
style: ButtonStyle.Danger,
label: "🗑️ Eliminar Canal",
custom_id: "remove_channel",
emoji: { name: "🗑️" }
},
{
type: 2,
style: ButtonStyle.Primary,
label: "🔄 Actualizar",
custom_id: "refresh_list",
emoji: { name: "🔄" }
}
]
};
const actionRow2 = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Secondary,
label: "📊 Estadísticas",
custom_id: "show_stats",
emoji: { name: "📈" }
},
{
type: 2,
style: ButtonStyle.Secondary,
label: "🧩 Ver Bloques",
custom_id: "show_blocks",
emoji: { name: "🧩" }
},
{
type: 2,
style: ButtonStyle.Secondary,
label: "❓ Ayuda",
custom_id: "show_help",
emoji: { name: "📖" }
}
]
};
const response = await message.reply({
embeds: [mainEmbed],
components: [actionRow1, actionRow2]
});
// Collector para manejar interacciones
const collector = response.createMessageComponentCollector({
time: 600000, // 10 minutos
filter: (i) => i.user.id === message.author.id
});
collector.on("collect", async (interaction) => {
switch (interaction.customId) {
case "add_channel":
await interaction.reply({
content: " **Añadir Canal**\n\nUsa el comando: `!setchannel-alliance`\n\nEste comando te guiará para configurar un nuevo canal de alianzas.",
flags: 64 // Ephemeral
});
break;
case "remove_channel":
await interaction.reply({
content: "🗑️ **Eliminar Canal**\n\nUsa el comando: `!removechannel-alliance`\n\nEste comando te permitirá eliminar canales de la configuración de alianzas.",
flags: 64 // Ephemeral
});
break;
case "refresh_list":
await interaction.reply({
content: "🔄 **Lista Actualizada**\n\nUsa el comando nuevamente: `!listchannels-alliance`\n\nEsto mostrará la información más reciente.",
flags: 64 // Ephemeral
});
break;
case "show_stats":
const detailedStats = channelDetails.map(c =>
`${c.channelName}: **${c.pointsCount}** puntos`
).join('\n');
await interaction.reply({
content: `📊 **Estadísticas Detalladas**\n\n**Puntos por Canal:**\n${detailedStats}\n\n**Total del Servidor:** ${totalPointsHistory} puntos`,
flags: 64 // Ephemeral
});
break;
case "show_blocks":
const blocksList = await client.prisma.blockV2Config.findMany({
where: { guildId: message.guildId! },
select: { name: true, id: true }
});
const blocksText = blocksList.length > 0
? blocksList.map((block: any, i: number) => `${i + 1}. \`${block.name}\``).join('\n')
: "No hay bloques configurados";
await interaction.reply({
content: `🧩 **Bloques Disponibles (${blocksList.length})**\n\n${blocksText}\n\n💡 Crea bloques con: \`!blockcreate <nombre>\``,
flags: 64 // Ephemeral
});
break;
case "show_help":
await interaction.reply({
content: `📖 **Ayuda - Sistema de Alianzas**\n\n**Comandos principales:**\n• \`!setchannel-alliance\` - Configurar canal\n• \`!removechannel-alliance\` - Eliminar canal\n• \`!listchannels-alliance\` - Ver configurados\n\n**Comandos de bloques:**\n• \`!blockcreate <nombre>\` - Crear bloque\n• \`!blockeditv2 <nombre>\` - Editar bloque\n• \`!embedlist\` - Ver todos los bloques`,
flags: 64 // Ephemeral
});
break;
}
});
collector.on("end", async () => {
try {
await response.edit({
components: [] // Remover botones cuando expire
});
} catch (error) {
// Ignorar errores si el mensaje fue eliminado
}
});
}
}

View File

@@ -0,0 +1,357 @@
import { CommandMessage } from "../../../core/types/commands";
// @ts-ignore
import { ComponentType, ButtonStyle, MessageFlags, ChannelType } from "discord.js";
export const command: CommandMessage = {
name: "removechannel-alliance",
type: "message",
aliases: ["removealchannel", "removechannelally", "delalchannel"],
cooldown: 10,
// @ts-ignore
run: async (message, args, client) => {
if (!message.member?.permissions.has("Administrator")) {
return message.reply("❌ No tienes permisos de Administrador.");
}
// Obtener canales configurados existentes
const existingChannels = await client.prisma.allianceChannel.findMany({
where: { guildId: message.guildId! },
include: { blockConfig: true }
});
if (existingChannels.length === 0) {
const noChannelsPanel = {
type: 17,
accent_color: 0xf04747,
components: [
{
type: 10,
content: "# 🗑️ **Eliminar Canal de Alianzas**"
},
{
type: 14,
spacing: 2,
divider: true
},
{
type: 10,
content: "📭 **No hay canales configurados**\n\nNo existen canales de alianza configurados en este servidor para eliminar.\n\n💡 **Sugerencia:** Usa `!setchannel-alliance` para configurar canales primero."
}
]
};
return message.reply({
flags: MessageFlags.SuppressEmbeds,
components: [noChannelsPanel]
});
}
// Panel principal de eliminación
const removePanel = {
type: 17,
accent_color: 0xf04747, // Rojo para eliminación
components: [
{
type: 10,
content: "# 🗑️ **Eliminar Canal de Alianzas**"
},
{
type: 14,
spacing: 2,
divider: true
},
{
type: 10,
content: `⚠️ **Atención:** Estás a punto de eliminar la configuración de alianzas de un canal.\n\n📊 **Estado actual:**\n• **${existingChannels.length}** canal(es) configurado(s)\n• **${existingChannels.filter((c: any) => c.isActive).length}** canal(es) activo(s)\n\n🎯 Selecciona el canal que deseas eliminar de la configuración:`
}
]
};
// Crear opciones para el selector de canales
const channelOptions = existingChannels.map((config: any) => {
const channel = message.guild!.channels.cache.get(config.channelId);
const channelName = channel ? `#${channel.name}` : `Canal Eliminado`;
const status = config.isActive ? "🟢 Activo" : "🔴 Inactivo";
return {
label: channelName,
value: config.channelId,
description: `${config.blockConfigName}${status}`,
emoji: { name: channel ? "💬" : "⚠️" }
};
}).slice(0, 25);
const channelSelectRow = {
type: 1,
components: [
{
type: 3,
custom_id: "channel_remove_select",
placeholder: "🗑️ Selecciona el canal a eliminar...",
options: channelOptions
}
]
};
const cancelRow = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Secondary,
label: "❌ Cancelar",
custom_id: "cancel_removal"
},
{
type: 2,
style: ButtonStyle.Primary,
label: "📋 Ver Configurados",
custom_id: "view_all_channels"
}
]
};
const panelMessage = await message.reply({
flags: MessageFlags.SuppressEmbeds,
components: [removePanel, channelSelectRow, cancelRow]
});
const collector = panelMessage.createMessageComponentCollector({
time: 300000, // 5 minutos
filter: (i) => i.user.id === message.author.id
});
collector.on("collect", async (interaction) => {
switch (interaction.customId) {
case "channel_remove_select":
if (interaction.isStringSelectMenu()) {
const selectedChannelId = interaction.values[0];
const selectedConfig = existingChannels.find((c: any) => c.channelId === selectedChannelId);
const selectedChannel = message.guild!.channels.cache.get(selectedChannelId);
const channelName = selectedChannel ? `#${selectedChannel.name}` : "Canal Eliminado";
// Panel de confirmación
const confirmPanel = {
type: 17,
accent_color: 0xff6b6b,
components: [
{
type: 10,
content: "⚠️ **Confirmar Eliminación**"
},
{
type: 14,
divider: true,
spacing: 2
},
{
type: 10,
content: `🎯 **Canal seleccionado:** ${channelName}\n` +
`🧩 **Configuración:** \`${selectedConfig?.blockConfigName}\`\n` +
`📊 **Estado:** ${selectedConfig?.isActive ? "🟢 Activo" : "🔴 Inactivo"}\n\n` +
`❗ **¿Estás seguro de eliminar esta configuración?**\n\n` +
`📝 **Efectos:**\n` +
`• Los usuarios ya no ganarán puntos en este canal\n` +
`• El historial de puntos se mantendrá\n` +
`• Esta acción NO se puede deshacer`
}
]
};
const confirmRow = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Danger,
label: "✅ Sí, Eliminar",
custom_id: `confirm_remove_${selectedChannelId}`,
emoji: { name: "🗑️" }
},
{
type: 2,
style: ButtonStyle.Secondary,
label: "❌ Cancelar",
custom_id: "cancel_removal"
}
]
};
await interaction.update({
components: [confirmPanel, confirmRow]
});
}
break;
case "cancel_removal":
const cancelPanel = {
type: 17,
accent_color: 0x36393f,
components: [
{
type: 10,
content: "❌ **Operación Cancelada**"
},
{
type: 14,
divider: true,
spacing: 1
},
{
type: 10,
content: "La eliminación ha sido cancelada.\nNingún canal fue modificado."
}
]
};
await interaction.update({
components: [cancelPanel]
});
collector.stop();
break;
case "view_all_channels":
await interaction.reply({
content: `📋 **Canales Configurados**\n\n${existingChannels.map((config: any, index: number) => {
const channel = message.guild!.channels.cache.get(config.channelId);
const channelName = channel ? `#${channel.name}` : "Canal Eliminado";
const status = config.isActive ? "🟢 Activo" : "🔴 Inactivo";
return `**${index + 1}.** ${channelName} - \`${config.blockConfigName}\`${status}`;
}).join('\n')}`,
flags: 64 // Ephemeral
});
break;
default:
// Manejo de confirmación de eliminación
if (interaction.customId.startsWith("confirm_remove_")) {
const channelId = interaction.customId.replace("confirm_remove_", "");
const channelConfig = existingChannels.find((c: any) => c.channelId === channelId);
const channel = message.guild!.channels.cache.get(channelId);
const channelName = channel ? `#${channel.name}` : "Canal Eliminado";
try {
// Eliminar la configuración del canal
await client.prisma.allianceChannel.delete({
where: {
guildId_channelId: {
guildId: message.guildId!,
channelId: channelId
}
}
});
const successPanel = {
type: 17,
accent_color: 0x57f287,
components: [
{
type: 10,
content: "✅ **Eliminación Exitosa**"
},
{
type: 14,
divider: true,
spacing: 2
},
{
type: 10,
content: `🗑️ **Canal eliminado de la configuración:**\n\n` +
`📺 **Canal:** ${channelName}\n` +
`🧩 **Configuración eliminada:** \`${channelConfig?.blockConfigName}\`\n\n` +
`✅ **Completado:** Los usuarios ya no ganarán puntos de alianza en este canal.\n\n` +
`💡 **Nota:** El historial de puntos anterior se mantiene intacto.`
}
]
};
const successActionsRow = {
type: 1,
components: [
{
type: 2,
style: ButtonStyle.Success,
label: "🏠 Finalizar",
custom_id: "finish_removal"
},
{
type: 2,
style: ButtonStyle.Danger,
label: "🗑️ Eliminar Otro",
custom_id: "remove_another"
}
]
};
await interaction.update({
components: [successPanel, successActionsRow]
});
} catch (error) {
const errorPanel = {
type: 17,
accent_color: 0xf04747,
components: [
{
type: 10,
content: "❌ **Error de Eliminación**"
},
{
type: 14,
divider: true,
spacing: 2
},
{
type: 10,
content: `💥 **Error al eliminar el canal:**\n\n` +
`📺 Canal: ${channelName}\n` +
`🧩 Configuración: \`${channelConfig?.blockConfigName}\`\n\n` +
`🔍 **Posibles causas:**\n` +
`• El canal ya fue eliminado\n` +
`• Error de base de datos\n` +
`• Permisos insuficientes\n\n` +
`🔄 Intenta nuevamente.`
}
]
};
await interaction.update({ components: [errorPanel] });
}
}
break;
}
});
collector.on("end", async (collected, reason) => {
if (reason === "time") {
const timeoutPanel = {
type: 17,
accent_color: 0x36393f,
components: [
{
type: 10,
content: "⏰ **Sesión Expirada**"
},
{
type: 14,
divider: true,
spacing: 1
},
{
type: 10,
content: "El panel de eliminación ha expirado.\nUsa el comando nuevamente para continuar."
}
]
};
try {
await panelMessage.edit({
components: [timeoutPanel]
});
} catch (error) {
// Mensaje eliminado o error de edición
}
}
});
}
}