diff --git a/bot.js b/bot.js index b617af8..86e7405 100644 --- a/bot.js +++ b/bot.js @@ -1,2274 +1,2662 @@ -require('dotenv').config(); -const TelegramBot = require('node-telegram-bot-api'); -const fs = require('fs'); -const path = require('path'); -const nodemailer = require('nodemailer'); -const stringSimilarity = require('string-similarity'); -const cron = require('node-cron'); -const axios = require('axios'); -const botStartTime = new Date(); // Startzeitpunkt des Bots - -// Token aus der .env-Datei laden -const token = process.env.BOT_TOKEN; -const bot = new TelegramBot(token, { polling: true }); - - -// Admins aus der .env-Datei laden und als Objekt speichern (ID -> {Name, Username, Zuständigkeit}, in der Reihenfolge) -const admins = process.env.ADMINS.split(',').reduce((acc, admin) => { - const [id, name, username, responsibility] = admin.split(':').map(val => val.trim()); - acc[id] = { name, username, responsibility }; - return acc; -}, {}); - -// Admin-IDs in der Reihenfolge speichern -const orderedAdminIds = Object.keys(admins); - -// Admin-Status-Objekt (speichert den Status jedes Admins) -let adminStatus = {}; - -// Initialen Status aller Admins auf "offline" setzen -Object.keys(admins).forEach(adminId => { - adminStatus[adminId] = 'offline'; -}); - -// Warteschlange für Benutzeranfragen -let requestQueue = []; - -// FAQ-Dateipfad -const dataDir = path.join(__dirname, 'data'); -const faqFilePath = path.join(dataDir, 'faq.json'); - -// Sicherstellen, dass das Verzeichnis existiert -if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir, { recursive: true }); -} - -// Sicherstellen, dass die FAQ-Datei existiert -if (!fs.existsSync(faqFilePath)) { - fs.writeFileSync(faqFilePath, JSON.stringify([])); -} - -// FAQ-Daten laden -let faqData = JSON.parse(fs.readFileSync(faqFilePath, 'utf8')); - -// Pfad zur link.json -const linksFilePath = path.join(dataDir, 'link.json'); - -// Sicherstellen, dass die link.json existiert -if (!fs.existsSync(linksFilePath)) { - fs.writeFileSync(linksFilePath, JSON.stringify([])); -} - -// Links-Daten laden -let linksData = JSON.parse(fs.readFileSync(linksFilePath, 'utf8')); - -// Bewertungsdaten -const ratingsFilePath = path.join(dataDir, 'ratings.json'); - -// Sicherstellen, dass die ratings.json existiert -if (!fs.existsSync(ratingsFilePath)) { - fs.writeFileSync(ratingsFilePath, JSON.stringify([])); -} - -// Ratings-Daten laden -let ratingsData = JSON.parse(fs.readFileSync(ratingsFilePath, 'utf8')); - - - - -// Funktion zum Überprüfen der Admin-Rechte in einer Gruppe -const checkBotAdminRights = async (chatId) => { - try { - const botId = await getBotId(); // Funktion zur Ermittlung der Bot-ID - const botInfo = await bot.getChatMember(chatId, botId); - - if (botInfo.status !== 'administrator' && botInfo.status !== 'creator') { - // Falls der Bot keine Admin-Rechte hat - const devId = process.env.DEV; - bot.sendMessage(devId, `❗ Der Bot benötigt Admin-Rechte in der Gruppe ${chatId}. Bitte gewähre Admin-Rechte oder überprüfe die Gruppeneinstellungen.`); - } - } catch (error) { - console.error('Error checking bot admin rights:', error); - } -}; - -// Funktion zur Ermittlung der Bot-ID -const getBotId = async () => { - try { - const botInfo = await bot.getMe(); - return botInfo.id; // Rückgabe der Bot-ID - } catch (error) { - console.error('Error getting bot ID:', error); - return null; // Rückgabe von null, falls ein Fehler auftritt - } -}; - -// Überprüfen aller Gruppen, in denen der Bot Mitglied ist -const checkAllGroupsAdminRights = async () => { - try { - const updates = await bot.getUpdates(); - const chatIds = new Set(); - - updates.forEach(update => { - if (update.message && update.message.chat && update.message.chat.id) { - chatIds.add(update.message.chat.id); // Alle Gruppen-IDs sammeln - } - }); - - chatIds.forEach(chatId => { - checkBotAdminRights(chatId); // Admin-Rechte für jede Gruppe überprüfen - }); - } catch (error) { - console.error('Error checking all group admin rights:', error); - } -}; - -// Auf Updates vom Bot hören -bot.on('message', async (msg) => { - const chatId = msg.chat.id; - - // Beispiel-Nachricht, wenn der Bot in einer neuen Gruppe hinzugefügt wird - if (msg.new_chat_members) { - console.log(`Bot joined new chat: ${chatId}`); - checkBotAdminRights(chatId); - } -}); - -// Initiale Überprüfung der Admin-Rechte in allen Gruppen -checkAllGroupsAdminRights(); - -bot.onText(/\/links/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Sperrte Benutzer können keine Befehle verwenden - } - - // Sicherstellen, dass linksData existiert und ein Array ist - if (!Array.isArray(linksData)) { - bot.sendMessage(chatId, '❗ Ein Fehler ist aufgetreten.') - .then(() => bot.deleteMessage(chatId, msg.message_id)); - return; - } - - // Links formatieren - const links = linksData.map((link, index) => { - return `${index + 1}. ${link.title}: ${link.url}`; - }).join('\n'); - - // Links dem Benutzer senden, ohne Linkvorschau - bot.sendMessage(userId, `🌐 Gespeicherte Links:\n\n${links}`, { - disable_web_page_preview: true // Deaktiviert die Linkvorschau - }).then(() => bot.deleteMessage(chatId, msg.message_id)); -}); - - -bot.onText(/\/add_links/, (msg) => { - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, `🔧 Bitte sende den Titel des Links:`) - .then(() => bot.once('message', async (titleMsg) => { - const title = titleMsg.text.trim(); - bot.sendMessage(userId, `🔧 Bitte sende die URL des Links:`) - .then(() => bot.once('message', async (urlMsg) => { - const url = urlMsg.text.trim(); - - if (title && url) { - linksData.push({ title, url }); - fs.writeFileSync(linksFilePath, JSON.stringify(linksData, null, 2)); - bot.sendMessage(userId, `✅ Link hinzugefügt.`) - .then(() => { - bot.deleteMessage(userId, titleMsg.message_id); - bot.deleteMessage(userId, urlMsg.message_id); - }); - } else { - bot.sendMessage(userId, `❌ Bitte stelle sicher, dass du sowohl Titel als auch URL eingibst.`); - } - })); - })); - } else { - bot.sendMessage(userId, '❗ Nur Admins können diesen Befehl verwenden.') - .then(() => bot.deleteMessage(userId, msg.message_id)); - } -}); - -bot.onText(/\/del_links/, (msg) => { - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, `🗑️ Bitte sende die Nummer des Links, den du löschen möchtest:`) - .then(() => bot.once('message', async (linkMsg) => { - const linkIndex = parseInt(linkMsg.text, 10) - 1; - - if (linkIndex >= 0 && linkIndex < linksData.length) { - linksData.splice(linkIndex, 1); - fs.writeFileSync(linksFilePath, JSON.stringify(linksData, null, 2)); - bot.sendMessage(userId, `✅ Link gelöscht.`) - .then(() => bot.deleteMessage(userId, linkMsg.message_id)); - } else { - bot.sendMessage(userId, `❌ Ungültige Link-Nummer.`); - } - })); - } else { - bot.sendMessage(userId, '❗ Nur Admins können diesen Befehl verwenden.') - .then(() => bot.deleteMessage(userId, msg.message_id)); - } -}); - -// Pfad zur "inviteLinks.json"-Datei für Einladungslinks -const inviteLinksFile = path.join(dataDir, 'inviteLinks.json'); - -// Sicherstellen, dass die "inviteLinks.json"-Datei existiert -if (!fs.existsSync(inviteLinksFile)) { - fs.writeFileSync(inviteLinksFile, JSON.stringify({})); -} - -// Funktion zum Laden der Einladungslinks aus der Datei -function loadInviteLinks() { - if (fs.existsSync(inviteLinksFile)) { - const data = fs.readFileSync(inviteLinksFile); - return JSON.parse(data); - } - return {}; -} - -// Funktion zum Speichern der Einladungslinks in der Datei -function saveInviteLinks() { - fs.writeFileSync(inviteLinksFile, JSON.stringify(inviteLinks, null, 2)); -} - -// Objekt zur Speicherung von Einladungslinks (wird aus der Datei geladen) -let inviteLinks = loadInviteLinks(); - -// /einladung-Befehl für alle Benutzer -bot.onText(/\/einladung/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - const userName = msg.from.username || `${msg.from.first_name} ${msg.from.last_name}`; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer bereits einen Einladungslink erstellt hat - if (inviteLinks[userId]) { - const existingLink = inviteLinks[userId].link; - bot.sendMessage(userId, `🔗 Du hast bereits einen Einladungslink erstellt: ${existingLink}`); - return; - } - - // Erstelle einen neuen Einladungslink für die Gruppe - bot.createChatInviteLink(chatId) - .then((inviteLink) => { - // Speichern des Einladungslinks und der Informationen über den Ersteller - inviteLinks[userId] = { - link: inviteLink.invite_link, // invite_link enthält den eigentlichen Link - createdBy: userName, - createdAt: new Date().toLocaleString() - }; - - // Links in der Datei speichern - saveInviteLinks(); - - // Den Einladungslink privat an den Benutzer senden - bot.sendMessage(userId, `🔗 Hier ist dein Einladungslink: ${inviteLink.invite_link}`); - - // Protokollierung, wer wann den Einladungslink erstellt hat - console.log(`Einladungslink erstellt von ${userName} (ID: ${userId}) am ${inviteLinks[userId].createdAt}`); - }) - .catch((error) => { - console.error('Fehler beim Erstellen des Einladungslinks:', error); - bot.sendMessage(userId, '❗ Es gab ein Problem beim Erstellen des Einladungslinks.'); - }); -}); - -// Admins können ihren Status mit /online ändern -bot.onText(/\/online/, (msg) => { - const adminId = msg.from.id.toString(); - - - if (admins[adminId]) { - adminStatus[adminId] = 'online'; - bot.sendMessage(adminId, `🟢 *Du bist jetzt als "online" markiert, ${admins[adminId].name}!*`); - - // Alle wartenden Anfragen an den jetzt online gegangenen Admin senden - requestQueue.forEach((request, index) => { - if (!request.handled) { - bot.sendMessage(adminId, `📩 *Neue Support-Anfrage von ${request.userName}:*\n\n${request.message}`); - requestQueue[index].handled = true; // Markiere die Anfrage als bearbeitet - } - }); - } else { - bot.sendMessage(adminId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// Admins können ihren Status mit /offline ändern -bot.onText(/\/offline/, (msg) => { - const adminId = msg.from.id.toString(); - - - if (admins[adminId]) { - adminStatus[adminId] = 'offline'; - bot.sendMessage(adminId, `🔴 *Du bist jetzt als "offline" markiert, ${admins[adminId].name}.*`); - } else { - bot.sendMessage(adminId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -bot.onText(/\/admin/, (msg) => { - const userId = msg.from.id; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Sperrte Benutzer können keine Befehle verwenden - } - - const sortedAdminIds = orderedAdminIds.sort((a, b) => a === '5507179337' ? -1 : b === '5507179337' ? 1 : 0); - - const adminList = sortedAdminIds.map(adminId => { - const statusIcon = adminStatus[adminId] === 'online' ? '🟢' : '🔴'; - const adminName = admins[adminId].name; - const adminUsername = admins[adminId].username.replace(/_/g, '\\_'); // Escape Unterstriche - const adminResponsibility = admins[adminId].responsibility || 'Keine Zuständigkeit angegeben'; - return `• ${statusIcon} *${adminName}*\n _@${adminUsername}_\n 📌 _Zuständigkeit:_ ${adminResponsibility}`; - }).join('\n\n'); - - bot.sendMessage(userId, `👮 *Liste der Admins:* 👮\n\n${adminList}`, { parse_mode: 'MarkdownV2' }) - .catch(error => { - console.error('Fehler beim Senden der Admin-Liste:', error); - }); -}); - -// Temporäre Speicherung der message_id -const commandMessages = {}; - -bot.onText(/\/chat/, async (msg) => { - const userId = msg.from.id; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Sperrte Benutzer können keine Befehle verwenden - } - - const userName = msg.from.username ? `@${msg.from.username}` : `Benutzer ${msg.from.first_name}`; - - // Speichern der message_id - commandMessages[userId] = commandMessages[userId] || {}; - commandMessages[userId]['/chat'] = msg.message_id; - - const onlineAdmins = orderedAdminIds.filter(adminId => adminStatus[adminId] === 'online'); - - if (onlineAdmins.length > 0) { - const options = { - reply_markup: { - inline_keyboard: onlineAdmins.map(adminId => [{ - text: `${adminStatus[adminId] === 'online' ? '🟢' : '🔴'} ${admins[adminId].name}`, - callback_data: adminId - }]) - } - }; - - bot.sendMessage(userId, "💬 *Wähle einen Admin aus, um Unterstützung zu erhalten:*", options) - .then(() => bot.deleteMessage(msg.chat.id, msg.message_id)); - } else { - bot.sendMessage(userId, "🔴 *Derzeit ist kein Admin online. Bitte schreibe dein Problem, und wir werden dich kontaktieren, sobald ein Admin verfügbar ist.*"); - bot.once('message', (userMsg) => { - const requestMessage = userMsg.text; - requestQueue.push({ userId, userName, message: requestMessage, handled: false }); - bot.sendMessage(userId, "✉️ *Deine Anfrage wurde an das Support-Team weitergeleitet.*"); - }); - } -}); - -// Reaktion auf die Auswahl eines Admins -bot.on('callback_query', async (callbackQuery) => { - const adminId = callbackQuery.data; // ID des ausgewählten Admins - const userId = callbackQuery.from.id; // ID des Anfragenden Benutzers - const userName = callbackQuery.from.username ? `@${callbackQuery.from.username}` : `Benutzer ${callbackQuery.from.first_name}`; - - if (adminStatus[adminId] === 'offline') { - bot.sendMessage(userId, "🔴 *Dieser Admin ist zur Zeit nicht online. Du kannst dein Problem schriftlich einreichen.*"); - bot.once('message', async (msg) => { - if (msg.chat.id === userId) { - requestQueue.push({ userId: userId, userName: userName, message: msg.text, handled: false }); - bot.sendMessage(userId, `✅ *Deine Nachricht wurde gespeichert und wird an den nächsten verfügbaren Admin weitergeleitet.*`); - } - }); - } else { - try { - // Benutzerdaten des Anfragenden Benutzers abrufen - const user = await bot.getChatMember(callbackQuery.message.chat.id, userId); - const userName = user.user.username ? `@${user.user.username}` : `Benutzer ${user.user.first_name}`; - - // Admins-Namen und Usernamen aus der .env-Datei nutzen - const adminName = admins[adminId].name; - const adminUsername = admins[adminId].username; - - const adminLink = `https://t.me/${adminUsername}`; - - // Nachricht an den ausgewählten Admin senden - bot.sendMessage(adminId, `🔔 *Du wurdest von ${userName} für Unterstützung ausgewählt.*\n\nBitte kontaktiere ihn in einem privaten Chat. Du kannst ihm direkt über diesen Link schreiben: ${userName}`); - - // Nachricht an den Benutzer senden - bot.sendMessage(userId, `✅ *Der Admin ${adminName} wurde benachrichtigt und wird sich bald bei dir melden.*`); - - // Ursprüngliche Nachricht (Befehl /chat) löschen - if (callbackQuery.message.reply_to_message && callbackQuery.message.reply_to_message.message_id) { - bot.deleteMessage(callbackQuery.message.chat.id, callbackQuery.message.reply_to_message.message_id); - } - bot.deleteMessage(callbackQuery.message.chat.id, callbackQuery.message.message_id); - } catch (error) { - console.error('Fehler beim Abrufen des Benutzernamens:', error); - /* bot.sendMessage(userId, '⚠️ *Es gab einen Fehler beim Abrufen des Benutzernamens. Bitte versuche es später erneut.*'); */ - } - } -}); - -const escapeMarkdown = (text) => { - return text - .replace(/([_*\[\]()~`>#+\-=|{}.!])/g, '\\$1') // Escape Markdown reserved characters - .replace(/(?:\r\n|\r|\n)/g, '\\n') // Escape newlines - .replace(/\./g, '\\.'); // Escape dots -}; - -// Funktion zum Senden der FAQ im privaten Chat -const sendFaqPrivately = (userId) => { - if (faqData.length > 0) { - // FAQs formatieren - const faqs = faqData.map((faq, index) => { - const question = faq.question; - const answer = faq.answer; - return `${index + 1}️⃣\nFrage: ${question}\nAntwort: ${answer}`; - }).join('\n\n'); - - bot.sendMessage(userId, `❓ FAQs: ❓\n\n${faqs}`) - .catch(error => { - console.error('Fehler beim Senden der FAQ:', error); - }); - } else { - bot.sendMessage(userId, '❗ Es sind keine FAQs verfügbar.'); - } -}; - -// Reaktion auf den /faq-Befehl -bot.onText(/\/faq/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.', { disable_web_page_preview: true }); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - const { expiry } = spammedUsers[userId]; - - // Nachricht für gesperrte Benutzer senden - if (expiry === 'permanent') { - bot.sendMessage(chatId, '❌ *Du bist dauerhaft gesperrt und kannst diesen Befehl nicht verwenden.*', { disable_web_page_preview: true }); - } else { - const formattedExpiry = formatTime(expiry); - bot.sendMessage(chatId, `❌ *Du bist gesperrt bis ${formattedExpiry} und kannst diesen Befehl nicht verwenden.*`, { disable_web_page_preview: true }); - } - return; // Verhindert weitere Verarbeitung, wenn der Benutzer gesperrt ist - } - - // Sende die FAQ-Nachricht direkt an den Benutzer im privaten Chat - sendFaqPrivately(userId); -}); - - -// /add_faq-Befehl, um FAQs hinzuzufügen (nur privat) -bot.onText(/\/add_faq/, (msg) => { - const userId = msg.from.id.toString(); - - if (!canExecuteCommand(userId)) { - bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, `🔧 *Bitte sende die FAQ ein:* \n\nFrage:`) - .then(() => bot.once('message', async (faqMsg) => { - const question = faqMsg.text.trim(); - bot.sendMessage(userId, `🔧 *Bitte sende die Antwort:*`) - .then(() => bot.once('message', async (answerMsg) => { - const answer = answerMsg.text.trim(); - - if (question && answer) { - faqData.push({ question, answer }); - fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); - bot.sendMessage(userId, `✅ *FAQ hinzugefügt.*`); - } else { - bot.sendMessage(userId, `❌ *Bitte stelle sicher, dass du sowohl Frage als auch Antwort eingibst.*`); - } - })); - })); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// /edit_faq-Befehl, um FAQs zu bearbeiten (nur privat) -bot.onText(/\/edit_faq/, (msg) => { - const userId = msg.from.id.toString(); - - if (!canExecuteCommand(userId)) { - bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, `🔧 *Bitte sende die Nummer der FAQ, die du bearbeiten möchtest:*`) - .then(() => bot.once('message', async (faqMsg) => { - const faqIndex = parseInt(faqMsg.text, 10) - 1; - - if (faqIndex >= 0 && faqIndex < faqData.length) { - bot.sendMessage(userId, `✏️ *Bitte sende die neue Frage:*`) - .then(() => bot.once('message', async (questionMsg) => { - const question = questionMsg.text.trim(); - bot.sendMessage(userId, `✏️ *Bitte sende die neue Antwort:*`) - .then(() => bot.once('message', async (answerMsg) => { - const answer = answerMsg.text.trim(); - - if (question && answer) { - faqData[faqIndex] = { question, answer }; - fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); - bot.sendMessage(userId, `✅ *FAQ aktualisiert.*`); - } else { - bot.sendMessage(userId, `❌ *Bitte stelle sicher, dass du sowohl Frage als auch Antwort eingibst.*`); - } - })); - })); - } else { - bot.sendMessage(userId, `❌ *Ungültige FAQ-Nummer.*`); - } - })); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// /del_faq-Befehl, um FAQs zu löschen (nur privat) -bot.onText(/\/del_faq/, (msg) => { - const userId = msg.from.id.toString(); - - if (!canExecuteCommand(userId)) { - bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, `🗑️ *Bitte sende die Nummer der FAQ, die du löschen möchtest:*`) - .then(() => bot.once('message', async (faqMsg) => { - const faqIndex = parseInt(faqMsg.text, 10) - 1; - - if (faqIndex >= 0 && faqIndex < faqData.length) { - faqData.splice(faqIndex, 1); - fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); - bot.sendMessage(userId, `✅ *FAQ gelöscht.*`); - } else { - bot.sendMessage(userId, `❌ *Ungültige FAQ-Nummer.*`); - } - })); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -const rateLimit = new Map(); // Speichert die Zeitstempel der letzten Ticket-Einreichung für jeden Benutzer - -bot.onText(/\/create_ticket/, (msg) => { - const userId = msg.from.id.toString(); - const currentTime = Date.now(); - - // Überprüfen, ob der Wartungsmodus aktiv ist und ob der Benutzer berechtigt ist - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Sperrte Benutzer können keine Befehle verwenden - } - - // Überprüfen, ob der Benutzer bereits ein Ticket eingereicht hat - if (rateLimit.has(userId)) { - const lastTicketTime = rateLimit.get(userId); - const timeSinceLastTicket = currentTime - lastTicketTime; - - // Überprüfen, ob 5 Minuten (300000 Millisekunden) seit dem letzten Ticket vergangen sind - if (timeSinceLastTicket < 300000) { - const timeLeft = Math.ceil((300000 - timeSinceLastTicket) / 60000); // Zeit übrig in Minuten - return bot.sendMessage(userId, `❌ *Du musst noch ${timeLeft} Minuten warten, bevor du ein weiteres Ticket senden kannst.*`); - } - } - - // Wenn der Benutzer noch keine Tickets gesendet hat oder das Zeitlimit abgelaufen ist - if (admins[userId]) { - bot.sendMessage(userId, '🔧 Bitte gib deinen Namen ein:') - .then(() => bot.once('message', async (nameMsg) => { - const name = nameMsg.text.trim(); - - if (!name) { - bot.sendMessage(userId, '❌ *Name ist erforderlich.*'); - return; - } - - bot.sendMessage(userId, '✉️ Bitte gib deine E-Mail-Adresse ein:') - .then(() => bot.once('message', async (emailMsg) => { - const email = emailMsg.text.trim(); - - // Simple E-Mail-Validierung - if (!email || !email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) { - bot.sendMessage(userId, '❌ *Ungültige E-Mail-Adresse.*'); - return; - } - - bot.sendMessage(userId, '📝 Bitte gib den Inhalt deines Tickets ein:') - .then(() => bot.once('message', async (ticketMsg) => { - const ticketContent = ticketMsg.text.trim(); - - if (!ticketContent) { - bot.sendMessage(userId, '❌ *Ticket-Inhalt ist erforderlich.*'); - return; - } - - // E-Mail-Transporter konfigurieren - const transporter = nodemailer.createTransport({ - service: 'gmail', - auth: { - user: process.env.EMAIL_USER, - pass: process.env.EMAIL_PASS - } - }); - - // E-Mail-Nachricht erstellen - const mailOptions = { - from: process.env.EMAIL_USER, - to: process.env.EMAIL_RECIPIENT, - subject: 'Neues Ticket vom Support-Bot', - text: `Neues Ticket von ${name} (${email}):\n\n${ticketContent}` - }; - - // E-Mail senden - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - console.error('Fehler beim Senden der E-Mail:', error); - bot.sendMessage(userId, '⚠️ *Es gab einen Fehler beim Senden des Tickets. Bitte versuche es später erneut.*'); - } else { - bot.sendMessage(userId, `✅ *Dein Ticket wurde erfolgreich eingereicht. Vielen Dank, ${name}!`); - } - }); - - // Zeitstempel des letzten Tickets speichern - rateLimit.set(userId, currentTime); - })); - })); - })); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// Beispiel für den /info-Befehl -bot.onText(/\/info/, (msg) => { - const chatId = msg.chat.id; - - if (!canExecuteCommand(msg.from.id.toString())) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Hier die Bot-Informationen eintragen - const botName = 'Support Bot'; // Ersetze dies durch den tatsächlichen Bot-Namen - const botVersion = '1.5.6'; // Ersetze dies durch die tatsächliche Version - const botAuthor = 'M_Viper'; // Ersetze dies durch den tatsächlichen Autor - const botLicense = 'MIT'; // Ersetze dies durch die tatsächliche Lizenz - - // Informationen ohne MarkdownV2-Formatierung - const infoMessage = ` -🤖 Bot Information: -- Name: ${botName} -- Version: ${botVersion} -- Author: ${botAuthor} -- License: ${botLicense} - `; - - bot.sendMessage(chatId, infoMessage) - .catch(error => { - console.error('Fehler beim Senden der Bot-Informationen:', error); - }); -}); - -const maintenanceModeFile = path.join(dataDir, 'maintenance_mode.json'); - -// Sicherstellen, dass die maintenance_mode.json existiert -if (!fs.existsSync(maintenanceModeFile)) { - fs.writeFileSync(maintenanceModeFile, JSON.stringify({ active: false }), 'utf8'); -} - -// Funktion zum Laden des Wartungsmodus-Status -const loadMaintenanceMode = () => { - return JSON.parse(fs.readFileSync(maintenanceModeFile, 'utf8')); -}; - -// Funktion zum Speichern des Wartungsmodus-Status -const saveMaintenanceMode = (status) => { - fs.writeFileSync(maintenanceModeFile, JSON.stringify(status, null, 2), 'utf8'); -}; - -// Überprüfen, ob der Wartungsmodus aktiviert ist -const isMaintenanceModeActive = () => { - const status = loadMaintenanceMode(); - return status.active; -}; - -// Funktion zum Umschalten des Wartungsmodus -const toggleMaintenanceMode = (adminId, action) => { - const status = loadMaintenanceMode(); - if (action === 'on') { - status.active = true; - saveMaintenanceMode(status); - bot.sendMessage(adminId, '🔧 Wartungsmodus wurde aktiviert.'); - } else if (action === 'off') { - status.active = false; - saveMaintenanceMode(status); - bot.sendMessage(adminId, '🔧 Wartungsmodus wurde deaktiviert.'); - } -}; - -// Reaktion auf den /maintenance_mode-Befehl -bot.onText(/\/wartung (on|off)/, (msg, match) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - const action = match[1]; // "on" oder "off" - - // Überprüfen, ob der Benutzer der Entwickler ist - const devId = process.env.DEV; - if (userId === devId) { - toggleMaintenanceMode(userId, action); - } else { - bot.sendMessage(chatId, '❌ Du hast keine Berechtigung, den Wartungsmodus zu ändern.'); - } -}); - -// Funktion zur Überprüfung, ob der Befehl während des Wartungsmodus ausgeführt werden kann -const canExecuteCommand = (userId) => { - return !isMaintenanceModeActive() || userId === process.env.DEV; -}; - -// Hilfe-Befehl -bot.onText(/\/help/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - const { expiry } = spammedUsers[userId]; - - // Nachricht für gesperrte Benutzer senden - if (expiry === 'permanent') { - bot.sendMessage(chatId, '❌ *Du bist dauerhaft gesperrt und kannst diesen Befehl nicht verwenden.*'); - } else { - const formattedExpiry = formatTime(expiry); - bot.sendMessage(chatId, `❌ *Du bist gesperrt bis ${formattedExpiry} und kannst diesen Befehl nicht verwenden.*`); - } - return; // Verhindert weitere Verarbeitung, wenn der Benutzer gesperrt ist - } - - // Normale Verarbeitung für nicht gesperrte Benutzer (User Befehle) - const helpMessage = `📋 Verfügbare Befehle:\n - -🔍 /help - Zeigt diese Hilfe-Nachricht an\n -🔗 /links - Zeigt eine Liste der gespeicherten Links an\n -❓ /faq - Zeigt die FAQ an\n -📝 /create_ticket - Reiche ein Support-Ticket ein\n -👥 /admin - Zeigt eine Liste der Admins und deren Status\n -💬 /chat - Fordere einen Chat mit einem Admin an\n -ℹ️ /info - Zeigt Informationen über den Bot an\n -⭐ /rate - Bewerte unseren Support\n -🔗 /einladung - Erstelle einen persönlichen Einladungslink\n -📅 /termin - Mache einen Chat-Termin mit einem Admin\n -🚨 /escalation - Melde ein Problem an alle Admins\n -📜 /terms - Zeigt die Nutzungsbedingungen des Bots an\n -🗑 /cancel_termin - Storniert einen Chat-Termin\n -`; - - bot.sendMessage(chatId, helpMessage); // Kein Markdown verwendet -}); - -// Hilfe-Befehl für Admins -bot.onText(/\/a_help/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfen, ob der Benutzer ein Admin ist (Admin Befehle) - if (admins[userId]) { - const adminHelpMessage = `📋 Verfügbare Admin-Befehle:\n - -🟢 /online - Setze deinen Status auf "online"\n -🔴 /offline - Setze deinen Status auf "offline"\n -📄 /add_faq - Füge einen neuen FAQ-Eintrag hinzu\n -✏️ /edit_faq - Bearbeite einen bestehenden FAQ-Eintrag\n -❌ /del_faq - Lösche einen FAQ-Eintrag\n -🔗 /add_links - Füge einen neuen Link hinzu\n -🚫 /del_links - Lösche einen Link\n -⭐ /view_ratings - Zeigt alle Bewertungen an\n -📊 /status - Zeigt Admins & Informationen an\n -📩 /msg_admin - Sende eine Nachricht an alle Admins\n -📝 /view_chat_history - Zeigt den Gesprächsverlauf eines Benutzers\n -📅 /my_termine - zeigt alle zukünftigen Chat-Termine an\n -🕐 /schedule_message - Geplante Nachricht erstellen\n -📌 /pin_message - Ermöglicht es Nachrichten in einem Chat anzupinnen.\n -🛑 /spam - Sperrt einen User für eine festgelegte Zeit\n -🔓 /unspam - Hebt die Sperre eines Users auf\n -🛠️ /maintenance_mode on|off - Wartungsmodus AN/AUS\n - -`; - - bot.sendMessage(chatId, adminHelpMessage) - .catch(error => console.log('Fehler beim Senden der Nachricht:', error)); - } else { - // Nachricht für Nicht-Admins - bot.sendMessage(chatId, "❌ Du hast keine Berechtigung, diesen Befehl zu verwenden.") - .catch(error => console.log('Fehler beim Senden der Nachricht:', error)); - } -}); - -// Admin-Nachrichten verarbeiten -bot.onText(/\/msg_admin/, (msg) => { - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - bot.sendMessage(userId, '🔧 *Bitte gib die Nachricht ein, die an alle Admins gesendet werden soll:*') - .then(() => bot.once('message', async (messageMsg) => { - const message = messageMsg.text.trim(); - - if (!message) { - bot.sendMessage(userId, '❌ *Die Nachricht darf nicht leer sein.*'); - return; - } - - orderedAdminIds.forEach(adminId => { - if (adminId !== userId) { - bot.sendMessage(adminId, `🔧 *Nachricht von ${admins[userId].name}:*\n\n${message}`); - } - }); - - bot.sendMessage(userId, '✅ *Nachricht an alle Admins gesendet.*'); - })); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// /rate-Befehl, um den Support zu bewerten -bot.onText(/\/rate/, (msg) => { - const userId = msg.from.id.toString(); - const username = msg.from.username ? `@${msg.from.username}` : 'Unbekannt'; // Username holen, wenn vorhanden - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Sperrte Benutzer können keine Befehle verwenden - } - - // Benutzer auffordern, eine Bewertung von 1 bis 10 abzugeben - bot.sendMessage(userId, `⭐️ *Bewerte unseren Support von 1 bis 10 Sternen:*`) - .then(() => bot.once('message', async (ratingMsg) => { - const rating = parseInt(ratingMsg.text, 10); - - // Validierung der Bewertung - if (isNaN(rating) || rating < 1 || rating > 10) { - bot.sendMessage(userId, '❌ *Bitte gib eine gültige Bewertung von 1 bis 10 Sternen ein.*'); - return; - } - - // Speichern der Bewertung - ratingsData.push({ userId, username, rating }); - fs.writeFileSync(ratingsFilePath, JSON.stringify(ratingsData, null, 2)); - bot.sendMessage(userId, `✅ *Danke für deine Bewertung!*`); - - // Optional: Benachrichtige den Admin oder speichere die Bewertung anders - })); -}); - -// /view_ratings-Befehl, um Bewertungen zu sehen (nur privat) -bot.onText(/\/view_ratings/, (msg) => { - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - if (ratingsData.length > 0) { - const ratings = ratingsData.map((entry) => `⭐️ Benutzer ${entry.username || entry.userId}: ${entry.rating} Sterne`).join('\n\n'); - bot.sendMessage(userId, `📊 *Bewertungen:* 📊\n\n${ratings}`); - } else { - bot.sendMessage(userId, '❗ Keine Bewertungen verfügbar.'); - } - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// Initialisierung der Daten -let usageData = []; -let fqaData = []; -let ticketsData = []; // Variable für die Tickets -let chatSessions = []; // Variable für Chats mit Admins - -fs.readFile(faqFilePath, 'utf8', (err, data) => { - if (err) { - console.error('Error loading FAQ data:', err); - return; - } - try { - fqaData = JSON.parse(data); - console.log('Loaded FAQ Data:', fqaData); // Logging zur Überprüfung - } catch (e) { - console.error('Error parsing FAQ data:', e); - } -}); - -// Beispiel: Chat-Daten speichern (Wird angenommen, dass beim Start eines Chats ein Zeitstempel gespeichert wird) -function startChatSession(userId, adminId) { - const startTime = Date.now(); - chatSessions.push({ userId, adminId, startTime }); -} - -// Beispiel: Chat-Daten beenden (Wird angenommen, dass beim Beenden eines Chats der Zeitstempel erfasst wird) -function endChatSession(userId, adminId) { - const endTime = Date.now(); - chatSessions = chatSessions.map(session => { - if (session.userId === userId && session.adminId === adminId && !session.endTime) { - session.endTime = endTime; - } - return session; - }); -} - -// Funktion zum Ermitteln des Webseitenstatus -const getWebsitesStatus = async () => { - const statusPromises = linksData.map(async (link) => { - try { - // Sende eine HTTP-GET-Anfrage an die Webseite - await axios.get(link.url, { timeout: 5000 }); - return `🟢 Online ${link.title}`; - } catch (error) { - return `🔴 Offline ${link.title}`; - } - }); - - // Warten, bis alle Status-Promises abgeschlossen sind - const statuses = await Promise.all(statusPromises); - return statuses.join('\n\n'); // Füge einen Abstand zwischen den Einträgen hinzu -}; - -// Funktion zur Berechnung der Laufzeit des Bots -const getBotUptime = () => { - const now = new Date(); - const uptimeMs = now - botStartTime; - const uptimeMin = Math.floor(uptimeMs / 60000); - const uptimeSec = ((uptimeMs % 60000) / 1000).toFixed(0); - return `${uptimeMin}m ${uptimeSec}s`; -}; - -// /status-Befehl, um den Status der Admins zu überprüfen -bot.onText(/\/status/, async (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - try { - // Status der Admins - const adminStatusMessages = orderedAdminIds.map(id => { - const status = adminStatus[id] || 'offline'; - const statusEmoji = status === 'online' ? '🟢' : '🔴'; - return `${statusEmoji} ${admins[id].name} (@${admins[id].username}): ${status}`; - }).join('\n\n'); - - // Weitere Statusinformationen - const totalUsages = usageData.length; // Anzahl der Nutzungen - const totalRatings = ratingsData.length; // Anzahl der Bewertungen - const totalFQA = fqaData.length; // Anzahl der FQA Einträge - const totalTickets = ticketsData.length; // Anzahl der Tickets - const totalLinks = linksData.length; // Anzahl der Links - const totalUsers = loadUsers().length; // Anzahl der Nutzer - const totalSpammedUsers = Object.keys(loadSpammedUsers()).length; // Anzahl der Sperrungen (Spam) - - // Dauer der Chats berechnen - const chatDurations = chatSessions.map(session => { - if (session.endTime) { - const durationMs = session.endTime - session.startTime; - const durationMin = Math.floor(durationMs / 60000); - const durationSec = ((durationMs % 60000) / 1000).toFixed(0); - return `🗣️ ${admins[session.adminId].name} (@${admins[session.adminId].username}): ${durationMin}m ${durationSec}s`; - } - return null; - }).filter(Boolean).join('\n'); - - // Wartungsmodus-Status - const maintenanceModeStatus = isMaintenanceModeActive() ? 'Aktiv' : 'Inaktiv'; - - // Status der Webseiten - const websiteStatus = await getWebsitesStatus(); - - // Laufzeit des Bots berechnen - const botUptime = getBotUptime(); - - const additionalInfo = `📊 Zusätzliche Informationen: 📊\n\n` + - `🔢 Anzahl der Nutzungen: ${totalUsages}\n\n` + - `⭐️ Anzahl der Bewertungen: ${totalRatings}\n\n` + - `❓ Anzahl der FAQ Einträge: ${totalFQA}\n\n` + - `🎟️ Anzahl der Tickets: ${totalTickets}\n\n` + - `🔗 Anzahl der Links: ${totalLinks}\n\n` + - `👥 Anzahl der Nutzer: ${totalUsers}\n\n` + - `🚫 Anzahl der Sperrungen (Spam): ${totalSpammedUsers}\n\n` + - `🕒 Chats mit Admins: \n${chatDurations || 'Keine aktiven Chats'}\n\n` + - `🔧 Wartungsmodus: ${maintenanceModeStatus}\n\n` + - `⏱️ Bot Laufzeit: ${botUptime}`; - - // Komplette Statusnachricht - const fullStatusMessage = `🛠️ Admin-Status: 🛠️\n\n${adminStatusMessages}\n\n` + - `══════════════════════════════\n\n` + - `${additionalInfo}\n\n` + - `══════════════════════════════\n\n` + - `🌐 Webseitenstatus: \n\n${websiteStatus}\n\n`; - - bot.sendMessage(chatId, fullStatusMessage); - } catch (error) { - console.error('Error while generating status message:', error); - bot.sendMessage(chatId, '❗ Es ist ein Fehler aufgetreten. Bitte versuche es später erneut.'); - } - } else { - bot.sendMessage(chatId, '❗ Nur Admins können diesen Befehl verwenden.'); - } -}); - -const repliesFilePath = path.join(dataDir, 'reply.json'); - -// Sicherstellen, dass die reply.json-Datei existiert und als Array initialisieren -if (!fs.existsSync(repliesFilePath)) { - fs.writeFileSync(repliesFilePath, JSON.stringify([])); // Leeres Array statt Objekt -} - -// Lädt Auto-Reply-Antworten aus der reply.json-Datei -let autoReplies; -try { - autoReplies = JSON.parse(fs.readFileSync(repliesFilePath, 'utf8')); - - // Falls die Datei versehentlich kein Array ist, setzen wir sie korrekt - if (!Array.isArray(autoReplies)) { - autoReplies = []; - fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); - } -} catch (error) { - console.error('Fehler beim Laden der Auto-Reply-Daten:', error); - autoReplies = []; // Falls Fehler auftritt, leeres Array initialisieren -} - -// Temporärer Speicher für Admins, die auf Eingaben warten -const pendingAutoReplies = {}; - -// Funktion zum Setzen einer automatischen Antwort -function setAutoReply(question, answer) { - try { - const replyData = { question, answer }; - autoReplies.push(replyData); - fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); - } catch (error) { - console.error('Fehler beim Speichern der Auto-Reply-Daten:', error); - } -} - -// /auto_reply-Befehl zum Starten des Prozesses -bot.onText(/\/auto_reply/, (msg) => { - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (admins[userId]) { - pendingAutoReplies[userId] = { step: 'waiting_for_question' }; - bot.sendMessage(userId, '✏️ *Bitte gib die Frage ein, auf die automatisch geantwortet werden soll.*'); - } else { - bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// Verarbeite Nachrichten und steuere den Frage-Antwort-Prozess -bot.on('message', (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text; - - if (pendingAutoReplies[userId]) { - const pendingReply = pendingAutoReplies[userId]; - - if (pendingReply.step === 'waiting_for_question') { - // Frage erhalten, nach der Antwort fragen - pendingReply.question = text.trim(); - pendingReply.step = 'waiting_for_answer'; - bot.sendMessage(userId, `📝 *Frage gespeichert:* "${pendingReply.question}". Bitte gib nun die Antwort ein.`); - } else if (pendingReply.step === 'waiting_for_answer') { - // Antwort erhalten, das Frage-Antwort-Paar speichern - const answer = text.trim(); - setAutoReply(pendingReply.question, answer); - bot.sendMessage(chatId, `✅ *Automatische Antwort für die Frage "${pendingReply.question}" wurde gespeichert.*`); - - // Entferne den Benutzer aus dem temporären Speicher - delete pendingAutoReplies[userId]; - } - } else if (text) { - // Verarbeite eingehende Nachrichten und sende eine automatische Antwort, wenn eine Frage ähnlich ist - const lowerCaseText = text.toLowerCase(); - - let highestSimilarity = 0; - let bestMatch = null; - - // Verwendet Fuzzy Matching, um ähnliche Fragen zu finden - for (const reply of autoReplies) { - const { question, answer } = reply; - - // Berechne die Ähnlichkeit zwischen der Benutzerfrage und den gespeicherten Fragen - try { - const similarity = stringSimilarity.compareTwoStrings(lowerCaseText, question.toLowerCase()); - - if (similarity > highestSimilarity) { - highestSimilarity = similarity; - bestMatch = answer; - } - } catch (error) { - console.error('Fehler bei der Textähnlichkeitsberechnung:', error); - } - } - - // Wenn eine hohe Ähnlichkeit festgestellt wurde (z.B. > 0.5), sende die passende Antwort - if (highestSimilarity > 0.5) { - bot.sendMessage(chatId, bestMatch); - } - } -}); - -const chatHistoryFilePath = path.join(dataDir, 'chat_history.json'); - -// Sicherstellen, dass die chat_history.json-Datei existiert -if (!fs.existsSync(chatHistoryFilePath)) { - fs.writeFileSync(chatHistoryFilePath, JSON.stringify({})); -} - -// Lädt den Gesprächsverlauf aus der chat_history.json-Datei -let chatHistory = {}; -try { - chatHistory = JSON.parse(fs.readFileSync(chatHistoryFilePath, 'utf8')); -} catch (error) { - console.error('Fehler beim Laden des Gesprächsverlaufs:', error); -} - -// Funktion zum Speichern eines Gesprächsverlaufs -function saveChatHistory(userId, userName, message) { - console.log(`Speichern der Nachricht für Benutzer ${userName}: ${message}`); - if (!chatHistory[userId]) { - chatHistory[userId] = { [userName]: [] }; - } else if (!chatHistory[userId][userName]) { - chatHistory[userId][userName] = []; - } - chatHistory[userId][userName].push(message); - try { - fs.writeFileSync(chatHistoryFilePath, JSON.stringify(chatHistory, null, 2)); - console.log('Chat-Verlauf erfolgreich gespeichert.'); - } catch (error) { - console.error('Fehler beim Speichern des Gesprächsverlaufs:', error); - } -} - -// Funktion zum Abrufen der Liste der Benutzer -function listUsers() { - const userList = Object.keys(chatHistory) - .map((userId, index) => { - const userName = Object.keys(chatHistory[userId])[0]; - return `${index + 1}. ${userName}`; - }) - .join('\n'); - return userList || 'Keine Benutzer gefunden.'; -} - -// Funktion zum Abrufen des Gesprächsverlaufs eines bestimmten Benutzers -function getChatHistory(userId) { - if (chatHistory[userId]) { - return Object.entries(chatHistory[userId]) - .map(([name, messages]) => `@${name}:\n${messages.join('\n')}`) - .join('\n\n'); - } - return 'Kein Verlauf gefunden.'; -} - -// /view_chat_history-Befehl zum Anzeigen der Liste der Benutzer -bot.onText(/\/view_chat_history/, (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfe, ob der Benutzer berechtigt ist (Admin-Check) - if (admins[userId]) { - const usersList = listUsers(); - bot.sendMessage(chatId, `🔍 *Wähle einen Benutzer aus der Liste aus:* \n\n${usersList}`); - // Temporären Speicher für die Auswahl der Benutzernummer - pendingSelections[userId] = { step: 'waiting_for_selection' }; - } else { - bot.sendMessage(chatId, '❗ *Nur Admins können diesen Befehl verwenden.*'); - } -}); - -// Temporärer Speicher für Benutzer, die auf Auswahl warten -const pendingSelections = {}; - -// Verarbeite die Auswahl des Benutzers -bot.on('message', (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text; - - if (admins[userId]) { - saveChatHistory(userId, msg.from.username || msg.from.first_name, text); - } - - if (pendingSelections[userId]) { - const pendingSelection = pendingSelections[userId]; - - if (pendingSelection.step === 'waiting_for_selection') { - const selectionIndex = parseInt(text.trim(), 10) - 1; - const userIds = Object.keys(chatHistory); - - if (selectionIndex >= 0 && selectionIndex < userIds.length) { - const selectedUserId = userIds[selectionIndex]; - const userName = Object.keys(chatHistory[selectedUserId])[0]; - const history = getChatHistory(selectedUserId); - bot.sendMessage(chatId, `📜 *Gesprächsverlauf für Benutzer ${userName} (${selectedUserId}):*\n\n${history}`); - } else { - bot.sendMessage(chatId, '❗ *Ungültige Auswahl. Bitte gib eine gültige Nummer ein.*'); - } - - // Entferne die temporären Daten nach der Auswahl - delete pendingSelections[userId]; - } - } else if (text) { - // Hier kannst du den normalen Nachrichtenverarbeitungsprozess fortsetzen - } -}); - -// Funktion zum Speichern eines Gesprächsverlaufs -function saveChatHistory(userId, userName, message) { - if (!chatHistory[userId]) { - chatHistory[userId] = { [userName]: [] }; - } else if (!chatHistory[userId][userName]) { - chatHistory[userId][userName] = []; - } - chatHistory[userId][userName].push(message); - fs.writeFileSync(chatHistoryFilePath, JSON.stringify(chatHistory, null, 2)); -} - -// Funktion zum Extrahieren von Fragen und Antworten aus Chat-Verlauf -function learnFromChatHistory() { - for (const [userId, userChats] of Object.entries(chatHistory)) { - for (const [userName, messages] of Object.entries(userChats)) { - // Hier können Sie die Logik anpassen, um Fragen und Antworten zu extrahieren - messages.forEach((message, index) => { - // Beispielhafte Logik: Jede zweite Nachricht als Antwort behandeln - if (index % 2 === 0) { - const question = message; - const answer = messages[index + 1] || 'Keine Antwort gefunden'; - const existingReply = autoReplies.find(r => r.question === question); - - if (!existingReply) { - autoReplies.push({ question, answer }); - fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); - } - } - }); - } - } -} - -// Funktion zum Verarbeiten von Nachrichten -bot.on('message', (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text; - - // Speichern des Gesprächsverlaufs - if (admins[userId]) { - saveChatHistory(userId, msg.from.username || msg.from.first_name, text); - } - - // Verarbeite eingehende Nachrichten und sende eine automatische Antwort, wenn eine Frage ähnlich ist - const lowerCaseText = text.toLowerCase(); - - let highestSimilarity = 0; - let bestMatch = null; - - // Verwendet Fuzzy Matching, um ähnliche Fragen zu finden - for (const reply of autoReplies) { - const { question, answer } = reply; - - try { - const similarity = stringSimilarity.compareTwoStrings(lowerCaseText, question.toLowerCase()); - - if (similarity > highestSimilarity) { - highestSimilarity = similarity; - bestMatch = answer; - } - } catch (error) { - console.error('Fehler bei der Textähnlichkeitsberechnung:', error); - } - } - - // Wenn eine hohe Ähnlichkeit festgestellt wurde (z.B. > 0.5), sende die passende Antwort - if (highestSimilarity > 0.5) { - bot.sendMessage(chatId, bestMatch); - } -}); - -// Automatisches Lernen aus Chat-Verlauf regelmäßig ausführen -setInterval(learnFromChatHistory, 24 * 60 * 60 * 1000); // Alle 24 Stunden - -// Verzeichnisse und Dateipfade -const appointmentsFilePath = path.join(dataDir, 'appointments.json'); - -// Sicherstellen, dass das Verzeichnis existiert -if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir, { recursive: true }); -} - -// Sicherstellen, dass die appointments.json-Datei existiert -if (!fs.existsSync(appointmentsFilePath)) { - fs.writeFileSync(appointmentsFilePath, JSON.stringify({})); -} - -// Lädt die Termine aus der appointments.json-Datei -let appointments = {}; -try { - appointments = JSON.parse(fs.readFileSync(appointmentsFilePath, 'utf8')); -} catch (error) { - console.error('Fehler beim Laden der Termine:', error); -} - -// Funktion zum Speichern der Termine -function saveAppointments() { - try { - fs.writeFileSync(appointmentsFilePath, JSON.stringify(appointments, null, 2)); - } catch (error) { - console.error('Fehler beim Speichern der Termine:', error); - } -} - -// Funktion zum Abrufen der Liste der Admins -function listAdmins() { - return Object.keys(admins).map(adminId => { - const admin = admins[adminId]; - const statusIcon = admin.status === 'online' ? '🟢' : '🔴'; - const adminName = admin.name || 'Unbekannt'; - const adminUsername = admin.username ? `@${admin.username}` : 'Unbekannt'; - const adminResponsibility = admin.responsibility || 'Keine Zuständigkeit angegeben'; - - return `• ${statusIcon} ${adminName}\n ${adminUsername}\n 📌 Zuständigkeit: ${adminResponsibility}`; - }).join('\n\n'); -} - -// Funktion zum Formatieren des Datums -function formatDate(date) { - const options = { weekday: 'short', day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; - return date.toLocaleDateString('de-DE', options).replace(',', ''); -} - -// /termin-Befehl zum Vereinbaren eines Chat-Termins -bot.onText(/\/termin/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - const username = msg.from.username || msg.from.first_name; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(chatId, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; // Gesperrte Benutzer können keine Befehle verwenden - } - - if (appointments[userId]) { - bot.sendMessage(chatId, '📅 Du hast bereits einen Termin geplant. Bitte warte auf den nächsten verfügbaren Termin.'); - return; - } - - bot.sendMessage(chatId, '🔍 Wähle einen Admin für den Chat-Termin aus:\n\n' + listAdmins()); - appointments[userId] = { step: 'waiting_for_admin', username }; // Speichere den Benutzernamen - saveAppointments(); -}); - -// Verarbeite die Auswahl des Admins und des Zeitpunkts -bot.on('message', (msg) => { - const userId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text.trim(); - - if (appointments[userId]) { - const appointment = appointments[userId]; - - if (appointment.step === 'waiting_for_admin') { - const adminName = text; - const adminId = Object.keys(admins).find(id => admins[id].name === adminName); - - if (adminId) { - appointment.adminId = adminId; - appointment.step = 'waiting_for_date'; - bot.sendMessage(chatId, '📅 Wähle ein Datum und eine Uhrzeit für den Chat-Termin (im Format YYYY-MM-DD HH:MM):'); - saveAppointments(); - } else { - bot.sendMessage(chatId, '❗ Ungültige Auswahl. Bitte wähle einen Admin aus der Liste aus.'); - } - } else if (appointment.step === 'waiting_for_date') { - const [date, time] = text.split(' '); - const appointmentDate = new Date(`${date}T${time}:00`); - - if (!isNaN(appointmentDate.getTime()) && appointmentDate > new Date()) { - appointment.date = appointmentDate; - appointment.step = 'confirmed'; - const formattedDate = formatDate(appointmentDate); - bot.sendMessage(chatId, '✅ Dein Termin wurde erfolgreich gebucht. Du erhältst Erinnerungen 10 Minuten und 5 Minuten vor Beginn.'); - bot.sendMessage(appointment.adminId, `📅 Du hast einen neuen Chat-Termin mit @${appointment.username} am ${formattedDate}.`); - saveAppointments(); - - // Erinnerungen an beide Parteien - const reminder10Min = appointmentDate - new Date() - 10 * 60 * 1000; - const reminder5Min = appointmentDate - new Date() - 5 * 60 * 1000; - const startTime = appointmentDate - new Date(); - - if (reminder10Min > 0) { - setTimeout(() => { - bot.sendMessage(userId, `⏰ Dein Chat-Termin mit @${admins[appointment.adminId].username} beginnt in 10 Minuten.`); - bot.sendMessage(appointment.adminId, `⏰ Dein Chat-Termin mit @${appointment.username} beginnt in 10 Minuten.`); - }, reminder10Min); - } - - if (reminder5Min > 0) { - setTimeout(() => { - bot.sendMessage(userId, `⏰ Dein Chat-Termin mit @${admins[appointment.adminId].username} beginnt in 5 Minuten.`); - bot.sendMessage(appointment.adminId, `⏰ Dein Chat-Termin mit @${appointment.username} beginnt in 5 Minuten.`); - }, reminder5Min); - } - - if (startTime > 0) { - setTimeout(() => { - bot.sendMessage(userId, `📅 Dein Chat-Termin mit @${admins[appointment.adminId].username} beginnt am ${formattedDate}. Starte den Chat jetzt!`); - bot.sendMessage(appointment.adminId, `📅 Dein Chat-Termin mit @${appointment.username} beginnt am ${formattedDate}. Starte den Chat jetzt!`); - admins[appointment.adminId].status = 'offline'; // Setze den Admin auf offline - saveAppointments(); // Speichere den Status - }, startTime); - } - } else { - bot.sendMessage(chatId, '❗ Ungültiges Datum oder Uhrzeit. Bitte gib ein gültiges Datum und eine gültige Uhrzeit im Format YYYY-MM-DD HH:MM an.'); - } - } - } -}); - -// /my_termine-Befehl für Admins -bot.onText(/\/my_termine/, (msg) => { - const adminId = msg.from.id.toString(); - const chatId = msg.chat.id; - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(adminId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (!admins[adminId]) { - bot.sendMessage(chatId, '❌ Du bist kein Admin und hast keinen Zugriff auf diesen Befehl.'); - return; - } - - const adminAppointments = Object.values(appointments).filter(appointment => appointment.adminId === adminId); - - if (adminAppointments.length > 0) { - let appointmentsList = '📅 Deine kommenden Termine:\n\n'; - adminAppointments.forEach(appointment => { - appointmentsList += `- Mit @${appointment.username} am ${formatDate(new Date(appointment.date))}\n`; - }); - bot.sendMessage(chatId, appointmentsList); - } else { - bot.sendMessage(chatId, '📅 Du hast keine anstehenden Termine.'); - } -}); - -// /cancel_termin-Befehl zum Stornieren eines Termins -bot.onText(/\/cancel_termin/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer einen Termin hat - if (appointments[userId] && appointments[userId].step === 'confirmed') { - const appointment = appointments[userId]; - const formattedDate = formatDate(new Date(appointment.date)); - - // Bestätigungsnachricht für den Benutzer - bot.sendMessage(chatId, `❗ Bist du sicher, dass du deinen Termin mit @${admins[appointment.adminId].username} am ${formattedDate} stornieren möchtest? Antworte mit 'Ja' oder 'Nein'.`); - - // Warten auf Bestätigung der Stornierung - bot.once('message', (confirmationMsg) => { - const confirmationText = confirmationMsg.text.trim().toLowerCase(); - - if (confirmationText === 'ja') { - // Termin stornieren - delete appointments[userId]; - saveAppointments(); // Sicherstellen, dass die Datei aktualisiert wird - - bot.sendMessage(chatId, '✅ Dein Termin wurde erfolgreich storniert.'); - bot.sendMessage(appointment.adminId, `❌ Der Termin mit @${appointment.username} am ${formattedDate} wurde vom Benutzer storniert.`); - } else { - bot.sendMessage(chatId, '❌ Die Stornierung wurde abgebrochen.'); - } - }); - } else { - bot.sendMessage(chatId, '❌ Du hast keinen geplanten Termin, den du stornieren könntest.'); - } -}); - -// Pfad zur Datei, in der die Benutzer-Daten gespeichert werden -const usersFilePath = path.join(dataDir, 'users.json'); - -// Pfad zur Datei, in der die geplanten Nachrichten gespeichert werden -const scheduledMessagesFilePath = path.join(dataDir, 'scheduled_messages.json'); - -// Sicherstellen, dass das Verzeichnis existiert -if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir, { recursive: true }); -} - -// Sicherstellen, dass die Dateien existieren -if (!fs.existsSync(usersFilePath)) { - fs.writeFileSync(usersFilePath, JSON.stringify([])); -} - -if (!fs.existsSync(scheduledMessagesFilePath)) { - fs.writeFileSync(scheduledMessagesFilePath, JSON.stringify([])); -} - -// Lädt die Benutzer-Daten aus der users.json-Datei -let users = []; -try { - users = JSON.parse(fs.readFileSync(usersFilePath, 'utf8')); -} catch (error) { - console.error('Fehler beim Laden der Benutzer-Daten:', error); -} - -// Lädt die geplanten Nachrichten aus der scheduled_messages.json-Datei -let scheduledMessages = []; -try { - scheduledMessages = JSON.parse(fs.readFileSync(scheduledMessagesFilePath, 'utf8')); -} catch (error) { - console.error('Fehler beim Laden der geplanten Nachrichten:', error); -} - -// Funktion zum Speichern der Benutzer-Daten -function saveUsers() { - try { - fs.writeFileSync(usersFilePath, JSON.stringify(users, null, 2)); - } catch (error) { - console.error('Fehler beim Speichern der Benutzer-Daten:', error); - } -} - -// Funktion zum Speichern der geplanten Nachrichten -function saveScheduledMessages() { - try { - fs.writeFileSync(scheduledMessagesFilePath, JSON.stringify(scheduledMessages, null, 2)); - } catch (error) { - console.error('Fehler beim Speichern der geplanten Nachrichten:', error); - } -} - -// Funktion zum Senden des Menüs -const sendMenu = (chatId) => { - const groupName = process.env.GROUP_NAME; - const botName = process.env.BOT_NAME; - - const menuText = `📢 *Willkommen beim SupportBot von ${groupName}*\n\n` + - `Hallo! Wir freuen uns, dass du bei ${groupName} bist. \n\n` + - `Hier kannst du Unterstützung zu verschiedenen Themen erhalten, wie z.B.:\n` + - `- Unsere Links\n` + - `- Häufig gestellte Fragen (FAQ)\n` + - `- Unterstützung durch unseren Support\n` + - `- Und vieles mehr!\n\n` + - `Nutze die Befehle in /help, um mehr über unsere Funktionen zu erfahren und Unterstützung zu erhalten.\n\n` + - `Falls du Fragen hast oder Hilfe benötigst, stehen wir dir jederzeit zur Verfügung.\n\n` + - `Viel Spaß mit dem ${botName}!`; - - const replyMarkup = { - reply_markup: { - inline_keyboard: [ - [ - { text: 'Mehr Hilfe', callback_data: 'more_help' } - ] - ] - } - }; - - bot.sendMessage(chatId, menuText, { parse_mode: 'Markdown', reply_markup: replyMarkup }); -}; - -// Reaktion auf den /start-Befehl -bot.onText(/\/start/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Prüfen, ob der Benutzer gesperrt ist - if (isUserSpammed(userId)) { - bot.sendMessage(chatId, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); - return; - } - - const userName = msg.from.username || `${msg.from.first_name} ${msg.from.last_name}`; - - // Überprüfen, ob die Benutzer-ID bereits gespeichert ist - if (!users.find(user => user.id === userId)) { - users.push({ - id: userId, - name: userName - }); - saveUsers(); - } - - sendMenu(chatId); -}); - -// Reaktion auf Callback-Querys (Button-Klicks) -bot.on('callback_query', (query) => { - const chatId = query.message.chat.id; - const data = query.data; - - if (data === 'more_help') { - // Sende die Hilfe-Nachricht - const helpText = `📚 *Hilfe und Unterstützung*\n\n` + - `Hier findest du Unterstützung für alle verfügbaren Funktionen:\n\n` + - `🔹 /help - Zeigt diese Hilfe-Nachricht an\n` + - `🔗 /links - Zeigt eine Liste der gespeicherten Links an\n` + - `❓ /faq - Zeigt die FAQ an\n` + - `📝 /create_ticket - Reiche ein Support-Ticket ein\n` + - `👥 /admin - Zeigt eine Liste der Admins und deren Status\n` + - `💬 /chat - Fordere einen Chat mit einem Admin an\n` + - `ℹ️ /info - Zeigt Informationen über den Bot an\n` + - `⭐ /rate - Bewerte unseren Support\n` + - `📅 /termin - Mache einen Chat-Termin mit einem Admin\n` + - `🚨 /escalation - Melde ein Problem an alle Admins\n` + - `📜 /terms - Zeigt die Nutzungsbedingungen des Bots an\n` + - `🗑 /cancel_termin - Storniert einen Chat-Termin\n` + - `🔗 /einladung - Erstelle einen Einladungslink für die Gruppe\n` + - `🔗 /einladen - Erstelle einen Einladungslink für die Gruppe` - - bot.sendMessage(chatId, helpText, { parse_mode: 'Markdown' }); - } - - // Optionale Bestätigung der Callback-Query - bot.answerCallbackQuery(query.id); -}); - -// Speichert den aktuellen Status des Benutzers für die Nachrichteneinstellung -let userStatus = {}; - -// Befehl zum Starten der Nachrichtplanung -bot.onText(/\/schedule_message/, (msg) => { - const chatId = msg.chat.id; - const adminId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(adminId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfen, ob der Benutzer ein autorisierter Admin ist - if (!admins[adminId]) { - bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); - return; - } - - userStatus[adminId] = { step: 'waiting_for_date', chatId }; - bot.sendMessage(chatId, '📅 Gib das Datum und die Uhrzeit für die geplante Nachricht im Format YYYY-MM-DD HH:MM an:'); -}); - -// Verarbeitet die Eingabe des Datums und der Uhrzeit -bot.on('message', (msg) => { - const adminId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text.trim(); - - if (userStatus[adminId]) { - const status = userStatus[adminId]; - - if (status.step === 'waiting_for_date') { - const [date, time] = text.split(' '); - const scheduledDate = new Date(`${date}T${time}:00`); - - if (!isNaN(scheduledDate.getTime()) && scheduledDate > new Date()) { - status.date = scheduledDate; - status.step = 'waiting_for_message'; - bot.sendMessage(chatId, '📝 Gib die Nachricht ein, die du planen möchtest:'); - } else { - bot.sendMessage(chatId, '❗ Ungültiges Datum oder Uhrzeit. Bitte gib ein gültiges Datum und eine gültige Uhrzeit im Format YYYY-MM-DD HH:MM an.'); - } - } else if (status.step === 'waiting_for_message') { - const message = text; - const scheduledDate = status.date; - scheduledMessages.push({ - adminId, - message, - dateTime: scheduledDate.toISOString() - }); - saveScheduledMessages(); - bot.sendMessage(chatId, `✅ Deine Nachricht wurde für ${formatDate(scheduledDate)} geplant.`); - delete userStatus[adminId]; // Status zurücksetzen - } - } -}); - -// Funktion zum Formatieren des Datums -function formatDate(date) { - const options = { weekday: 'short', day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; - return date.toLocaleDateString('de-DE', options).replace(',', ''); -} - -// Verarbeite geplante Nachrichten -cron.schedule('* * * * *', () => { // Jede Minute überprüfen - const now = new Date().toISOString(); - scheduledMessages.forEach((scheduledMessage, index) => { - if (new Date(scheduledMessage.dateTime) <= new Date()) { - users.forEach(user => { - bot.sendMessage(user.id, scheduledMessage.message); - }); - scheduledMessages.splice(index, 1); // Entferne gesendete Nachricht - saveScheduledMessages(); - } - }); -}); - -// Verarbeitet neue Benutzerinteraktionen (fängt alle neuen Benutzer auf) -bot.on('new_chat_members', (msg) => { - const chatId = msg.chat.id; - const newMembers = msg.new_chat_members; - - newMembers.forEach((member) => { - const userId = member.id.toString(); - const userName = member.username || `${member.first_name} ${member.last_name}`; - - // Überprüfen, ob der Benutzer bereits gespeichert ist - if (!users.find(user => user.id === userId)) { - users.push({ - id: userId, - name: userName - }); - saveUsers(); - } - }); -}); - -// Funktion zum Senden der Nutzungsbedingungen -const sendTerms = (chatId) => { - const termsText = `📜 *Nutzungsbedingungen*\n\n` + - `Hier sind die Nutzungsbedingungen für die Nutzung unseres Bots:\n\n` + - `1. Du verpflichtest dich, die Dienste des Bots gemäß den geltenden Gesetzen zu nutzen.\n` + - `2. Missbrauch des Bots, einschließlich Spam oder andere unangemessene Aktivitäten, ist untersagt.\n` + - `3. Der Bot speichert keine persönlichen Daten ohne deine Zustimmung.\n` + - `4. Bei Fragen oder Problemen wende dich bitte an unseren Support.\n\n` + - `Bitte halte dich an diese Bedingungen, um einen reibungslosen Service zu gewährleisten.`; - - bot.sendMessage(chatId, termsText, { parse_mode: 'Markdown' }); -}; - -// Reaktion auf den /terms-Befehl -bot.onText(/\/terms/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Sende die Nutzungsbedingungen an den Benutzer - sendTerms(chatId); -}); - -// Funktion zum Überprüfen, ob ein Benutzer ein Admin ist -const isAdmin = (userId) => { - return admins[userId.toString()] !== undefined; -}; - -// Speichert den aktuellen Status des Admins für den /pin_message-Befehl -let pinMessageStatus = {}; - -// Reaktion auf den /pin_message-Befehl -bot.onText(/\/pin_message/, (msg) => { - const chatId = msg.chat.id; - const adminId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(adminId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfen, ob der Benutzer ein Admin ist - if (!isAdmin(adminId)) { - bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); - return; - } - - // Status auf "wartet auf Nachricht" setzen - pinMessageStatus[adminId] = { chatId, step: 'waiting_for_message' }; - bot.sendMessage(chatId, '📝 Bitte gib die Nachricht ein, die du anheften möchtest:'); -}); - -// Verarbeitet die Nachrichteneingabe -bot.on('message', (msg) => { - const adminId = msg.from.id.toString(); - const chatId = msg.chat.id; - const text = msg.text.trim(); - - // Überprüfen, ob der Admin eine Nachricht senden soll - if (pinMessageStatus[adminId] && pinMessageStatus[adminId].chatId === chatId) { - if (pinMessageStatus[adminId].step === 'waiting_for_message') { - // Nachricht senden und anheften - bot.sendMessage(chatId, text, { reply_markup: { remove_keyboard: true } }) - .then((sentMessage) => { - bot.pinChatMessage(chatId, sentMessage.message_id) - .then(() => { - bot.sendMessage(chatId, '✅ Die Nachricht wurde erfolgreich angeheftet.'); - }) - .catch(error => bot.sendMessage(chatId, `❗ Fehler beim Anheften der Nachricht: ${error.message}`)); - }) - .catch(error => bot.sendMessage(chatId, `❗ Fehler beim Senden der Nachricht: ${error.message}`)); - - // Status zurücksetzen - delete pinMessageStatus[adminId]; - } - } -}); - -const spammedUsersFile = path.join(dataDir, 'spammed_users.json'); -const usersFile = path.join(dataDir, 'users.json'); // Pfad zur users.json - -// Prüfe, ob der Ordner und die Dateien existieren, und erstelle sie, falls nicht -if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir); -} - -if (!fs.existsSync(spammedUsersFile)) { - fs.writeFileSync(spammedUsersFile, JSON.stringify({}), 'utf8'); -} - -if (!fs.existsSync(usersFile)) { - fs.writeFileSync(usersFile, JSON.stringify([]), 'utf8'); // Leere Liste, wenn users.json nicht existiert -} - -// Funktion zum Laden der gesperrten Benutzer aus der Datei -const loadSpammedUsers = () => { - const data = fs.readFileSync(spammedUsersFile, 'utf8'); - return JSON.parse(data); -}; - -// Funktion zum Speichern der gesperrten Benutzer in der Datei -const saveSpammedUsers = (spammedUsers) => { - fs.writeFileSync(spammedUsersFile, JSON.stringify(spammedUsers, null, 2), 'utf8'); -}; - -// Funktion zum Laden der Benutzer aus der users.json-Datei -const loadUsers = () => { - const data = fs.readFileSync(usersFile, 'utf8'); - return JSON.parse(data); -}; - -let spammedUsers = loadSpammedUsers(); // Gesperrte Benutzer laden - -// Liste der verfügbaren Sperrzeiten -const timeOptions = { - '30 Minuten': 30 * 60 * 1000, - '1 Stunde': 60 * 60 * 1000, - '2 Stunden': 2 * 60 * 60 * 1000, - '3 Stunden': 3 * 60 * 60 * 1000, - '4 Stunden': 4 * 60 * 60 * 1000, - '5 Stunden': 5 * 60 * 60 * 1000, - '24 Stunden': 24 * 60 * 60 * 1000, - 'Permanent': 'permanent' -}; - -let spamStep = {}; // Speichert den Fortschritt des /spam Befehls - -// Funktion, um zu überprüfen, ob ein Benutzer gesperrt ist -const isUserSpammed = (userId) => { - if (spammedUsers[userId]) { - const { expiry } = spammedUsers[userId]; - if (expiry === 'permanent' || expiry > Date.now()) { - return true; - } else { - // Sperre ist abgelaufen, Benutzer entsperren - delete spammedUsers[userId]; - saveSpammedUsers(spammedUsers); - return false; - } - } - return false; -}; - -// Funktion, um eine lesbare Uhrzeit zu generieren -const formatTime = (timestamp) => { - const date = new Date(timestamp); - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - const day = date.getDate().toString().padStart(2, '0'); - const month = (date.getMonth() + 1).toString().padStart(2, '0'); - const year = date.getFullYear(); - return `${hours}:${minutes} Uhr, am ${day}.${month}.${year}`; -}; - -// Reaktion auf den /spam-Befehl (Start) -bot.onText(/\/spam/, (msg) => { - const chatId = msg.chat.id; - const adminId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(adminId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfen, ob der Benutzer ein Admin ist - if (!isAdmin(adminId)) { - bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); - return; - } - - // Frage nach dem Benutzernamen - spamStep[chatId] = { step: 'askUser' }; // Setzt den nächsten Schritt - bot.sendMessage(chatId, 'Bitte gib den Benutzernamen ein (@Name):'); -}); - -// Antwort auf die Eingabe des Benutzernamens -bot.on('message', (msg) => { - const chatId = msg.chat.id; - - if (spamStep[chatId]) { - const currentStep = spamStep[chatId].step; - - if (currentStep === 'askUser') { - const username = msg.text.trim().replace('@', ''); // Entferne das @-Zeichen - - // Benutzer in der users.json anhand des Namens finden - const targetUser = users.find(user => user.name.toLowerCase() === username.toLowerCase()); - - if (!targetUser) { - bot.sendMessage(chatId, `❌ Benutzer ${username} nicht gefunden. Bitte erneut versuchen.`); - return; - } - - spamStep[chatId].targetUser = targetUser; - spamStep[chatId].step = 'askTime'; // Nächster Schritt - bot.sendMessage(chatId, 'Wähle die Sperrdauer aus:', { - reply_markup: { - inline_keyboard: [ - [{ text: '30 Minuten', callback_data: '30 Minuten' }], - [{ text: '1 Stunde', callback_data: '1 Stunde' }], - [{ text: '2 Stunden', callback_data: '2 Stunden' }], - [{ text: '3 Stunden', callback_data: '3 Stunden' }], - [{ text: '4 Stunden', callback_data: '4 Stunden' }], - [{ text: '5 Stunden', callback_data: '5 Stunden' }], - [{ text: '24 Stunden', callback_data: '24 Stunden' }], - [{ text: 'Permanent', callback_data: 'Permanent' }] - ] - } - }); - } - } -}); - -// Reaktion auf die Zeit-Auswahl -bot.on('callback_query', (query) => { - const chatId = query.message.chat.id; - const selectedTime = query.data; - - if (spamStep[chatId] && spamStep[chatId].step === 'askTime') { - const targetUser = spamStep[chatId].targetUser; - - if (!timeOptions[selectedTime]) { - bot.sendMessage(chatId, '❌ Ungültige Zeitangabe.'); - return; - } - - const timeDuration = timeOptions[selectedTime]; - const targetUserId = targetUser.id; - - // Benutzer sperren - const expiryTime = timeDuration === 'permanent' ? 'permanent' : Date.now() + timeDuration; - spammedUsers[targetUserId] = { expiry: expiryTime }; - - saveSpammedUsers(spammedUsers); // Gesperrte Benutzer speichern - - let successMessage; - - if (timeDuration === 'permanent') { - successMessage = `✅ Benutzer @${targetUser.name} wurde dauerhaft gesperrt.`; - } else { - const formattedTime = formatTime(expiryTime); - successMessage = `✅ Benutzer @${targetUser.name} wurde bis ${formattedTime} gesperrt.`; - } - - bot.sendMessage(chatId, successMessage); - - // Bereinige den Schritt - delete spamStep[chatId]; - } -}); - -// Reaktion auf den /unspam-Befehl (Start) -bot.onText(/\/unspam/, (msg) => { - const chatId = msg.chat.id; - const adminId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(adminId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - // Überprüfen, ob der Benutzer ein Admin ist - if (!isAdmin(adminId)) { - bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); - return; - } - - // Frage nach dem Benutzernamen - bot.sendMessage(chatId, 'Bitte gib den Benutzernamen des zu entsperrenden Benutzers ein (@Name):'); - - // Speichert den Schritt zur Entsperrung - spamStep[chatId] = { step: 'askUserToUnspam' }; -}); - -// Reaktion auf die Eingabe des Benutzernamens für die Entsperrung -bot.on('message', (msg) => { - const chatId = msg.chat.id; - - if (spamStep[chatId] && spamStep[chatId].step === 'askUserToUnspam') { - const username = msg.text.trim().replace('@', ''); // Entferne das @-Zeichen - - // Benutzer in der users.json anhand des Namens finden - const users = loadUsers(); // Lädt alle Benutzer - const targetUser = users.find(user => user.name.toLowerCase() === username.toLowerCase()); - - if (!targetUser) { - bot.sendMessage(chatId, `❌ Benutzer ${username} nicht gefunden. Bitte erneut versuchen.`); - return; - } - - const targetUserId = targetUser.id; - - // Überprüfen, ob der Benutzer gesperrt ist - if (!isUserSpammed(targetUserId)) { - bot.sendMessage(chatId, `❌ Benutzer @${targetUser.name} ist nicht gesperrt.`); - } else { - // Benutzer entsperren - delete spammedUsers[targetUserId]; - saveSpammedUsers(spammedUsers); // Gesperrte Benutzer aktualisieren - - bot.sendMessage(chatId, `✅ Benutzer @${targetUser.name} wurde erfolgreich entsperrt.`); - } - - // Bereinige den Schritt - delete spamStep[chatId]; - } -}); - - -// Funktion zum Senden der Nachricht an alle Admins -const notifyAdmins = (message) => { - if (Array.isArray(admins)) { - admins.forEach(adminId => { - bot.sendMessage(adminId, message).catch(error => { - console.error(`Fehler beim Senden der Nachricht an Admin ${adminId}:`, error); - }); - }); - } else { - console.error('Admins-Variable ist kein Array:', admins); - } -}; - -// Funktion zum Senden der Nachricht an alle Admins -const notifyAllAdmins = (message) => { - Object.keys(admins).forEach(adminId => { - bot.sendMessage(adminId, `🚨 *WICHTIG:* Ein Benutzer hat ein Problem gemeldet:\n\n${message}`, { parse_mode: 'Markdown' }); - }); -}; - -// Reaktion auf den /escalation-Befehl -bot.onText(/\/escalation/, (msg) => { - const chatId = msg.chat.id; - const userId = msg.from.id.toString(); - - // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann - if (!canExecuteCommand(userId)) { - bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); - return; - } - - if (isUserSpammed(userId)) { - bot.sendMessage(chatId, '❌ Du wurdest gesperrt und kannst diesen Befehl nicht verwenden.'); - return; - } - - // Frage nach dem Problem - bot.sendMessage(chatId, 'Bitte beschreibe dein Problem:'); - spamStep[chatId] = { step: 'askProblem' }; -}); - -// Antwort auf die Eingabe des Problems -bot.on('message', (msg) => { - const chatId = msg.chat.id; - - if (spamStep[chatId]) { - const currentStep = spamStep[chatId].step; - - if (currentStep === 'askProblem') { - const problemDescription = msg.text.trim(); - - // Nachricht an alle Admins senden - notifyAllAdmins(problemDescription); - - bot.sendMessage(chatId, '✅ Dein Problem wurde an alle Admins weitergeleitet.'); - - // Bereinige den Schritt - delete spamStep[chatId]; - } - } -}); - - - - - - - - - - - - - - - - - - - - +require('dotenv').config(); +const TelegramBot = require('node-telegram-bot-api'); +const fs = require('fs'); +const path = require('path'); +const nodemailer = require('nodemailer'); +const stringSimilarity = require('string-similarity'); +const cron = require('node-cron'); +const axios = require('axios'); +const botStartTime = new Date(); // Startzeitpunkt des Bots + +// Token aus der .env-Datei laden +const token = process.env.BOT_TOKEN; +const bot = new TelegramBot(token, { polling: true }); + + +// Admins aus der .env-Datei laden und als Objekt speichern (ID -> {Name, Username, Zuständigkeit}, in der Reihenfolge) +const admins = process.env.ADMINS.split(',').reduce((acc, admin) => { + const [id, name, username, responsibility] = admin.split(':').map(val => val.trim()); + acc[id] = { name, username, responsibility }; + return acc; +}, {}); + +// Admin-IDs in der Reihenfolge speichern +const orderedAdminIds = Object.keys(admins); + +// Admin-Status-Objekt (speichert den Status jedes Admins) +let adminStatus = {}; + +// Initialen Status aller Admins auf "offline" setzen +Object.keys(admins).forEach(adminId => { + adminStatus[adminId] = 'offline'; +}); + +// Warteschlange für Benutzeranfragen +let requestQueue = []; + +// FAQ-Dateipfad +const dataDir = path.join(__dirname, 'data'); +const faqFilePath = path.join(dataDir, 'faq.json'); + +// Sicherstellen, dass das Verzeichnis existiert +if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); +} + +// Sicherstellen, dass die FAQ-Datei existiert +if (!fs.existsSync(faqFilePath)) { + fs.writeFileSync(faqFilePath, JSON.stringify([])); +} + +// FAQ-Daten laden +let faqData = JSON.parse(fs.readFileSync(faqFilePath, 'utf8')); + +// Pfad zur link.json +const linksFilePath = path.join(dataDir, 'link.json'); + +// Sicherstellen, dass die link.json existiert +if (!fs.existsSync(linksFilePath)) { + fs.writeFileSync(linksFilePath, JSON.stringify([])); +} + +// Links-Daten laden +let linksData = JSON.parse(fs.readFileSync(linksFilePath, 'utf8')); + +// Bewertungsdaten +const ratingsFilePath = path.join(dataDir, 'ratings.json'); + +// Sicherstellen, dass die ratings.json existiert +if (!fs.existsSync(ratingsFilePath)) { + fs.writeFileSync(ratingsFilePath, JSON.stringify([])); +} + +// Ratings-Daten laden +let ratingsData = JSON.parse(fs.readFileSync(ratingsFilePath, 'utf8')); + +// Funktion zum Überprüfen der Admin-Rechte in einer Gruppe +const checkBotAdminRights = async (chatId) => { + try { + const botId = await getBotId(); // Funktion zur Ermittlung der Bot-ID + const botInfo = await bot.getChatMember(chatId, botId); + + if (botInfo.status !== 'administrator' && botInfo.status !== 'creator') { + // Falls der Bot keine Admin-Rechte hat + const devId = process.env.DEV; + bot.sendMessage(devId, `❗ Der Bot benötigt Admin-Rechte in der Gruppe ${chatId}. Bitte gewähre Admin-Rechte oder überprüfe die Gruppeneinstellungen.`); + } + } catch (error) { + console.error('Error checking bot admin rights:', error); + } +}; + +// Funktion zur Ermittlung der Bot-ID +const getBotId = async () => { + try { + const botInfo = await bot.getMe(); + return botInfo.id; // Rückgabe der Bot-ID + } catch (error) { + console.error('Error getting bot ID:', error); + return null; // Rückgabe von null, falls ein Fehler auftritt + } +}; + +// Überprüfen aller Gruppen, in denen der Bot Mitglied ist +const checkAllGroupsAdminRights = async () => { + try { + const updates = await bot.getUpdates(); + const chatIds = new Set(); + + updates.forEach(update => { + if (update.message && update.message.chat && update.message.chat.id) { + chatIds.add(update.message.chat.id); // Alle Gruppen-IDs sammeln + } + }); + + chatIds.forEach(chatId => { + checkBotAdminRights(chatId); // Admin-Rechte für jede Gruppe überprüfen + }); + } catch (error) { + console.error('Error checking all group admin rights:', error); + } +}; + +// Auf Updates vom Bot hören +bot.on('message', async (msg) => { + const chatId = msg.chat.id; + + // Beispiel-Nachricht, wenn der Bot in einer neuen Gruppe hinzugefügt wird + if (msg.new_chat_members) { + console.log(`Bot joined new chat: ${chatId}`); + checkBotAdminRights(chatId); + } +}); + +const reportFilePath = path.join(dataDir, 'nachrichten_report.json'); +if (!fs.existsSync(reportFilePath)) { + fs.writeFileSync(reportFilePath, JSON.stringify([])); +} + +let reportsData = JSON.parse(fs.readFileSync(reportFilePath, 'utf8')); + +// Funktion zum Bereinigen der Meldedaten +const cleanReportData = (report) => { + return { + userId: report.userId, + userName: report.userName, + authorName: report.authorName, // Verfasser der gemeldeten Nachricht + message: report.message, + timestamp: report.timestamp, + handled: report.handled + }; +}; + +// Funktion zum Speichern von gemeldeten Nachrichten +const saveReport = (report) => { + reportsData.push(cleanReportData(report)); + fs.writeFileSync(reportFilePath, JSON.stringify(reportsData, null, 2)); +}; + +// Funktion zum Finden des nächsten online Admins +const findNextOnlineAdmin = () => { + return orderedAdminIds.find(adminId => adminStatus[adminId] === 'online'); +}; + +// Funktion zum Senden von Warteschlangen-Nachrichten an den nächsten online Admin +const sendQueuedReportsToAdmin = (adminId) => { + const adminReports = reportsData.filter(report => !report.handled); + adminReports.forEach(report => { + bot.sendMessage(adminId, `📩 *Eine Nachricht wurde gemeldet:*\n\nMelder: @${report.userName}\nVerfasser: @${report.authorName}\n\n"${report.message}"`); + report.handled = true; // Markiere die Nachricht als bearbeitet + }); + fs.writeFileSync(reportFilePath, JSON.stringify(reportsData, null, 2)); // Speichern der aktualisierten Daten +}; + +// Befehl zum Melden von Nachrichten +bot.onText(/\/report/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id; + bot.sendMessage(chatId, 'Bitte wähle eine Nachricht aus der Gruppe, die du melden möchtest, indem du auf die Nachricht antwortest.'); + + bot.once('message', async (reportMsg) => { + if (reportMsg.chat.id === chatId && reportMsg.reply_to_message && reportMsg.reply_to_message.text) { + const adminId = findNextOnlineAdmin(); + const report = { + userId: userId, + userName: msg.from.username, // Melder der Nachricht + authorName: reportMsg.reply_to_message.from.username || 'Unbekannt', // Verfasser der gemeldeten Nachricht + message: reportMsg.reply_to_message.text, + timestamp: new Date().toISOString(), + handled: false // Neue Eigenschaft, um zu verfolgen, ob die Nachricht bearbeitet wurde + }; + saveReport(report); + + if (adminId) { + bot.sendMessage(adminId, `📩 *Eine Nachricht wurde gemeldet:*\n\nMelder: @${report.userName}\nVerfasser: @${report.authorName}\n\n"${report.message}"`); + bot.sendMessage(chatId, 'Vielen Dank! Die ausgewählte Nachricht wurde gemeldet und an einen Admin weitergeleitet.'); + } else { + bot.sendMessage(chatId, 'Momentan sind keine Admins online. Deine Meldung wird gespeichert und einem Admin gesendet, sobald dieser online kommt.'); + } + } else { + bot.sendMessage(chatId, 'Die Nachricht konnte nicht gefunden werden oder sie ist leer.'); + } + }); +}); + +// Admins können ihren Status mit /online ändern +bot.onText(/\/online/, async (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + + if (admins[adminId]) { + adminStatus[adminId] = 'online'; + bot.sendMessage(adminId, `🟢 *Du bist jetzt als "online" markiert, ${admins[adminId].name}!*`); + + const onlineStatusMessage = `🟢 Admin @${admins[adminId].name} ist online`; + try { + const sentMessage = await bot.sendMessage(chatId, onlineStatusMessage); + pinnedMessageId = sentMessage.message_id; + await bot.pinChatMessage(chatId, pinnedMessageId); + } catch (error) { + bot.sendMessage(chatId, `❗ Fehler beim Senden oder Anheften der Nachricht: ${error.message}`); + } + + // Sende alle gespeicherten Meldungen an den jetzt online gegangenen Admin + sendQueuedReportsToAdmin(adminId); + } else { + bot.sendMessage(adminId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Admins können ihren Status mit /offline ändern +bot.onText(/\/offline/, async (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + + if (admins[adminId]) { + adminStatus[adminId] = 'offline'; + bot.sendMessage(adminId, `🔴 *Du bist jetzt als "offline" markiert, ${admins[adminId].name}.*`); + + if (pinnedMessageId !== null) { + try { + await bot.unpinChatMessage(chatId); // Kein message_id erforderlich, entpinnt alle angehefteten Nachrichten + pinnedMessageId = null; // Setze die ID auf null, nachdem die Nachricht entfernt wurde + } catch (error) { + bot.sendMessage(chatId, `❗ Fehler beim Entfernen der angehefteten Nachricht: ${error.message}`); + } + } + } else { + bot.sendMessage(adminId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Cron-Job: Setze alle Admins um Mitternacht auf offline +cron.schedule('0 0 * * *', () => { + Object.keys(admins).forEach(adminId => { + if (adminStatus[adminId] === 'online') { + adminStatus[adminId] = 'offline'; + bot.sendMessage(adminId, `🔴 Du wurdest um 00:00 Uhr automatisch offline gesetzt, ${admins[adminId].name}.`); + } + }); + console.log("Alle Admins wurden um 00:00 Uhr auf offline gesetzt."); +}); + +// Initiale Überprüfung der Admin-Rechte in allen Gruppen +checkAllGroupsAdminRights(); + +bot.onText(/\/links/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Sperrte Benutzer können keine Befehle verwenden + } + + // Sicherstellen, dass linksData existiert und ein Array ist + if (!Array.isArray(linksData)) { + bot.sendMessage(chatId, '❗ Ein Fehler ist aufgetreten.') + .then(() => bot.deleteMessage(chatId, msg.message_id)); + return; + } + + // Links formatieren + const links = linksData.map((link, index) => { + return `${index + 1}. ${link.title}: ${link.url}`; + }).join('\n'); + + // Links dem Benutzer senden, ohne Linkvorschau + bot.sendMessage(userId, `🌐 Gespeicherte Links:\n\n${links}`, { + disable_web_page_preview: true // Deaktiviert die Linkvorschau + }).then(() => bot.deleteMessage(chatId, msg.message_id)); +}); + +bot.onText(/\/add_links/, (msg) => { + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, `🔧 Bitte sende den Titel des Links:`) + .then(() => bot.once('message', async (titleMsg) => { + const title = titleMsg.text.trim(); + bot.sendMessage(userId, `🔧 Bitte sende die URL des Links:`) + .then(() => bot.once('message', async (urlMsg) => { + const url = urlMsg.text.trim(); + + if (title && url) { + linksData.push({ title, url }); + fs.writeFileSync(linksFilePath, JSON.stringify(linksData, null, 2)); + bot.sendMessage(userId, `✅ Link hinzugefügt.`) + .then(() => { + bot.deleteMessage(userId, titleMsg.message_id); + bot.deleteMessage(userId, urlMsg.message_id); + }); + } else { + bot.sendMessage(userId, `❌ Bitte stelle sicher, dass du sowohl Titel als auch URL eingibst.`); + } + })); + })); + } else { + bot.sendMessage(userId, '❗ Nur Admins können diesen Befehl verwenden.') + .then(() => bot.deleteMessage(userId, msg.message_id)); + } +}); + +bot.onText(/\/del_links/, (msg) => { + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, `🗑️ Bitte sende die Nummer des Links, den du löschen möchtest:`) + .then(() => bot.once('message', async (linkMsg) => { + const linkIndex = parseInt(linkMsg.text, 10) - 1; + + if (linkIndex >= 0 && linkIndex < linksData.length) { + linksData.splice(linkIndex, 1); + fs.writeFileSync(linksFilePath, JSON.stringify(linksData, null, 2)); + bot.sendMessage(userId, `✅ Link gelöscht.`) + .then(() => bot.deleteMessage(userId, linkMsg.message_id)); + } else { + bot.sendMessage(userId, `❌ Ungültige Link-Nummer.`); + } + })); + } else { + bot.sendMessage(userId, '❗ Nur Admins können diesen Befehl verwenden.') + .then(() => bot.deleteMessage(userId, msg.message_id)); + } +}); + +// Pfad zur "inviteLinks.json"-Datei für Einladungslinks +const inviteLinksFile = path.join(dataDir, 'inviteLinks.json'); + +// Sicherstellen, dass die "inviteLinks.json"-Datei existiert +if (!fs.existsSync(inviteLinksFile)) { + fs.writeFileSync(inviteLinksFile, JSON.stringify({})); +} + +// Funktion zum Laden der Einladungslinks aus der Datei +function loadInviteLinks() { + if (fs.existsSync(inviteLinksFile)) { + const data = fs.readFileSync(inviteLinksFile); + return JSON.parse(data); + } + return {}; +} + +// Funktion zum Speichern der Einladungslinks in der Datei +function saveInviteLinks() { + fs.writeFileSync(inviteLinksFile, JSON.stringify(inviteLinks, null, 2)); +} + +// Objekt zur Speicherung von Einladungslinks (wird aus der Datei geladen) +let inviteLinks = loadInviteLinks(); + +// /einladung-Befehl für alle Benutzer +bot.onText(/\/einladung/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + const userName = msg.from.username || `${msg.from.first_name} ${msg.from.last_name}`; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer bereits einen Einladungslink erstellt hat + if (inviteLinks[userId]) { + const existingLink = inviteLinks[userId].link; + bot.sendMessage(userId, `🔗 Du hast bereits einen Einladungslink erstellt: ${existingLink}`); + return; + } + + // Erstelle einen neuen Einladungslink für die Gruppe + bot.createChatInviteLink(chatId) + .then((inviteLink) => { + // Speichern des Einladungslinks und der Informationen über den Ersteller + inviteLinks[userId] = { + link: inviteLink.invite_link, // invite_link enthält den eigentlichen Link + createdBy: userName, + createdAt: new Date().toLocaleString() + }; + + // Links in der Datei speichern + saveInviteLinks(); + + // Den Einladungslink privat an den Benutzer senden + bot.sendMessage(userId, `🔗 Hier ist dein Einladungslink: ${inviteLink.invite_link}`); + + // Protokollierung, wer wann den Einladungslink erstellt hat + console.log(`Einladungslink erstellt von ${userName} (ID: ${userId}) am ${inviteLinks[userId].createdAt}`); + }) + .catch((error) => { + console.error('Fehler beim Erstellen des Einladungslinks:', error); + bot.sendMessage(userId, '❗ Es gab ein Problem beim Erstellen des Einladungslinks.'); + }); +}); + +// Befehl zum Löschen der letzten n Nachrichten +bot.onText(/\/clear (\d+)/, async (msg, match) => { + const chatId = msg.chat.id; + const userId = msg.from.id; + const numMessagesToDelete = parseInt(match[1], 10); // Die Anzahl der zu löschenden Nachrichten + + // Überprüfen, ob der Benutzer ein Admin ist + if (admins[userId]) { + try { + // Erhalte die ID der Nachricht, ab der Nachrichten gelöscht werden sollen + const fromMessageId = msg.message_id; + + // Löschen der letzten `n` Nachrichten + for (let i = 0; i < numMessagesToDelete; i++) { + const messageIdToDelete = fromMessageId - i; + try { + await bot.deleteMessage(chatId, messageIdToDelete); + } catch (error) { + console.error(`Fehler beim Löschen der Nachricht ${messageIdToDelete}:`, error); + } + } + + // Bestätigung, dass die Nachrichten gelöscht wurden + bot.sendMessage(chatId, `🗑️ Es wurden ${numMessagesToDelete} Nachrichten gelöscht.`); + } catch (error) { + console.error('Fehler beim Löschen der Nachrichten:', error); + bot.sendMessage(chatId, '❗ Es gab ein Problem beim Löschen der Nachrichten.'); + } + } else { + bot.sendMessage(chatId, '❗ Nur Admins dürfen diesen Befehl verwenden.'); + } +}); + +// Reaktion auf den /pin_message-Befehl +bot.onText(/\/pin_message/, (msg) => { + const chatId = msg.chat.id; + const adminId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(adminId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfen, ob der Benutzer ein Admin ist + if (!isAdmin(adminId)) { + bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); + return; + } + + // Status auf "wartet auf Nachricht" setzen + pinMessageStatus[adminId] = { chatId, step: 'waiting_for_message' }; + bot.sendMessage(chatId, '📝 Bitte gib die Nachricht ein, die du anheften möchtest:'); +}); + +// Verarbeitet die Nachrichteneingabe +bot.on('message', (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text.trim(); + + // Überprüfen, ob der Admin eine Nachricht senden soll + if (pinMessageStatus[adminId] && pinMessageStatus[adminId].chatId === chatId) { + if (pinMessageStatus[adminId].step === 'waiting_for_message') { + // Nachricht senden und anheften + bot.sendMessage(chatId, text, { reply_markup: { remove_keyboard: true } }) + .then((sentMessage) => { + bot.pinChatMessage(chatId, sentMessage.message_id) + .then(() => { + bot.sendMessage(chatId, '✅ Die Nachricht wurde erfolgreich angeheftet.'); + }) + .catch(error => bot.sendMessage(chatId, `❗ Fehler beim Anheften der Nachricht: ${error.message}`)); + }) + .catch(error => bot.sendMessage(chatId, `❗ Fehler beim Senden der Nachricht: ${error.message}`)); + + // Status zurücksetzen + delete pinMessageStatus[adminId]; + } + } +}); + +bot.onText(/\/admin/, (msg) => { + const userId = msg.from.id; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Sperrte Benutzer können keine Befehle verwenden + } + + const sortedAdminIds = orderedAdminIds.sort((a, b) => a === '5507179337' ? -1 : b === '5507179337' ? 1 : 0); + + const adminList = sortedAdminIds.map(adminId => { + const statusIcon = adminStatus[adminId] === 'online' ? '🟢' : '🔴'; + const adminName = admins[adminId].name; + const adminUsername = admins[adminId].username.replace(/_/g, '\\_'); // Escape Unterstriche + const adminResponsibility = admins[adminId].responsibility || 'Keine Zuständigkeit angegeben'; + return `• ${statusIcon} *${adminName}*\n _@${adminUsername}_\n 📌 _Zuständigkeit:_ ${adminResponsibility}`; + }).join('\n\n'); + + bot.sendMessage(userId, `👮 *Liste der Admins:* 👮\n\n${adminList}`, { parse_mode: 'MarkdownV2' }) + .catch(error => { + console.error('Fehler beim Senden der Admin-Liste:', error); + }); +}); + +// Temporäre Speicherung der message_id +const commandMessages = {}; + +bot.onText(/\/chat/, async (msg) => { + const userId = msg.from.id; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Sperrte Benutzer können keine Befehle verwenden + } + + const userName = msg.from.username ? `@${msg.from.username}` : `Benutzer ${msg.from.first_name}`; + + // Speichern der message_id + commandMessages[userId] = commandMessages[userId] || {}; + commandMessages[userId]['/chat'] = msg.message_id; + + const onlineAdmins = orderedAdminIds.filter(adminId => adminStatus[adminId] === 'online'); + + if (onlineAdmins.length > 0) { + const options = { + reply_markup: { + inline_keyboard: onlineAdmins.map(adminId => [{ + text: `${adminStatus[adminId] === 'online' ? '🟢' : '🔴'} ${admins[adminId].name}`, + callback_data: adminId + }]) + } + }; + + bot.sendMessage(userId, "💬 *Wähle einen Admin aus, um Unterstützung zu erhalten:*", options) + .then(() => bot.deleteMessage(msg.chat.id, msg.message_id)); + } else { + bot.sendMessage(userId, "🔴 *Derzeit ist kein Admin online. Bitte schreibe dein Problem, und wir werden dich kontaktieren, sobald ein Admin verfügbar ist.*"); + bot.once('message', (userMsg) => { + const requestMessage = userMsg.text; + requestQueue.push({ userId, userName, message: requestMessage, handled: false }); + bot.sendMessage(userId, "✉️ *Deine Anfrage wurde an das Support-Team weitergeleitet.*"); + }); + } +}); + +// Reaktion auf die Auswahl eines Admins +bot.on('callback_query', async (callbackQuery) => { + const adminId = callbackQuery.data; // ID des ausgewählten Admins + const userId = callbackQuery.from.id; // ID des Anfragenden Benutzers + const userName = callbackQuery.from.username ? `@${callbackQuery.from.username}` : `Benutzer ${callbackQuery.from.first_name}`; + + if (adminStatus[adminId] === 'offline') { + bot.sendMessage(userId, "🔴 *Dieser Admin ist zur Zeit nicht online. Du kannst dein Problem schriftlich einreichen.*"); + bot.once('message', async (msg) => { + if (msg.chat.id === userId) { + requestQueue.push({ userId: userId, userName: userName, message: msg.text, handled: false }); + bot.sendMessage(userId, `✅ *Deine Nachricht wurde gespeichert und wird an den nächsten verfügbaren Admin weitergeleitet.*`); + } + }); + } else { + try { + // Benutzerdaten des Anfragenden Benutzers abrufen + const user = await bot.getChatMember(callbackQuery.message.chat.id, userId); + const userName = user.user.username ? `@${user.user.username}` : `Benutzer ${user.user.first_name}`; + + // Admins-Namen und Usernamen aus der .env-Datei nutzen + const adminName = admins[adminId].name; + const adminUsername = admins[adminId].username; + + const adminLink = `https://t.me/${adminUsername}`; + + // Nachricht an den ausgewählten Admin senden + bot.sendMessage(adminId, `🔔 *Du wurdest von ${userName} für Unterstützung ausgewählt.*\n\nBitte kontaktiere ihn in einem privaten Chat. Du kannst ihm direkt über diesen Link schreiben: ${userName}`); + + // Nachricht an den Benutzer senden + bot.sendMessage(userId, `✅ *Der Admin ${adminName} wurde benachrichtigt und wird sich bald bei dir melden.*`); + + // Ursprüngliche Nachricht (Befehl /chat) löschen + if (callbackQuery.message.reply_to_message && callbackQuery.message.reply_to_message.message_id) { + bot.deleteMessage(callbackQuery.message.chat.id, callbackQuery.message.reply_to_message.message_id); + } + bot.deleteMessage(callbackQuery.message.chat.id, callbackQuery.message.message_id); + } catch (error) { + console.error('Fehler beim Abrufen des Benutzernamens:', error); + /* bot.sendMessage(userId, '⚠️ *Es gab einen Fehler beim Abrufen des Benutzernamens. Bitte versuche es später erneut.*'); */ + } + } +}); + +const escapeMarkdown = (text) => { + return text + .replace(/([_*\[\]()~`>#+\-=|{}.!])/g, '\\$1') // Escape Markdown reserved characters + .replace(/(?:\r\n|\r|\n)/g, '\\n') // Escape newlines + .replace(/\./g, '\\.'); // Escape dots +}; + +// Senden der Fragenliste im privaten Chat +const sendFaqList = (userId) => { + if (faqData.length > 0) { + const faqs = faqData.map((faq, index) => { + const question = faq.question; + return `${index + 1}️⃣ ${escapeMarkdown(question)}`; + }).join('\n\n'); + + bot.sendMessage(userId, `❓ FAQs: ❓\n\nBitte wähle eine Frage, indem du die entsprechende Nummer eingibst:\n\n${faqs}`) + .catch(error => { + console.error('Fehler beim Senden der FAQ-Liste:', error); + }); + } else { + bot.sendMessage(userId, '❗ Es sind keine FAQs verfügbar.'); + } +}; + +// Reaktion auf den /faq-Befehl +bot.onText(/\/faq/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.', { disable_web_page_preview: true }); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + const { expiry } = spammedUsers[userId]; + + // Nachricht für gesperrte Benutzer senden + if (expiry === 'permanent') { + bot.sendMessage(chatId, '❌ *Du bist dauerhaft gesperrt und kannst diesen Befehl nicht verwenden.*', { disable_web_page_preview: true }); + } else { + const formattedExpiry = formatTime(expiry); + bot.sendMessage(chatId, `❌ *Du bist gesperrt bis ${formattedExpiry} und kannst diesen Befehl nicht verwenden.*`, { disable_web_page_preview: true }); + } + return; // Verhindert weitere Verarbeitung, wenn der Benutzer gesperrt ist + } + + // Sende die FAQ-Liste direkt an den Benutzer im privaten Chat + sendFaqList(userId); +}); + +// Reaktion auf die Eingabe einer Frage-Nummer +bot.on('message', (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + return; // Befehl wird nicht weiter verarbeitet, wenn der Bot im Wartungsmodus ist + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + return; // Befehl wird nicht weiter verarbeitet, wenn der Benutzer gesperrt ist + } + + // Verarbeiten der FAQ-Anfrage + const questionNumber = parseInt(msg.text, 10); + if (!isNaN(questionNumber) && questionNumber >= 1 && questionNumber <= faqData.length) { + const selectedFaq = faqData[questionNumber - 1]; + const answer = selectedFaq.answer; + bot.sendMessage(userId, `🔍 Antwort auf Frage ${questionNumber}:\n\n${escapeMarkdown(answer)}`); + } +}); + +// /add_faq-Befehl, um FAQs hinzuzufügen (nur privat) +bot.onText(/\/add_faq/, (msg) => { + const userId = msg.from.id.toString(); + + if (!canExecuteCommand(userId)) { + bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, `🔧 *Bitte sende die FAQ ein:* \n\nFrage:`) + .then(() => bot.once('message', async (faqMsg) => { + const question = faqMsg.text.trim(); + bot.sendMessage(userId, `🔧 *Bitte sende die Antwort:*`) + .then(() => bot.once('message', async (answerMsg) => { + const answer = answerMsg.text.trim(); + + if (question && answer) { + faqData.push({ question, answer }); + fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); + bot.sendMessage(userId, `✅ *FAQ hinzugefügt.*`); + } else { + bot.sendMessage(userId, `❌ *Bitte stelle sicher, dass du sowohl Frage als auch Antwort eingibst.*`); + } + })); + })); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// /edit_faq-Befehl, um FAQs zu bearbeiten (nur privat) +bot.onText(/\/edit_faq/, (msg) => { + const userId = msg.from.id.toString(); + + if (!canExecuteCommand(userId)) { + bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, `🔧 *Bitte sende die Nummer der FAQ, die du bearbeiten möchtest:*`) + .then(() => bot.once('message', async (faqMsg) => { + const faqIndex = parseInt(faqMsg.text, 10) - 1; + + if (faqIndex >= 0 && faqIndex < faqData.length) { + bot.sendMessage(userId, `✏️ *Bitte sende die neue Frage:*`) + .then(() => bot.once('message', async (questionMsg) => { + const question = questionMsg.text.trim(); + bot.sendMessage(userId, `✏️ *Bitte sende die neue Antwort:*`) + .then(() => bot.once('message', async (answerMsg) => { + const answer = answerMsg.text.trim(); + + if (question && answer) { + faqData[faqIndex] = { question, answer }; + fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); + bot.sendMessage(userId, `✅ *FAQ aktualisiert.*`); + } else { + bot.sendMessage(userId, `❌ *Bitte stelle sicher, dass du sowohl Frage als auch Antwort eingibst.*`); + } + })); + })); + } else { + bot.sendMessage(userId, `❌ *Ungültige FAQ-Nummer.*`); + } + })); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// /del_faq-Befehl, um FAQs zu löschen (nur privat) +bot.onText(/\/del_faq/, (msg) => { + const userId = msg.from.id.toString(); + + if (!canExecuteCommand(userId)) { + bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, `🗑️ *Bitte sende die Nummer der FAQ, die du löschen möchtest:*`) + .then(() => bot.once('message', async (faqMsg) => { + const faqIndex = parseInt(faqMsg.text, 10) - 1; + + if (faqIndex >= 0 && faqIndex < faqData.length) { + faqData.splice(faqIndex, 1); + fs.writeFileSync(faqFilePath, JSON.stringify(faqData, null, 2)); + bot.sendMessage(userId, `✅ *FAQ gelöscht.*`); + } else { + bot.sendMessage(userId, `❌ *Ungültige FAQ-Nummer.*`); + } + })); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +const rateLimit = new Map(); // Speichert die Zeitstempel der letzten Ticket-Einreichung für jeden Benutzer + +bot.onText(/\/create_ticket/, (msg) => { + const userId = msg.from.id.toString(); + const currentTime = Date.now(); + + // Überprüfen, ob der Wartungsmodus aktiv ist und ob der Benutzer berechtigt ist + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Sperrte Benutzer können keine Befehle verwenden + } + + // Überprüfen, ob der Benutzer bereits ein Ticket eingereicht hat + if (rateLimit.has(userId)) { + const lastTicketTime = rateLimit.get(userId); + const timeSinceLastTicket = currentTime - lastTicketTime; + + // Überprüfen, ob 5 Minuten (300000 Millisekunden) seit dem letzten Ticket vergangen sind + if (timeSinceLastTicket < 300000) { + const timeLeft = Math.ceil((300000 - timeSinceLastTicket) / 60000); // Zeit übrig in Minuten + return bot.sendMessage(userId, `❌ *Du musst noch ${timeLeft} Minuten warten, bevor du ein weiteres Ticket senden kannst.*`); + } + } + + // Wenn der Benutzer noch keine Tickets gesendet hat oder das Zeitlimit abgelaufen ist + if (admins[userId]) { + bot.sendMessage(userId, '🔧 Bitte gib deinen Namen ein:') + .then(() => bot.once('message', async (nameMsg) => { + const name = nameMsg.text.trim(); + + if (!name) { + bot.sendMessage(userId, '❌ *Name ist erforderlich.*'); + return; + } + + bot.sendMessage(userId, '✉️ Bitte gib deine E-Mail-Adresse ein:') + .then(() => bot.once('message', async (emailMsg) => { + const email = emailMsg.text.trim(); + + // Simple E-Mail-Validierung + if (!email || !email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) { + bot.sendMessage(userId, '❌ *Ungültige E-Mail-Adresse.*'); + return; + } + + bot.sendMessage(userId, '📝 Bitte gib den Inhalt deines Tickets ein:') + .then(() => bot.once('message', async (ticketMsg) => { + const ticketContent = ticketMsg.text.trim(); + + if (!ticketContent) { + bot.sendMessage(userId, '❌ *Ticket-Inhalt ist erforderlich.*'); + return; + } + + // E-Mail-Transporter konfigurieren + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS + } + }); + + // E-Mail-Nachricht erstellen + const mailOptions = { + from: process.env.EMAIL_USER, + to: process.env.EMAIL_RECIPIENT, + subject: 'Neues Ticket vom Support-Bot', + text: `Neues Ticket von ${name} (${email}):\n\n${ticketContent}` + }; + + // E-Mail senden + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + console.error('Fehler beim Senden der E-Mail:', error); + bot.sendMessage(userId, '⚠️ *Es gab einen Fehler beim Senden des Tickets. Bitte versuche es später erneut.*'); + } else { + bot.sendMessage(userId, `✅ *Dein Ticket wurde erfolgreich eingereicht. Vielen Dank, ${name}!`); + } + }); + + // Zeitstempel des letzten Tickets speichern + rateLimit.set(userId, currentTime); + })); + })); + })); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Beispiel für den /info-Befehl +bot.onText(/\/info/, (msg) => { + const chatId = msg.chat.id; + + if (!canExecuteCommand(msg.from.id.toString())) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Hier die Bot-Informationen eintragen + const botName = 'Support Bot'; // Ersetze dies durch den tatsächlichen Bot-Namen + const botVersion = '1.5.9'; // Ersetze dies durch die tatsächliche Version + const botAuthor = 'M_Viper'; // Ersetze dies durch den tatsächlichen Autor + const botLicense = 'MIT'; // Ersetze dies durch die tatsächliche Lizenz + + // Informationen ohne MarkdownV2-Formatierung + const infoMessage = ` +🤖 Bot Information: +- Name: ${botName} +- Version: ${botVersion} +- Author: ${botAuthor} +- License: ${botLicense} + `; + + bot.sendMessage(chatId, infoMessage) + .catch(error => { + console.error('Fehler beim Senden der Bot-Informationen:', error); + }); +}); + +const maintenanceModeFile = path.join(dataDir, 'maintenance_mode.json'); + +// Sicherstellen, dass die maintenance_mode.json existiert +if (!fs.existsSync(maintenanceModeFile)) { + fs.writeFileSync(maintenanceModeFile, JSON.stringify({ active: false }), 'utf8'); +} + +// Funktion zum Laden des Wartungsmodus-Status +const loadMaintenanceMode = () => { + return JSON.parse(fs.readFileSync(maintenanceModeFile, 'utf8')); +}; + +// Funktion zum Speichern des Wartungsmodus-Status +const saveMaintenanceMode = (status) => { + fs.writeFileSync(maintenanceModeFile, JSON.stringify(status, null, 2), 'utf8'); +}; + +// Überprüfen, ob der Wartungsmodus aktiviert ist +const isMaintenanceModeActive = () => { + const status = loadMaintenanceMode(); + return status.active; +}; + +// Funktion zum Umschalten des Wartungsmodus +const toggleMaintenanceMode = (adminId, action) => { + const status = loadMaintenanceMode(); + if (action === 'on') { + status.active = true; + saveMaintenanceMode(status); + bot.sendMessage(adminId, '🔧 Wartungsmodus wurde aktiviert.'); + } else if (action === 'off') { + status.active = false; + saveMaintenanceMode(status); + bot.sendMessage(adminId, '🔧 Wartungsmodus wurde deaktiviert.'); + } +}; + +// Reaktion auf den /maintenance_mode-Befehl +bot.onText(/\/wartung (on|off)/, (msg, match) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + const action = match[1]; // "on" oder "off" + + // Überprüfen, ob der Benutzer der Entwickler ist + const devId = process.env.DEV; + if (userId === devId) { + toggleMaintenanceMode(userId, action); + } else { + bot.sendMessage(chatId, '❌ Du hast keine Berechtigung, den Wartungsmodus zu ändern.'); + } +}); + +// Funktion zur Überprüfung, ob der Befehl während des Wartungsmodus ausgeführt werden kann +const canExecuteCommand = (userId) => { + return !isMaintenanceModeActive() || userId === process.env.DEV; +}; + +// Hilfe-Befehl +bot.onText(/\/help/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + const { expiry } = spammedUsers[userId]; + + // Nachricht für gesperrte Benutzer senden + if (expiry === 'permanent') { + bot.sendMessage(chatId, '❌ *Du bist dauerhaft gesperrt und kannst diesen Befehl nicht verwenden.*'); + } else { + const formattedExpiry = formatTime(expiry); + bot.sendMessage(chatId, `❌ *Du bist gesperrt bis ${formattedExpiry} und kannst diesen Befehl nicht verwenden.*`); + } + return; // Verhindert weitere Verarbeitung, wenn der Benutzer gesperrt ist + } + + // Normale Verarbeitung für nicht gesperrte Benutzer (User Befehle) + const helpMessage = `📋 Verfügbare Befehle:\n + +🔍 /help - Zeigt diese Hilfe-Nachricht an\n +🔗 /links - Zeigt eine Liste der gespeicherten Links an\n +❓ /faq - Zeigt die FAQ an\n +📝 /create_ticket - Reiche ein Support-Ticket ein\n +👥 /admin - Zeigt eine Liste der Admins und deren Status\n +💬 /chat - Fordere einen Chat mit einem Admin an\n +ℹ️ /info - Zeigt Informationen über den Bot an\n +⭐ /rate - Bewerte unseren Support\n +🔗 /einladung - Erstelle einen persönlichen Einladungslink\n +📅 /termin - Mache einen Chat-Termin mit einem Admin\n +📩 /report - Melde eine Nachricht an die Admins\n +🚨 @admin - Informiere die Admins über eine Erwähnung im Chat\n +🚨 /escalation - Melde ein Problem an alle Admins\n +📜 /terms - Zeigt die Nutzungsbedingungen des Bots an\n +🗑 /cancel_termin - Storniert einen Chat-Termin\n +🎓 /tutorial - Startet ein Tutorial\n +`; + + bot.sendMessage(chatId, helpMessage); // Kein Markdown verwendet +}); + +// Hilfe-Befehl für Admins +bot.onText(/\/a_help/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfen, ob der Benutzer ein Admin ist (Admin Befehle) + if (admins[userId]) { + const adminHelpMessage = `📋 Verfügbare Admin-Befehle:\n + +🟢 /online - Setze deinen Status auf "online"\n +🔴 /offline - Setze deinen Status auf "offline"\n +📄 /add_faq - Füge einen neuen FAQ-Eintrag hinzu\n +✏️ /edit_faq - Bearbeite einen bestehenden FAQ-Eintrag\n +❌ /del_faq - Lösche einen FAQ-Eintrag\n +🔗 /add_links - Füge einen neuen Link hinzu\n +🚫 /del_links - Lösche einen Link\n +⭐ /view_ratings - Zeigt alle Bewertungen an\n +📊 /status - Zeigt Admins & Informationen an\n +📩 /msg_admin - Sende eine Nachricht an alle Admins\n +📝 /view_chat_history - Zeigt den Gesprächsverlauf eines Benutzers\n +📅 /my_termine - zeigt alle zukünftigen Chat-Termine an\n +🕐 /schedule_message - Geplante Nachricht erstellen\n +📌 /pin_message - Ermöglicht es Nachrichten in einem Chat anzupinnen.\n +🛑 /spam - Sperrt einen User für eine festgelegte Zeit\n +🔓 /unspam - Hebt die Sperre eines Users auf\n +🗑️ /clear "Zahl" - Löscht die letzten [Zahl] Nachrichten\n +🔄 /auto_reply - Funktion für automatische Antworten\n +🛠️ /maintenance_mode on|off - Wartungsmodus AN/AUS\n +`; + + bot.sendMessage(chatId, adminHelpMessage) + .catch(error => console.log('Fehler beim Senden der Nachricht:', error)); + } else { + // Nachricht für Nicht-Admins + bot.sendMessage(chatId, "❌ Du hast keine Berechtigung, diesen Befehl zu verwenden.") + .catch(error => console.log('Fehler beim Senden der Nachricht:', error)); + } +}); + +// Admin-Nachrichten verarbeiten +bot.onText(/\/msg_admin/, (msg) => { + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + bot.sendMessage(userId, '🔧 *Bitte gib die Nachricht ein, die an alle Admins gesendet werden soll:*') + .then(() => bot.once('message', async (messageMsg) => { + const message = messageMsg.text.trim(); + + if (!message) { + bot.sendMessage(userId, '❌ *Die Nachricht darf nicht leer sein.*'); + return; + } + + orderedAdminIds.forEach(adminId => { + if (adminId !== userId) { + bot.sendMessage(adminId, `🔧 *Nachricht von ${admins[userId].name}:*\n\n${message}`); + } + }); + + bot.sendMessage(userId, '✅ *Nachricht an alle Admins gesendet.*'); + })); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// /rate-Befehl, um den Support zu bewerten +bot.onText(/\/rate/, (msg) => { + const userId = msg.from.id.toString(); + const username = msg.from.username ? `@${msg.from.username}` : 'Unbekannt'; // Username holen, wenn vorhanden + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(msg.chat.id, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(msg.chat.id, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Sperrte Benutzer können keine Befehle verwenden + } + + // Benutzer auffordern, eine Bewertung von 1 bis 10 abzugeben + bot.sendMessage(userId, `⭐️ *Bewerte unseren Support von 1 bis 10 Sternen:*`) + .then(() => bot.once('message', async (ratingMsg) => { + const rating = parseInt(ratingMsg.text, 10); + + // Validierung der Bewertung + if (isNaN(rating) || rating < 1 || rating > 10) { + bot.sendMessage(userId, '❌ *Bitte gib eine gültige Bewertung von 1 bis 10 Sternen ein.*'); + return; + } + + // Speichern der Bewertung + ratingsData.push({ userId, username, rating }); + fs.writeFileSync(ratingsFilePath, JSON.stringify(ratingsData, null, 2)); + bot.sendMessage(userId, `✅ *Danke für deine Bewertung!*`); + + // Optional: Benachrichtige den Admin oder speichere die Bewertung anders + })); +}); + +// /view_ratings-Befehl, um Bewertungen zu sehen (nur privat) +bot.onText(/\/view_ratings/, (msg) => { + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + if (ratingsData.length > 0) { + const ratings = ratingsData.map((entry) => `⭐️ Benutzer ${entry.username || entry.userId}: ${entry.rating} Sterne`).join('\n\n'); + bot.sendMessage(userId, `📊 *Bewertungen:* 📊\n\n${ratings}`); + } else { + bot.sendMessage(userId, '❗ Keine Bewertungen verfügbar.'); + } + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Initialisierung der Daten +let usageData = []; +let fqaData = []; +let ticketsData = []; // Variable für die Tickets +let chatSessions = []; // Variable für Chats mit Admins + +fs.readFile(faqFilePath, 'utf8', (err, data) => { + if (err) { + console.error('Error loading FAQ data:', err); + return; + } + try { + fqaData = JSON.parse(data); + console.log('Loaded FAQ Data:', fqaData); // Logging zur Überprüfung + } catch (e) { + console.error('Error parsing FAQ data:', e); + } +}); + +// Beispiel: Chat-Daten speichern (Wird angenommen, dass beim Start eines Chats ein Zeitstempel gespeichert wird) +function startChatSession(userId, adminId) { + const startTime = Date.now(); + chatSessions.push({ userId, adminId, startTime }); +} + +// Beispiel: Chat-Daten beenden (Wird angenommen, dass beim Beenden eines Chats der Zeitstempel erfasst wird) +function endChatSession(userId, adminId) { + const endTime = Date.now(); + chatSessions = chatSessions.map(session => { + if (session.userId === userId && session.adminId === adminId && !session.endTime) { + session.endTime = endTime; + } + return session; + }); +} + +// Funktion zum Ermitteln des Webseitenstatus +const getWebsitesStatus = async () => { + const statusPromises = linksData.map(async (link) => { + try { + // Sende eine HTTP-GET-Anfrage an die Webseite + await axios.get(link.url, { timeout: 5000 }); + return `🟢 Online ${link.title}`; + } catch (error) { + return `🔴 Offline ${link.title}`; + } + }); + + // Warten, bis alle Status-Promises abgeschlossen sind + const statuses = await Promise.all(statusPromises); + return statuses.join('\n\n'); // Füge einen Abstand zwischen den Einträgen hinzu +}; + +// Funktion zur Berechnung der Laufzeit des Bots +const getBotUptime = () => { + const now = new Date(); + const uptimeMs = now - botStartTime; + const uptimeMin = Math.floor(uptimeMs / 60000); + const uptimeSec = ((uptimeMs % 60000) / 1000).toFixed(0); + return `${uptimeMin}m ${uptimeSec}s`; +}; + +// /status-Befehl, um den Status der Admins zu überprüfen +bot.onText(/\/status/, async (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + try { + // Status der Admins + const adminStatusMessages = orderedAdminIds.map(id => { + const status = adminStatus[id] || 'offline'; + const statusEmoji = status === 'online' ? '🟢' : '🔴'; + return `${statusEmoji} ${admins[id].name} (@${admins[id].username}): ${status}`; + }).join('\n\n'); + + // Weitere Statusinformationen + const totalUsages = usageData.length; // Anzahl der Nutzungen + const totalRatings = ratingsData.length; // Anzahl der Bewertungen + const totalFQA = fqaData.length; // Anzahl der FQA Einträge + const totalTickets = ticketsData.length; // Anzahl der Tickets + const totalLinks = linksData.length; // Anzahl der Links + const totalUsers = loadUsers().length; // Anzahl der Nutzer + const totalSpammedUsers = Object.keys(loadSpammedUsers()).length; // Anzahl der Sperrungen (Spam) + + // Dauer der Chats berechnen + const chatDurations = chatSessions.map(session => { + if (session.endTime) { + const durationMs = session.endTime - session.startTime; + const durationMin = Math.floor(durationMs / 60000); + const durationSec = ((durationMs % 60000) / 1000).toFixed(0); + return `🗣️ ${admins[session.adminId].name} (@${admins[session.adminId].username}): ${durationMin}m ${durationSec}s`; + } + return null; + }).filter(Boolean).join('\n'); + + // Wartungsmodus-Status + const maintenanceModeStatus = isMaintenanceModeActive() ? 'Aktiv' : 'Inaktiv'; + + // Status der Webseiten + const websiteStatus = await getWebsitesStatus(); + + // Laufzeit des Bots berechnen + const botUptime = getBotUptime(); + + const additionalInfo = `📊 Zusätzliche Informationen: 📊\n\n` + + `🔢 Anzahl der Nutzungen: ${totalUsages}\n\n` + + `⭐️ Anzahl der Bewertungen: ${totalRatings}\n\n` + + `❓ Anzahl der FAQ Einträge: ${totalFQA}\n\n` + + `🎟️ Anzahl der Tickets: ${totalTickets}\n\n` + + `🔗 Anzahl der Links: ${totalLinks}\n\n` + + `👥 Anzahl der Nutzer: ${totalUsers}\n\n` + + `🚫 Anzahl der Sperrungen (Spam): ${totalSpammedUsers}\n\n` + + `🕒 Chats mit Admins: \n${chatDurations || 'Keine aktiven Chats'}\n\n` + + `🔧 Wartungsmodus: ${maintenanceModeStatus}\n\n` + + `⏱️ Bot Laufzeit: ${botUptime}`; + + // Komplette Statusnachricht + const fullStatusMessage = `🛠️ Admin-Status: 🛠️\n\n${adminStatusMessages}\n\n` + + `══════════════════════════════\n\n` + + `${additionalInfo}\n\n` + + `══════════════════════════════\n\n` + + `🌐 Webseitenstatus: \n\n${websiteStatus}\n\n`; + + bot.sendMessage(chatId, fullStatusMessage); + } catch (error) { + console.error('Error while generating status message:', error); + bot.sendMessage(chatId, '❗ Es ist ein Fehler aufgetreten. Bitte versuche es später erneut.'); + } + } else { + bot.sendMessage(chatId, '❗ Nur Admins können diesen Befehl verwenden.'); + } +}); + +const repliesFilePath = path.join(dataDir, 'reply.json'); + +// Sicherstellen, dass die reply.json-Datei existiert und als Array initialisieren +if (!fs.existsSync(repliesFilePath)) { + fs.writeFileSync(repliesFilePath, JSON.stringify([])); // Leeres Array statt Objekt +} + +// Lädt Auto-Reply-Antworten aus der reply.json-Datei +let autoReplies; +try { + autoReplies = JSON.parse(fs.readFileSync(repliesFilePath, 'utf8')); + + // Falls die Datei versehentlich kein Array ist, setzen wir sie korrekt + if (!Array.isArray(autoReplies)) { + autoReplies = []; + fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); + } +} catch (error) { + console.error('Fehler beim Laden der Auto-Reply-Daten:', error); + autoReplies = []; // Falls Fehler auftritt, leeres Array initialisieren +} + +// Temporärer Speicher für Admins, die auf Eingaben warten +const pendingAutoReplies = {}; + +// Funktion zum Setzen einer automatischen Antwort +function setAutoReply(question, answer) { + try { + const replyData = { question, answer }; + autoReplies.push(replyData); + fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); + } catch (error) { + console.error('Fehler beim Speichern der Auto-Reply-Daten:', error); + } +} + +// /auto_reply-Befehl zum Starten des Prozesses +bot.onText(/\/auto_reply/, (msg) => { + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(userId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (admins[userId]) { + pendingAutoReplies[userId] = { step: 'waiting_for_question' }; + bot.sendMessage(userId, '✏️ *Bitte gib die Frage ein, auf die automatisch geantwortet werden soll.*'); + } else { + bot.sendMessage(userId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Verarbeite Nachrichten und steuere den Frage-Antwort-Prozess +bot.on('message', (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text; + + if (pendingAutoReplies[userId]) { + const pendingReply = pendingAutoReplies[userId]; + + if (pendingReply.step === 'waiting_for_question') { + // Frage erhalten, nach der Antwort fragen + pendingReply.question = text.trim(); + pendingReply.step = 'waiting_for_answer'; + bot.sendMessage(userId, `📝 *Frage gespeichert:* "${pendingReply.question}". Bitte gib nun die Antwort ein.`); + } else if (pendingReply.step === 'waiting_for_answer') { + // Antwort erhalten, das Frage-Antwort-Paar speichern + const answer = text.trim(); + setAutoReply(pendingReply.question, answer); + bot.sendMessage(chatId, `✅ *Automatische Antwort für die Frage "${pendingReply.question}" wurde gespeichert.*`); + + // Entferne den Benutzer aus dem temporären Speicher + delete pendingAutoReplies[userId]; + } + } else if (text) { + // Verarbeite eingehende Nachrichten und sende eine automatische Antwort, wenn eine Frage ähnlich ist + const lowerCaseText = text.toLowerCase(); + + let highestSimilarity = 0; + let bestMatch = null; + + // Verwendet Fuzzy Matching, um ähnliche Fragen zu finden + for (const reply of autoReplies) { + const { question, answer } = reply; + + // Berechne die Ähnlichkeit zwischen der Benutzerfrage und den gespeicherten Fragen + try { + const similarity = stringSimilarity.compareTwoStrings(lowerCaseText, question.toLowerCase()); + + if (similarity > highestSimilarity) { + highestSimilarity = similarity; + bestMatch = answer; + } + } catch (error) { + console.error('Fehler bei der Textähnlichkeitsberechnung:', error); + } + } + + // Wenn eine hohe Ähnlichkeit festgestellt wurde (z.B. > 0.5), sende die passende Antwort + if (highestSimilarity > 0.5) { + bot.sendMessage(chatId, bestMatch); + } + } +}); + +const chatHistoryFilePath = path.join(dataDir, 'chat_history.json'); + +// Sicherstellen, dass die chat_history.json-Datei existiert +if (!fs.existsSync(chatHistoryFilePath)) { + fs.writeFileSync(chatHistoryFilePath, JSON.stringify({})); +} + +// Lädt den Gesprächsverlauf aus der chat_history.json-Datei +let chatHistory = {}; +try { + chatHistory = JSON.parse(fs.readFileSync(chatHistoryFilePath, 'utf8')); +} catch (error) { + console.error('Fehler beim Laden des Gesprächsverlaufs:', error); +} + +// Funktion zum Speichern eines Gesprächsverlaufs +function saveChatHistory(userId, userName, message) { + console.log(`Speichern der Nachricht für Benutzer ${userName}: ${message}`); + if (!chatHistory[userId]) { + chatHistory[userId] = { [userName]: [] }; + } else if (!chatHistory[userId][userName]) { + chatHistory[userId][userName] = []; + } + chatHistory[userId][userName].push(message); + try { + fs.writeFileSync(chatHistoryFilePath, JSON.stringify(chatHistory, null, 2)); + console.log('Chat-Verlauf erfolgreich gespeichert.'); + } catch (error) { + console.error('Fehler beim Speichern des Gesprächsverlaufs:', error); + } +} + +// Funktion zum Abrufen der Liste der Benutzer +function listUsers() { + const userList = Object.keys(chatHistory) + .map((userId, index) => { + const userName = Object.keys(chatHistory[userId])[0]; + return `${index + 1}. ${userName}`; + }) + .join('\n'); + return userList || 'Keine Benutzer gefunden.'; +} + +// Funktion zum Abrufen des Gesprächsverlaufs eines bestimmten Benutzers +function getChatHistory(userId) { + if (chatHistory[userId]) { + return Object.entries(chatHistory[userId]) + .map(([name, messages]) => `@${name}:\n${messages.join('\n')}`) + .join('\n\n'); + } + return 'Kein Verlauf gefunden.'; +} + +// /view_chat_history-Befehl zum Anzeigen der Liste der Benutzer +bot.onText(/\/view_chat_history/, (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfe, ob der Benutzer berechtigt ist (Admin-Check) + if (admins[userId]) { + const usersList = listUsers(); + bot.sendMessage(chatId, `🔍 *Wähle einen Benutzer aus der Liste aus:* \n\n${usersList}`); + // Temporären Speicher für die Auswahl der Benutzernummer + pendingSelections[userId] = { step: 'waiting_for_selection' }; + } else { + bot.sendMessage(chatId, '❗ *Nur Admins können diesen Befehl verwenden.*'); + } +}); + +// Temporärer Speicher für Benutzer, die auf Auswahl warten +const pendingSelections = {}; + +// Verarbeite die Auswahl des Benutzers +bot.on('message', (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text; + + if (admins[userId]) { + saveChatHistory(userId, msg.from.username || msg.from.first_name, text); + } + + if (pendingSelections[userId]) { + const pendingSelection = pendingSelections[userId]; + + if (pendingSelection.step === 'waiting_for_selection') { + const selectionIndex = parseInt(text.trim(), 10) - 1; + const userIds = Object.keys(chatHistory); + + if (selectionIndex >= 0 && selectionIndex < userIds.length) { + const selectedUserId = userIds[selectionIndex]; + const userName = Object.keys(chatHistory[selectedUserId])[0]; + const history = getChatHistory(selectedUserId); + bot.sendMessage(chatId, `📜 *Gesprächsverlauf für Benutzer ${userName} (${selectedUserId}):*\n\n${history}`); + } else { + bot.sendMessage(chatId, '❗ *Ungültige Auswahl. Bitte gib eine gültige Nummer ein.*'); + } + + // Entferne die temporären Daten nach der Auswahl + delete pendingSelections[userId]; + } + } else if (text) { + // Hier kannst du den normalen Nachrichtenverarbeitungsprozess fortsetzen + } +}); + +// Funktion zum Speichern eines Gesprächsverlaufs +function saveChatHistory(userId, userName, message) { + if (!chatHistory[userId]) { + chatHistory[userId] = { [userName]: [] }; + } else if (!chatHistory[userId][userName]) { + chatHistory[userId][userName] = []; + } + chatHistory[userId][userName].push(message); + fs.writeFileSync(chatHistoryFilePath, JSON.stringify(chatHistory, null, 2)); +} + +// Funktion zum Extrahieren von Fragen und Antworten aus Chat-Verlauf +function learnFromChatHistory() { + for (const [userId, userChats] of Object.entries(chatHistory)) { + for (const [userName, messages] of Object.entries(userChats)) { + // Hier können Sie die Logik anpassen, um Fragen und Antworten zu extrahieren + messages.forEach((message, index) => { + // Beispielhafte Logik: Jede zweite Nachricht als Antwort behandeln + if (index % 2 === 0) { + const question = message; + const answer = messages[index + 1] || 'Keine Antwort gefunden'; + const existingReply = autoReplies.find(r => r.question === question); + + if (!existingReply) { + autoReplies.push({ question, answer }); + fs.writeFileSync(repliesFilePath, JSON.stringify(autoReplies, null, 2)); + } + } + }); + } + } +} + +// Funktion zum Verarbeiten von Nachrichten +bot.on('message', (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text; + + // Speichern des Gesprächsverlaufs + if (admins[userId]) { + saveChatHistory(userId, msg.from.username || msg.from.first_name, text); + } + + // Verarbeite eingehende Nachrichten und sende eine automatische Antwort, wenn eine Frage ähnlich ist + const lowerCaseText = text.toLowerCase(); + + let highestSimilarity = 0; + let bestMatch = null; + + // Verwendet Fuzzy Matching, um ähnliche Fragen zu finden + for (const reply of autoReplies) { + const { question, answer } = reply; + + try { + const similarity = stringSimilarity.compareTwoStrings(lowerCaseText, question.toLowerCase()); + + if (similarity > highestSimilarity) { + highestSimilarity = similarity; + bestMatch = answer; + } + } catch (error) { + console.error('Fehler bei der Textähnlichkeitsberechnung:', error); + } + } + + // Wenn eine hohe Ähnlichkeit festgestellt wurde (z.B. > 0.5), sende die passende Antwort + if (highestSimilarity > 0.5) { + bot.sendMessage(chatId, bestMatch); + } +}); + +// Automatisches Lernen aus Chat-Verlauf regelmäßig ausführen +setInterval(learnFromChatHistory, 24 * 60 * 60 * 1000); // Alle 24 Stunden + +// Verzeichnisse und Dateipfade +const appointmentsFilePath = path.join(dataDir, 'appointments.json'); + +// Sicherstellen, dass das Verzeichnis existiert +if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); +} + +// Sicherstellen, dass die appointments.json-Datei existiert +if (!fs.existsSync(appointmentsFilePath)) { + fs.writeFileSync(appointmentsFilePath, JSON.stringify({})); +} + +// Lädt die Termine aus der appointments.json-Datei +let appointments = {}; +try { + appointments = JSON.parse(fs.readFileSync(appointmentsFilePath, 'utf8')); +} catch (error) { + console.error('Fehler beim Laden der Termine:', error); +} + +// Funktion zum Speichern der Termine +function saveAppointments() { + try { + fs.writeFileSync(appointmentsFilePath, JSON.stringify(appointments, null, 2)); + } catch (error) { + console.error('Fehler beim Speichern der Termine:', error); + } +} + +// Funktion zum Abrufen der Liste der Admins +function listAdmins() { + return Object.keys(admins).map(adminId => { + const admin = admins[adminId]; + const statusIcon = admin.status === 'online' ? '🟢' : '🔴'; + const adminName = admin.name || 'Unbekannt'; + const adminUsername = admin.username ? `@${admin.username}` : 'Unbekannt'; + const adminResponsibility = admin.responsibility || 'Keine Zuständigkeit angegeben'; + + return `• ${statusIcon} ${adminName}\n ${adminUsername}\n 📌 Zuständigkeit: ${adminResponsibility}`; + }).join('\n\n'); +} + +// Beispielhafte Datenstruktur für interne Benachrichtigungen +const notifications = {}; // { [userId]: { confirmationMessageId: string, reminders: { reminder10Min: NodeJS.Timeout, reminder5Min: NodeJS.Timeout } } } + +// Funktion zum Formatieren des Datums +function formatDate(date) { + const options = { weekday: 'short', day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + return date.toLocaleDateString('de-DE', options).replace(',', ''); +} + +// /termin-Befehl zum Vereinbaren eines Chat-Termin +bot.onText(/\/termin/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + const username = msg.from.username || msg.from.first_name; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(chatId, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; // Gesperrte Benutzer können keine Befehle verwenden + } + + if (appointments[userId]) { + bot.sendMessage(chatId, '📅 Du hast bereits einen Termin geplant. Bitte warte auf den nächsten verfügbaren Termin.'); + return; + } + + bot.sendMessage(chatId, '🔍 Wähle einen Admin für den Chat-Termin aus:\n\n' + listAdmins()); + appointments[userId] = { step: 'waiting_for_admin', username, reminders: {} }; // Speichere den Benutzernamen und Platz für Erinnerungen + saveAppointments(); +}); + +// Verarbeite die Auswahl des Admins und des Zeitpunkts +bot.on('message', (msg) => { + const userId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text.trim(); + + if (appointments[userId]) { + const appointment = appointments[userId]; + + if (appointment.step === 'waiting_for_admin') { + const adminName = text; + const adminId = Object.keys(admins).find(id => admins[id].name === adminName); + + if (adminId) { + appointment.adminId = adminId; + appointment.step = 'waiting_for_date'; + bot.sendMessage(chatId, '📅 Wähle ein Datum und eine Uhrzeit für den Chat-Termin (im Format YYYY-MM-DD HH:MM):'); + saveAppointments(); + } else { + bot.sendMessage(chatId, '❗ Ungültige Auswahl. Bitte wähle einen Admin aus der Liste aus.'); + } + } else if (appointment.step === 'waiting_for_date') { + const [date, time] = text.split(' '); + const appointmentDate = new Date(`${date}T${time}:00`); + + if (!isNaN(appointmentDate.getTime()) && appointmentDate > new Date()) { + appointment.date = appointmentDate; + appointment.step = 'waiting_for_admin_confirmation'; + const formattedDate = formatDate(appointmentDate); + + // Benachrichtige den Admin zur Bestätigung + bot.sendMessage(appointment.adminId, `📅 @${appointment.username} hat einen Chat-Termin angefordert am: \n\n${formattedDate}. \n\nBestätige den Termin mit /confirm oder schlage einen neuen Termin vor dazu Kontaktiere @${appointment.username}.`); + + // Speichern der internen Benachrichtigung + bot.sendMessage(userId, `🔔 Dein Termin wurde an den Admin zur Bestätigung gesendet.`).then(sentMsg => { + if (!notifications[userId]) notifications[userId] = { reminders: {} }; + notifications[userId].confirmationMessageId = sentMsg.message_id; + }); + + saveAppointments(); + } else { + bot.sendMessage(chatId, '❗ Ungültiges Datum oder Uhrzeit. Bitte gib ein gültiges Datum und eine gültige Uhrzeit im Format YYYY-MM-DD HH:MM an.'); + } + } + } +}); + +// /confirm-Befehl für Admins zur Bestätigung +bot.onText(/\/confirm/, (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + + // Finde den Benutzer, dessen Termin bestätigt werden soll + const userId = Object.keys(appointments).find(id => appointments[id].adminId === adminId && appointments[id].step === 'waiting_for_admin_confirmation'); + if (userId) { + const appointment = appointments[userId]; + const appointmentDate = new Date(appointment.date); + appointment.step = 'confirmed'; + const formattedDate = formatDate(appointmentDate); + + bot.sendMessage(chatId, '✅ Der Termin wurde erfolgreich bestätigt. Du erhältst Erinnerungen 10 Minuten und 5 Minuten vor Beginn.'); + bot.sendMessage(userId, `✅ Dein Termin mit @${admins[adminId].username} wurde bestätigt für ${formattedDate}.`); + + // Erinnerungen an beide Parteien + const reminder10Min = appointmentDate - new Date() - 10 * 60 * 1000; + const reminder5Min = appointmentDate - new Date() - 5 * 60 * 1000; + const startTime = appointmentDate - new Date(); + + if (reminder10Min > 0) { + const reminder10MinId = setTimeout(() => { + bot.sendMessage(userId, `⏰ Dein Chat-Termin mit @${admins[adminId].username} beginnt in 10 Minuten.`); + bot.sendMessage(adminId, `⏰ Dein Chat-Termin mit @${admins[adminId].username} beginnt in 10 Minuten.`); + }, reminder10Min); + appointments[userId].reminders.reminder10Min = reminder10MinId; + } + + if (reminder5Min > 0) { + const reminder5MinId = setTimeout(() => { + bot.sendMessage(userId, `⏰ Dein Chat-Termin mit @${admins[adminId].username} beginnt in 5 Minuten.`); + bot.sendMessage(adminId, `⏰ Dein Chat-Termin mit @${admins[adminId].username} beginnt in 5 Minuten.`); + }, reminder5Min); + appointments[userId].reminders.reminder5Min = reminder5MinId; + } + + if (startTime > 0) { + setTimeout(() => { + admins[adminId].status = 'offline'; // Setze den Admin auf offline + saveAppointments(); // Speichere den Status + }, startTime); + } + } else { + bot.sendMessage(chatId, '❌ Kein Termin zur Bestätigung gefunden.'); + } +}); + +const steps = {}; // Ein Objekt, um den Status der Benutzer-Interaktionen zu verfolgen + +// Starte den Vorschlagsprozess mit dem Befehl /suggest +bot.onText(/\/suggest/, (msg) => { + const userId = msg.from.id; + const chatId = msg.chat.id; + + // Stelle sicher, dass du die ID des ursprünglichen Erstellers verwendest + const originalCreatorId = userId; // Ersetze dies durch die Logik, um den ursprünglichen Ersteller zu finden + + steps[userId] = { + step: 'waiting_for_date', + chatId: chatId, + originalCreatorId: originalCreatorId // Speichern der ID des ursprünglichen Erstellers + }; + + bot.sendMessage(chatId, '📅 Bitte gib das neue Datum für den Chat-Termin im Format YYYY-MM-DD ein:'); +}); + +// Verarbeite das Datum und frage nach der Uhrzeit +bot.on('message', async (msg) => { + const userId = msg.from.id; + const chatId = msg.chat.id; + const messageText = msg.text.trim(); + + if (steps[userId]) { + const userStep = steps[userId].step; + const originalCreatorId = steps[userId].originalCreatorId; // Abrufen der ID des ursprünglichen Erstellers + + if (userStep === 'waiting_for_date') { + // Validierung des Datums + if (/^\d{4}-\d{2}-\d{2}$/.test(messageText)) { + steps[userId].date = messageText; + steps[userId].step = 'waiting_for_time'; + bot.sendMessage(chatId, '🕒 Bitte gib die Uhrzeit für den neuen Termin im Format HH:MM ein:'); + } else { + bot.sendMessage(chatId, '❌ Das Datum ist ungültig. Bitte gib das Datum im Format YYYY-MM-DD ein:'); + } + } else if (userStep === 'waiting_for_time') { + // Validierung der Uhrzeit + if (/^\d{2}:\d{2}$/.test(messageText)) { + const formattedDate = `${steps[userId].date} um ${messageText}`; + const userChatId = steps[userId].chatId; // ID des Chats mit dem Benutzer + + // Informiere den Benutzer über den neuen Termin + bot.sendMessage(userChatId, `📅 Der neue Termin wurde auf den ${formattedDate} festgelegt.`); + + // Informiere den ursprünglichen Ersteller des Termins, aber nicht den Admin + if (originalCreatorId && originalCreatorId !== userId) { + bot.sendMessage(originalCreatorId, `📅 Der Termin wurde auf den ${formattedDate} geändert.`); + } + + // Beende den Vorschlagsprozess + delete steps[userId]; + } else { + bot.sendMessage(chatId, '❌ Die Uhrzeit ist ungültig. Bitte gib die Uhrzeit im Format HH:MM ein:'); + } + } + } +}); + +// /my_termine-Befehl für Admins +bot.onText(/\/my_termine/, (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(adminId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (!admins[adminId]) { + bot.sendMessage(chatId, '❌ Du bist kein Admin und hast keinen Zugriff auf diesen Befehl.'); + return; + } + + const adminAppointments = Object.values(appointments).filter(appointment => appointment.adminId === adminId); + + if (adminAppointments.length > 0) { + let appointmentsList = '📅 Deine kommenden Termine:\n\n'; + adminAppointments.forEach(appointment => { + if (appointment.step === 'confirmed') { + appointmentsList += `- Mit @${appointment.username} am ${formatDate(new Date(appointment.date))}\n`; + } + }); + bot.sendMessage(chatId, appointmentsList); + } else { + bot.sendMessage(chatId, '📅 Du hast keine anstehenden Termine.'); + } +}); + +// /cancel_termin-Befehl zum Stornieren eines Termins +bot.onText(/\/cancel_termin/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer einen Termin hat + if (appointments[userId] && appointments[userId].step === 'confirmed') { + const appointment = appointments[userId]; + const formattedDate = formatDate(new Date(appointment.date)); + + // Bestätigungsnachricht für den Benutzer + bot.sendMessage(chatId, `❗ Bist du sicher, dass du deinen Termin mit @${admins[appointment.adminId].username} am ${formattedDate} stornieren möchtest? Antworte mit 'Ja' oder 'Nein'.`); + + // Warten auf Bestätigung der Stornierung + bot.once('message', (confirmationMsg) => { + const confirmationText = confirmationMsg.text.trim().toLowerCase(); + + if (confirmationText === 'ja') { + // Erinnerungen löschen + if (appointment.reminders.reminder10Min) { + clearTimeout(appointment.reminders.reminder10Min); + } + if (appointment.reminders.reminder5Min) { + clearTimeout(appointment.reminders.reminder5Min); + } + + // Termin stornieren + delete appointments[userId]; + saveAppointments(); // Sicherstellen, dass die Datei aktualisiert wird + + bot.sendMessage(chatId, '✅ Dein Termin wurde erfolgreich storniert.'); + bot.sendMessage(appointment.adminId, `❌ Der Termin mit @${appointment.username} am ${formattedDate} wurde vom Benutzer storniert.`); + + // Interne Benachrichtigungen löschen + removeInternalNotifications(appointment); + + } else { + bot.sendMessage(chatId, '❌ Die Stornierung wurde abgebrochen.'); + } + }); + } else { + bot.sendMessage(chatId, '❌ Du hast keinen geplanten Termin, den du stornieren könntest.'); + } +}); + +// Beispielhafte Funktion zum Löschen interner Benachrichtigungen (falls verwendet) +function removeInternalNotifications(appointment) { + // Löschen der Bestätigungsnachricht an den Benutzer + if (notifications[appointment.username]) { + if (notifications[appointment.username].confirmationMessageId) { + bot.deleteMessage(appointment.username, notifications[appointment.username].confirmationMessageId).catch(error => { + console.error('Fehler beim Löschen der Bestätigungsnachricht:', error); + }); + } + // Löschen der Erinnerungen + if (notifications[appointment.username].reminders) { + if (notifications[appointment.username].reminders.reminder10Min) { + clearTimeout(notifications[appointment.username].reminders.reminder10Min); + } + if (notifications[appointment.username].reminders.reminder5Min) { + clearTimeout(notifications[appointment.username].reminders.reminder5Min); + } + } + delete notifications[appointment.username]; + } +} + + +// Pfad zur Datei, in der die Benutzer-Daten gespeichert werden +const usersFilePath = path.join(dataDir, 'users.json'); + +// Pfad zur Datei, in der die geplanten Nachrichten gespeichert werden +const scheduledMessagesFilePath = path.join(dataDir, 'scheduled_messages.json'); + +// Sicherstellen, dass das Verzeichnis existiert +if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); +} + +// Sicherstellen, dass die Dateien existieren +if (!fs.existsSync(usersFilePath)) { + fs.writeFileSync(usersFilePath, JSON.stringify([])); +} + +if (!fs.existsSync(scheduledMessagesFilePath)) { + fs.writeFileSync(scheduledMessagesFilePath, JSON.stringify([])); +} + +// Lädt die Benutzer-Daten aus der users.json-Datei +let users = []; +try { + users = JSON.parse(fs.readFileSync(usersFilePath, 'utf8')); +} catch (error) { + console.error('Fehler beim Laden der Benutzer-Daten:', error); +} + +// Lädt die geplanten Nachrichten aus der scheduled_messages.json-Datei +let scheduledMessages = []; +try { + scheduledMessages = JSON.parse(fs.readFileSync(scheduledMessagesFilePath, 'utf8')); +} catch (error) { + console.error('Fehler beim Laden der geplanten Nachrichten:', error); +} + +// Funktion zum Speichern der Benutzer-Daten +function saveUsers() { + try { + fs.writeFileSync(usersFilePath, JSON.stringify(users, null, 2)); + } catch (error) { + console.error('Fehler beim Speichern der Benutzer-Daten:', error); + } +} + +// Funktion zum Speichern der geplanten Nachrichten +function saveScheduledMessages() { + try { + fs.writeFileSync(scheduledMessagesFilePath, JSON.stringify(scheduledMessages, null, 2)); + } catch (error) { + console.error('Fehler beim Speichern der geplanten Nachrichten:', error); + } +} + +// Funktion zum Senden des Menüs +const sendMenu = (chatId) => { + const groupName = process.env.GROUP_NAME; + const botName = process.env.BOT_NAME; + + const menuText = `📢 *Willkommen beim SupportBot von ${groupName}*\n\n` + + `Hallo! Wir freuen uns, dass du bei ${groupName} bist. \n\n` + + `Hier kannst du Unterstützung zu verschiedenen Themen erhalten, wie z.B.:\n` + + `- Unsere Links\n` + + `- Häufig gestellte Fragen (FAQ)\n` + + `- Unterstützung durch unseren Support\n` + + `- Und vieles mehr!\n\n` + + `Nutze die Befehle in /help, um mehr über unsere Funktionen zu erfahren und Unterstützung zu erhalten.\n\n` + + `Falls du Fragen hast oder Hilfe benötigst, stehen wir dir jederzeit zur Verfügung.\n\n` + + `Viel Spaß mit dem ${botName}!`; + + const replyMarkup = { + reply_markup: { + inline_keyboard: [ + [ + { text: 'Mehr Hilfe', callback_data: 'more_help' } + ] + ] + } + }; + + bot.sendMessage(chatId, menuText, { parse_mode: 'Markdown', reply_markup: replyMarkup }); +}; + +// Reaktion auf den /start-Befehl +bot.onText(/\/start/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Prüfen, ob der Benutzer gesperrt ist + if (isUserSpammed(userId)) { + bot.sendMessage(chatId, '❌ Du bist gesperrt und kannst diesen Befehl nicht verwenden.'); + return; + } + + const userName = msg.from.username || `${msg.from.first_name} ${msg.from.last_name}`; + + // Überprüfen, ob die Benutzer-ID bereits gespeichert ist + if (!users.find(user => user.id === userId)) { + users.push({ + id: userId, + name: userName + }); + saveUsers(); + } + + sendMenu(chatId); +}); + +// Reaktion auf Callback-Querys (Button-Klicks) +bot.on('callback_query', (query) => { + const chatId = query.message.chat.id; + const data = query.data; + + if (data === 'more_help') { + // Sende die Hilfe-Nachricht + const helpText = `📚 *Hilfe und Unterstützung*\n\n` + + `Hier findest du Unterstützung für alle verfügbaren Funktionen:\n\n` + + `🔹 /help - Zeigt diese Hilfe-Nachricht an\n` + + `🔗 /links - Zeigt eine Liste der gespeicherten Links an\n` + + `❓ /faq - Zeigt die FAQ an\n` + + `📝 /create_ticket - Reiche ein Support-Ticket ein\n` + + `👥 /admin - Zeigt eine Liste der Admins und deren Status\n` + + `💬 /chat - Fordere einen Chat mit einem Admin an\n` + + `ℹ️ /info - Zeigt Informationen über den Bot an\n` + + `⭐ /rate - Bewerte unseren Support\n` + + `📅 /termin - Mache einen Chat-Termin mit einem Admin\n` + + `🚨 /escalation - Melde ein Problem an alle Admins\n` + + `📜 /terms - Zeigt die Nutzungsbedingungen des Bots an\n` + + `🗑 /cancel_termin - Storniert einen Chat-Termin\n` + + `🔗 /einladung - Erstelle einen Einladungslink für die Gruppe\n` + + `🔗 /einladen - Erstelle einen Einladungslink für die Gruppe` + + bot.sendMessage(chatId, helpText, { parse_mode: 'Markdown' }); + } + + // Optionale Bestätigung der Callback-Query + bot.answerCallbackQuery(query.id); +}); + +// Speichert den aktuellen Status des Benutzers für die Nachrichteneinstellung +let userStatus = {}; + +// Befehl zum Starten der Nachrichtplanung +bot.onText(/\/schedule_message/, (msg) => { + const chatId = msg.chat.id; + const adminId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(adminId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfen, ob der Benutzer ein autorisierter Admin ist + if (!admins[adminId]) { + bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); + return; + } + + userStatus[adminId] = { step: 'waiting_for_date', chatId }; + bot.sendMessage(chatId, '📅 Gib das Datum und die Uhrzeit für die geplante Nachricht im Format YYYY-MM-DD HH:MM an:'); +}); + +// Verarbeitet die Eingabe des Datums und der Uhrzeit +bot.on('message', (msg) => { + const adminId = msg.from.id.toString(); + const chatId = msg.chat.id; + const text = msg.text.trim(); + + if (userStatus[adminId]) { + const status = userStatus[adminId]; + + if (status.step === 'waiting_for_date') { + const [date, time] = text.split(' '); + const scheduledDate = new Date(`${date}T${time}:00`); + + if (!isNaN(scheduledDate.getTime()) && scheduledDate > new Date()) { + status.date = scheduledDate; + status.step = 'waiting_for_message'; + bot.sendMessage(chatId, '📝 Gib die Nachricht ein, die du planen möchtest:'); + } else { + bot.sendMessage(chatId, '❗ Ungültiges Datum oder Uhrzeit. Bitte gib ein gültiges Datum und eine gültige Uhrzeit im Format YYYY-MM-DD HH:MM an.'); + } + } else if (status.step === 'waiting_for_message') { + const message = text; + const scheduledDate = status.date; + scheduledMessages.push({ + adminId, + message, + dateTime: scheduledDate.toISOString() + }); + saveScheduledMessages(); + bot.sendMessage(chatId, `✅ Deine Nachricht wurde für ${formatDate(scheduledDate)} geplant.`); + delete userStatus[adminId]; // Status zurücksetzen + } + } +}); + +// Funktion zum Formatieren des Datums +function formatDate(date) { + const options = { weekday: 'short', day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }; + return date.toLocaleDateString('de-DE', options).replace(',', ''); +} + +// Verarbeite geplante Nachrichten +cron.schedule('* * * * *', () => { // Jede Minute überprüfen + const now = new Date().toISOString(); + scheduledMessages.forEach((scheduledMessage, index) => { + if (new Date(scheduledMessage.dateTime) <= new Date()) { + users.forEach(user => { + bot.sendMessage(user.id, scheduledMessage.message); + }); + scheduledMessages.splice(index, 1); // Entferne gesendete Nachricht + saveScheduledMessages(); + } + }); +}); + +// Verarbeitet neue Benutzerinteraktionen (fängt alle neuen Benutzer auf) +bot.on('new_chat_members', (msg) => { + const chatId = msg.chat.id; + const newMembers = msg.new_chat_members; + + newMembers.forEach((member) => { + const userId = member.id.toString(); + const userName = member.username || `${member.first_name} ${member.last_name}`; + + // Überprüfen, ob der Benutzer bereits gespeichert ist + if (!users.find(user => user.id === userId)) { + users.push({ + id: userId, + name: userName + }); + saveUsers(); + } + }); +}); + +// Funktion zum Senden der Nutzungsbedingungen +const sendTerms = (chatId) => { + const termsText = `📜 *Nutzungsbedingungen*\n\n` + + `Hier sind die Nutzungsbedingungen für die Nutzung unseres Bots:\n\n` + + `1. Du verpflichtest dich, die Dienste des Bots gemäß den geltenden Gesetzen zu nutzen.\n` + + `2. Missbrauch des Bots, einschließlich Spam oder andere unangemessene Aktivitäten, ist untersagt.\n` + + `3. Der Bot speichert keine persönlichen Daten ohne deine Zustimmung.\n` + + `4. Bei Fragen oder Problemen wende dich bitte an unseren Support.\n\n` + + `Bitte halte dich an diese Bedingungen, um einen reibungslosen Service zu gewährleisten.`; + + bot.sendMessage(chatId, termsText, { parse_mode: 'Markdown' }); +}; + +// Reaktion auf den /terms-Befehl +bot.onText(/\/terms/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Sende die Nutzungsbedingungen an den Benutzer + sendTerms(chatId); +}); + +// Funktion zum Überprüfen, ob ein Benutzer ein Admin ist +const isAdmin = (userId) => { + return admins[userId.toString()] !== undefined; +}; + +// Speichert den aktuellen Status des Admins für den /pin_message-Befehl +let pinMessageStatus = {}; + +const spammedUsersFile = path.join(dataDir, 'spammed_users.json'); +const usersFile = path.join(dataDir, 'users.json'); // Pfad zur users.json + +// Prüfe, ob der Ordner und die Dateien existieren, und erstelle sie, falls nicht +if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir); +} + +if (!fs.existsSync(spammedUsersFile)) { + fs.writeFileSync(spammedUsersFile, JSON.stringify({}), 'utf8'); +} + +if (!fs.existsSync(usersFile)) { + fs.writeFileSync(usersFile, JSON.stringify([]), 'utf8'); // Leere Liste, wenn users.json nicht existiert +} + +// Funktion zum Laden der gesperrten Benutzer aus der Datei +const loadSpammedUsers = () => { + const data = fs.readFileSync(spammedUsersFile, 'utf8'); + return JSON.parse(data); +}; + +// Funktion zum Speichern der gesperrten Benutzer in der Datei +const saveSpammedUsers = (spammedUsers) => { + fs.writeFileSync(spammedUsersFile, JSON.stringify(spammedUsers, null, 2), 'utf8'); +}; + +// Funktion zum Laden der Benutzer aus der users.json-Datei +const loadUsers = () => { + const data = fs.readFileSync(usersFile, 'utf8'); + return JSON.parse(data); +}; + +let spammedUsers = loadSpammedUsers(); // Gesperrte Benutzer laden + +// Liste der verfügbaren Sperrzeiten +const timeOptions = { + '30 Minuten': 30 * 60 * 1000, + '1 Stunde': 60 * 60 * 1000, + '2 Stunden': 2 * 60 * 60 * 1000, + '3 Stunden': 3 * 60 * 60 * 1000, + '4 Stunden': 4 * 60 * 60 * 1000, + '5 Stunden': 5 * 60 * 60 * 1000, + '24 Stunden': 24 * 60 * 60 * 1000, + 'Permanent': 'permanent' +}; + +let spamStep = {}; // Speichert den Fortschritt des /spam Befehls + +// Funktion, um zu überprüfen, ob ein Benutzer gesperrt ist +const isUserSpammed = (userId) => { + if (spammedUsers[userId]) { + const { expiry } = spammedUsers[userId]; + if (expiry === 'permanent' || expiry > Date.now()) { + return true; + } else { + // Sperre ist abgelaufen, Benutzer entsperren + delete spammedUsers[userId]; + saveSpammedUsers(spammedUsers); + return false; + } + } + return false; +}; + +// Funktion, um eine lesbare Uhrzeit zu generieren +const formatTime = (timestamp) => { + const date = new Date(timestamp); + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const year = date.getFullYear(); + return `${hours}:${minutes} Uhr, am ${day}.${month}.${year}`; +}; + +// Reaktion auf den /spam-Befehl (Start) +bot.onText(/\/spam/, (msg) => { + const chatId = msg.chat.id; + const adminId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(adminId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfen, ob der Benutzer ein Admin ist + if (!isAdmin(adminId)) { + bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); + return; + } + + // Frage nach dem Benutzernamen + spamStep[chatId] = { step: 'askUser' }; // Setzt den nächsten Schritt + bot.sendMessage(chatId, 'Bitte gib den Benutzernamen ein (@Name):'); +}); + +// Antwort auf die Eingabe des Benutzernamens +bot.on('message', (msg) => { + const chatId = msg.chat.id; + + if (spamStep[chatId]) { + const currentStep = spamStep[chatId].step; + + if (currentStep === 'askUser') { + const username = msg.text.trim().replace('@', ''); // Entferne das @-Zeichen + + // Benutzer in der users.json anhand des Namens finden + const targetUser = users.find(user => user.name.toLowerCase() === username.toLowerCase()); + + if (!targetUser) { + bot.sendMessage(chatId, `❌ Benutzer ${username} nicht gefunden. Bitte erneut versuchen.`); + return; + } + + spamStep[chatId].targetUser = targetUser; + spamStep[chatId].step = 'askTime'; // Nächster Schritt + bot.sendMessage(chatId, 'Wähle die Sperrdauer aus:', { + reply_markup: { + inline_keyboard: [ + [{ text: '30 Minuten', callback_data: '30 Minuten' }], + [{ text: '1 Stunde', callback_data: '1 Stunde' }], + [{ text: '2 Stunden', callback_data: '2 Stunden' }], + [{ text: '3 Stunden', callback_data: '3 Stunden' }], + [{ text: '4 Stunden', callback_data: '4 Stunden' }], + [{ text: '5 Stunden', callback_data: '5 Stunden' }], + [{ text: '24 Stunden', callback_data: '24 Stunden' }], + [{ text: 'Permanent', callback_data: 'Permanent' }] + ] + } + }); + } + } +}); + +// Reaktion auf die Zeit-Auswahl +bot.on('callback_query', (query) => { + const chatId = query.message.chat.id; + const selectedTime = query.data; + + if (spamStep[chatId] && spamStep[chatId].step === 'askTime') { + const targetUser = spamStep[chatId].targetUser; + + if (!timeOptions[selectedTime]) { + bot.sendMessage(chatId, '❌ Ungültige Zeitangabe.'); + return; + } + + const timeDuration = timeOptions[selectedTime]; + const targetUserId = targetUser.id; + + // Benutzer sperren + const expiryTime = timeDuration === 'permanent' ? 'permanent' : Date.now() + timeDuration; + spammedUsers[targetUserId] = { expiry: expiryTime }; + + saveSpammedUsers(spammedUsers); // Gesperrte Benutzer speichern + + let successMessage; + + if (timeDuration === 'permanent') { + successMessage = `✅ Benutzer @${targetUser.name} wurde dauerhaft gesperrt.`; + } else { + const formattedTime = formatTime(expiryTime); + successMessage = `✅ Benutzer @${targetUser.name} wurde bis ${formattedTime} gesperrt.`; + } + + bot.sendMessage(chatId, successMessage); + + // Bereinige den Schritt + delete spamStep[chatId]; + } +}); + +// Reaktion auf den /unspam-Befehl (Start) +bot.onText(/\/unspam/, (msg) => { + const chatId = msg.chat.id; + const adminId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(adminId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + // Überprüfen, ob der Benutzer ein Admin ist + if (!isAdmin(adminId)) { + bot.sendMessage(chatId, '❌ Du bist kein autorisierter Admin und hast keinen Zugriff auf diesen Befehl.'); + return; + } + + // Frage nach dem Benutzernamen + bot.sendMessage(chatId, 'Bitte gib den Benutzernamen des zu entsperrenden Benutzers ein (@Name):'); + + // Speichert den Schritt zur Entsperrung + spamStep[chatId] = { step: 'askUserToUnspam' }; +}); + +// Reaktion auf die Eingabe des Benutzernamens für die Entsperrung +bot.on('message', (msg) => { + const chatId = msg.chat.id; + + if (spamStep[chatId] && spamStep[chatId].step === 'askUserToUnspam') { + const username = msg.text.trim().replace('@', ''); // Entferne das @-Zeichen + + // Benutzer in der users.json anhand des Namens finden + const users = loadUsers(); // Lädt alle Benutzer + const targetUser = users.find(user => user.name.toLowerCase() === username.toLowerCase()); + + if (!targetUser) { + bot.sendMessage(chatId, `❌ Benutzer ${username} nicht gefunden. Bitte erneut versuchen.`); + return; + } + + const targetUserId = targetUser.id; + + // Überprüfen, ob der Benutzer gesperrt ist + if (!isUserSpammed(targetUserId)) { + bot.sendMessage(chatId, `❌ Benutzer @${targetUser.name} ist nicht gesperrt.`); + } else { + // Benutzer entsperren + delete spammedUsers[targetUserId]; + saveSpammedUsers(spammedUsers); // Gesperrte Benutzer aktualisieren + + bot.sendMessage(chatId, `✅ Benutzer @${targetUser.name} wurde erfolgreich entsperrt.`); + } + + // Bereinige den Schritt + delete spamStep[chatId]; + } +}); + + +// Funktion zum Senden der Nachricht an alle Admins +const notifyAdmins = (message) => { + Object.keys(admins).forEach(adminId => { + const adminInfo = admins[adminId]; + bot.sendMessage(adminId, message).catch(error => { + console.error(`Fehler beim Senden der Nachricht an Admin ${adminInfo.name} (${adminId}):`, error); + }); + }); +}; + +// Funktion zum Senden der Nachricht an alle Admins +const notifyAllAdmins = (message) => { + Object.keys(admins).forEach(adminId => { + const adminInfo = admins[adminId]; + bot.sendMessage(adminId, `🚨 *WICHTIG:* Ein Benutzer hat ein Problem gemeldet:\n\n${message}`, { parse_mode: 'Markdown' }); + }); +}; + +// Reaktion auf den /escalation-Befehl +bot.onText(/\/escalation/, (msg) => { + const chatId = msg.chat.id; + const userId = msg.from.id.toString(); + + // Überprüfen, ob der Befehl während des Wartungsmodus ausgeführt werden kann + if (!canExecuteCommand(userId)) { + bot.sendMessage(chatId, '🔧 Der Bot befindet sich derzeit im Wartungsmodus. Bitte versuche es später erneut.'); + return; + } + + if (isUserSpammed(userId)) { + bot.sendMessage(chatId, '❌ Du wurdest gesperrt und kannst diesen Befehl nicht verwenden.'); + return; + } + + // Frage nach dem Problem + bot.sendMessage(chatId, 'Bitte beschreibe dein Problem:'); + spamStep[chatId] = { step: 'askProblem' }; +}); + +// Antwort auf die Eingabe des Problems +bot.on('message', (msg) => { + const chatId = msg.chat.id; + + if (spamStep[chatId]) { + const currentStep = spamStep[chatId].step; + + if (currentStep === 'askProblem') { + const problemDescription = msg.text.trim(); + + // Nachricht an alle Admins senden + notifyAllAdmins(problemDescription); + + bot.sendMessage(chatId, '✅ Dein Problem wurde an alle Admins weitergeleitet.'); + + // Bereinige den Schritt + delete spamStep[chatId]; + } + } +}); + +// Nachrichtenevent abfangen, um @admin zu erkennen und Admins zu benachrichtigen +bot.on('message', (msg) => { + const chatId = msg.chat.id; + const messageId = msg.message_id; + + // Überprüfen, ob die Nachricht @admin enthält + if (msg.text && msg.text.includes('@admin')) { + const messageContent = `User: @${msg.from.username}\n`; + + // Der Link zur Nachricht: Für Gruppen oder Kanäle muss die Chat-ID in der Form -100xxxxxxxxxxxxx dargestellt werden. + const messageLink = `https://t.me/c/${chatId.toString().replace('-100', '')}/${messageId}`; + + // Admins benachrichtigen + notifyAdmins(`🚨 *@admin wurde im Chat erwähnt:*\n\n${messageContent}\nLink: [Zur Nachricht]\n(${messageLink})`); + + // Bestätigung an den Benutzer senden + bot.sendMessage(chatId, 'Die Admins wurden über deine Nachricht informiert.'); + } +}); + +// Schritt-für-Schritt-Tutorial +const tutorialSteps = [ + { + command: '/help', + text: 'Der Befehl /help zeigt dir eine Übersicht aller verfügbaren Befehle des Bots an. Dies ist besonders nützlich, wenn du nicht sicher bist, welche Funktionen der Bot bietet oder wie du bestimmte Aufgaben ausführen kannst. Die Hilfe-Nachricht enthält eine kurze Beschreibung jedes Befehls, damit du schnell herausfinden kannst, was du tun möchtest.' + }, + { + command: '/links', + text: 'Mit dem Befehl /links kannst du eine Liste von gespeicherten Links einsehen, die für dich nützlich sein könnten. Diese Links können zu wichtigen Ressourcen, Websites oder anderen relevanten Informationen führen, die dir helfen, deine Aufgaben effizienter zu erledigen.' + }, + { + command: '/faq', + text: 'Der Befehl /faq zeigt dir die häufig gestellten Fragen (FAQ) an. Hier findest du Antworten auf die Fragen, die oft von anderen Benutzern gestellt werden. Dies ist hilfreich, um schnelle Antworten auf allgemeine Fragen zu erhalten, ohne auf direkten Support angewiesen zu sein.' + }, + { + command: '/create_ticket', + text: 'Mit dem Befehl /create_ticket kannst du ein Support-Ticket erstellen, wenn du Hilfe oder Unterstützung benötigst. Das Ticket wird an das Support-Team weitergeleitet, das deine Anfrage bearbeiten wird. Dieser Befehl ist besonders nützlich, wenn du ein spezifisches Problem hast, das gelöst werden muss.' + }, + { + command: '/admin', + text: 'Der Befehl /admin zeigt dir eine Liste aller Administratoren des Bots sowie deren aktuellen Status an. Hier kannst du sehen, wer für die Verwaltung des Bots zuständig ist und ob diese Admins gerade verfügbar sind, um dir zu helfen.' + }, + { + command: '/chat', + text: 'Mit dem Befehl /chat kannst du einen Chat mit einem Administrator anfordern. Wenn du direkte Hilfe oder eine persönliche Beratung benötigst, kannst du diesen Befehl verwenden, um ein Gespräch mit einem Admin zu initiieren und deine Anliegen direkt zu besprechen.' + }, + { + command: '/info', + text: 'Der Befehl /info gibt dir grundlegende Informationen über den Bot. Dies kann Details zu den Funktionen des Bots, seine Hauptziele oder andere nützliche Informationen umfassen, die dir helfen, den Bot besser zu verstehen und seine Möglichkeiten voll auszuschöpfen.' + }, + { + command: '/rate', + text: 'Mit dem Befehl /rate kannst du den Support bewerten, den du erhalten hast. Dies ermöglicht es dem Bot-Team, Feedback zu sammeln und den Service kontinuierlich zu verbessern. Deine Bewertung hilft uns, die Qualität des Supports zu gewährleisten und anzupassen.' + }, + { + command: '/einladung', + text: 'Der Befehl /einladung erstellt einen persönlichen Einladungslink. Diesen Link kannst du an andere weitergeben, um sie einzuladen oder zu einer bestimmten Gruppe oder einem Kanal hinzuzufügen. Ideal, wenn du neue Benutzer oder Teilnehmer in deine Community integrieren möchtest.' + }, + { + command: '/termin', + text: 'Mit dem Befehl /termin kannst du einen Chat-Termin mit einem Administrator vereinbaren. Dies ermöglicht dir, einen spezifischen Zeitpunkt zu wählen, um mit einem Admin zu sprechen, anstatt auf eine spontane Verfügbarkeit zu warten.' + }, + { + command: '/report', + text: 'Der Befehl /report ermöglicht es dir, eine Nachricht an die Admins zu melden. Wenn du auf ein Problem oder einen Vorfall stößt, den du den Admins mitteilen möchtest, kannst du diesen Befehl verwenden, um eine Meldung zu erstellen, die von den Admins überprüft wird.' + }, + { + command: '/escalation', + text: 'Mit dem Befehl /escalation kannst du ein Problem an alle Administratoren melden. Dies ist besonders nützlich, wenn du ein dringendes oder kritisches Problem hast, das sofortige Aufmerksamkeit von mehreren Admins erfordert. Deine Meldung wird an alle Admins weitergeleitet.' + }, + { + command: '/terms', + text: 'Der Befehl /terms zeigt dir die Nutzungsbedingungen des Bots an. Diese Bedingungen umfassen die Regeln und Richtlinien, die du beim Verwenden des Bots beachten musst. Es ist wichtig, diese Bedingungen zu kennen, um sicherzustellen, dass du den Bot korrekt und gemäß den festgelegten Richtlinien nutzt.' + }, + { + command: '/cancel_termin', + text: 'Mit dem Befehl /cancel_termin kannst du einen bereits vereinbarten Chat-Termin stornieren. Falls du nicht mehr an dem Termin teilnehmen kannst oder ihn aus einem anderen Grund absagen musst, kannst du diesen Befehl verwenden, um den Termin zu annullieren.' + }, +]; + +let stepIndex = 0; +let currentChatId = null; + +bot.onText(/\/tutorial/, (msg) => { + const chatId = msg.chat.id; + currentChatId = chatId; // Speichern der Chat-ID + stepIndex = 0; // Zurücksetzen des Schritts auf 0 + sendTutorialStep(chatId); +}); + +const sendTutorialStep = (chatId) => { + if (stepIndex < tutorialSteps.length) { + const step = tutorialSteps[stepIndex]; + const message = `**Schritt ${stepIndex + 1}:**\n\n${step.text}\n\nTippe ${step.command}, um diesen Befehl zu testen.`; + + bot.sendMessage(chatId, message, { + reply_markup: { + inline_keyboard: [ + [{ text: 'Weiter', callback_data: 'next_step' }] + ] + } + }); + } else { + bot.sendMessage(chatId, 'Das Tutorial ist abgeschlossen! Wenn du weitere Fragen hast, verwende den Befehl /help.'); + } +}; + +bot.on('callback_query', (callbackQuery) => { + const chatId = callbackQuery.message.chat.id; + const data = callbackQuery.data; + + if (data === 'next_step' && chatId === currentChatId) { + stepIndex++; + sendTutorialStep(chatId); + } +}); + +bot.onText(/\/(help|links|faq|create_ticket|admin|chat|info|rate|einladung|termin|report|escalation|terms|cancel_termin)/, (msg) => { + const chatId = msg.chat.id; + + if (chatId === currentChatId) { + bot.sendMessage(chatId, `Du hast den Befehl ${msg.text} verwendet. Bitte tippe "Weiter", um den nächsten Schritt im Tutorial zu beginnen.`, { + reply_markup: { + inline_keyboard: [ + [{ text: 'Weiter', callback_data: 'next_step' }] + ] + } + }); + } +}); + console.log('Support-Bot mit Statusprüfung und Benachrichtigungen läuft...'); \ No newline at end of file