import discord from .data.models import TicketData class FeedbackView(discord.ui.View): def __init__(self, bot, storage, ticket: TicketData, staff_rating_only: bool = False): super().__init__(timeout=86400) # 24h timeout self.bot = bot self.storage = storage self.ticket = ticket self.rating = 0 self.comment = "" self.staff_rating_only = staff_rating_only # Add Select Menu for Rating self.add_item(RatingSelect()) @discord.ui.button(label="📝 Laisser un commentaire", style=discord.ButtonStyle.secondary, custom_id="feedback_comment", row=1) async def comment_button(self, interaction: discord.Interaction, button: discord.ui.Button): await interaction.response.send_modal(FeedbackModal(self)) @discord.ui.button(label="✅ Envoyer", style=discord.ButtonStyle.green, custom_id="feedback_submit", row=1) async def submit_button(self, interaction: discord.Interaction, button: discord.ui.Button): if self.rating == 0: await interaction.response.send_message("❌ Veuillez sélectionner une note avant d'envoyer.", ephemeral=True) return # Save feedback self.ticket.rating = self.rating self.ticket.feedback = self.comment if self.comment else "Aucun commentaire" self.storage.save_ticket(self.ticket) # Disable view for child in self.children: child.disabled = True # If this is a staff rating only view, we don't send the normal message if not self.staff_rating_only: await interaction.response.edit_message(content="✅ Merci pour votre retour !", view=self, embed=None) else: await interaction.response.edit_message(content="✅ Note envoyée !", view=self, embed=None) # Log feedback if configured try: # Reload ticket to ensure we have latest data (especially claimed_by) # We need to use the channel_id to find the ticket reloaded_ticket = self.storage.load_ticket(self.ticket.channel_id) if reloaded_ticket: self.ticket = reloaded_ticket print(f"DEBUG: Reloaded ticket {self.ticket.channel_id}. Claimed by: {self.ticket.claimed_by}", flush=True) else: print(f"DEBUG: Could not reload ticket {self.ticket.channel_id}", flush=True) print(f"DEBUG: Feedback submitted for {self.ticket.channel_id}", flush=True) if self.ticket.claimed_by: staff_user = self.bot.get_user(self.ticket.claimed_by) print(f"DEBUG: Staff user from cache: {staff_user}", flush=True) if not staff_user: # Try fetching if not in cache try: staff_user = await self.bot.fetch_user(self.ticket.claimed_by) print(f"DEBUG: Staff user fetched: {staff_user}", flush=True) except Exception as e: print(f"DEBUG: Failed to fetch staff user: {e}", flush=True) pass if staff_user: # Create feedback embed embed = discord.Embed( title="📝 Nouveau Commentaire Reçu", description=f"Un utilisateur a laissé un avis sur le ticket #{self.ticket.channel_id}", color=discord.Color.gold() if self.rating < 3 else discord.Color.green(), timestamp=discord.utils.utcnow() ) embed.add_field( name="Note", value=f"{'⭐' * self.rating} ({self.rating}/5)", inline=True ) # Add user info if possible user = self.bot.get_user(self.ticket.user_id) user_name = f"{user.name} ({user.id})" if user else f"Utilisateur {self.ticket.user_id}" embed.add_field( name="Utilisateur", value=user_name, inline=True ) feedback_text = self.comment if self.comment else "Aucun commentaire écrit." embed.add_field( name="Commentaire", value=feedback_text, inline=False ) try: await staff_user.send(embed=embed) print(f"DEBUG: DM sent successfully to {staff_user}", flush=True) except discord.Forbidden: print(f"DEBUG: DM failed - Forbidden (DMs closed)", flush=True) except Exception as e: print(f"DEBUG: Error sending feedback DM: {e}", flush=True) else: print("DEBUG: Staff user object is None", flush=True) else: print("DEBUG: Ticket has no claimed_by value", flush=True) except Exception as e: print(f"Error in feedback notification: {e}", flush=True) class RatingSelect(discord.ui.Select): def __init__(self): options = [ discord.SelectOption(label="⭐⭐⭐⭐⭐ (Excellent)", value="5", description="Service parfait !"), discord.SelectOption(label="⭐⭐⭐⭐ (Très bien)", value="4", description="Très bon service"), discord.SelectOption(label="⭐⭐⭐ (Bien)", value="3", description="Correct"), discord.SelectOption(label="⭐⭐ (Moyen)", value="2", description="Peut mieux faire"), discord.SelectOption(label="⭐ (Mauvais)", value="1", description="Insatisfaisant") ] super().__init__(placeholder="Notez le service...", min_values=1, max_values=1, options=options, row=0) async def callback(self, interaction: discord.Interaction): self.view.rating = int(self.values[0]) await interaction.response.defer() class FeedbackModal(discord.ui.Modal): def __init__(self, view): super().__init__(title="Votre avis") self.view = view self.comment = discord.ui.TextInput( label="Commentaire", style=discord.TextStyle.paragraph, placeholder="Dites-nous ce que vous avez pensé du support...", required=True, max_length=1000 ) self.add_item(self.comment) async def on_submit(self, interaction: discord.Interaction): self.view.comment = self.comment.value await interaction.response.send_message("Commentaire enregistré ! N'oubliez pas de valider avec 'Envoyer'.", ephemeral=True)