From 876eb1a080de364e6a0c6289393170b3dc310a95 Mon Sep 17 00:00:00 2001 From: Mow910 Date: Thu, 5 Mar 2026 00:08:50 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20d'un=20syst=C3=A8me=20de=20gestion=20de?= =?UTF-8?q?s=20utilisateurs=20en=20ligne=20dans=20la=20shoutbox=20pour=20l?= =?UTF-8?q?es=20mod=C3=A9rateurs=20Twitch.=20Impl=C3=A9mentation=20d'un=20?= =?UTF-8?q?endpoint=20de=20heartbeat=20pour=20suivre=20la=20pr=C3=A9sence?= =?UTF-8?q?=20des=20mod=C3=A9rateurs=20et=20mise=20=C3=A0=20jour=20de=20l'?= =?UTF-8?q?interface=20utilisateur=20pour=20afficher=20la=20liste=20des=20?= =?UTF-8?q?utilisateurs=20en=20ligne.=20Am=C3=A9lioration=20de=20l'exp?= =?UTF-8?q?=C3=A9rience=20utilisateur=20avec=20un=20bouton=20pour=20ouvrir?= =?UTF-8?q?=20la=20shoutbox=20en=20popout.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/__init__.py | 1 + webapp/templates/shoutbox-popout.html | 190 ++++++++++++++++++++++++ webapp/templates/twitch-moderation.html | 54 ++++++- webapp/twitch_moderation.py | 21 +++ 4 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 webapp/templates/shoutbox-popout.html diff --git a/webapp/__init__.py b/webapp/__init__.py index ef2d6fe..b37149c 100644 --- a/webapp/__init__.py +++ b/webapp/__init__.py @@ -16,6 +16,7 @@ webapp.config["BOT_STATUS"] = { "twitch_is_live": False, "twitch_viewer_count": 0, "twitch_chat_messages": [], # Derniers messages du chat (max 100) + "shoutbox_heartbeats": {}, # {"username": datetime} — présence des modos } login_manager = LoginManager() diff --git a/webapp/templates/shoutbox-popout.html b/webapp/templates/shoutbox-popout.html new file mode 100644 index 0000000..17d2922 --- /dev/null +++ b/webapp/templates/shoutbox-popout.html @@ -0,0 +1,190 @@ + + + + + +Shoutbox Modos + + + + + +
+
+ + Shoutbox Modos + +
+
+
+ + 0 en ligne +
+
+
+ +
+
+
Aucun message
+
+
+
En ligne
+
+
---
+
+
+
+ +
+
+ > + + +
+
+ + + + diff --git a/webapp/templates/twitch-moderation.html b/webapp/templates/twitch-moderation.html index fb487fb..505e303 100644 --- a/webapp/templates/twitch-moderation.html +++ b/webapp/templates/twitch-moderation.html @@ -297,10 +297,24 @@ Shoutbox Modos - +
+ + +
-
-
Aucun message
+
+
+
Aucun message
+
+
+
En ligne
+
+
---
+
+
@@ -974,6 +988,33 @@ function addShoutboxItem(item) { if (shoutboxAutoScroll) display.scrollTop = display.scrollHeight; } +function updateOnlineList(users) { + var list = document.getElementById('shoutboxOnlineList'); + if (!list) return; + if (!users || users.length === 0) { + list.innerHTML = '
---
'; + return; + } + list.innerHTML = ''; + users.forEach(function(u) { + var el = document.createElement('div'); + el.className = 'flex items-center gap-1.5 text-xs text-gray-300'; + el.innerHTML = '' + escapeHtml(u); + list.appendChild(el); + }); +} + +function shoutboxHeartbeat() { + fetch('{{ url_for("shoutbox_heartbeat") }}', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: '{}' + }) + .then(function(r) { return r.json(); }) + .then(function(data) { updateOnlineList(data.online_users); }) + .catch(function() {}); +} + function fetchShoutbox() { var url = '{{ url_for("shoutbox_messages") }}'; if (shoutboxLastTimestamp) url += '?since=' + encodeURIComponent(shoutboxLastTimestamp); @@ -985,12 +1026,17 @@ function fetchShoutbox() { data.items.forEach(addShoutboxItem); } if (data.timestamp) shoutboxLastTimestamp = data.timestamp; + if (data.online_users) updateOnlineList(data.online_users); var cnt = document.getElementById('shoutboxCount'); if (cnt) cnt.textContent = '(' + shoutboxKnownIds.size + ')'; }) .catch(function(e) { console.error('Shoutbox error:', e); }); } +function openShoutboxPopout() { + window.open('{{ url_for("shoutbox_popout") }}', 'shoutbox_popout', 'width=520,height=420,resizable=yes,scrollbars=no,menubar=no,toolbar=no,location=no,status=no'); +} + function sendShoutboxMessage(event) { event.preventDefault(); var input = document.getElementById('shoutboxInput'); @@ -1040,5 +1086,7 @@ document.getElementById('shoutboxDisplay').addEventListener('scroll', function() setInterval(fetchShoutbox, 3000); fetchShoutbox(); +setInterval(shoutboxHeartbeat, 10000); +shoutboxHeartbeat(); {% endblock %} diff --git a/webapp/twitch_moderation.py b/webapp/twitch_moderation.py index 48e2c65..160fdc0 100644 --- a/webapp/twitch_moderation.py +++ b/webapp/twitch_moderation.py @@ -557,9 +557,24 @@ def shoutbox_messages(): return jsonify({ "items": items, "timestamp": datetime.now().isoformat(), + "online_users": _get_online_users(), }) +def _get_online_users(): + heartbeats = webapp.config["BOT_STATUS"].get("shoutbox_heartbeats", {}) + cutoff = datetime.now() - timedelta(seconds=15) + return sorted(u for u, t in heartbeats.items() if t > cutoff) + + +@webapp.route("/twitch-moderation/shoutbox/heartbeat", methods=['POST']) +@require_page("twitch_moderation") +def shoutbox_heartbeat(): + hb = webapp.config["BOT_STATUS"].setdefault("shoutbox_heartbeats", {}) + hb[current_user.username] = datetime.now() + return jsonify({"online_users": _get_online_users()}) + + @webapp.route("/twitch-moderation/shoutbox/clear") @require_page("twitch_moderation") def shoutbox_clear(): @@ -568,3 +583,9 @@ def shoutbox_clear(): ModShoutboxMessage.query.delete() db.session.commit() return jsonify({"success": True}) + + +@webapp.route("/twitch-moderation/shoutbox/popout") +@require_page("twitch_moderation") +def shoutbox_popout(): + return render_template("shoutbox-popout.html")