import discord from discord import app_commands from discord.ext import commands, tasks from datetime import datetime from zoneinfo import ZoneInfo from utils.gestion_taches import ( ajouter_tache, lister_taches_utilisateur, taches_proches, update_tache_status, charger_taches, supprimer_tache, sauvegarder_taches ) PRIORITES = ["Haute", "Moyenne", "Basse", "Critique", "Faible"] class RappelTacheView(discord.ui.View): def __init__(self, tid: str): super().__init__(timeout=None) self.tid = tid @discord.ui.button(label="✅ Marquer comme faite", style=discord.ButtonStyle.success, custom_id="btn_mark_done") async def mark_done(self, interaction: discord.Interaction, button: discord.ui.Button): success = await update_tache_status(self.tid, "Terminée") if success: await interaction.response.send_message( f"✅ La tâche #{self.tid} a été marquée comme terminée !", ephemeral=True) else: await interaction.response.send_message( "❌ Impossible de mettre à jour la tâche. Peut-être déjà terminée ?", ephemeral=True) self.disable_all_items() await interaction.message.edit(view=self) class MesTachesPaginator(discord.ui.View): def __init__(self, interaction: discord.Interaction, taches_list: list[tuple], per_page=5): super().__init__(timeout=120) self.interaction = interaction self.taches = taches_list self.per_page = per_page self.page = 0 self.max_page = (len(taches_list) - 1) // per_page def get_embed(self): embed = discord.Embed(title="📝 Vos Tâches Assignées", color=discord.Color.green()) start = self.page * self.per_page end = start + self.per_page for tid, t in self.taches[start:end]: embed.add_field( name=f"#{tid} - {t['titre']}", value=f"📅 Échéance : {t['échéance']}\n⚠️ Priorité : {t['priorité']}\n📌 Statut : {t['statut']}", inline=False ) embed.set_footer(text=f"Page {self.page + 1} / {self.max_page + 1}") return embed @discord.ui.button(label="⬅️", style=discord.ButtonStyle.secondary) async def previous_page(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user.id != self.interaction.user.id: await interaction.response.send_message("❌ Ce n'est pas votre pagination.", ephemeral=True) return if self.page > 0: self.page -= 1 await interaction.response.edit_message(embed=self.get_embed(), view=self) else: await interaction.response.defer() @discord.ui.button(label="➡️", style=discord.ButtonStyle.secondary) async def next_page(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user.id != self.interaction.user.id: await interaction.response.send_message("❌ Ce n'est pas votre pagination.", ephemeral=True) return if self.page < self.max_page: self.page += 1 await interaction.response.edit_message(embed=self.get_embed(), view=self) else: await interaction.response.defer() class JiraDiscord(commands.Cog): def __init__(self, bot): self.bot = bot self.rappels.start() def cog_unload(self): self.rappels.cancel() async def autocomplete_priorite(self, interaction: discord.Interaction, current: str): return [ app_commands.Choice(name=prio, value=prio) for prio in PRIORITES if current.lower() in prio.lower() ][:5] @app_commands.command(name="nouvelle_tache", description="Créer une nouvelle tâche") @app_commands.describe( titre="Titre de la tâche", description="Description de la tâche", assigne="Utilisateur assigné", priorite="Niveau de priorité (ex: Haute, Moyenne, Basse)", echeance="Date d'échéance au format JJ/MM/AAAA" ) async def nouvelle_tache( self, interaction: discord.Interaction, titre: str, description: str, assigne: discord.User, priorite: str, echeance: str ): data = await charger_taches() for tid, tache in data.get("taches", {}).items(): if tache["assigné"] == assigne.id and tache["titre"].lower() == titre.lower(): return await interaction.response.send_message( f"❌ {assigne.mention} a déjà une tâche avec ce titre.", ephemeral=True) try: date_obj = datetime.strptime(echeance, "%d/%m/%Y") date_str = date_obj.strftime("%Y-%m-%d") except ValueError: return await interaction.response.send_message( "❌ Format de date invalide (JJ/MM/AAAA).", ephemeral=True) id_tache = await ajouter_tache(titre, description, assigne.id, priorite, date_str, interaction.user.id) embed = discord.Embed( title=f"📌 Nouvelle Tâche #{id_tache}", description=description, color=discord.Color.blurple() ) embed.set_author(name=f"Assignée à {assigne.display_name}", icon_url=assigne.display_avatar.url) embed.add_field(name="🗂 Titre", value=titre, inline=False) embed.add_field(name="⚠️ Priorité", value=priorite, inline=True) embed.add_field(name="📅 Échéance", value=echeance, inline=True) embed.set_footer(text=f"Créée par {interaction.user.display_name}", icon_url=interaction.user.display_avatar.url) await interaction.response.send_message(embed=embed) try: await assigne.send( f"👋 Bonjour {assigne.display_name},\n\nUne nouvelle tâche t'a été assignée par {interaction.user.mention} :", embed=embed ) except Exception: pass @nouvelle_tache.autocomplete("priorite") async def autocomplete_priorite_handler(self, interaction: discord.Interaction, current: str): return await self.autocomplete_priorite(interaction, current) @app_commands.command(name="mes_taches", description="Lister mes tâches assignées") async def mes_taches(self, interaction: discord.Interaction): taches = await lister_taches_utilisateur(interaction.user.id) if not taches: await interaction.response.send_message("🚫 Aucune tâche ne vous est assignée.", ephemeral=True) return taches_list = list(taches.items()) if len(taches_list) <= 5: embed = discord.Embed(title="📝 Vos Tâches Assignées", color=discord.Color.green()) for tid, t in taches_list: embed.add_field( name=f"#{tid} - {t['titre']}", value=f"📅 Échéance : {t['échéance']}\n⚠️ Priorité : {t['priorité']}\n📌 Statut : {t['statut']}", inline=False ) await interaction.response.send_message(embed=embed, ephemeral=True) else: view = MesTachesPaginator(interaction, taches_list) await interaction.response.send_message(embed=view.get_embed(), view=view, ephemeral=True) @app_commands.command(name="update_tache", description="Mettre à jour le statut et la priorité d'une tâche") @app_commands.describe( id_tache="ID de la tâche à mettre à jour", statut="Nouveau statut de la tâche", priorite="Nouvelle priorité (optionnel)" ) async def update_tache( self, interaction: discord.Interaction, id_tache: str, statut: str, priorite: str = None ): data = await charger_taches() if id_tache not in data.get("taches", {}): return await interaction.response.send_message("❌ Tâche non trouvée.", ephemeral=True) tache = data["taches"][id_tache] if tache["assigné"] != interaction.user.id: return await interaction.response.send_message("❌ Vous ne pouvez pas mettre à jour le statut de cette tâche.", ephemeral=True) statut_update = await update_tache_status(id_tache, statut) priorite_update = True if priorite: tache["priorité"] = priorite await sauvegarder_taches(data) if statut_update and priorite_update: await interaction.response.send_message( f"✅ Le statut de la tâche #{id_tache} a été mis à jour à **{statut}**." + (f"\nLa priorité est maintenant **{priorite}**." if priorite else ""), ephemeral=True ) if tache["créé_par"] != interaction.user.id: try: creator = await self.bot.fetch_user(tache["créé_par"]) await creator.send( f"🔔 La tâche #{id_tache} que vous avez créée a été mise à jour par {interaction.user.mention} :\n" f"**Nouveau statut** : {statut}" + (f"\n**Nouvelle priorité** : {priorite}" if priorite else "") ) except Exception: pass else: await interaction.response.send_message("❌ Erreur lors de la mise à jour de la tâche.", ephemeral=True) @update_tache.autocomplete("priorite") async def autocomplete_priorite_update(self, interaction: discord.Interaction, current: str): return await self.autocomplete_priorite(interaction, current) @app_commands.command(name="supprimer_tache", description="Supprimer une tâche") @app_commands.describe( id_tache="ID de la tâche à supprimer" ) async def supprimer_tache_cmd(self, interaction: discord.Interaction, id_tache: str): data = await charger_taches() if id_tache not in data.get("taches", {}): return await interaction.response.send_message("❌ Tâche non trouvée.", ephemeral=True) tache = data["taches"][id_tache] perms = interaction.user.guild_permissions can_delete = ( tache["créé_par"] == interaction.user.id or tache["assigné"] == interaction.user.id or perms.administrator ) if not can_delete: return await interaction.response.send_message("❌ Vous ne pouvez pas supprimer cette tâche.", ephemeral=True) success = await supprimer_tache(id_tache) if success: await interaction.response.send_message(f"🗑️ La tâche #{id_tache} a été supprimée.", ephemeral=True) else: await interaction.response.send_message("❌ Erreur lors de la suppression de la tâche.", ephemeral=True) @tasks.loop(seconds=30) async def rappels(self): now = datetime.now(ZoneInfo("Europe/Paris")) if now.hour == 9 and now.minute == 0: taches = await taches_proches() for tid, t in taches.items(): try: user = await self.bot.fetch_user(t["assigné"]) embed = discord.Embed( title=f"🔔 Rappel Tâche #{tid}", description=t["description"], color=discord.Color.orange() ) embed.add_field(name="🗂 Titre", value=t["titre"], inline=False) embed.add_field(name="⚠️ Priorité", value=t["priorité"], inline=True) embed.add_field(name="📅 Échéance", value=t["échéance"], inline=True) embed.set_footer(text="Clique sur le bouton si tu as fini !") view = RappelTacheView(tid) await user.send(embed=embed, view=view) except Exception: continue @rappels.before_loop async def avant_rappel(self): await self.bot.wait_until_ready() async def setup(bot): await bot.add_cog(JiraDiscord(bot))