mirror of
https://github.com/skylanix/MamieHenriette.git
synced 2026-02-06 06:40:35 +01:00
Ajout d'un système de notifications YouTube avec une nouvelle table youtube_notification dans la base de données, intégration de la vérification des vidéos YouTube, et création d'une interface web pour gérer les notifications. Le bot Discord enverra des alertes pour les nouvelles vidéos détectées.
This commit is contained in:
@@ -61,3 +61,13 @@ class AntiCheatCache(db.Model):
|
|||||||
notes = db.Column(db.String(1024))
|
notes = db.Column(db.String(1024))
|
||||||
updated_at = db.Column(db.DateTime)
|
updated_at = db.Column(db.DateTime)
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -76,3 +76,13 @@ CREATE TABLE IF NOT EXISTS `member_invites` (
|
|||||||
`inviter_name` VARCHAR(256),
|
`inviter_name` VARCHAR(256),
|
||||||
`join_date` DATETIME NOT NULL
|
`join_date` DATETIME NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `youtube_notification` (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
`enable` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
`channel_id` VARCHAR(128) NOT NULL,
|
||||||
|
`notify_channel` INTEGER NOT NULL,
|
||||||
|
`message` VARCHAR(2000) NOT NULL,
|
||||||
|
`video_type` VARCHAR(16) NOT NULL DEFAULT 'all',
|
||||||
|
`last_video_id` VARCHAR(128)
|
||||||
|
);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from discordbot.moderation import (
|
|||||||
handle_say_command
|
handle_say_command
|
||||||
)
|
)
|
||||||
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
|
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
|
||||||
|
from discordbot.youtube import checkYouTubeVideos
|
||||||
from protondb import searhProtonDb
|
from protondb import searhProtonDb
|
||||||
|
|
||||||
class DiscordBot(discord.Client):
|
class DiscordBot(discord.Client):
|
||||||
@@ -35,6 +36,7 @@ class DiscordBot(discord.Client):
|
|||||||
|
|
||||||
self.loop.create_task(self.updateStatus())
|
self.loop.create_task(self.updateStatus())
|
||||||
self.loop.create_task(self.updateHumbleBundle())
|
self.loop.create_task(self.updateHumbleBundle())
|
||||||
|
self.loop.create_task(self.updateYouTube())
|
||||||
|
|
||||||
async def updateStatus(self):
|
async def updateStatus(self):
|
||||||
while not self.is_closed():
|
while not self.is_closed():
|
||||||
@@ -50,6 +52,12 @@ class DiscordBot(discord.Client):
|
|||||||
while not self.is_closed():
|
while not self.is_closed():
|
||||||
await checkHumbleBundleAndNotify(self)
|
await checkHumbleBundleAndNotify(self)
|
||||||
await asyncio.sleep(30*60)
|
await asyncio.sleep(30*60)
|
||||||
|
|
||||||
|
async def updateYouTube(self):
|
||||||
|
while not self.is_closed():
|
||||||
|
await checkYouTubeVideos()
|
||||||
|
# Vérification toutes les 5 minutes (comme pour Twitch)
|
||||||
|
await asyncio.sleep(5*60)
|
||||||
|
|
||||||
def getAllTextChannel(self) -> list[TextChannel]:
|
def getAllTextChannel(self) -> list[TextChannel]:
|
||||||
channels = []
|
channels = []
|
||||||
|
|||||||
180
discordbot/youtube.py
Normal file
180
discordbot/youtube.py
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
import logging
|
||||||
|
import asyncio
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from database import db
|
||||||
|
from database.models import YouTubeNotification
|
||||||
|
from webapp import webapp
|
||||||
|
|
||||||
|
logger = logging.getLogger('youtube-notification')
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
async def checkYouTubeVideos():
|
||||||
|
with webapp.app_context():
|
||||||
|
try:
|
||||||
|
notifications: list[YouTubeNotification] = YouTubeNotification.query.filter_by(enable=True).all()
|
||||||
|
|
||||||
|
for notification in notifications:
|
||||||
|
try:
|
||||||
|
await _checkChannelVideos(notification)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la vérification de la chaîne {notification.channel_id}: {e}")
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la vérification YouTube: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
async def _checkChannelVideos(notification: YouTubeNotification):
|
||||||
|
try:
|
||||||
|
channel_id = notification.channel_id
|
||||||
|
|
||||||
|
rss_url = f"https://www.youtube.com/feeds/videos.xml?channel_id={channel_id}"
|
||||||
|
|
||||||
|
response = await asyncio.to_thread(requests.get, rss_url, timeout=10)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
logger.error(f"Erreur HTTP {response.status_code} lors de la récupération du RSS pour {channel_id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
root = ET.fromstring(response.content)
|
||||||
|
|
||||||
|
ns = {'atom': 'http://www.w3.org/2005/Atom', 'yt': 'http://www.youtube.com/xml/schemas/2015', 'media': 'http://search.yahoo.com/mrss/'}
|
||||||
|
|
||||||
|
entries = root.findall('atom:entry', ns)
|
||||||
|
|
||||||
|
if not entries:
|
||||||
|
logger.warning(f"Aucune vidéo trouvée dans le RSS pour {channel_id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
videos = []
|
||||||
|
for entry in entries:
|
||||||
|
video_id = entry.find('yt:videoId', ns)
|
||||||
|
if video_id is None:
|
||||||
|
continue
|
||||||
|
video_id = video_id.text
|
||||||
|
|
||||||
|
title_elem = entry.find('atom:title', ns)
|
||||||
|
video_title = title_elem.text if title_elem is not None else 'Sans titre'
|
||||||
|
|
||||||
|
link_elem = entry.find('atom:link', ns)
|
||||||
|
video_url = link_elem.get('href') if link_elem is not None else f"https://www.youtube.com/watch?v={video_id}"
|
||||||
|
|
||||||
|
published_elem = entry.find('atom:published', ns)
|
||||||
|
published_at = published_elem.text if published_elem is not None else ''
|
||||||
|
|
||||||
|
author_elem = entry.find('atom:author/atom:name', ns)
|
||||||
|
channel_name = author_elem.text if author_elem is not None else 'Inconnu'
|
||||||
|
|
||||||
|
thumbnail = None
|
||||||
|
media_thumbnail = entry.find('media:group/media:thumbnail', ns)
|
||||||
|
if media_thumbnail is not None:
|
||||||
|
thumbnail = media_thumbnail.get('url')
|
||||||
|
|
||||||
|
is_short = False
|
||||||
|
if video_title and ('#shorts' in video_title.lower() or '#short' in video_title.lower()):
|
||||||
|
is_short = True
|
||||||
|
|
||||||
|
if notification.video_type == 'all':
|
||||||
|
videos.append((video_id, {
|
||||||
|
'title': video_title,
|
||||||
|
'url': video_url,
|
||||||
|
'published': published_at,
|
||||||
|
'channel_name': channel_name,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'is_short': is_short
|
||||||
|
}))
|
||||||
|
elif notification.video_type == 'short' and is_short:
|
||||||
|
videos.append((video_id, {
|
||||||
|
'title': video_title,
|
||||||
|
'url': video_url,
|
||||||
|
'published': published_at,
|
||||||
|
'channel_name': channel_name,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'is_short': is_short
|
||||||
|
}))
|
||||||
|
elif notification.video_type == 'video' and not is_short:
|
||||||
|
videos.append((video_id, {
|
||||||
|
'title': video_title,
|
||||||
|
'url': video_url,
|
||||||
|
'published': published_at,
|
||||||
|
'channel_name': channel_name,
|
||||||
|
'thumbnail': thumbnail,
|
||||||
|
'is_short': is_short
|
||||||
|
}))
|
||||||
|
|
||||||
|
videos.sort(key=lambda x: x[1]['published'], reverse=True)
|
||||||
|
|
||||||
|
if videos:
|
||||||
|
latest_video_id, latest_video = videos[0]
|
||||||
|
|
||||||
|
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}")
|
||||||
|
await _notifyVideo(notification, latest_video, latest_video_id)
|
||||||
|
notification.last_video_id = latest_video_id
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la vérification des vidéos: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
async def _notifyVideo(notification: YouTubeNotification, video_data: dict, video_id: str):
|
||||||
|
from discordbot import bot
|
||||||
|
try:
|
||||||
|
channel_name = video_data.get('channel_name', 'Inconnu')
|
||||||
|
video_title = video_data.get('title', 'Sans titre')
|
||||||
|
video_url = video_data.get('url', f"https://www.youtube.com/watch?v={video_id}")
|
||||||
|
thumbnail = video_data.get('thumbnail', '')
|
||||||
|
published_at = video_data.get('published', '')
|
||||||
|
is_short = video_data.get('is_short', False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
message = notification.message.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 as e:
|
||||||
|
logger.error(f"Variable manquante dans le message de notification: {e}")
|
||||||
|
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))
|
||||||
|
|
||||||
|
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):
|
||||||
|
from discordbot import bot
|
||||||
|
try:
|
||||||
|
discord_channel = bot.get_channel(channel_id)
|
||||||
|
if not discord_channel:
|
||||||
|
logger.error(f"Canal Discord {channel_id} introuvable")
|
||||||
|
return
|
||||||
|
|
||||||
|
import discord
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=video_title,
|
||||||
|
url=video_url,
|
||||||
|
color=0xFF0000
|
||||||
|
)
|
||||||
|
embed.set_author(name=channel_name, icon_url="https://www.youtube.com/img/desktop/yt_1200.png")
|
||||||
|
if thumbnail:
|
||||||
|
embed.set_image(url=thumbnail)
|
||||||
|
|
||||||
|
await discord_channel.send(message, embed=embed)
|
||||||
|
logger.info(f"Notification YouTube envoyée avec succès")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de l'envoi du message Discord: {e}")
|
||||||
@@ -2,4 +2,4 @@ from flask import Flask
|
|||||||
|
|
||||||
webapp = Flask(__name__)
|
webapp = Flask(__name__)
|
||||||
|
|
||||||
from webapp import commandes, configurations, index, humeurs, protondb, live_alert, twitch_auth, moderation
|
from webapp import commandes, configurations, index, humeurs, protondb, live_alert, twitch_auth, moderation, youtube
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<a href="/"><img src="/static/ico/favicon.ico"></a>
|
<a href="/"><img src="/static/ico/favicon.ico"></a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/live-alert">Alerte live</a></li>
|
<li><a href="/live-alert">Alerte live</a></li>
|
||||||
|
<li><a href="/youtube">YouTube</a></li>
|
||||||
<li><a href="/commandes">Commandes</a></li>
|
<li><a href="/commandes">Commandes</a></li>
|
||||||
<li><a href="/humeurs">Humeurs</a></li>
|
<li><a href="/humeurs">Humeurs</a></li>
|
||||||
<li><a href="/moderation">Modération</a></li>
|
<li><a href="/moderation">Modération</a></li>
|
||||||
|
|||||||
113
webapp/templates/youtube.html
Normal file
113
webapp/templates/youtube.html
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
{% extends "template.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Notifications YouTube</h1>
|
||||||
|
|
||||||
|
{% if msg %}
|
||||||
|
<div id="alert-msg" class="alert alert-{{ msg_type }}" style="padding: 10px; margin: 10px 0; border: 1px solid {{ '#f00' if msg_type == 'error' else '#0f0' }}; background-color: {{ '#ffe0e0' if msg_type == 'error' else '#e0ffe0' }};">
|
||||||
|
{{ msg }}
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(function() {
|
||||||
|
var el = document.getElementById('alert-msg');
|
||||||
|
if (el) el.style.display = 'none';
|
||||||
|
}, 5000);
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Liste des chaînes YouTube surveillées pour les notifications de nouvelles vidéos.
|
||||||
|
|
||||||
|
Le bot vérifie toutes les 5 minutes les nouvelles vidéos des chaînes en dessous.
|
||||||
|
Quand une nouvelle vidéo est détectée, le bot enverra une notification sur Discord.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if not notification %}
|
||||||
|
<h2>Notifications</h2>
|
||||||
|
<table class="live-alert">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Chaîne YouTube</th>
|
||||||
|
<th>Canal Discord</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Message</th>
|
||||||
|
<th>#</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for notification in notifications %}
|
||||||
|
<tr>
|
||||||
|
<td>{{notification.channel_id}}</td>
|
||||||
|
<td>{{notification.notify_channel_name}}</td>
|
||||||
|
<td>
|
||||||
|
{% if notification.video_type == 'all' %}
|
||||||
|
Toutes
|
||||||
|
{% elif notification.video_type == 'video' %}
|
||||||
|
Vidéos uniquement
|
||||||
|
{% elif notification.video_type == 'short' %}
|
||||||
|
Shorts uniquement
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{notification.message}}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('toggleYouTube', id = notification.id) }}" class="icon">{{ '✅' if notification.enable else '❌' }}</a>
|
||||||
|
<a href="{{ url_for('openEditYouTube', id = notification.id) }}" class="icon">✐</a>
|
||||||
|
<a href="{{ url_for('delYouTube', id = notification.id) }}"
|
||||||
|
onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette notification ?')" class="icon">🗑</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2>{{ 'Editer une notification' if notification else 'Ajouter une notification YouTube' }}</h2>
|
||||||
|
<form action="{{ url_for('submitEditYouTube', id = notification.id) if notification else url_for('addYouTube') }}" method="POST">
|
||||||
|
<label for="channel_id">Lien ou ID de la chaîne YouTube</label>
|
||||||
|
<input name="channel_id" type="text" maxlength="256" required="required" value="{{notification.channel_id if notification}}" placeholder="https://www.youtube.com/@513v3 ou https://www.youtube.com/channel/UC... ou UC..."/>
|
||||||
|
<label for="notify_channel">Canal de Notification Discord</label>
|
||||||
|
<select name="notify_channel">
|
||||||
|
{% for channel in channels %}
|
||||||
|
<option value="{{channel.id}}"{% if notification and notification.notify_channel == channel.id %}
|
||||||
|
selected="selected" {% endif %}>{{channel.name}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<label for="video_type">Type de vidéo à notifier</label>
|
||||||
|
<select name="video_type">
|
||||||
|
<option value="all"{% if notification and notification.video_type == 'all' %} selected="selected" {% endif %}>Toutes (vidéos + shorts)</option>
|
||||||
|
<option value="video"{% if notification and notification.video_type == 'video' %} selected="selected" {% endif %}>Vidéos uniquement</option>
|
||||||
|
<option value="short"{% if notification and notification.video_type == 'short' %} selected="selected" {% endif %}>Shorts uniquement</option>
|
||||||
|
</select>
|
||||||
|
<label for="message">Message</label>
|
||||||
|
<textarea name="message" rows="5" cols="50" required="required">{{notification.message if notification}}</textarea>
|
||||||
|
<input type="Submit" value="{{ 'Modifier' if notification else 'Ajouter' }}">
|
||||||
|
<p>
|
||||||
|
Vous pouvez coller directement le lien de la chaîne YouTube dans n'importe quel format :
|
||||||
|
<ul>
|
||||||
|
<li><strong>Lien avec handle :</strong> <code>https://www.youtube.com/@513v3</code></li>
|
||||||
|
<li><strong>Lien avec ID :</strong> <code>https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxxxxxxxxxxxx</code></li>
|
||||||
|
<li><strong>ID seul :</strong> <code>UCxxxxxxxxxxxxxxxxxxxxxxxxxx</code></li>
|
||||||
|
<li><strong>Handle seul :</strong> <code>@513v3</code></li>
|
||||||
|
</ul>
|
||||||
|
Le système extraira automatiquement l'ID de la chaîne.
|
||||||
|
<br><br>
|
||||||
|
<strong>Note :</strong> Les notifications utilisent le flux RSS YouTube, aucune clé API n'est nécessaire !
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Pour le message vous avez accès à ces variables :
|
||||||
|
<ul>
|
||||||
|
<li><code>{channel_name}</code> : nom de la chaîne YouTube</li>
|
||||||
|
<li><code>{video_title}</code> : titre de la vidéo</li>
|
||||||
|
<li><code>{video_url}</code> : lien vers la vidéo</li>
|
||||||
|
<li><code>{video_id}</code> : ID de la vidéo</li>
|
||||||
|
<li><code>{thumbnail}</code> : URL de la miniature</li>
|
||||||
|
<li><code>{published_at}</code> : date de publication</li>
|
||||||
|
<li><code>{is_short}</code> : True si c'est un short, False sinon</li>
|
||||||
|
</ul>
|
||||||
|
Le message est au format <a href="https://commonmark.org/" target="_blank">common-mark</a> dans la limite de ce que
|
||||||
|
support Discord.
|
||||||
|
Exemple : <code>🎥 Nouvelle vidéo de {channel_name} : [{video_title}]({video_url})</code>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
157
webapp/youtube.py
Normal file
157
webapp/youtube.py
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import re
|
||||||
|
import requests
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
from flask import render_template, request, redirect, url_for
|
||||||
|
|
||||||
|
from webapp import webapp
|
||||||
|
from database import db
|
||||||
|
from database.models import YouTubeNotification
|
||||||
|
from discordbot import bot
|
||||||
|
|
||||||
|
|
||||||
|
def extract_channel_id(channel_input: str) -> str:
|
||||||
|
"""Extrait l'ID de la chaîne YouTube depuis différents formats"""
|
||||||
|
if not channel_input:
|
||||||
|
return None
|
||||||
|
|
||||||
|
channel_input = channel_input.strip()
|
||||||
|
|
||||||
|
if channel_input.startswith('UC') and len(channel_input) == 24:
|
||||||
|
return channel_input
|
||||||
|
|
||||||
|
if '/channel/' in channel_input:
|
||||||
|
match = re.search(r'/channel/([a-zA-Z0-9_-]{24})', channel_input)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
|
if '/c/' in channel_input or '/user/' in channel_input:
|
||||||
|
parts = channel_input.split('/')
|
||||||
|
for i, part in enumerate(parts):
|
||||||
|
if part in ['c', 'user'] and i + 1 < len(parts):
|
||||||
|
handle = parts[i + 1].split('?')[0].split('&')[0]
|
||||||
|
channel_id = _get_channel_id_from_handle(handle)
|
||||||
|
if channel_id:
|
||||||
|
return channel_id
|
||||||
|
|
||||||
|
if '@' in channel_input:
|
||||||
|
handle = re.search(r'@([a-zA-Z0-9_-]+)', channel_input)
|
||||||
|
if handle:
|
||||||
|
channel_id = _get_channel_id_from_handle(handle.group(1))
|
||||||
|
if channel_id:
|
||||||
|
return channel_id
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _get_channel_id_from_handle(handle: str) -> str:
|
||||||
|
"""Récupère l'ID de la chaîne depuis un handle en utilisant le flux RSS"""
|
||||||
|
try:
|
||||||
|
url = f"https://www.youtube.com/@{handle}"
|
||||||
|
response = requests.get(url, timeout=10, allow_redirects=True)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
channel_id_match = re.search(r'"channelId":"([^"]{24})"', response.text)
|
||||||
|
if channel_id_match:
|
||||||
|
return channel_id_match.group(1)
|
||||||
|
|
||||||
|
canonical_match = re.search(r'<link rel="canonical" href="https://www\.youtube\.com/channel/([^"]{24})"', response.text)
|
||||||
|
if canonical_match:
|
||||||
|
return canonical_match.group(1)
|
||||||
|
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube")
|
||||||
|
def openYouTube():
|
||||||
|
notifications: list[YouTubeNotification] = YouTubeNotification.query.all()
|
||||||
|
channels = bot.getAllTextChannel()
|
||||||
|
for notification in notifications:
|
||||||
|
for channel in channels:
|
||||||
|
if notification.notify_channel == channel.id:
|
||||||
|
notification.notify_channel_name = channel.name
|
||||||
|
msg = request.args.get('msg')
|
||||||
|
msg_type = request.args.get('type', 'info')
|
||||||
|
return render_template("youtube.html", notifications=notifications, channels=channels, msg=msg, msg_type=msg_type)
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube/add", methods=['POST'])
|
||||||
|
def addYouTube():
|
||||||
|
channel_input = request.form.get('channel_id', '').strip()
|
||||||
|
channel_id = extract_channel_id(channel_input)
|
||||||
|
|
||||||
|
if not channel_id:
|
||||||
|
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': f"Impossible d'extraire l'ID de la chaîne depuis : {channel_input}. Veuillez vérifier le lien.", 'type': 'error'}))
|
||||||
|
|
||||||
|
notify_channel_str = request.form.get('notify_channel')
|
||||||
|
if not notify_channel_str:
|
||||||
|
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': "Veuillez sélectionner un canal Discord. Assurez-vous que le bot Discord est connecté.", 'type': 'error'}))
|
||||||
|
|
||||||
|
try:
|
||||||
|
notify_channel = int(notify_channel_str)
|
||||||
|
except ValueError:
|
||||||
|
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': "Canal Discord invalide.", 'type': 'error'}))
|
||||||
|
|
||||||
|
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')
|
||||||
|
)
|
||||||
|
db.session.add(notification)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': f"Notification ajoutée avec succès pour la chaîne {channel_id}", 'type': 'success'}))
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube/toggle/<int:id>")
|
||||||
|
def toggleYouTube(id):
|
||||||
|
notification: YouTubeNotification = YouTubeNotification.query.get_or_404(id)
|
||||||
|
notification.enable = not notification.enable
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for("openYouTube"))
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube/edit/<int:id>")
|
||||||
|
def openEditYouTube(id):
|
||||||
|
notification = YouTubeNotification.query.get_or_404(id)
|
||||||
|
channels = bot.getAllTextChannel()
|
||||||
|
msg = request.args.get('msg')
|
||||||
|
msg_type = request.args.get('type', 'info')
|
||||||
|
return render_template("youtube.html", notification=notification, channels=channels, notifications=YouTubeNotification.query.all(), msg=msg, msg_type=msg_type)
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube/edit/<int:id>", methods=['POST'])
|
||||||
|
def submitEditYouTube(id):
|
||||||
|
notification: YouTubeNotification = YouTubeNotification.query.get_or_404(id)
|
||||||
|
|
||||||
|
channel_input = request.form.get('channel_id', '').strip()
|
||||||
|
channel_id = extract_channel_id(channel_input)
|
||||||
|
|
||||||
|
if not channel_id:
|
||||||
|
return redirect(url_for("openEditYouTube", id=id) + "?" + urlencode({'msg': f"Impossible d'extraire l'ID de la chaîne depuis : {channel_input}. Veuillez vérifier le lien.", 'type': 'error'}))
|
||||||
|
|
||||||
|
notify_channel_str = request.form.get('notify_channel')
|
||||||
|
if not notify_channel_str:
|
||||||
|
return redirect(url_for("openEditYouTube", id=id) + "?" + urlencode({'msg': "Veuillez sélectionner un canal Discord. Assurez-vous que le bot Discord est connecté.", 'type': 'error'}))
|
||||||
|
|
||||||
|
try:
|
||||||
|
notify_channel = int(notify_channel_str)
|
||||||
|
except ValueError:
|
||||||
|
return redirect(url_for("openEditYouTube", id=id) + "?" + urlencode({'msg': "Canal Discord invalide.", 'type': 'error'}))
|
||||||
|
|
||||||
|
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')
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for("openYouTube") + "?" + urlencode({'msg': "Notification modifiée avec succès", 'type': 'success'}))
|
||||||
|
|
||||||
|
|
||||||
|
@webapp.route("/youtube/del/<int:id>")
|
||||||
|
def delYouTube(id):
|
||||||
|
notification = YouTubeNotification.query.get_or_404(id)
|
||||||
|
db.session.delete(notification)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for("openYouTube"))
|
||||||
Reference in New Issue
Block a user