Ajout de fonctionnalités majeures Twitch, Discord et interface web
Nouvelles fonctionnalités : - Système de modération Twitch complet (bans, timeouts, avertissements) - Filtre de liens intelligent pour Twitch avec whitelist/blacklist - Notifications d'événements Twitch (follows, subs, raids, etc.) - Système Freeloot Discord avec flux RSS dédié - Salons automatiques Discord (création/suppression dynamique) - Authentification utilisateur pour l'interface web (login/register) - Gestion des utilisateurs et permissions - Interface de modération Twitch dans la webapp - Interface de gestion des événements Twitch - Configuration des paramètres utilisateur - Migration BDD pour les mots bannis Améliorations de l'interface : - Refonte complète des templates (configurations, commandes, humeurs, etc.) - Nouvelle page de settings utilisateur - Page de gestion des utilisateurs (admin) - Page d'erreur 403 personnalisée - Amélioration de la navigation et du design global - Intégration de nouvelles sections dans le menu principal Modifications techniques : - Ajout de nouveaux modèles en base de données - Extension des helpers database - Mise à jour des dépendances (requirements.txt) - Amélioration de la gestion des annonces Twitch - Refactorisation du code pour meilleure maintenabilité Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+202
-11
@@ -59,9 +59,9 @@ def _doPreImportMigration(cursor:Cursor):
|
||||
_renameTable('game_bundle', 'game_bundle_old', cursor)
|
||||
|
||||
def _doPostImportMigration(cursor:Cursor):
|
||||
if _tableEmpty('game_bundle', cursor) :
|
||||
if _tableEmpty('game_bundle', cursor) and _tableExists('game_bundle_old', cursor):
|
||||
logging.info("remplir game_bundle avec game_bundle_old")
|
||||
bundles = cursor.execute(f'SELECT * FROM game_bundle_old').fetchall()
|
||||
bundles = cursor.execute('SELECT * FROM game_bundle_old').fetchall()
|
||||
for bundle in bundles :
|
||||
name = bundle[1]
|
||||
json_data = json.loads(bundle[2])
|
||||
@@ -90,18 +90,209 @@ def _doPostImportMigration(cursor:Cursor):
|
||||
except Exception as e:
|
||||
logging.warning(f"Colonne youtube_notification.{col_name}: {e}")
|
||||
|
||||
if _tableExists('commande', cursor) and not _tableHaveColumn('commande', 'twitch_permission', cursor):
|
||||
try:
|
||||
cursor.execute("ALTER TABLE commande ADD COLUMN twitch_permission VARCHAR(16) DEFAULT 'viewer'")
|
||||
logging.info("Colonne twitch_permission ajoutée à commande")
|
||||
except Exception as e:
|
||||
logging.warning(f"Colonne commande.twitch_permission: {e}")
|
||||
|
||||
|
||||
def _doAddColumnMigrations(cursor: Cursor):
|
||||
"""Migrations d'ajout de colonnes. Exécutées à part pour ne pas dépendre du script principal."""
|
||||
if _tableExists('commande', cursor) and not _tableHaveColumn('commande', 'twitch_permission', cursor):
|
||||
try:
|
||||
cursor.execute("ALTER TABLE commande ADD COLUMN twitch_permission VARCHAR(16) DEFAULT 'viewer'")
|
||||
logging.info("Colonne twitch_permission ajoutée à commande")
|
||||
except Exception as e:
|
||||
logging.warning(f"Colonne commande.twitch_permission: {e}")
|
||||
if _tableExists('live_alert', cursor) and not _tableHaveColumn('live_alert', 'watch_activity', cursor):
|
||||
try:
|
||||
cursor.execute("ALTER TABLE live_alert ADD COLUMN watch_activity BOOLEAN NOT NULL DEFAULT 0")
|
||||
logging.info("Colonne watch_activity ajoutée à live_alert")
|
||||
except Exception as e:
|
||||
logging.warning(f"Colonne live_alert.watch_activity: {e}")
|
||||
|
||||
# Colonnes embed pour live_alert (message par défaut en embed)
|
||||
if _tableExists('live_alert', cursor):
|
||||
live_alert_embed_columns = [
|
||||
('embed_title', 'VARCHAR(256)'),
|
||||
('embed_description', 'VARCHAR(2000)'),
|
||||
('embed_color', 'VARCHAR(8) DEFAULT "9146FF"'),
|
||||
('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 live_alert_embed_columns:
|
||||
if not _tableHaveColumn('live_alert', col_name, cursor):
|
||||
try:
|
||||
cursor.execute(f'ALTER TABLE live_alert ADD COLUMN {col_name} {col_type}')
|
||||
logging.info(f"Colonne {col_name} ajoutée à live_alert")
|
||||
except Exception as e:
|
||||
logging.warning(f"Colonne live_alert.{col_name}: {e}")
|
||||
|
||||
# Table twitch_event_notification + seed des 4 types
|
||||
if not _tableExists('twitch_event_notification', cursor):
|
||||
try:
|
||||
cursor.execute("""
|
||||
CREATE TABLE twitch_event_notification (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_type VARCHAR(32) UNIQUE NOT NULL,
|
||||
enable BOOLEAN NOT NULL DEFAULT 1,
|
||||
notify_twitch_chat BOOLEAN NOT NULL DEFAULT 1,
|
||||
notify_discord BOOLEAN NOT NULL DEFAULT 0,
|
||||
discord_channel_id INTEGER NULL,
|
||||
message_twitch VARCHAR(500) NOT NULL DEFAULT '',
|
||||
message_discord VARCHAR(2000) NULL,
|
||||
embed_color VARCHAR(8) DEFAULT '9146FF',
|
||||
embed_title VARCHAR(256) NULL,
|
||||
embed_description VARCHAR(2000) NULL,
|
||||
embed_thumbnail BOOLEAN NOT NULL DEFAULT 1,
|
||||
last_clip_id VARCHAR(128) NULL
|
||||
)
|
||||
""")
|
||||
logging.info("Table twitch_event_notification créée")
|
||||
except Exception as e:
|
||||
logging.warning(f"Table twitch_event_notification: {e}")
|
||||
if _tableExists('twitch_event_notification', cursor) and _tableEmpty('twitch_event_notification', cursor):
|
||||
for ev in ('sub', 'follow', 'raid', 'clip'):
|
||||
try:
|
||||
cursor.execute(
|
||||
"INSERT INTO twitch_event_notification (event_type, message_twitch) VALUES (?, ?)",
|
||||
(ev, 'Merci {user} !' if ev != 'raid' else 'Bienvenue aux viewers de {from_broadcaster_name} !'),
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"Seed twitch_event_notification {ev}: {e}")
|
||||
|
||||
# Table webapp_user (auth)
|
||||
if not _tableExists('webapp_user', cursor):
|
||||
try:
|
||||
cursor.execute("""
|
||||
CREATE TABLE webapp_user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
email VARCHAR(256) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(256) NOT NULL,
|
||||
role VARCHAR(64) NOT NULL DEFAULT 'viewer_twitch',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
logging.info("Table webapp_user créée")
|
||||
except Exception as e:
|
||||
logging.warning(f"Table webapp_user: {e}")
|
||||
|
||||
# Tables webapp_role et webapp_page_permission
|
||||
if not _tableExists('webapp_role', cursor):
|
||||
try:
|
||||
cursor.execute("""
|
||||
CREATE TABLE webapp_role (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(64) UNIQUE NOT NULL,
|
||||
level INTEGER NOT NULL DEFAULT 0
|
||||
)
|
||||
""")
|
||||
logging.info("Table webapp_role créée")
|
||||
except Exception as e:
|
||||
logging.warning(f"Table webapp_role: {e}")
|
||||
if not _tableExists('webapp_page_permission', cursor):
|
||||
try:
|
||||
cursor.execute("""
|
||||
CREATE TABLE webapp_page_permission (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
page_key VARCHAR(64) UNIQUE NOT NULL,
|
||||
min_level INTEGER NOT NULL DEFAULT 0,
|
||||
write_level INTEGER NULL
|
||||
)
|
||||
""")
|
||||
logging.info("Table webapp_page_permission créée")
|
||||
except Exception as e:
|
||||
logging.warning(f"Table webapp_page_permission: {e}")
|
||||
|
||||
|
||||
def _doSeedAuth(cursor: Cursor):
|
||||
"""Seed rôles par défaut et permissions des pages si vides."""
|
||||
from database.models import ROLE_ORDER
|
||||
if not _tableExists('webapp_role', cursor):
|
||||
return
|
||||
if cursor.execute("SELECT COUNT(*) FROM webapp_role").fetchone()[0] > 0:
|
||||
return
|
||||
default_roles = [
|
||||
("viewer_twitch", 0),
|
||||
("utilisateur_discord", 1),
|
||||
("moderateur_discord", 2),
|
||||
("expert_discord", 3),
|
||||
("moderateur_twitch", 4),
|
||||
("super_administrateur", 5),
|
||||
]
|
||||
for name, level in default_roles:
|
||||
try:
|
||||
cursor.execute("INSERT INTO webapp_role (name, level) VALUES (?, ?)", (name, level))
|
||||
except Exception as e:
|
||||
logging.warning(f"Seed role {name}: {e}")
|
||||
logging.info("Rôles par défaut insérés")
|
||||
|
||||
if not _tableExists('webapp_page_permission', cursor):
|
||||
return
|
||||
if cursor.execute("SELECT COUNT(*) FROM webapp_page_permission").fetchone()[0] > 0:
|
||||
return
|
||||
# page_key, min_level, write_level (NULL = même que min_level)
|
||||
default_pages = [
|
||||
("index", 0, None),
|
||||
("configurations", 5, 5),
|
||||
("commandes", 1, 2),
|
||||
("humeurs", 1, 2),
|
||||
("live_alert", 0, 4),
|
||||
("announcements", 0, 4),
|
||||
("twitch_moderation", 0, 4),
|
||||
("link_filter", 0, 4),
|
||||
("twitch_events", 0, 4),
|
||||
("youtube", 1, 2),
|
||||
("protondb", 1, 2),
|
||||
("freeloot", 1, 2),
|
||||
("moderation", 1, 2),
|
||||
("users", 5, 5),
|
||||
("settings", 5, 5),
|
||||
]
|
||||
for page_key, min_level, wl in default_pages:
|
||||
try:
|
||||
cursor.execute(
|
||||
"INSERT INTO webapp_page_permission (page_key, min_level, write_level) VALUES (?, ?, ?)",
|
||||
(page_key, min_level, wl),
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"Seed page {page_key}: {e}")
|
||||
logging.info("Permissions pages par défaut insérées")
|
||||
|
||||
# Inscriptions activées par défaut
|
||||
if _tableExists("configuration", cursor):
|
||||
try:
|
||||
cursor.execute(
|
||||
"INSERT OR IGNORE INTO configuration (key, value) VALUES ('registration_enabled', 'true')"
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"Config registration_enabled: {e}")
|
||||
|
||||
|
||||
with webapp.app_context():
|
||||
with open('database/schema.sql', 'r') as f:
|
||||
sql = f.read()
|
||||
connection : Connection = db.session.connection().connection
|
||||
connection: Connection = db.session.connection().connection
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
_doPreImportMigration(cursor)
|
||||
cursor.executescript(sql)
|
||||
_doPostImportMigration(cursor)
|
||||
connection.commit()
|
||||
except Exception as e:
|
||||
logging.error(f"lors de l'import de la bdd : {e}")
|
||||
finally:
|
||||
try:
|
||||
cursor : Cursor = connection.cursor()
|
||||
_doPreImportMigration(cursor)
|
||||
cursor.executescript(sql)
|
||||
_doPostImportMigration(cursor)
|
||||
cursor = connection.cursor()
|
||||
_doAddColumnMigrations(cursor)
|
||||
_doSeedAuth(cursor)
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
except Exception as e:
|
||||
logging.error(f"lors de l'import de la bdd : {e}")
|
||||
finally:
|
||||
connection.close()
|
||||
logging.warning(f"migrations colonnes : {e}")
|
||||
connection.close()
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Migration: Ajout de la table twitch_banned_word
|
||||
-- Date: 2026-02-10
|
||||
-- Description: Permet de gérer les mots interdits dans le chat Twitch
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_banned_word` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`word` VARCHAR(256) UNIQUE NOT NULL,
|
||||
`enabled` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`timeout_duration` INTEGER NOT NULL DEFAULT 60,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
+144
-1
@@ -1,4 +1,62 @@
|
||||
from datetime import datetime
|
||||
from database import db
|
||||
from flask_login import UserMixin
|
||||
|
||||
# Rôles par défaut (niveau 0 à 5) — seed en base via migration
|
||||
ROLE_ORDER = [
|
||||
"viewer_twitch",
|
||||
"utilisateur_discord",
|
||||
"moderateur_discord",
|
||||
"expert_discord",
|
||||
"moderateur_twitch",
|
||||
"super_administrateur",
|
||||
]
|
||||
|
||||
def role_level(role_name: str) -> int:
|
||||
"""Retourne le niveau du rôle depuis la table webapp_role (-1 si inconnu)."""
|
||||
if not role_name:
|
||||
return -1
|
||||
r = WebappRole.query.filter_by(name=role_name).first()
|
||||
return r.level if r else -1
|
||||
|
||||
class WebappRole(db.Model):
|
||||
__tablename__ = "webapp_role"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(64), unique=True, nullable=False)
|
||||
level = db.Column(db.Integer, nullable=False, default=0)
|
||||
description = db.Column(db.String(256), nullable=True)
|
||||
color = db.Column(db.String(7), nullable=True, default="#6B7280") # Couleur hexadécimale pour l'affichage
|
||||
icon = db.Column(db.String(32), nullable=True) # Nom d'icône (ex: 'user', 'shield', 'crown')
|
||||
|
||||
class PagePermission(db.Model):
|
||||
__tablename__ = "webapp_page_permission"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
page_key = db.Column(db.String(64), unique=True, nullable=False)
|
||||
min_level = db.Column(db.Integer, nullable=False, default=0)
|
||||
write_level = db.Column(db.Integer, nullable=True)
|
||||
category = db.Column(db.String(32), nullable=True, default="general") # Catégorie: 'general', 'moderation', 'content', 'config'
|
||||
description = db.Column(db.String(256), nullable=True) # Description de la page
|
||||
|
||||
class WebappUser(db.Model, UserMixin):
|
||||
__tablename__ = "webapp_user"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(64), unique=True, nullable=False)
|
||||
email = db.Column(db.String(256), unique=True, nullable=False)
|
||||
password_hash = db.Column(db.String(256), nullable=False)
|
||||
role = db.Column(db.String(64), nullable=False, default="viewer_twitch")
|
||||
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||
|
||||
def get_level(self) -> int:
|
||||
return role_level(self.role)
|
||||
|
||||
def has_role_at_least(self, min_role: str) -> bool:
|
||||
return self.get_level() >= role_level(min_role)
|
||||
|
||||
def has_level_at_least(self, level: int) -> bool:
|
||||
return self.get_level() >= level
|
||||
|
||||
def has_any_role(self, roles: list) -> bool:
|
||||
return self.role in roles
|
||||
|
||||
class Configuration(db.Model):
|
||||
key = db.Column(db.String(32), primary_key=True)
|
||||
@@ -25,7 +83,17 @@ class LiveAlert(db.Model):
|
||||
online = db.Column(db.Boolean, default=False)
|
||||
login = db.Column(db.String(128))
|
||||
notify_channel = db.Column(db.Integer)
|
||||
message = db.Column(db.String(2000))
|
||||
message = db.Column(db.String(2000)) # message optionnel avant l'embed
|
||||
watch_activity = db.Column(db.Boolean, default=False)
|
||||
# Personnalisation de l'embed Discord (comme YouTube)
|
||||
embed_title = db.Column(db.String(256))
|
||||
embed_description = db.Column(db.String(2000))
|
||||
embed_color = db.Column(db.String(8), default='9146FF') # violet Twitch
|
||||
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)
|
||||
|
||||
class TwitchAnnouncement(db.Model):
|
||||
__tablename__ = 'twitch_announcement'
|
||||
@@ -37,12 +105,14 @@ class TwitchAnnouncement(db.Model):
|
||||
min_chat_messages = db.Column(db.Integer, default=0)
|
||||
last_sent = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
# Niveaux de permission Twitch pour les commandes personnalisées : viewer, sub, vip, moderator
|
||||
class Commande(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
discord_enable = db.Column(db.Boolean, default=True)
|
||||
twitch_enable = db.Column(db.Boolean, default=True)
|
||||
trigger = db.Column(db.String(32), unique=True)
|
||||
response = db.Column(db.String(2000))
|
||||
twitch_permission = db.Column(db.String(16), default='viewer') # viewer | sub | vip | moderator
|
||||
|
||||
class ModerationEvent(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
@@ -55,6 +125,46 @@ class ModerationEvent(db.Model):
|
||||
staff_name = db.Column(db.String(256))
|
||||
duration = db.Column(db.Integer)
|
||||
|
||||
|
||||
class TwitchModerationLog(db.Model):
|
||||
__tablename__ = 'twitch_moderation_log'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
action = db.Column(db.String(32))
|
||||
moderator = db.Column(db.String(256))
|
||||
target = db.Column(db.String(256))
|
||||
details = db.Column(db.String(512))
|
||||
created_at = db.Column(db.DateTime)
|
||||
|
||||
|
||||
class TwitchLinkFilter(db.Model):
|
||||
__tablename__ = 'twitch_link_filter'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
enabled = db.Column(db.Boolean, default=False)
|
||||
allow_subscribers = db.Column(db.Boolean, default=True)
|
||||
allow_vips = db.Column(db.Boolean, default=True)
|
||||
allow_moderators = db.Column(db.Boolean, default=True)
|
||||
timeout_duration = db.Column(db.Integer, default=60)
|
||||
warning_message = db.Column(db.String(500), default="Les liens ne sont pas autorises dans le chat.")
|
||||
|
||||
|
||||
class TwitchAllowedDomain(db.Model):
|
||||
__tablename__ = 'twitch_allowed_domain'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
domain = db.Column(db.String(256), unique=True)
|
||||
|
||||
|
||||
class TwitchPermit(db.Model):
|
||||
__tablename__ = 'twitch_permit'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(256))
|
||||
expires_at = db.Column(db.DateTime)
|
||||
|
||||
|
||||
class TwitchAllowedUser(db.Model):
|
||||
__tablename__ = 'twitch_allowed_user'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(256), unique=True)
|
||||
|
||||
class AntiCheatCache(db.Model):
|
||||
__tablename__ = 'anticheat_cache'
|
||||
steam_id = db.Column(db.String(32), primary_key=True)
|
||||
@@ -84,3 +194,36 @@ class YouTubeNotification(db.Model):
|
||||
embed_thumbnail = db.Column(db.Boolean, default=True)
|
||||
embed_image = db.Column(db.Boolean, default=True)
|
||||
|
||||
|
||||
class FreeLootEntry(db.Model):
|
||||
__tablename__ = 'freeloot_entry'
|
||||
entry_id = db.Column(db.String(256), primary_key=True)
|
||||
|
||||
|
||||
class TwitchEventNotification(db.Model):
|
||||
"""Configuration des notifications par type d'événement (sub, follow, raid, clip)."""
|
||||
__tablename__ = 'twitch_event_notification'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
event_type = db.Column(db.String(32), unique=True, nullable=False) # sub, follow, raid, clip
|
||||
enable = db.Column(db.Boolean, default=True)
|
||||
notify_twitch_chat = db.Column(db.Boolean, default=True)
|
||||
notify_discord = db.Column(db.Boolean, default=False)
|
||||
discord_channel_id = db.Column(db.Integer, nullable=True)
|
||||
message_twitch = db.Column(db.String(500), default='')
|
||||
message_discord = db.Column(db.String(2000), nullable=True)
|
||||
embed_color = db.Column(db.String(8), default='9146FF')
|
||||
embed_title = db.Column(db.String(256), nullable=True)
|
||||
embed_description = db.Column(db.String(2000), nullable=True)
|
||||
embed_thumbnail = db.Column(db.Boolean, default=True)
|
||||
last_clip_id = db.Column(db.String(128), nullable=True) # pour détecter les nouveaux clips
|
||||
|
||||
|
||||
class TwitchBannedWord(db.Model):
|
||||
"""Mots interdits dans le chat Twitch."""
|
||||
__tablename__ = 'twitch_banned_word'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
word = db.Column(db.String(256), unique=True, nullable=False)
|
||||
enabled = db.Column(db.Boolean, default=True)
|
||||
timeout_duration = db.Column(db.Integer, default=60) # durée du timeout en secondes
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
|
||||
+103
-2
@@ -28,7 +28,16 @@ CREATE TABLE IF NOT EXISTS live_alert (
|
||||
`online` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`login` VARCHAR(128) UNIQUE NOT NULL,
|
||||
`notify_channel` INTEGER NOT NULL,
|
||||
`message` VARCHAR(2000) NOT NULL
|
||||
`message` VARCHAR(2000),
|
||||
`watch_activity` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`embed_title` VARCHAR(256),
|
||||
`embed_description` VARCHAR(2000),
|
||||
`embed_color` VARCHAR(8) DEFAULT '9146FF',
|
||||
`embed_footer` VARCHAR(2048),
|
||||
`embed_author_name` VARCHAR(256),
|
||||
`embed_author_icon` VARCHAR(512),
|
||||
`embed_thumbnail` BOOLEAN DEFAULT TRUE,
|
||||
`embed_image` BOOLEAN DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_announcement` (
|
||||
@@ -46,7 +55,8 @@ CREATE TABLE IF NOT EXISTS `commande` (
|
||||
`discord_enable` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`twitch_enable` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`trigger` VARCHAR(16) UNIQUE NOT NULL,
|
||||
`response` VARCHAR(2000) NOT NULL
|
||||
`response` VARCHAR(2000) NOT NULL,
|
||||
`twitch_permission` VARCHAR(16) DEFAULT 'viewer'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `moderation_event` (
|
||||
@@ -61,6 +71,15 @@ CREATE TABLE IF NOT EXISTS `moderation_event` (
|
||||
`duration` INTEGER NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_moderation_log` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`action` VARCHAR(32) NOT NULL,
|
||||
`moderator` VARCHAR(256) NOT NULL,
|
||||
`target` VARCHAR(256),
|
||||
`details` VARCHAR(512),
|
||||
`created_at` DATETIME NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `anticheat_cache` (
|
||||
steam_id VARCHAR(32) PRIMARY KEY,
|
||||
game_name VARCHAR(256) NOT NULL,
|
||||
@@ -80,6 +99,40 @@ CREATE TABLE IF NOT EXISTS `member_invites` (
|
||||
`join_date` DATETIME NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_link_filter` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`enabled` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`allow_subscribers` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`allow_vips` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`allow_moderators` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`timeout_duration` INTEGER NOT NULL DEFAULT 60,
|
||||
`warning_message` VARCHAR(500) NOT NULL DEFAULT 'Les liens ne sont pas autorises dans le chat.'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_allowed_domain` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`domain` VARCHAR(256) UNIQUE NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_permit` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`username` VARCHAR(256) NOT NULL,
|
||||
`expires_at` DATETIME NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_allowed_user` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`username` VARCHAR(256) UNIQUE NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `twitch_banned_word` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`word` VARCHAR(256) UNIQUE NOT NULL,
|
||||
`enabled` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`timeout_duration` INTEGER NOT NULL DEFAULT 60,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `youtube_notification` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`enable` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
@@ -97,3 +150,51 @@ CREATE TABLE IF NOT EXISTS `youtube_notification` (
|
||||
`embed_thumbnail` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`embed_image` BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `webapp_user` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
email VARCHAR(256) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(256) NOT NULL,
|
||||
role VARCHAR(64) NOT NULL DEFAULT 'viewer_twitch',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `webapp_role` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(64) UNIQUE NOT NULL,
|
||||
level INTEGER NOT NULL DEFAULT 0,
|
||||
description VARCHAR(256) NULL,
|
||||
color VARCHAR(7) NULL DEFAULT '#6B7280',
|
||||
icon VARCHAR(32) NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `webapp_page_permission` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
page_key VARCHAR(64) UNIQUE NOT NULL,
|
||||
min_level INTEGER NOT NULL DEFAULT 0,
|
||||
write_level INTEGER NULL,
|
||||
category VARCHAR(32) NULL DEFAULT 'general',
|
||||
description VARCHAR(256) NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `freeloot_entry` (
|
||||
entry_id VARCHAR(256) PRIMARY KEY
|
||||
);
|
||||
|
||||
-- Notifications d'événements Twitch (sub, follow, raid, clip) : chat Twitch et/ou canal Discord
|
||||
CREATE TABLE IF NOT EXISTS `twitch_event_notification` (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_type VARCHAR(32) UNIQUE NOT NULL,
|
||||
`enable` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
notify_twitch_chat BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
notify_discord BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
discord_channel_id INTEGER NULL,
|
||||
message_twitch VARCHAR(500) NOT NULL DEFAULT '',
|
||||
message_discord VARCHAR(2000) NULL,
|
||||
embed_color VARCHAR(8) DEFAULT '9146FF',
|
||||
embed_title VARCHAR(256) NULL,
|
||||
embed_description VARCHAR(2000) NULL,
|
||||
embed_thumbnail BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
last_clip_id VARCHAR(128) NULL
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user