Première version de la mise à jour du suivie des bugs

This commit is contained in:
Mathis 2026-03-14 17:05:20 +01:00
parent fd9251fc6e
commit d155ebfcb0
2 changed files with 235 additions and 49 deletions

View file

@ -1,7 +1,8 @@
import discord
from discord import app_commands
from discord.ext import commands, tasks
from discord.ext import commands
from utils.gitlab_client import gitlab_client
from aiohttp import web
import logging
import json
import os
@ -109,61 +110,139 @@ class FeatureSuggestionModal(discord.ui.Modal, title="Suggérer une fonctionnali
class BugReport(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.check_gitlab_issues.start()
async def cog_load(self):
self.web_app = web.Application()
self.web_app.router.add_post('/bot_event', self.handle_bot_event)
self.runner = web.AppRunner(self.web_app)
await self.runner.setup()
self.site = web.TCPSite(self.runner, '127.0.0.1', 5001)
await self.site.start()
kuby_logger.info("Internal Bot Webhook Server started on 127.0.0.1:5001")
def cog_unload(self):
self.check_gitlab_issues.cancel()
@tasks.loop(minutes=30)
async def check_gitlab_issues(self):
"""Vérifie périodiquement si des issues suivies ont été fermées"""
if not os.path.exists(REPORTS_FILE):
return
if hasattr(self, 'runner'):
self.bot.loop.create_task(self.runner.cleanup())
async def handle_bot_event(self, request):
try:
payload = await request.json()
event_type = payload.get("object_kind")
if event_type not in ["issue", "note"]:
return web.json_response({"status": "ignored"}, status=200)
if event_type == "issue":
issue_iid = payload.get("object_attributes", {}).get("iid")
else:
issue_iid = payload.get("issue", {}).get("iid")
if not issue_iid:
return web.json_response({"status": "no issue id"}, status=200)
if not os.path.exists(REPORTS_FILE):
return web.json_response({"status": "no reports file"}, status=200)
with open(REPORTS_FILE, "r") as f:
reports = json.load(f)
if not reports:
return
issues_to_remove = []
for issue_iid, user_id in reports.items():
issue = await gitlab_client.get_issue(int(issue_iid))
if issue and issue.get("state") == "closed":
# L'issue est fermée ! On prévient l'utilisateur
user = self.bot.get_user(user_id)
if user:
try:
is_suggestion = "[SUGGESTION]" in issue.get('title', '')
title_type = "Suggestion Implémentée !" if is_suggestion else "🛠️ Bug Résolu !"
msg_type = "suggestion" if is_suggestion else "bug"
status_val = "Implémenté / Terminé" if is_suggestion else "Terminé / Résolu"
embed = discord.Embed(
title=title_type,
description=f"Bonne nouvelle ! Votre {msg_type} (**{issue.get('title')}**) a été marqué comme terminé sur GitLab.",
color=discord.Color.green()
)
embed.add_field(name="Statut", value=status_val)
embed.add_field(name="Prochaine étape", value="La mise à jour arrive prochainement !")
embed.set_footer(text="Merci de votre aide pour améliorer le bot.")
await user.send(embed=embed)
issues_to_remove.append(issue_iid)
except Exception as e:
kuby_logger.error(f"Impossible d'envoyer un MP à {user_id}: {e}")
else:
# On ne peut pas trouver l'user, on retire quand même pour ne pas boucler
issues_to_remove.append(issue_iid)
if issues_to_remove:
for iid in issues_to_remove:
del reports[iid]
with open(REPORTS_FILE, "w") as f:
json.dump(reports, f, indent=4)
user_id = reports.get(str(issue_iid))
if not user_id:
return web.json_response({"status": "untracked issue"}, status=200)
user = self.bot.get_user(user_id)
if not user:
try:
user = await self.bot.fetch_user(user_id)
except:
pass
if not user:
return web.json_response({"status": "user not found"}, status=200)
app_info = await self.bot.application_info()
dev = app_info.owner
issue_title = payload.get("object_attributes", {}).get("title", f"#{issue_iid}")
if event_type == "note":
issue_title = payload.get("issue", {}).get("title", f"#{issue_iid}")
if event_type == "issue":
action = payload.get("object_attributes", {}).get("action")
changes = payload.get("changes", {})
# Check for label changes
if "labels" in changes:
curr_labels = [l.get("title") for l in changes["labels"].get("current", []) if l.get("title")]
display_labels = [l for l in curr_labels if not l.startswith("Priority::") and l not in ["bug", "manual-report", "manual-suggestion"]]
if display_labels:
current_labels_str = ", ".join(display_labels)
else:
current_labels_str = "Mis à jour"
try:
embed = discord.Embed(
title="🛠️ Mise à jour de votre signalement !",
description=f"Le statut de votre rapport **{issue_title}** a été mis à jour par l'équipe.",
color=discord.Color.blue()
)
embed.add_field(name="Nouveaux Labels / Statuts", value=current_labels_str)
await user.send(embed=embed)
if dev:
await dev.send(f"✅ [FIABLE] L'utilisateur {user} ({user.id}) a bien reçu la notification de statut **{current_labels_str}** pour l'issue #{issue_iid} ({issue_title}).")
except Exception as e:
if dev:
await dev.send(f"❌ [ERREUR] Impossible de notifier l'utilisateur {user} pour l'issue #{issue_iid} : {e}")
# Check if it was closed
if action == "close" or payload.get("object_attributes", {}).get("state") == "closed":
try:
embed = discord.Embed(
title="🛠️ Bug / Suggestion Terminé(e) !",
description=f"Bonne nouvelle ! Votre signalement **{issue_title}** a été marqué comme terminé ou résolu.",
color=discord.Color.green()
)
embed.add_field(name="Prochaine étape", value="La mise à jour arrive prochainement (ou est déjà là) !")
embed.set_footer(text="Merci pour votre aide !")
await user.send(embed=embed)
if dev:
await dev.send(f"✅ [FIABLE] L'utilisateur {user} ({user.id}) a bien reçu la notification de CLÔTURE pour l'issue #{issue_iid}.")
except Exception as e:
if dev:
await dev.send(f"❌ [ERREUR] Impossible d'annoncer la clôture à {user} pour l'issue #{issue_iid} : {e}")
elif event_type == "note":
note_attr = payload.get("object_attributes", {})
is_system = note_attr.get("system", False)
if not is_system:
note_body = note_attr.get("note", "")
author_name = payload.get("user", {}).get("name", "Développeur")
try:
embed = discord.Embed(
title="💬 Nouveau commentaire sur votre signalement",
description=f"Le développeur a répondu à votre rapport **{issue_title}** :\n\n>>> {note_body}",
color=discord.Color.orange()
)
embed.set_footer(text=f"Par {author_name}")
await user.send(embed=embed)
if dev:
await dev.send(f"✅ [FIABLE] L'utilisateur {user} ({user.id}) a bien reçu votre commentaire pour l'issue #{issue_iid}.")
except Exception as e:
if dev:
await dev.send(f"❌ [ERREUR] Impossible d'envoyer votre commentaire à {user} pour l'issue #{issue_iid} : {e}")
return web.json_response({"status": "success"}, status=200)
except Exception as e:
kuby_logger.error(f"Erreur lors du cycle de vérification GitLab: {e}")
kuby_logger.error(f"Error handling bot event: {e}")
return web.json_response({"status": "error", "message": str(e)}, status=500)
@app_commands.command(name="signaler_bug", description="Signaler un bug aux développeurs")
@app_commands.choices(priority=[
@ -172,11 +251,17 @@ class BugReport(commands.Cog):
app_commands.Choice(name="Haute", value="High"),
app_commands.Choice(name="Urgente", value="Urgent"),
])
async def signaler_bug(self, interaction: discord.Interaction, priority: app_commands.Choice[str]):
async def signaler_bug(self, interaction: discord.Interaction, priority: app_commands.Choice[str], mot_de_passe: str):
if mot_de_passe != "01thisma":
await interaction.response.send_message("❌ Mot de passe incorrect. Vous n'êtes pas autorisé à signaler un bug.", ephemeral=True)
return
await interaction.response.send_modal(BugReportModal(priority))
@app_commands.command(name="suggerer_fonctionnalite", description="Proposer une nouvelle fonctionnalité pour le bot")
async def suggerer_fonctionnalite(self, interaction: discord.Interaction):
async def suggerer_fonctionnalite(self, interaction: discord.Interaction, mot_de_passe: str):
if mot_de_passe != "01thisma":
await interaction.response.send_message("❌ Mot de passe incorrect.", ephemeral=True)
return
await interaction.response.send_modal(FeatureSuggestionModal())
async def setup(bot):