require("dotenv").config(); const { Telegraf, Markup } = require("telegraf"); const axios = require("axios"); const express = require("express"); const path = require("path"); const fs = require("fs"); const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN); const app = express(); const PORT = 3000; const PLEX_URL = process.env.PLEX_URL; const PLEX_TOKEN = process.env.PLEX_TOKEN; const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID; const monitoredUsers = new Set(["user1", "666Bong"]); // Hier die Plex-Namen eintragen let activeSessions = new Map(); // Speichert aktive Wiedergaben let userSessions = new Map(); // Speichert aktive Sessions pro Benutzer let lastNotified = new Map(); // Speichert die Benachrichtigungen pro Benutzer Session let lastNotifiedDevices = new Map(); // Speichert, ob eine Warnung für zwei Geräte bereits gesendet wurde let userViolations = new Map(); // Speichert Verstöße für Benutzer let bannedUsers = new Map(); // Speichert gebannte Benutzer und ihre Ban-Dauer let whitelist = new Set(); // Set für Whitelisted Benutzer const whitelistFile = path.join(__dirname, 'whitelist.json'); let maintenanceMode = false; const PASSWORD = process.env.DASHBOARD_PASSWORD; // Passwort aus der .env Datei // Statisches Dashboard im 'public' Ordner app.use(express.static(path.join(__dirname, 'public'))); // Startseite mit Passwortabfrage app.get("/index", (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); const os = require('os'); // API-Endpunkt zum Abrufen der Statistiken app.get('/stats', (req, res) => { // Abrufen der Statistiken: aktive Sessions, gebannte Benutzer, Verstöße const activeSessionsCount = getActiveSessionsCount(); const bannedUsersCount = getBannedUsersCount(); const violationsCount = getViolationsCount(); const recentActivities = getRecentActivities(); // CPU- und RAM-Nutzung const serverCpu = getCpuUsage(); const serverRam = getRamUsage(); // Antwort als JSON res.json({ activeSessions: activeSessionsCount, bannedUsers: bannedUsersCount, violations: violationsCount, serverCpu, serverRam, recentActivities }); }); // Funktion zum Abrufen der CPU-Auslastung function getCpuUsage() { const cpus = os.cpus(); let idle = 0; let total = 0; cpus.forEach(cpu => { for (type in cpu.times) { total += cpu.times[type]; } idle += cpu.times.idle; }); return Math.round(((total - idle) / total) * 100); } // Funktion zum Abrufen der RAM-Auslastung function getRamUsage() { const totalMemory = os.totalmem(); const freeMemory = os.freemem(); return Math.round(((totalMemory - freeMemory) / totalMemory) * 100); } // Funktion zum Abrufen der Anzahl der aktiven Sessions function getActiveSessionsCount() { return activeSessions.size; } // Funktion zum Abrufen der Anzahl gebannter Benutzer function getBannedUsersCount() { return bannedUsers.size; } // Funktion zum Abrufen der Anzahl der Verstöße function getViolationsCount() { return Array.from(userViolations.values()).reduce((acc, violations) => acc + violations, 0); } let isAutoActive = false; function getRecentActivities() { const autoStatus = autoMode ? 'Automatik Aktiv' : 'Automatik Nicht Aktiv'; return [ `${autoStatus}` ]; } // Funktion zum Abrufen der aktuellen Wiedergabe async function checkPlexActivity() { try { console.log("🔄 Plex-Wiedergaben werden überprüft..."); const response = await axios.get(`${PLEX_URL}/status/sessions`, { headers: { "X-Plex-Token": PLEX_TOKEN }, }); const sessions = response.data.MediaContainer.Metadata || []; let newActiveSessions = new Map(); let newUserSessions = new Map(); // Sammle alle Sessions für Benutzer for (const session of sessions) { const title = session.title; const user = session.User?.title; const ip = session.Player?.publicAddress || session.Player?.address || "Unbekannt"; const sessionId = session.Session?.id; if (!sessionId || !user) continue; newActiveSessions.set(sessionId, { title, user, ip }); if (!newUserSessions.has(user)) { newUserSessions.set(user, []); } newUserSessions.get(user).push({ sessionId, title, ip }); // Wenn der Benutzer auf der Whitelist ist, überspringe weitere Prüfungen if (isUserWhitelisted(user)) { continue; // Verhindert die Verarbeitung des Benutzers, wenn er auf der Whitelist ist } // Prüfen, ob der Benutzer Accountsharing hat und mehrere Geräte verwendet if (monitoredUsers.has(user) && newUserSessions.get(user).length > 1) { console.log(`🚫 Accountsharing erkannt bei ${user}. Wiedergabe wird gestoppt.`); const stopMessage = "🚫 Accountsharing verboten. Dein Stream wurde beendet."; await stopPlaybackWithMessage(user, stopMessage); // Verstoß zählen und ggf. sperren let violations = userViolations.get(user) || 0; if (violations >= 2) { bannedUsers.set(user, Date.now()); userViolations.delete(user); bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `🚫 ${user} wurde aufgrund von wiederholtem Accountsharing für 3 Stunden gesperrt.` ); } else { userViolations.set(user, violations + 1); bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `⚠️ Warnung! Accountsharing erkannt. (${violations + 1}/3 Verstöße)` ); } } // Wenn der Benutzer auf mehreren Geräten angemeldet ist, sende eine Warnung if (newUserSessions.get(user).length > 1 && !lastNotifiedDevices.has(user)) { const sessionsDetails = newUserSessions.get(user) .map(s => `📍 **IP-Adresse:** ${s.ip}\n🎞️ **Film:** ${s.title}`) .join("\n\n"); bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `🚨 **Achtung! Zwei Geräte mit demselben Benutzer verbunden!**\n\n👤 **Name:** ${user} \n\n${sessionsDetails}`, Markup.inlineKeyboard([[Markup.button.callback("🚫 Accountsharing verboten", `share_ban_${user}`)]]), ); lastNotifiedDevices.set(user, Date.now()); } if (!lastNotified.has(sessionId)) { bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `🎬 **Neue Wiedergabe erkannt!**\n\n👤 **Name:** ${user} \n📍 **IP-Adresse:** ${ip} \n🎞️ **Film:** ${title}` ); lastNotified.set(sessionId, Date.now()); } } // Bereinigung der inaktiven Sessions for (const [sessionId] of activeSessions) { if (!newActiveSessions.has(sessionId)) { const session = activeSessions.get(sessionId); const user = session.user; const userSessionsList = userSessions.get(user); if (userSessionsList) { const index = userSessionsList.findIndex(s => s.sessionId === sessionId); if (index !== -1) { userSessionsList.splice(index, 1); if (userSessionsList.length === 0) { userSessions.delete(user); lastNotifiedDevices.delete(user); } } } activeSessions.delete(sessionId); } } activeSessions = newActiveSessions; userSessions = newUserSessions; console.log("✅ Plex-Wiedergaben erfolgreich aktualisiert."); } catch (error) { console.error("❌ Fehler beim Abrufen der Plex-Daten:", error.message); } } // Wiedergabe stoppen für alle Sessions eines Benutzers async function stopPlaybackWithMessage(userOrSessionId, message) { try { const sessions = userSessions.get(userOrSessionId) || []; for (const session of sessions) { await axios.post( `${PLEX_URL}/status/sessions/terminate?sessionId=${session.sessionId}&reason=${encodeURIComponent(message)}`, null, { headers: { "X-Plex-Token": PLEX_TOKEN }, } ); } if (userSessions.has(userOrSessionId)) { userSessions.delete(userOrSessionId); } if (activeSessions.has(userOrSessionId)) { activeSessions.delete(userOrSessionId); } lastNotifiedDevices.delete(userOrSessionId); return true; } catch (error) { console.error("❌ Fehler beim Stoppen der Wiedergabe:", error.message); return false; } } // Aktion für den "Accountsharing verboten"-Button bot.action(/^share_ban_(\w+)$/, async (ctx) => { const user = ctx.match[1]; if (!user) { return ctx.reply("❌ Fehler: Benutzer nicht gefunden."); } // Zähle die Verstöße des Benutzers let violations = userViolations.get(user) || 0; if (violations >= 2) { // Temporären Bann einführen, wenn der Benutzer 3 Verstöße hat bannedUsers.set(user, Date.now()); userViolations.delete(user); // Verstöße zurücksetzen ctx.reply(`🚫 ${user} wurde aufgrund von wiederholtem Accountsharing vorübergehend gesperrt. Der Bann wird in 3 Stunden aufgehoben.`); } else { // Ansonsten die Zahl der Verstöße erhöhen userViolations.set(user, violations + 1); ctx.reply(`⚠️ Warnung! Accountsharing erkannt. (${violations + 1}/3 Verstöße)`); } const responseText = "🚫 Accountsharing ist nicht erlaubt. Zugriff verweigert."; const success = await stopPlaybackWithMessage(user, responseText); if (success) { ctx.reply(`✅ Alle Streams von ${user} wurden gestoppt und die Nachricht "Accountsharing verboten" wurde gesendet.`); } else { ctx.reply("❌ Fehler beim Stoppen der Wiedergabe."); } }); // **Neuer Befehl /reload für manuelle Prüfung** bot.command("reload", async (ctx) => { ctx.reply("🔄 Wiedergaben werden erneut überprüft..."); await checkPlexActivity(); ctx.reply("✅ Überprüfung abgeschlossen."); }); // **Geplante Neustarts und Wartungsmodus** bot.command('maintenance', async (ctx) => { if (maintenanceMode) { return ctx.reply('🚨 Wartungsmodus ist bereits aktiviert.'); } maintenanceMode = true; ctx.reply('🔧 Wartungsmodus aktiviert. Alle weiteren Aktivitäten werden angehalten.'); }); bot.command('end_maintenance', async (ctx) => { if (!maintenanceMode) { return ctx.reply('🚨 Wartungsmodus ist derzeit nicht aktiv.'); } maintenanceMode = false; ctx.reply('✅ Wartungsmodus beendet. Alle Aktivitäten sind wieder normal.'); }); // **Geräteverwaltung** bot.command('devices', async (ctx) => { const activeDeviceList = Array.from(activeSessions.values()) .map(s => `📱 **Gerät:** ${s.title}, **IP:** ${s.ip}`); if (activeDeviceList.length === 0) { return ctx.reply('❌ Keine Geräte aktuell verbunden.'); } const deviceListMessage = '🔌 **Aktuelle Geräte:**\n' + activeDeviceList.join('\n'); ctx.reply(deviceListMessage); }); // Unban-Befehl zum Aufheben des Banns bot.command('unban', async (ctx) => { const user = ctx.message.text.split(' ')[1]; if (!user) { return ctx.reply('❌ Bitte gib den Namen des Benutzers an, den du entbannen möchtest.'); } // Überprüfen, ob der Benutzer gebannt ist if (!bannedUsers.has(user)) { return ctx.reply(`❌ Benutzer ${user} ist derzeit nicht gebannt.`); } // Bann aufheben bannedUsers.delete(user); ctx.reply(`✅ Der Bann für ${user} wurde erfolgreich aufgehoben. Der Benutzer kann wieder auf Plex zugreifen.`); }); // Hilfe-Befehl bot.command('help', async (ctx) => { const helpMessage = ` 🤖 **Telegram Plex Bot Hilfe** **Verfügbare Befehle:** /reload - Führt eine manuelle Prüfung aller aktiven Wiedergaben durch.\n /stats - Zeigt Statistiken zu aktiven Sessions, gebannten Benutzern, Verstöße und Whitelist-Nutzer.\n /whitelist - Fügt einen Benutzer zur Whitelist hinzu (verhindert Accountsharing-Überprüfung).\n /remove_whitelist - Entfernt einen Benutzer von der Whitelist.\n /unban - Hebt den Bann für einen Benutzer auf.\n /multiple_devices - Zeigt Benutzer mit mehreren Geräten an.\n /server_status - Prüft den Status des Plex-Servers.\n /stats - Zeigt eine Zusammenfassung der aktuellen Plex-Nutzung, einschließlich aktiver Sessions und Verstöße.\n /help - Zeigt diese Hilfe-Nachricht an.\n **Wichtige Hinweise:**\n - Der Bot überprüft regelmäßig alle aktiven Plex-Wiedergaben.\n - Wird Accountsharing festgestellt, sendet der Bot eine Warnung an den Administrator.\n - Bei wiederholtem Accountsharing wird der Benutzer temporär gesperrt.\n - Nur Benutzer, die nicht auf der Whitelist sind, werden überprüft.\n - Der Bot sendet tägliche Zusammenfassungen der gesperrten Benutzer und anderer relevanter Informationen.\n `; await ctx.reply(helpMessage); }); bot.command('multiple_devices', async (ctx) => { const multipleDevicesUsers = Array.from(userSessions.entries()) .filter(([user, sessions]) => sessions.length > 1) .map(([user, sessions]) => `${user}: ${sessions.length} Geräte`); if (multipleDevicesUsers.length === 0) { return ctx.reply('❌ Keine Benutzer mit mehreren Geräten gefunden.'); } const message = '📱 Benutzer mit mehreren Geräten:\n' + multipleDevicesUsers.join('\n'); ctx.reply(message); }); setInterval(async () => { const bannedUsersList = Array.from(bannedUsers.keys()).join(', '); const whitelistedUsersList = Array.from(whitelist).join(', '); const violationsCount = getViolationsCount(); const autoModeStatus = isAutoActive ? 'Automatik Aktiv' : 'Automatik Nicht Aktiv'; const statsMessage = ` 📅 **Tägliche Zusammenfassung:** - **Aktuell gesperrte Benutzer:** ${bannedUsersList || 'Keine'} - **Whitelisted Benutzer:** ${whitelistedUsersList || 'Keine'} - **Verstöße insgesamt:** ${violationsCount} - **Automatikmodus:** ${autoModeStatus} `; bot.telegram.sendMessage(TELEGRAM_CHAT_ID, statsMessage); }, 86400000); // Täglich (24 Stunden) bot.command('server_status', async (ctx) => { try { const response = await axios.get(`${PLEX_URL}/status?X-Plex-Token=${PLEX_TOKEN}`); if (response.status === 200) { ctx.reply('✅ Plex-Server läuft einwandfrei!'); } } catch (error) { ctx.reply('❌ Fehler beim Abrufen des Plex-Server-Status.'); } }); // **Stats Befehl** bot.command('stats', async (ctx) => { const activeSessionsCount = activeSessions.size; const bannedUsersCount = bannedUsers.size; const totalViolations = Array.from(userViolations.values()).reduce((acc, violations) => acc + violations, 0); const whitelistedUsersCount = whitelist.size; ctx.reply(` 📊 **Statistiken:** - Aktive Sessions: ${activeSessionsCount} - Gebannte Benutzer: ${bannedUsersCount} - Gesamte Verstöße: ${totalViolations} - Whitelisted Benutzer: ${whitelistedUsersCount} `); }); // **Whitelist Befehl zum Hinzufügen** // Funktion zum Laden der Whitelist aus der Datei function loadWhitelist() { try { const data = fs.readFileSync(whitelistFile, 'utf8'); whitelist = new Set(JSON.parse(data)); } catch (err) { console.error('Fehler beim Laden der Whitelist:', err.message); } } // Funktion zum Speichern der Whitelist in der Datei function saveWhitelist() { try { fs.writeFileSync(whitelistFile, JSON.stringify(Array.from(whitelist), null, 2)); } catch (err) { console.error('Fehler beim Speichern der Whitelist:', err.message); } } // Beim Starten des Bots die Whitelist laden loadWhitelist(); // Funktion zum Überprüfen, ob ein Benutzer auf der Whitelist ist function isUserWhitelisted(user) { return whitelist.has(user); } // **Whitelist Befehl zum Hinzufügen** bot.command('whitelist', async (ctx) => { const user = ctx.message.text.split(' ')[1]; if (!user) { return ctx.reply('❌ Bitte gib den Namen des Benutzers an, den du auf die Whitelist setzen möchtest.'); } // Überprüfen, ob der Benutzer bereits auf der Whitelist ist if (whitelist.has(user)) { return ctx.reply(`❌ Benutzer ${user} ist bereits auf der Whitelist.`); } // Benutzer zur Whitelist hinzufügen whitelist.add(user); saveWhitelist(); // Die Änderungen speichern ctx.reply(`✅ Benutzer ${user} wurde erfolgreich zur Whitelist hinzugefügt.`); }); // **Whitelist Befehl zum Entfernen** bot.command('remove_whitelist', async (ctx) => { const user = ctx.message.text.split(' ')[1]; if (!user) { return ctx.reply('❌ Bitte gib den Namen des Benutzers an, den du von der Whitelist entfernen möchtest.'); } // Überprüfen, ob der Benutzer in der Whitelist ist if (!whitelist.has(user)) { return ctx.reply(`❌ Benutzer ${user} ist nicht auf der Whitelist.`); } // Benutzer von der Whitelist entfernen whitelist.delete(user); saveWhitelist(); // Die Änderungen speichern ctx.reply(`✅ Benutzer ${user} wurde erfolgreich von der Whitelist entfernt.`); }); // Funktion zum Überprüfen, ob ein Benutzer auf der Whitelist ist function isUserWhitelisted(user) { return whitelist.has(user); } bot.command('reset_violations', async (ctx) => { const user = ctx.message.text.split(' ')[1]; if (!user) { return ctx.reply('❌ Bitte gib den Namen des Benutzers an, dessen Verstöße du zurücksetzen möchtest.'); } // Verstöße zurücksetzen userViolations.set(user, 0); ctx.reply(`✅ Die Verstöße für Benutzer ${user} wurden zurückgesetzt.`); }); // Bot starten bot.launch(); // Server für Status-Check app.get("/", (req, res) => { res.send("Telegram-Plex-Bot läuft!"); }); let autoMode = false; function getRecentActivities() { const autoStatus = autoMode ? 'Aktiv' : 'Nicht Aktiv'; // Hier kannst du deine Logik einbauen, um die letzten Aktivitäten zurückzugeben return [ `Automatik Status: ${autoStatus}` ]; } // /auto-Befehl zum Aktivieren/Deaktivieren des Auto-Modus bot.command('auto', async (ctx) => { autoMode = !autoMode; if (autoMode) { ctx.reply('🚀 Der Auto-Modus wurde aktiviert! Alle Accountsharings werden automatisch beendet.'); } else { ctx.reply('❌ Der Auto-Modus wurde deaktiviert.'); } }); function getRecentActivities() { const autoStatus = autoMode ? 'Aktiv' : 'Nicht Aktiv'; return [ `Automatik Status: ${autoStatus}` ]; } // Funktion zur automatischen Beendigung von Accountsharing, wenn der Auto-Modus aktiviert ist async function handleAutoMode() { if (!autoMode) return; for (const [user, sessions] of userSessions.entries()) { // Überprüfen, ob der Benutzer auf der Whitelist steht if (whitelist.has(user)) { console.log(`✅ ${user} ist auf der Whitelist und wird nicht betroffen.`); continue; // Überspringe den Benutzer, wenn er auf der Whitelist steht } if (sessions.length > 1) { console.log(`🚫 Automatisches Beenden von Accountsharing für ${user}.`); const stopMessage = "🚫 Accountsharing verboten. Dein Stream wurde automatisch beendet."; await stopPlaybackWithMessage(user, stopMessage); // Verstöße zählen und ggf. sperren let violations = userViolations.get(user) || 0; if (violations >= 2) { bannedUsers.set(user, Date.now()); userViolations.delete(user); bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `🚫 ${user} wurde aufgrund von wiederholtem Accountsharing für 3 Stunden gesperrt.` ); } else { userViolations.set(user, violations + 1); bot.telegram.sendMessage( TELEGRAM_CHAT_ID, `⚠️ Warnung! Accountsharing erkannt. (${violations + 1}/3 Verstöße)` ); } } } } // Modifizierter setInterval-Aufruf für die Auto-Logik setInterval(async () => { await checkPlexActivity(); await handleAutoMode(); // Überprüft und beendet automatisch Accountsharing im Auto-Modus }, 30000); // Alle 30 Sekunden app.listen(PORT, () => console.log(`🚀 Server läuft auf Port ${PORT}`));