From a8d2a0e0636e47f8db38c26d38965c4658c3c1cc Mon Sep 17 00:00:00 2001
From: Mow910
Date: Sun, 25 Jan 2026 17:45:59 +0100
Subject: [PATCH] =?UTF-8?q?Ajout=20de=20nouvelles=20colonnes=20pour=20la?=
=?UTF-8?q?=20personnalisation=20des=20notifications=20YouTube=20dans=20la?=
=?UTF-8?q?=20table=20`youtube=5Fnotification`,=20y=20compris=20le=20titre?=
=?UTF-8?q?,=20la=20description,=20la=20couleur,=20le=20pied=20de=20page,?=
=?UTF-8?q?=20le=20nom=20et=20l'ic=C3=B4ne=20de=20l'auteur,=20ainsi=20que?=
=?UTF-8?q?=20des=20options=20pour=20afficher=20la=20miniature=20et=20l'im?=
=?UTF-8?q?age.=20Mise=20=C3=A0=20jour=20de=20l'interface=20web=20pour=20p?=
=?UTF-8?q?ermettre=20la=20configuration=20de=20ces=20options=20et=20ajout?=
=?UTF-8?q?=20d'une=20pr=C3=A9visualisation=20de=20l'embed=20Discord.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
database/__init__.py | 27 ++++
database/models.py | 16 ++-
database/schema.sql | 10 +-
discordbot/youtube.py | 63 ++++++++--
webapp/templates/youtube.html | 226 +++++++++++++++++++++++++++-------
webapp/youtube.py | 26 +++-
6 files changed, 306 insertions(+), 62 deletions(-)
diff --git a/database/__init__.py b/database/__init__.py
index 9d1d48e..444d20f 100644
--- a/database/__init__.py
+++ b/database/__init__.py
@@ -33,7 +33,13 @@ def _set_sqlite_pragma(dbapi_connection, connection_record):
except Exception:
pass
+def _tableExists(table_name:str, cursor:Cursor) -> bool:
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
+ return cursor.fetchone() is not None
+
def _tableHaveColumn(table_name:str, column_name:str, cursor:Cursor) -> bool:
+ if not _tableExists(table_name, cursor):
+ return False
cursor.execute(f'PRAGMA table_info({table_name})')
columns = cursor.fetchall()
return any(col[1] == column_name for col in columns)
@@ -64,6 +70,27 @@ def _doPostImportMigration(cursor:Cursor):
cursor.execute('INSERT INTO game_bundle(url, name, json) VALUES (?, ?, ?)', (url, name, json.dumps(json_data)))
logging.info("suppression de la table temporaire game_bundle_old")
_dropTable('game_bundle_old', cursor)
+
+ if _tableExists('youtube_notification', cursor):
+ logging.info("Migration de la table youtube_notification: ajout des colonnes d'embed")
+ embed_columns = [
+ ('embed_title', 'VARCHAR(256)'),
+ ('embed_description', 'VARCHAR(2000)'),
+ ('embed_color', 'VARCHAR(8) DEFAULT "FF0000"'),
+ ('embed_footer', 'VARCHAR(2048)'),
+ ('embed_author_name', 'VARCHAR(256)'),
+ ('embed_author_icon', 'VARCHAR(512)'),
+ ('embed_thumbnail', 'BOOLEAN DEFAULT 1'),
+ ('embed_image', 'BOOLEAN DEFAULT 1')
+ ]
+ for col_name, col_type in embed_columns:
+ if not _tableHaveColumn('youtube_notification', col_name, cursor):
+ try:
+ cursor.execute(f'ALTER TABLE youtube_notification ADD COLUMN {col_name} {col_type}')
+ logging.info(f"Colonne {col_name} ajoutée à youtube_notification")
+ except Exception as e:
+ logging.error(f"Impossible d'ajouter la colonne {col_name}: {e}")
+ raise
with webapp.app_context():
with open('database/schema.sql', 'r') as f:
diff --git a/database/models.py b/database/models.py
index e174fce..1562652 100644
--- a/database/models.py
+++ b/database/models.py
@@ -65,9 +65,17 @@ class YouTubeNotification(db.Model):
__tablename__ = 'youtube_notification'
id = db.Column(db.Integer, primary_key=True)
enable = db.Column(db.Boolean, default=True)
- channel_id = db.Column(db.String(128)) # ID de la chaîne YouTube
- notify_channel = db.Column(db.Integer) # ID du canal Discord
+ channel_id = db.Column(db.String(128))
+ notify_channel = db.Column(db.Integer)
message = db.Column(db.String(2000))
- video_type = db.Column(db.String(16), default='all') # 'all', 'video', 'short'
- last_video_id = db.Column(db.String(128)) # ID de la dernière vidéo notifiée
+ video_type = db.Column(db.String(16), default='all')
+ last_video_id = db.Column(db.String(128))
+ embed_title = db.Column(db.String(256))
+ embed_description = db.Column(db.String(2000))
+ embed_color = db.Column(db.String(8), default='FF0000')
+ embed_footer = db.Column(db.String(2048))
+ embed_author_name = db.Column(db.String(256))
+ embed_author_icon = db.Column(db.String(512))
+ embed_thumbnail = db.Column(db.Boolean, default=True)
+ embed_image = db.Column(db.Boolean, default=True)
diff --git a/database/schema.sql b/database/schema.sql
index 4f36e26..0af5439 100644
--- a/database/schema.sql
+++ b/database/schema.sql
@@ -84,5 +84,13 @@ CREATE TABLE IF NOT EXISTS `youtube_notification` (
`notify_channel` INTEGER NOT NULL,
`message` VARCHAR(2000) NOT NULL,
`video_type` VARCHAR(16) NOT NULL DEFAULT 'all',
- `last_video_id` VARCHAR(128)
+ `last_video_id` VARCHAR(128),
+ `embed_title` VARCHAR(256),
+ `embed_description` VARCHAR(2000),
+ `embed_color` VARCHAR(8) NOT NULL DEFAULT 'FF0000',
+ `embed_footer` VARCHAR(2048),
+ `embed_author_name` VARCHAR(256),
+ `embed_author_icon` VARCHAR(512),
+ `embed_thumbnail` BOOLEAN NOT NULL DEFAULT TRUE,
+ `embed_image` BOOLEAN NOT NULL DEFAULT TRUE
);
diff --git a/discordbot/youtube.py b/discordbot/youtube.py
index 7211fca..aa78962 100644
--- a/discordbot/youtube.py
+++ b/discordbot/youtube.py
@@ -149,31 +149,76 @@ async def _notifyVideo(notification: YouTubeNotification, video_data: dict, vide
message = f"🎥 Nouvelle vidéo de {channel_name}: [{video_title}]({video_url})"
logger.info(f"Envoi de notification YouTube: {message}")
- bot.loop.create_task(_sendMessage(notification.notify_channel, message, video_url, thumbnail, video_title, channel_name))
+ bot.loop.create_task(_sendMessage(notification, message, video_url, thumbnail, video_title, channel_name, video_id, published_at, is_short))
except Exception as e:
logger.error(f"Erreur lors de la notification: {e}")
-async def _sendMessage(channel_id: int, message: str, video_url: str, thumbnail: str, video_title: str, channel_name: str):
+def _format_embed_text(text: str, channel_name: str, video_title: str, video_url: str, video_id: str, thumbnail: str, published_at: str, is_short: bool) -> str:
+ """Formate un texte d'embed avec les variables disponibles"""
+ if not text:
+ return None
+ try:
+ return text.format(
+ channel_name=channel_name or 'Inconnu',
+ video_title=video_title or 'Sans titre',
+ video_url=video_url,
+ video_id=video_id,
+ thumbnail=thumbnail or '',
+ published_at=published_at or '',
+ is_short=is_short
+ )
+ except KeyError:
+ return text
+
+
+async def _sendMessage(notification: YouTubeNotification, message: str, video_url: str, thumbnail: str, video_title: str, channel_name: str, video_id: str, published_at: str, is_short: bool):
from discordbot import bot
try:
- discord_channel = bot.get_channel(channel_id)
+ discord_channel = bot.get_channel(notification.notify_channel)
if not discord_channel:
- logger.error(f"Canal Discord {channel_id} introuvable")
+ logger.error(f"Canal Discord {notification.notify_channel} introuvable")
return
import discord
+
+ embed_title = _format_embed_text(notification.embed_title, channel_name, video_title, video_url, video_id, thumbnail, published_at, is_short) if notification.embed_title else video_title
+ embed_description = _format_embed_text(notification.embed_description, channel_name, video_title, video_url, video_id, thumbnail, published_at, is_short) if notification.embed_description else None
+
+ try:
+ embed_color = int(notification.embed_color or 'FF0000', 16)
+ except ValueError:
+ embed_color = 0xFF0000
+
embed = discord.Embed(
- title=video_title,
+ title=embed_title,
url=video_url,
- color=0xFF0000
+ color=embed_color
)
- embed.set_author(name=channel_name, icon_url="https://www.youtube.com/img/desktop/yt_1200.png")
- if thumbnail:
+
+ if embed_description:
+ embed.description = embed_description
+
+ author_name = _format_embed_text(notification.embed_author_name, channel_name, video_title, video_url, video_id, thumbnail, published_at, is_short) if notification.embed_author_name else channel_name
+ author_icon = notification.embed_author_icon if notification.embed_author_icon else "https://www.youtube.com/img/desktop/yt_1200.png"
+ embed.set_author(name=author_name, icon_url=author_icon)
+
+ if notification.embed_thumbnail and thumbnail:
+ embed.set_thumbnail(url=thumbnail)
+
+ if notification.embed_image and thumbnail:
embed.set_image(url=thumbnail)
- await discord_channel.send(message, embed=embed)
+ if notification.embed_footer:
+ footer_text = _format_embed_text(notification.embed_footer, channel_name, video_title, video_url, video_id, thumbnail, published_at, is_short)
+ if footer_text:
+ embed.set_footer(text=footer_text)
+
+ if message and message.strip():
+ await discord_channel.send(message, embed=embed)
+ else:
+ await discord_channel.send(embed=embed)
logger.info(f"Notification YouTube envoyée avec succès")
except Exception as e:
diff --git a/webapp/templates/youtube.html b/webapp/templates/youtube.html
index 66d2241..e36fdef 100644
--- a/webapp/templates/youtube.html
+++ b/webapp/templates/youtube.html
@@ -62,52 +62,184 @@
{% endif %}
{{ 'Editer une notification' if notification else 'Ajouter une notification YouTube' }}
-
-
- Pour le message vous avez accès à ces variables :
-
- {channel_name} : nom de la chaîne YouTube
- {video_title} : titre de la vidéo
- {video_url} : lien vers la vidéo
- {video_id} : ID de la vidéo
- {thumbnail} : URL de la miniature
- {published_at} : date de publication
- {is_short} : True si c'est un short, False sinon
-
- Le message est au format common-mark dans la limite de ce que
- support Discord.
- Exemple : 🎥 Nouvelle vidéo de {channel_name} : [{video_title}]({video_url})
-
-
+
+
+
+
+
+
+ Variables disponibles pour l'embed :
+
+ {channel_name} : nom de la chaîne YouTube
+ {video_title} : titre de la vidéo
+ {video_url} : lien vers la vidéo
+ {video_id} : ID de la vidéo
+ {thumbnail} : URL de la miniature
+ {published_at} : date de publication
+ {is_short} : True si c'est un short, False sinon
+
+
{% endblock %}
diff --git a/webapp/youtube.py b/webapp/youtube.py
index 0e70118..6f8ae7b 100644
--- a/webapp/youtube.py
+++ b/webapp/youtube.py
@@ -93,12 +93,24 @@ def addYouTube():
except ValueError:
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': "Canal Discord invalide.", 'type': 'error'}))
+ embed_color = request.form.get('embed_color', 'FF0000').strip().lstrip('#')
+ if len(embed_color) != 6:
+ embed_color = 'FF0000'
+
notification = YouTubeNotification(
enable=True,
channel_id=channel_id,
notify_channel=notify_channel,
message=request.form.get('message'),
- video_type=request.form.get('video_type', 'all')
+ video_type=request.form.get('video_type', 'all'),
+ embed_title=request.form.get('embed_title') or None,
+ embed_description=request.form.get('embed_description') or None,
+ embed_color=embed_color,
+ embed_footer=request.form.get('embed_footer') or None,
+ embed_author_name=request.form.get('embed_author_name') or None,
+ embed_author_icon=request.form.get('embed_author_icon') or None,
+ embed_thumbnail=request.form.get('embed_thumbnail') == 'on',
+ embed_image=request.form.get('embed_image') == 'on'
)
db.session.add(notification)
db.session.commit()
@@ -141,10 +153,22 @@ def submitEditYouTube(id):
except ValueError:
return redirect(url_for("openEditYouTube", id=id) + "?" + urlencode({'msg': "Canal Discord invalide.", 'type': 'error'}))
+ embed_color = request.form.get('embed_color', 'FF0000').strip().lstrip('#')
+ if len(embed_color) != 6:
+ embed_color = 'FF0000'
+
notification.channel_id = channel_id
notification.notify_channel = notify_channel
notification.message = request.form.get('message')
notification.video_type = request.form.get('video_type', 'all')
+ notification.embed_title = request.form.get('embed_title') or None
+ notification.embed_description = request.form.get('embed_description') or None
+ notification.embed_color = embed_color
+ notification.embed_footer = request.form.get('embed_footer') or None
+ notification.embed_author_name = request.form.get('embed_author_name') or None
+ notification.embed_author_icon = request.form.get('embed_author_icon') or None
+ notification.embed_thumbnail = request.form.get('embed_thumbnail') == 'on'
+ notification.embed_image = request.form.get('embed_image') == 'on'
db.session.commit()
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': "Notification modifiée avec succès", 'type': 'success'}))