diff --git a/EXEMPLE_ARRIVER.png b/EXEMPLE_ARRIVER.png new file mode 100644 index 0000000..092c725 Binary files /dev/null and b/EXEMPLE_ARRIVER.png differ diff --git a/commandes/ticket/__init__.py b/commandes/ticket/__init__.py index aecc64f..4aae0fb 100644 --- a/commandes/ticket/__init__.py +++ b/commandes/ticket/__init__.py @@ -185,7 +185,7 @@ class TicketPanelView(disnake.ui.View): accessory=disnake.ui.Button( label=cat.name, style=disnake.ButtonStyle.primary, - custom_id=f"cat_{cat.id}_{int(disnake.utils.time_snowflake(disnake.utils.utcnow()) / 1000)}" + custom_id=f"catv2_{cat.id}_{int(disnake.utils.time_snowflake(disnake.utils.utcnow()) / 1000)}" ) ) ) @@ -200,8 +200,13 @@ class TicketPanelView(disnake.ui.View): import traceback traceback.print_exc() # Fallback: texte simple avec view legacy - cat_list = "\n".join(f"{cat.emoji} **{cat.name}** — {cat.description or 'Aucune description'}" for cat in self.config.categories[:5]) - if not interaction.response.is_done(): + if interaction.response.is_done(): + await interaction.followup.send( + f"**🎫 Créer un Ticket**\n\nSélectionnez une catégorie ci-dessous:", + view=CategorySelectionView(self.bot, self.config), + ephemeral=True + ) + else: await interaction.response.send_message( f"**🎫 Créer un Ticket**\n\nSélectionnez une catégorie ci-dessous:", view=CategorySelectionView(self.bot, self.config), @@ -2239,11 +2244,15 @@ class CategoryManagerView(disnake.ui.View): async def callback(self, interaction: disnake.ModalInteraction): import uuid cat_id = str(uuid.uuid4())[:8] + name_val = interaction.text_values.get("add_cat_name", "Nouvelle Catégorie") + desc_val = interaction.text_values.get("add_cat_desc", "") + emoji_val = interaction.text_values.get("add_cat_emoji", "🎫") + category = TicketCategory( id=cat_id, - name=self.name.value, - description=self.description.value or "", - emoji=self.emoji.value or "🎫" + name=name_val, + description=desc_val, + emoji=emoji_val ) self.config.categories.append(category) self.storage.save_config(interaction.guild_id, self.config) @@ -2847,10 +2856,10 @@ class TicketCommands(commands.Cog): if not custom_id: return - # Accept both ticket_* / cat_* / close_* custom_ids + # Accept both ticket_* / catv2_* / close_* custom_ids if not ( str(custom_id).startswith("ticket_") - or str(custom_id).startswith("cat_") + or str(custom_id).startswith("catv2_") or str(custom_id) in {"close_confirm", "close_cancel", "delay_cancel"} ): return @@ -2875,20 +2884,10 @@ class TicketCommands(commands.Cog): try: # Routage manuel - if custom_id == "ticket_create": - view = TicketPanelView(self.bot, config, self.storage) - await view._create_callback(inter) - elif custom_id == "ticket_my_tickets": - view = TicketPanelView(self.bot, config, self.storage) - await view._my_tickets_callback(inter) - elif custom_id == "ticket_analytics": - view = TicketPanelView(self.bot, config, self.storage) - await view._analytics_callback(inter) - - # ✅ BUGFIX: Sélection de catégorie en V2 => custom_id = cat_{cat.id}_{snowflake} - elif custom_id.startswith("cat_"): + # ✅ BUGFIX: Sélection de catégorie en V2 => custom_id = catv2_{cat.id}_{snowflake} + if custom_id.startswith("catv2_"): try: - # format: cat__ + # format: catv2__ parts = custom_id.split("_") if len(parts) >= 3: cat_id = "_".join(parts[1:-1]) @@ -2904,7 +2903,7 @@ class TicketCommands(commands.Cog): modal = TicketPriorityModal(self.bot, config, category) await inter.response.send_modal(modal) except Exception as e: - kuby_logger.error(f"[TicketSystem] cat_ routing error: {e}", exc_info=True) + kuby_logger.error(f"[TicketSystem] catv2_ routing error: {e}", exc_info=True) if not inter.response.is_done(): await inter.response.send_message(f"Erreur interne: {e}", ephemeral=True) diff --git a/commandes/ticket/data/models.py b/commandes/ticket/data/models.py index d03ce03..22ca9f5 100644 --- a/commandes/ticket/data/models.py +++ b/commandes/ticket/data/models.py @@ -67,7 +67,7 @@ class TicketCategory: self.description = description self.emoji = emoji self.color = color - self.staff_roles = staff_roles or [] + self.staff_roles = list(staff_roles) if staff_roles is not None else [] self.welcome_message = welcome_message or "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu." self.require_reason = require_reason self.max_tickets_per_user = max_tickets_per_user diff --git a/commandes/welcome.py b/commandes/welcome.py index 0f33fe6..2721ff3 100644 --- a/commandes/welcome.py +++ b/commandes/welcome.py @@ -93,63 +93,56 @@ class Welcome(commands.Cog): background = Image.open(bg_path) draw = ImageDraw.Draw(background) - # Charger la police avec support des accents - font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf" - if not os.path.exists(font_path): - kuby_logger.warning(f"[Welcome] Police DejaVu introuvable, fallback sur police custom") - font_path = os.path.join(self.base_dir, 'custom_font_large.otf') + # Charger les polices custom (comme sur EXEMPLE_ARRIVER.png) + font_large_path = os.path.join(self.base_dir, 'custom_font_large.otf') + font_small_path = os.path.join(self.base_dir, 'custom_font_small.otf') - font = ImageFont.truetype(font_path, 55) - - # Construire le message à afficher sur la bannière - display_message = custom_message if custom_message else "Bienvenue {membre} chez {server}" - - # Remplacer les placeholders - try: - display_message = display_message.format( - membre=username, - member=username, - server=server_name or "", - serveur=server_name or "", - username=username, - servername=server_name or "", - ) - except Exception: - pass # Si placeholders inconnus, garder tel quel + # Les 3 lignes de texte à afficher (format identique à l'exemple) + line1_text = "BIENVENUE" + line2_text = username.upper() + line3_text = (server_name or "").upper() # Zone de texte disponible (à droite de l'avatar) text_area_left = 280 text_area_right = background.width - 20 text_area_width = text_area_right - text_area_left + text_area_center_x = text_area_left + text_area_width // 2 - # Découper le texte en lignes qui tiennent dans la zone - words = display_message.split() - lines = [] - current_line = "" - for word in words: - test_line = f"{current_line} {word}".strip() - bbox = draw.textbbox((0, 0), test_line, font=font) - if bbox[2] - bbox[0] <= text_area_width: - current_line = test_line - else: - if current_line: - lines.append(current_line) - current_line = word - if current_line: - lines.append(current_line) + # Fonction pour trouver la taille de police optimale + def fit_font(font_path, text, max_size, max_width): + size = max_size + while size > 10: + font = ImageFont.truetype(font_path, size) + bbox = draw.textbbox((0, 0), text, font=font) + w = bbox[2] - bbox[0] + if w <= max_width: + h = bbox[3] - bbox[1] + return font, w, h + size -= 2 + font = ImageFont.truetype(font_path, 10) + bbox = draw.textbbox((0, 0), text, font=font) + return font, bbox[2] - bbox[0], bbox[3] - bbox[1] - wrapped_text = "\n".join(lines) + # Adapter chaque ligne à la zone disponible + font1, w1, h1 = fit_font(font_large_path, line1_text, 65, text_area_width) + font2, w2, h2 = fit_font(font_small_path, line2_text, 35, text_area_width) + font3, w3, h3 = fit_font(font_large_path, line3_text, 65, text_area_width) - # Mesurer le bloc de texte complet - bbox = draw.textbbox((0, 0), wrapped_text, font=font) - text_width = bbox[2] - bbox[0] - text_height = bbox[3] - bbox[1] + # Espacement entre les lignes + spacing_1_2 = 15 # entre BIENVENUE et username + spacing_2_3 = 20 # entre username et nom du serveur + total_height = h1 + spacing_1_2 + h2 + spacing_2_3 + h3 - # Centrer le bloc dans la zone disponible - text_x = text_area_left + (text_area_width - text_width) // 2 - text_y = (background.height - text_height) // 2 + # Centrer verticalement le bloc de 3 lignes + start_y = (background.height - total_height) // 2 - draw.text((text_x, text_y), wrapped_text, font=font, fill=(255, 255, 255), align="center") + # Dessiner chaque ligne centrée horizontalement dans la zone + y = start_y + draw.text((text_area_center_x - w1 // 2, y), line1_text, font=font1, fill=(255, 255, 255)) + y += h1 + spacing_1_2 + draw.text((text_area_center_x - w2 // 2, y), line2_text, font=font2, fill=(255, 255, 255)) + y += h2 + spacing_2_3 + draw.text((text_area_center_x - w3 // 2, y), line3_text, font=font3, fill=(255, 255, 255)) # Ajouter l'avatar diff --git a/test_welcome_default_bg.png b/test_welcome_default_bg.png new file mode 100644 index 0000000..2fdae12 Binary files /dev/null and b/test_welcome_default_bg.png differ diff --git a/test_welcome_final.png b/test_welcome_final.png new file mode 100644 index 0000000..f332f8e Binary files /dev/null and b/test_welcome_final.png differ diff --git a/test_welcome_fixed.png b/test_welcome_fixed.png new file mode 100644 index 0000000..62a3656 Binary files /dev/null and b/test_welcome_fixed.png differ diff --git a/test_welcome_output.png b/test_welcome_output.png new file mode 100644 index 0000000..7d573ae Binary files /dev/null and b/test_welcome_output.png differ diff --git a/test_welcome_real.png b/test_welcome_real.png new file mode 100644 index 0000000..5075af0 Binary files /dev/null and b/test_welcome_real.png differ