import discord from botdiscord.translate import get_lang_mapping, get_flag_mapping, get_name_to_code, translate_text from botdiscord.database import get_message, save_translation, get_cached_translation class TranslationView(discord.ui.View): def __init__(self, languages: list = None): super().__init__(timeout=None) if languages: flag_mapping = get_flag_mapping() name_to_code = get_name_to_code() for lang in languages: lang_code = name_to_code.get(lang) flag = flag_mapping.get(lang_code, "") if lang_code else "" # El custom_id es vital para la persistencia custom_id = f"btn_trans_{lang_code}" self.add_item(TranslationButton(lang, lang_code, flag, custom_id)) class TranslationButton(discord.ui.Button): def __init__(self, lang_name: str, lang_code: str, flag: str, custom_id: str): label = flag if flag else lang_name super().__init__(label=label, style=discord.ButtonStyle.primary, custom_id=custom_id) self.lang_code = lang_code async def callback(self, interaction: discord.Interaction): # 1. Avisamos a Discord que estamos procesando (evita el "Interacción fallida" por timeout) await interaction.response.defer() try: if not interaction.message.reference: await interaction.followup.send("⚠️ No se pudo encontrar la referencia al mensaje original.", ephemeral=True) return original_msg_id = interaction.message.reference.message_id db_msg = get_message(original_msg_id) if not db_msg: # Si no está en MySQL, intentamos ver si el mensaje actual tiene el texto (fallback) await interaction.followup.send("⚠️ Mensaje no encontrado en la base de datos.", ephemeral=True) return text = db_msg['content'] mentions_map = db_msg['mentions_map'] # Verificamos caché cached = get_cached_translation(original_msg_id, self.lang_code) if cached: translated = cached else: translated = await translate_text(text, self.lang_code) save_translation(original_msg_id, self.lang_code, translated) # Procesar traducción import html import re translated = html.unescape(translated) if mentions_map: for placeholder, mention in mentions_map.items(): match = re.search(r'm\d+', placeholder) if not match: continue tag_num = match.group() open_pattern = re.compile(rf'<\s*{tag_num}\s*/?\s*>') translated = open_pattern.sub(mention, translated) close_pattern = re.compile(rf'<\s*/\s*{tag_num}\s*>') translated = close_pattern.sub('', translated) # 2. Usamos edit_original_response porque ya hicimos defer() await interaction.edit_original_response(content=translated, view=self.view) except Exception as e: print(f"[ERROR UI] Error en callback de traducción: {e}") await interaction.followup.send(f"❌ Error al traducir: {str(e)}", ephemeral=True) class ConfigSelect(discord.ui.Select): def __init__(self, guild_id: int, bot_type: str = "discord"): from botdiscord.database import get_active_languages lang_mapping = get_lang_mapping(bot_type) flag_mapping = get_flag_mapping(bot_type) active = get_active_languages(guild_id) options = [] for name, code in lang_mapping.items(): flag = flag_mapping.get(code, "") if flag: options.append(discord.SelectOption(label=flag, value=name, default=(code in active))) else: options.append(discord.SelectOption(label=name, value=name, default=(code in active))) super().__init__( placeholder="Selecciona los idiomas activos...", min_values=0, max_values=len(options), options=options ) async def callback(self, interaction: discord.Interaction): from botdiscord.database import set_active_languages from botdiscord.translate import get_lang_mapping, get_flag_mapping guild_id = interaction.guild_id lang_mapping = get_lang_mapping("discord") flag_mapping = get_flag_mapping("discord") selected_codes = [lang_mapping[val] for val in self.values] set_active_languages(guild_id, selected_codes) selected_flags = [] for val in self.values: code = lang_mapping.get(val) flag = flag_mapping.get(code, "") if code else "" selected_flags.append(flag if flag else val) await interaction.response.send_message( f"Configuración actualizada: {', '.join(selected_flags)}", ephemeral=True ) class ConfigView(discord.ui.View): def __init__(self, guild_id: int, bot_type: str = "discord"): super().__init__() self.add_item(ConfigSelect(guild_id, bot_type))