Fix YouTube notification delivery

This commit is contained in:
2026-08-16 21:13:40 +02:00
parent e23f0a0385
commit 7fcb196bf3
2 changed files with 55 additions and 32 deletions
+10 -6
View File
@@ -44,6 +44,7 @@ class DiscordBot(discord.Client):
super().__init__(intents=intents)
self.tree = app_commands.CommandTree(self)
self.synced = False
self.background_tasks_started = False
async def setup_hook(self):
for cmd in (
@@ -98,11 +99,15 @@ class DiscordBot(discord.Client):
await cleanup_orphaned_auto_rooms(self)
self.loop.create_task(self.updateStatus())
self.loop.create_task(self.updateHumbleBundle())
self.loop.create_task(self.updateYouTube())
self.loop.create_task(self.updateFreeLoot())
self.loop.create_task(self.updatePatreon())
# on_ready est rappelé après une reconnexion : ne pas démarrer plusieurs
# boucles de surveillance, qui peuvent envoyer des notifications en double.
if not self.background_tasks_started:
self.background_tasks_started = True
self.loop.create_task(self.updateStatus())
self.loop.create_task(self.updateHumbleBundle())
self.loop.create_task(self.updateYouTube())
self.loop.create_task(self.updateFreeLoot())
self.loop.create_task(self.updatePatreon())
async def on_disconnect(self):
webapp.config["BOT_STATUS"]["discord_connected"] = False
@@ -267,4 +272,3 @@ async def on_invite_create(invite):
@bot.event
async def on_invite_delete(invite):
await updateInviteCache(invite.guild)
+45 -26
View File
@@ -125,31 +125,46 @@ async def _checkChannelVideos(notification: YouTubeNotification, is_first_check:
for vid, vdata in videos:
_save_video_history(notification.id, vid, vdata, notified=False)
if videos:
latest_video_id, latest_video = videos[0]
if is_first_check:
if not notification.last_video_id or notification.last_video_id != latest_video_id:
logger.info(f"YouTube: synchronisation initiale pour {channel_id}, dernière vidéo: {latest_video_id}")
notification.last_video_id = latest_video_id
db.session.commit()
if not videos:
return
latest_video_id, _ = videos[0]
if is_first_check or not notification.last_video_id:
# Au démarrage, on initialise le curseur sans annoncer l'historique.
notification.last_video_id = latest_video_id
db.session.commit()
logger.info(f"YouTube: synchronisation initiale pour {channel_id}, dernière vidéo: {latest_video_id}")
return
# Le flux est trié du plus récent au plus ancien. On envoie donc toutes les
# vidéos postérieures au curseur, dans l'ordre de publication.
last_video_index = next(
(index for index, (video_id, _) in enumerate(videos) if video_id == notification.last_video_id),
None,
)
if last_video_index is None:
# Le curseur n'est plus dans le flux (ou le filtre vidéo a changé) :
# ne pas rejouer tout l'historique, mais notifier la dernière vidéo.
pending_videos = [videos[0]]
logger.warning(
f"YouTube: curseur {notification.last_video_id} absent du flux pour {channel_id}; "
f"notification de la dernière vidéo uniquement"
)
else:
pending_videos = list(reversed(videos[:last_video_index]))
embed_config = _extract_embed_config(notification)
for video_id, video_data in pending_videos:
logger.info(f"Nouvelle vidéo détectée: {video_id} pour la chaîne {channel_id}")
success = await _notifyVideo(embed_config, video_data, video_id)
if not success:
# Ne pas avancer le curseur : la vidéo sera réessayée au prochain cycle.
logger.warning(f"Notification échouée pour {video_id}; nouvel essai au prochain contrôle")
return
if not notification.last_video_id:
notification.last_video_id = latest_video_id
db.session.commit()
return
if latest_video_id != notification.last_video_id:
logger.info(f"Nouvelle vidéo détectée: {latest_video_id} pour la chaîne {notification.channel_id}")
embed_config = _extract_embed_config(notification)
success = await _notifyVideo(embed_config, latest_video, latest_video_id)
if success:
_save_video_history(notification.id, latest_video_id, latest_video, notified=True)
else:
logger.warning(f"Notification échouée pour {latest_video_id}, vidéo enregistrée comme non notifiée")
notification.last_video_id = latest_video_id
db.session.commit()
_save_video_history(notification.id, video_id, video_data, notified=True)
notification.last_video_id = video_id
db.session.commit()
except Exception as e:
logger.error(f"Erreur lors de la vérification des vidéos: {e}")
@@ -242,9 +257,13 @@ async def _sendMessage(embed_config: dict, message: str, video_url: str, thumbna
"""Envoie le message Discord. Retourne True si l'envoi a réussi."""
from discordbot import bot
try:
discord_channel = bot.get_channel(embed_config['notify_channel'])
channel_id = int(embed_config['notify_channel'])
discord_channel = bot.get_channel(channel_id)
if not discord_channel:
logger.error(f"Canal Discord {embed_config['notify_channel']} introuvable")
# Le salon peut ne pas être présent dans le cache local après une reconnexion.
discord_channel = await bot.fetch_channel(channel_id)
if not discord_channel:
logger.error(f"Canal Discord {channel_id} introuvable")
return False
embed_title_text = _format_embed_text(embed_config['embed_title'], channel_name, video_title, video_url, video_id, thumbnail, published_at, is_short) if embed_config['embed_title'] else video_title