diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..2613c55 --- /dev/null +++ b/TODO.md @@ -0,0 +1,13 @@ +# TODO - Ticket: fermeture restreinte après prise en charge + +- [ ] Mettre à jour la permission de fermeture côté joueur vs staff pour les tickets (mode général) : + - Joueur : uniquement si `TicketStatus.OPEN` + - Staff : autorisé même si `TicketStatus.CLAIMED` +- [x] Mettre à jour la permission de fermeture côté confirmation `close_confirm` (routeur `on_interaction`) avec la même règle. +- [x] Appliquer la même contrainte au mode recrutement (boutons `recruitment_close` / accept/refuse) : + - Joueur ne peut pas fermer si ticket déjà pris en charge (si applicable selon votre logique de "claim"). +- [x] Tester manuellement : + - Ticket OPEN => fermeture joueur OK + - Ticket CLAIMED => fermeture joueur refusée, staff OK + - Recrutement : fermeture conformes à la contrainte + diff --git a/commandes/invites.py b/commandes/invites.py index 3a2ecd6..fb80974 100644 --- a/commandes/invites.py +++ b/commandes/invites.py @@ -191,11 +191,16 @@ class Invites(commands.Cog): current_present = 0 for mid in invited_ids: - if guild.get_member(mid): + member = guild.get_member(mid) + if member is not None: + # "membres présents" doit refléter la présence réelle : on considère présent + # uniquement les membres qui sont encore sur le serveur. current_present += 1 else: kuby_logger.debug(f"[Invites] Membre invité {mid} non trouvé dans le serveur {guild_id}") - + + # Total = tous les invités enregistrés pour cet inviteur. + # "présents" = ceux qui sont encore sur le serveur (donc baisse quand quelqu'un quitte). return len(invited_ids), current_present except Exception as e: kuby_logger.error(f"[Invites] Erreur lors de la récupération des statistiques d'invitations pour {user_id}: {e}") diff --git a/commandes/ticket/__init__.py b/commandes/ticket/__init__.py index 9dbaa87..95cbc0f 100644 --- a/commandes/ticket/__init__.py +++ b/commandes/ticket/__init__.py @@ -1053,9 +1053,13 @@ class TicketManagementView(disnake.ui.View): f"ticket_user={getattr(self.ticket,'user_id',None)}" ) # Vérifier si l'utilisateur peut fermer le ticket + # Règle voulue: + # - Staff: toujours autorisé + # - Joueur: uniquement si le ticket n'est pas encore pris en charge (OPEN) can_close = ( - interaction.user.id == self.ticket.user_id or - self._is_staff(interaction) + self._is_staff(interaction) or ( + interaction.user.id == self.ticket.user_id and self.ticket.status == TicketStatus.OPEN + ) ) if not can_close: @@ -1270,9 +1274,13 @@ class CloseConfirmationView(disnake.ui.View): async def confirm_callback(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction): """L'utilisateur confirme la fermeture""" # Vérifier les permissions + # Règle voulue: + # - Staff: toujours autorisé + # - Joueur: uniquement si le ticket n'est pas encore pris en charge (OPEN) can_close = ( - interaction.user.id == self.ticket.user_id or - self._is_staff(interaction) + self._is_staff(interaction) or ( + interaction.user.id == self.ticket.user_id and self.ticket.status == TicketStatus.OPEN + ) ) if not can_close: @@ -3486,7 +3494,16 @@ class TicketCommands(commands.Cog): return # Vérifier que c'est du staff - if not is_staff(inter, config, category): + # Règle voulue: + # - Staff: toujours autorisé + # - Joueur: uniquement si le ticket n'est pas encore pris en charge (OPEN) + # Ici on impose strictement staff (le bouton est staff dans la UI), + # et on protège aussi contre un éventuel usage côté user. + if ( + not is_staff(inter, config, category) and not ( + inter.user.id == ticket.user_id and ticket.status == TicketStatus.OPEN + ) + ): await inter.response.send_message("Réservé au staff.", ephemeral=True) return @@ -3562,9 +3579,13 @@ class TicketCommands(commands.Cog): await inter.response.send_message("Ticket non trouvé.", ephemeral=True) return + # Règle voulue: + # - Staff: toujours autorisé + # - Joueur: uniquement si le ticket n'est pas encore pris en charge (OPEN) can_close = ( - inter.user.id == ticket.user_id or - is_staff(inter, config, config.get_category(ticket.category_id)) + is_staff(inter, config, config.get_category(ticket.category_id)) or ( + inter.user.id == ticket.user_id and ticket.status == TicketStatus.OPEN + ) ) if not can_close: await inter.response.send_message("Vous ne pouvez pas fermer ce ticket.", ephemeral=True)