Skip to content

Commit 4b391f2

Browse files
authored
Merge pull request #14 from CapituloJaverianoACM/develop
feat/imageImprovement
2 parents fcd9e7e + 150bb9d commit 4b391f2

File tree

2 files changed

+120
-172
lines changed

2 files changed

+120
-172
lines changed

src/commands/announce-handlers.ts

Lines changed: 119 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,92 @@ const PRESET_COLORS = [
2727
{ name: '⚪ Blanco Discord', value: '#5865F2' },
2828
];
2929

30+
/**
31+
* Construye los componentes (dropdowns y botones) para el anuncio
32+
*/
33+
function buildAnnouncementComponents(session: any, cfg: any) {
34+
const rows = [];
35+
36+
// Dropdown de colores
37+
const colorMenu = new StringSelectMenuBuilder()
38+
.setCustomId(`announce:color:${session.userId}`)
39+
.setPlaceholder('🎨 Selecciona un color')
40+
.addOptions(
41+
PRESET_COLORS.map((color) =>
42+
new StringSelectMenuOptionBuilder()
43+
.setLabel(color.name)
44+
.setValue(color.value)
45+
.setDefault(session.announcement.color === color.value),
46+
),
47+
);
48+
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(colorMenu));
49+
50+
// Dropdown de roles a mencionar (si existen roles de notificaciones configurados)
51+
const notificationRoles = [];
52+
const seenRoleIds = new Set<string>();
53+
54+
// Agregar roles solo si no están duplicados
55+
if (cfg?.roles.laLiga && !seenRoleIds.has(cfg.roles.laLiga)) {
56+
notificationRoles.push({ label: '⚽ La Liga', value: cfg.roles.laLiga });
57+
seenRoleIds.add(cfg.roles.laLiga);
58+
}
59+
if (cfg?.roles.preParciales && !seenRoleIds.has(cfg.roles.preParciales)) {
60+
notificationRoles.push({ label: '📚 Pre-Parciales', value: cfg.roles.preParciales });
61+
seenRoleIds.add(cfg.roles.preParciales);
62+
}
63+
if (cfg?.roles.cursos && !seenRoleIds.has(cfg.roles.cursos)) {
64+
notificationRoles.push({ label: '📖 Cursos', value: cfg.roles.cursos });
65+
seenRoleIds.add(cfg.roles.cursos);
66+
}
67+
if (cfg?.roles.notificacionesGenerales && !seenRoleIds.has(cfg.roles.notificacionesGenerales)) {
68+
notificationRoles.push({
69+
label: '🔔 Notificaciones Generales',
70+
value: cfg.roles.notificacionesGenerales,
71+
});
72+
seenRoleIds.add(cfg.roles.notificacionesGenerales);
73+
}
74+
75+
if (notificationRoles.length > 0) {
76+
const rolesMenu = new StringSelectMenuBuilder()
77+
.setCustomId(`announce:roles:${session.userId}`)
78+
.setPlaceholder('🔔 Selecciona roles a mencionar (opcional)')
79+
.setMinValues(0)
80+
.setMaxValues(notificationRoles.length)
81+
.addOptions(
82+
notificationRoles.map((role) =>
83+
new StringSelectMenuOptionBuilder()
84+
.setLabel(role.label)
85+
.setValue(role.value)
86+
.setDefault(session.announcement.roles?.includes(role.value) || false),
87+
),
88+
);
89+
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(rolesMenu));
90+
}
91+
92+
// Botones de acción
93+
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
94+
new ButtonBuilder()
95+
.setCustomId(`announce:edit:${session.userId}`)
96+
.setLabel('✏️ Editar Texto')
97+
.setStyle(ButtonStyle.Secondary),
98+
new ButtonBuilder()
99+
.setCustomId(`announce:image:${session.userId}`)
100+
.setLabel('🖼️ Imagen')
101+
.setStyle(ButtonStyle.Secondary),
102+
new ButtonBuilder()
103+
.setCustomId(`announce:publish:${session.userId}`)
104+
.setLabel('📢 Publicar')
105+
.setStyle(ButtonStyle.Success),
106+
new ButtonBuilder()
107+
.setCustomId(`announce:cancel:${session.userId}`)
108+
.setLabel('❌ Cancelar')
109+
.setStyle(ButtonStyle.Danger),
110+
);
111+
rows.push(actionRow);
112+
113+
return rows;
114+
}
115+
30116
/**
31117
* Handler para el modal del announce
32118
*/
@@ -98,109 +184,43 @@ export async function handleAnnounceModal(interaction: any) {
98184
flags: 1 << 6,
99185
});
100186

101-
// Actualizar el mensaje original del preview usando el mensaje guardado
187+
// Actualizar el mensaje original del preview usando interaction del mensaje original
102188
try {
103-
if (session.previewMessage) {
189+
logger.info('Attempting to update preview via webhook', {
190+
requestId: session.requestId,
191+
hasOriginalInteraction: !!session.originalInteraction,
192+
imageUrl,
193+
});
194+
195+
if (session.originalInteraction) {
104196
const embed = createAnnouncementPreview(session);
105197
const cfg = getGuildConfig(session.guildId);
106198

107-
// Reconstruir los componentes (necesarios para que Discord re-renderice el embed)
108-
const rows = [];
109-
110-
// Dropdown de colores
111-
const colorMenu = new StringSelectMenuBuilder()
112-
.setCustomId(`announce:color:${session.userId}`)
113-
.setPlaceholder('🎨 Selecciona un color')
114-
.addOptions(
115-
PRESET_COLORS.map((color) =>
116-
new StringSelectMenuOptionBuilder()
117-
.setLabel(color.name)
118-
.setValue(color.value)
119-
.setDefault(session.announcement.color === color.value),
120-
),
121-
);
122-
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(colorMenu));
123-
124-
// Dropdown de roles
125-
const notificationRoles = [];
126-
const seenRoleIds = new Set<string>();
127-
128-
if (cfg?.roles.laLiga && !seenRoleIds.has(cfg.roles.laLiga)) {
129-
notificationRoles.push({ label: '⚽ La Liga', value: cfg.roles.laLiga });
130-
seenRoleIds.add(cfg.roles.laLiga);
131-
}
132-
if (cfg?.roles.preParciales && !seenRoleIds.has(cfg.roles.preParciales)) {
133-
notificationRoles.push({ label: '📚 Pre-Parciales', value: cfg.roles.preParciales });
134-
seenRoleIds.add(cfg.roles.preParciales);
135-
}
136-
if (cfg?.roles.cursos && !seenRoleIds.has(cfg.roles.cursos)) {
137-
notificationRoles.push({ label: '📖 Cursos', value: cfg.roles.cursos });
138-
seenRoleIds.add(cfg.roles.cursos);
139-
}
140-
if (
141-
cfg?.roles.notificacionesGenerales &&
142-
!seenRoleIds.has(cfg.roles.notificacionesGenerales)
143-
) {
144-
notificationRoles.push({
145-
label: '🔔 Notificaciones Generales',
146-
value: cfg.roles.notificacionesGenerales,
147-
});
148-
seenRoleIds.add(cfg.roles.notificacionesGenerales);
149-
}
150-
151-
if (notificationRoles.length > 0) {
152-
const rolesMenu = new StringSelectMenuBuilder()
153-
.setCustomId(`announce:roles:${session.userId}`)
154-
.setPlaceholder('🔔 Selecciona roles a mencionar (opcional)')
155-
.setMinValues(0)
156-
.setMaxValues(notificationRoles.length)
157-
.addOptions(
158-
notificationRoles.map((role) =>
159-
new StringSelectMenuOptionBuilder()
160-
.setLabel(role.label)
161-
.setValue(role.value)
162-
.setDefault(session.announcement.roles?.includes(role.value) || false),
163-
),
164-
);
165-
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(rolesMenu));
166-
}
167-
168-
// Botones
169-
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
170-
new ButtonBuilder()
171-
.setCustomId(`announce:edit:${session.userId}`)
172-
.setLabel('✏️ Editar Texto')
173-
.setStyle(ButtonStyle.Secondary),
174-
new ButtonBuilder()
175-
.setCustomId(`announce:image:${session.userId}`)
176-
.setLabel('🖼️ Imagen')
177-
.setStyle(ButtonStyle.Secondary),
178-
new ButtonBuilder()
179-
.setCustomId(`announce:publish:${session.userId}`)
180-
.setLabel('📢 Publicar')
181-
.setStyle(ButtonStyle.Success),
182-
new ButtonBuilder()
183-
.setCustomId(`announce:cancel:${session.userId}`)
184-
.setLabel('❌ Cancelar')
185-
.setStyle(ButtonStyle.Danger),
186-
);
187-
rows.push(actionRow);
188-
189-
// Actualizar el mensaje con embed y componentes
190-
await session.previewMessage.edit({ embeds: [embed], components: rows });
191-
192-
logger.info('Preview updated with image', {
199+
// Usar la función auxiliar para construir los componentes
200+
const rows = buildAnnouncementComponents(session, cfg);
201+
202+
logger.info('About to edit preview via editReply', {
203+
requestId: session.requestId,
204+
embedHasImage: !!session.announcement.image,
205+
embedImage: session.announcement.image,
206+
});
207+
208+
// Usar editReply en la interacción original (funciona con efímeros)
209+
await session.originalInteraction.editReply({ embeds: [embed], components: rows });
210+
211+
logger.info('Preview updated successfully with image', {
193212
requestId: session.requestId,
194213
hasImage: !!imageUrl,
195214
});
196215
} else {
197-
logger.warn('No preview message found to update', {
216+
logger.warn('No original interaction found to update', {
198217
requestId: session.requestId,
199218
});
200219
}
201220
} catch (err) {
202221
logger.error('Failed to update preview after image change', {
203222
error: err instanceof Error ? err.message : String(err),
223+
stack: err instanceof Error ? err.stack : undefined,
204224
requestId: session.requestId,
205225
});
206226
}
@@ -214,94 +234,22 @@ async function showAnnouncementOptions(interaction: any, session: any) {
214234
const embed = createAnnouncementPreview(session);
215235
const cfg = getGuildConfig(session.guildId);
216236

217-
const rows = [];
218-
219-
// Dropdown de colores
220-
const colorMenu = new StringSelectMenuBuilder()
221-
.setCustomId(`announce:color:${session.userId}`)
222-
.setPlaceholder('🎨 Selecciona un color')
223-
.addOptions(
224-
PRESET_COLORS.map((color) =>
225-
new StringSelectMenuOptionBuilder()
226-
.setLabel(color.name)
227-
.setValue(color.value)
228-
.setDefault(session.announcement.color === color.value),
229-
),
230-
);
231-
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(colorMenu));
232-
233-
// Dropdown de roles a mencionar (si existen roles de notificaciones configurados)
234-
const notificationRoles = [];
235-
const seenRoleIds = new Set<string>();
236-
237-
// Agregar roles solo si no están duplicados
238-
if (cfg?.roles.laLiga && !seenRoleIds.has(cfg.roles.laLiga)) {
239-
notificationRoles.push({ label: '⚽ La Liga', value: cfg.roles.laLiga });
240-
seenRoleIds.add(cfg.roles.laLiga);
241-
}
242-
if (cfg?.roles.preParciales && !seenRoleIds.has(cfg.roles.preParciales)) {
243-
notificationRoles.push({ label: '📚 Pre-Parciales', value: cfg.roles.preParciales });
244-
seenRoleIds.add(cfg.roles.preParciales);
245-
}
246-
if (cfg?.roles.cursos && !seenRoleIds.has(cfg.roles.cursos)) {
247-
notificationRoles.push({ label: '📖 Cursos', value: cfg.roles.cursos });
248-
seenRoleIds.add(cfg.roles.cursos);
249-
}
250-
if (cfg?.roles.notificacionesGenerales && !seenRoleIds.has(cfg.roles.notificacionesGenerales)) {
251-
notificationRoles.push({
252-
label: '🔔 Notificaciones Generales',
253-
value: cfg.roles.notificacionesGenerales,
254-
});
255-
seenRoleIds.add(cfg.roles.notificacionesGenerales);
256-
}
257-
258-
if (notificationRoles.length > 0) {
259-
const rolesMenu = new StringSelectMenuBuilder()
260-
.setCustomId(`announce:roles:${session.userId}`)
261-
.setPlaceholder('🔔 Selecciona roles a mencionar (opcional)')
262-
.setMinValues(0)
263-
.setMaxValues(notificationRoles.length)
264-
.addOptions(
265-
notificationRoles.map((role) =>
266-
new StringSelectMenuOptionBuilder()
267-
.setLabel(role.label)
268-
.setValue(role.value)
269-
.setDefault(session.announcement.roles?.includes(role.value) || false),
270-
),
271-
);
272-
rows.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(rolesMenu));
273-
}
237+
// Usar la función auxiliar para construir los componentes
238+
const rows = buildAnnouncementComponents(session, cfg);
274239

275-
// Botones de acción
276-
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
277-
new ButtonBuilder()
278-
.setCustomId(`announce:edit:${session.userId}`)
279-
.setLabel('✏️ Editar Texto')
280-
.setStyle(ButtonStyle.Secondary),
281-
new ButtonBuilder()
282-
.setCustomId(`announce:image:${session.userId}`)
283-
.setLabel('🖼️ Imagen')
284-
.setStyle(ButtonStyle.Secondary),
285-
new ButtonBuilder()
286-
.setCustomId(`announce:publish:${session.userId}`)
287-
.setLabel('📢 Publicar')
288-
.setStyle(ButtonStyle.Success),
289-
new ButtonBuilder()
290-
.setCustomId(`announce:cancel:${session.userId}`)
291-
.setLabel('❌ Cancelar')
292-
.setStyle(ButtonStyle.Danger),
293-
);
294-
rows.push(actionRow);
295-
296-
const reply = await interaction.reply({
240+
await interaction.reply({
297241
embeds: [embed],
298242
components: rows,
299243
flags: 1 << 6,
300-
fetchReply: true, // Obtener el mensaje para poder editarlo después
301244
});
302245

303-
// Guardar el mensaje para poder actualizarlo después
304-
session.previewMessage = reply;
246+
// Guardar la interacción original para poder usar editReply después
247+
session.originalInteraction = interaction;
248+
249+
logger.info('Preview message created and saved', {
250+
requestId: session.requestId,
251+
hasInteraction: !!interaction,
252+
});
305253
}
306254

307255
/**

src/commands/announce.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ async function execute(interaction: any) {
135135
guildId,
136136
requestId,
137137
channelId: cfg.channels.announcements,
138-
previewMessage: undefined, // Se guardará el mensaje del preview para actualizarlo
138+
originalInteraction: undefined, // Se guardará la interacción original para usar editReply
139139
announcement: {
140140
title: undefined,
141141
message: undefined,

0 commit comments

Comments
 (0)