From 3534363f98467b45bbbe4df9a0d39c25d08181ac Mon Sep 17 00:00:00 2001 From: Lowei Date: Fri, 22 May 2026 18:46:32 +0200 Subject: [PATCH] =?UTF-8?q?fix(bot):=20am=C3=A9liorer=20la=20robustesse=20?= =?UTF-8?q?des=20handlers=20d'erreurs=20Discord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - advanced_logger.py: parsing NDJSON plus robuste pour les fichiers JSON corrompus ou malformés lors de la vérification des rôles précédents. Évite l'erreur "Expecting value: line 2 column 1". - bot.py: simplification de la détection d'erreur 403 Missing Permissions (codes 50013 et 20023) lors de la restauration des rôles au join d'un membre. Évite le log d'erreur "Failed to restore safe roles" quand c'est juste un problème de permissions/bot role hierarchy. - bug_report.py: simplification de la détection du code 50007 (Cannot send messages to this user) lors de l'envoi de notifications de labels GitLab. Évite le log "Erreur inattendue dans la notification de label". Co-Authored-By: Claude Opus 4.6 --- bot.py | 7 +++++++ commandes/bug_report.py | 7 +++---- src/advanced_logger.py | 31 +++++++++++++++++-------------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/bot.py b/bot.py index 6883ee5..eca411f 100755 --- a/bot.py +++ b/bot.py @@ -189,6 +189,13 @@ class MyBot(commands.Bot): is_transient = isinstance(e, disnake.HTTPException) and e.status in [500, 502, 503, 504] if not isinstance(e, disnake.HTTPException): is_transient = True + # 403 with code 50013 = Missing Permissions - don't retry + if isinstance(e, disnake.HTTPException) and e.status == 403: + error_code = getattr(e, 'code', None) + # 50013 = Missing Permissions, 20023 = Cannot modify a role higher than bot's highest role + if error_code in (50013, 20023): + kuby_logger.warning(f"Missing Manage Roles permission to restore safe roles for {member} in {member.guild.name} - please ensure the bot has the Manage Roles permission") + break if is_transient and i < retries - 1: await asyncio.sleep((i + 1) * 2) continue diff --git a/commandes/bug_report.py b/commandes/bug_report.py index bab31e3..e319851 100644 --- a/commandes/bug_report.py +++ b/commandes/bug_report.py @@ -323,11 +323,10 @@ class BugReport(commands.Cog): f"**{current_labels_str}** pour l'issue #{issue_iid} ({issue_title})." ) except (disnake.Forbidden, disnake.HTTPException) as e: - if isinstance(e, disnake.Forbidden) or ( - isinstance(e, disnake.HTTPException) and e.code == 50007 - ): + error_code = getattr(e, 'code', None) + if isinstance(e, disnake.Forbidden) or error_code == 50007: kuby_logger.warning( - f"Impossible d'envoyer un MP à {user} ({user.id}) - MPs désactivés (Code: {getattr(e, 'code', 'Unknown')})" + f"Impossible d'envoyer un MP à {user} ({user.id}) - MPs désactivés (Code: {error_code})" ) if dev and dev.id != user.id: await dev.send( diff --git a/src/advanced_logger.py b/src/advanced_logger.py index f4cbfd5..9c65f39 100755 --- a/src/advanced_logger.py +++ b/src/advanced_logger.py @@ -123,22 +123,25 @@ class AdvancedLogger: try: logs = json.loads(content) except json.JSONDecodeError: - # Fallback: try to strip brackets and commas - content_clean = content.strip('[]').strip() - # This is getting complex, let's just try line-by-line fallback + # File is corrupt or semi-corrupt, try line-by-line pass - # If not a list or failed list parse, try NDJSON line-by-line - if not logs: - for line in content.splitlines(): - line = line.strip() - if not line: continue - # Strip trailing/leading commas in case of semi-corrupt legacy conversion - line = line.strip(',') - try: - logs.append(json.loads(line)) - except json.JSONDecodeError: - continue # Skip corrupt lines + # Try NDJSON line-by-line (handles both legacy and current format) + lines = content.splitlines() + for line in lines: + line = line.strip() + if not line: + continue + # Strip trailing/leading commas in case of semi-corrupt lines + line = line.strip(',') + if not line: + continue + try: + parsed = json.loads(line) + if isinstance(parsed, dict): + logs.append(parsed) + except json.JSONDecodeError: + continue # Skip corrupt lines # Guard against empty logs list after parsing if not logs: