diff --git a/index-bot.js b/index-bot.js new file mode 100644 index 0000000..185095c --- /dev/null +++ b/index-bot.js @@ -0,0 +1,439 @@ +require('dotenv').config(); // .env Datei laden + +const axios = require('axios'); +const fs = require('fs'); +const path = require('path'); +const express = require('express'); +const app = express(); +const PORT = process.env.PORT || 3000; + +// Funktion zum Suchen von Inhalten in einer Liste basierend auf dem Suchbegriff +function searchContent(list, query) { + return list.filter(item => item.topic.toLowerCase().includes(query.toLowerCase())); +} + +// Öffentlichen Ordner für HTML und CSS bereitstellen +app.use(express.static('public')); + +// Bot-API-Token aus der .env Datei laden +const token = process.env.BOT_TOKEN; + +// Telegram Bot API URL +const apiUrl = `https://api.telegram.org/bot${token}`; + +// Benutzer, die den /add Befehl nutzen dürfen +const allowedUsers = process.env.ALLOWED_USERS.split(','); + +// Variablen zur Speicherung der Buttons und der Eingabeschritte +let filmList = loadButtonsFromFile('film'); +let serienList = loadButtonsFromFile('serien'); +let kinderfilmeList = loadButtonsFromFile('kinderfilme'); +let animeList = loadButtonsFromFile('anime'); +let animeSerienList = loadButtonsFromFile('animeserien'); // Hinzugefügt: Anime-Serien +let jahreszeitenZauberList = loadButtonsFromFile('jahreszeitenzauber'); // Hinzugefügt: Jahreszeiten-Zauber +let userSteps = {}; + +// Funktion zum Laden der Buttons aus einer JSON-Datei je nach Kategorie +function loadButtonsFromFile(category) { + const filePath = path.join(__dirname, `${category}.json`); + if (fs.existsSync(filePath)) { + try { + const fileData = fs.readFileSync(filePath, 'utf-8'); + return JSON.parse(fileData); + } catch (err) { + console.error(`Fehler beim Laden der ${category}-Datei:`, err.message); + } + } + return []; // Leere Liste zurückgeben +} + +// Funktion zum Speichern der Buttons in einer Datei für eine Kategorie +function saveButtonsToFile(categoryList, category) { + const filePath = path.join(__dirname, `${category}.json`); + // Bestehende Einträge laden und neue Einträge anfügen + fs.writeFileSync(filePath, JSON.stringify(categoryList, null, 2), 'utf-8'); +} + +// Funktion zum Senden einer Nachricht an Telegram +function sendMessage(chatId, text, replyMarkup) { + const url = `${apiUrl}/sendMessage`; + const data = { + chat_id: chatId, + text: text, + reply_markup: replyMarkup, + }; + return axios.post(url, data); +} + +// Funktion zum Senden eines Inline-Keyboards +function sendInlineKeyboard(chatId, text, buttons) { + const url = `${apiUrl}/sendMessage`; + const data = { + chat_id: chatId, + text: text, + reply_markup: { + inline_keyboard: buttons + } + }; + return axios.post(url, data); +} + +// Funktion zum Erstellen eines Inline-Keyboards für das Inhaltsverzeichnis +function createInlineButtons(list) { + const buttons = []; + let row = []; + + list.forEach(item => { + const button = { text: item.topic, url: item.link }; + + // Falls das Thema unter 25 Zeichen hat, wird versucht, einen weiteren Button in die gleiche Zeile zu setzen + if (item.topic.length <= 25) { + row.push(button); + if (row.length === 2) { + buttons.push(row); + row = []; + } + } else { + // Falls das Thema mehr als 25 Zeichen hat, kommt der Button alleine in eine Zeile + buttons.push([button]); + } + }); + + // Verbleibende Buttons, die nicht hinzugefügt wurden, in einer letzten Zeile speichern + if (row.length > 0) buttons.push(row); + + return buttons; +} + +// Funktion zum Verarbeiten der Updates +async function processUpdates(updates) { + for (const update of updates) { + const { message, callback_query } = update; + + if (message && message.text) { + const { chat, text } = message; + + // Wenn der Benutzer den /start Befehl eingibt + if (text === '/start') { + await sendMessage( + chat.id, + "🎉 **Willkommen beim Bot!** 🌟\n\n" + + "🔍 **Entdecke spannende Inhalte:**\n" + + "Nutze den Befehl `/index`, um das Inhaltsverzeichnis aufzurufen und eine Kategorie auszuwählen, die dich interessiert.\n\n" + + "📌 **Funktionen:**\n" + + "- Durchsuche Inhalte mit `/search`\n" + + "- Erhalte Infos mit `/info`\n\n" + + "💡 **Tipp:** Du kannst jederzeit `/help` eingeben, um eine Übersicht über alle Befehle zu erhalten.\n\n" + + "Viel Spaß! 🚀" + ); + } + + // Wenn der Benutzer den /help Befehl eingibt + if (text === '/help') { + await sendMessage( + chat.id, + "📖 **Hilfe & Befehlsübersicht**\n\n" + + "Hier sind alle verfügbaren Befehle:\n\n" + + "📌 **Allgemeine Befehle:**\n" + + "- `/start` - Begrüßung und Einführung in den Bot.\n" + + "- `/help` - Zeigt diese Übersicht an.\n" + + "- `/index` - Zeigt das Inhaltsverzeichnis mit Kategorien.\n" + + "- `/info` - Zeigt die Anzahl der Buttons pro Kategorie.\n\n" + + "🔍 **Erweiterte Funktionen:**\n" + + "- `/search` - Suche nach Inhalten basierend auf einem Stichwort.\n\n" + + "👮 **Admin-Befehle:**\n" + + "- `/add` - Fügt neue Buttons hinzu (nur für berechtigte Nutzer).\n" + + "- `/reload` - Lädt die Button-Daten neu (nur für berechtigte Nutzer).\n\n" + + "💡 **Tipp:**\n" + + "Erkunde das Inhaltsverzeichnis mit `/index` oder suche direkt mit `/search`. Viel Spaß beim Entdecken! 🚀" + ); + } + + // Wenn der Benutzer den /index Befehl eingibt + else if (text === '/index') { + // Zeige die Kategorie-Buttons + const categoryButtons = [ + [ + { text: '🎬 Film', callback_data: 'index_film' }, + { text: '📺 Serien', callback_data: 'index_serien' }, + ], + + [ + { text: '🧸 Kinderfilme', callback_data: 'index_kinderfilme' }, + { text: '🍿 Anime', callback_data: 'index_anime' }, + ], + + [ + { text: '🎥 Anime-Serien', callback_data: 'index_animeserien' }, + { text: '🌸 Jahreszeiten-Zauber', callback_data: 'index_jahreszeitenzauber' }, + ], + + // Hinzugefügter Button für die Suche + [ + { text: '🔍 Suche', callback_data: 'search' } + ] + ]; + await sendInlineKeyboard(chat.id, '🗂️ Wähle eine Kategorie oder starte eine Suche:', categoryButtons); + } + + // Wenn der Benutzer den Befehl /add eingibt + else if (text === '/add') { + // Überprüfen, ob der Benutzer berechtigt ist + if (!allowedUsers.includes(chat.id.toString())) { + await sendMessage(chat.id, "❌ Du hast keine Berechtigung, den /add Befehl zu verwenden."); + return; + } + + const addCategoryButtons = [ + [ + { text: '🎬 Film', callback_data: 'add_film' }, + { text: '📺 Serien', callback_data: 'add_serien' }, + ], + + [ + { text: '🧸 Kinderfilme', callback_data: 'add_kinderfilme' }, + { text: '🍿 Anime', callback_data: 'add_anime' }, + ], + + [ + { text: '🎥 Anime-Serien', callback_data: 'add_animeserien' }, // Hinzugefügt: Anime-Serien + { text: '🌸 Jahreszeiten-Zauber', callback_data: 'add_jahreszeitenzauber' }, // Hinzugefügt: Jahreszeiten-Zauber + ] + ]; + await sendInlineKeyboard(chat.id, '🗂️ Wähle die Kategorie für den neuen Button:', addCategoryButtons); + } + + else if (text === '/info') { + // Zähle die Anzahl der Buttons pro Kategorie + const categoryInfo = { + "🎬 Film": filmList.length, + "📺 Serien": serienList.length, + "🧸 Kinderfilme": kinderfilmeList.length, + "🍿 Anime": animeList.length, + "🎥 Anime-Serien": animeSerienList.length, + "🌸 Jahreszeiten-Zauber": jahreszeitenZauberList.length + }; + + let infoMessage = "📊 **Info über die Anzahl der Filme pro Kategorie**:\n\n\n"; + + // Füge die Anzahl der Buttons für jede Kategorie zur Nachricht hinzu + for (const [category, count] of Object.entries(categoryInfo)) { + infoMessage += `${category}: ${count} Film(e)\n\n`; + } + + // Sende die Nachricht + await sendMessage(chat.id, infoMessage); + } + + + // **Hier fügst du den /reload Befehl ein** + else if (text === '/reload') { + // Überprüfen, ob der Benutzer berechtigt ist + if (!allowedUsers.includes(chat.id.toString())) { + await sendMessage(chat.id, "❌ Du hast keine Berechtigung, den /reload Befehl zu verwenden."); + return; + } + + // Alle Listen neu laden + filmList = loadButtonsFromFile('film'); + serienList = loadButtonsFromFile('serien'); + kinderfilmeList = loadButtonsFromFile('kinderfilme'); + animeList = loadButtonsFromFile('anime'); + animeSerienList = loadButtonsFromFile('animeserien'); + jahreszeitenZauberList = loadButtonsFromFile('jahreszeitenzauber'); + + // Bestätigung senden + await sendMessage(chat.id, "✅ Alle Buttons wurden neu geladen."); + } + + // Wenn der Benutzer einen Suchbegriff eingibt + else if (userSteps[chat.id] && userSteps[chat.id].step === 'searchQuery') { + const query = text; + + // Alle Listen zusammenfassen, die durchsucht werden sollen + const allLists = [...filmList, ...serienList, ...kinderfilmeList, ...animeList, ...animeSerienList, ...jahreszeitenZauberList]; + + // Suche nach Übereinstimmungen in allen Listen + const results = searchContent(allLists, query); + + // Wenn keine Treffer gefunden wurden + if (results.length === 0) { + await sendMessage(chat.id, `‼️ Keine Ergebnisse für "${query}" gefunden.`); + } else { + const buttons = createInlineButtons(results); + await sendInlineKeyboard(chat.id, `🔍 Ergebnisse für "${query}":`, buttons); + } + + // Schritt zurücksetzen + delete userSteps[chat.id]; + } + + // Wenn der Benutzer den Button-Text eingibt (für /add) + else if (userSteps[chat.id] && userSteps[chat.id].step === 'buttonText') { + const buttonText = text; + userSteps[chat.id].buttonText = buttonText; + userSteps[chat.id].step = 'buttonLink'; + await sendMessage(chat.id, '🔗 Jetzt gib den Link zur Nachricht ein:'); + } + + // Wenn der Benutzer den Link eingibt (für /add) + else if (userSteps[chat.id] && userSteps[chat.id].step === 'buttonLink') { + const buttonLink = text; + const buttonText = userSteps[chat.id].buttonText; + const category = userSteps[chat.id].category; + + // Den Button zur richtigen Kategorie hinzufügen + let categoryList; + switch (category) { + case 'film': + filmList.push({ topic: buttonText, link: buttonLink }); + categoryList = filmList; + break; + case 'serien': + serienList.push({ topic: buttonText, link: buttonLink }); + categoryList = serienList; + break; + case 'kinderfilme': + kinderfilmeList.push({ topic: buttonText, link: buttonLink }); + categoryList = kinderfilmeList; + break; + case 'anime': + animeList.push({ topic: buttonText, link: buttonLink }); + categoryList = animeList; + break; + case 'animeserien': + animeSerienList.push({ topic: buttonText, link: buttonLink }); + categoryList = animeSerienList; // Hinzugefügt: Anime-Serien + break; + case 'jahreszeitenzauber': + jahreszeitenZauberList.push({ topic: buttonText, link: buttonLink }); + categoryList = jahreszeitenZauberList; // Hinzugefügt: Jahreszeiten-Zauber + break; + } + + saveButtonsToFile(categoryList, category); + await sendMessage(chat.id, `✅ Button mit dem Text "${buttonText}" und Link "${buttonLink}" wurde zu ${category} hinzugefügt!`); + + // Schritt zurücksetzen + delete userSteps[chat.id]; + } + } + + else if (callback_query && callback_query.data === 'search') { + const chatId = callback_query.message.chat.id; // Extrahiere die chat.id aus der callback_query + await sendMessage(chatId, "🔍 Gib den Suchbegriff ein, nach dem du suchen möchtest:"); + userSteps[chatId] = { step: 'searchQuery' }; // Wechsle in den Suchmodus + } + + // Wenn der Benutzer eine Kategorie für das Inhaltsverzeichnis auswählt + else if (callback_query) { + const { data, message } = callback_query; + const chatId = message.chat.id; + + // Unbekannte Callback-Daten + if (!data.startsWith('index_') && !data.startsWith('add_') && data !== 'search') { + await sendMessage(chatId, '❌ Unbekannter Befehl.'); + return; + } + + // Kategorie basierend auf dem Callback-Datenwert laden + let selectedList; + let categoryName; + + // Kategorien für den Index + if (data === 'index_film') { + filmList = loadButtonsFromFile('film'); + selectedList = filmList; + categoryName = 'Film'; + } else if (data === 'index_serien') { + serienList = loadButtonsFromFile('serien'); + selectedList = serienList; + categoryName = 'Serien'; + } else if (data === 'index_kinderfilme') { + kinderfilmeList = loadButtonsFromFile('kinderfilme'); + selectedList = kinderfilmeList; + categoryName = 'Kinderfilme'; + } else if (data === 'index_anime') { + animeList = loadButtonsFromFile('anime'); + selectedList = animeList; + categoryName = 'Anime'; + } else if (data === 'index_animeserien') { // Hinzugefügt: Anime-Serien + animeSerienList = loadButtonsFromFile('animeserien'); + selectedList = animeSerienList; + categoryName = 'Anime-Serien'; + } else if (data === 'index_jahreszeitenzauber') { // Hinzugefügt: Jahreszeiten-Zauber + jahreszeitenZauberList = loadButtonsFromFile('jahreszeitenzauber'); + selectedList = jahreszeitenZauberList; + categoryName = 'Jahreszeiten-Zauber'; + } + + // Kategorien für /add + if (data.startsWith('add_')) { + const category = data.split('_')[1]; + userSteps[chatId] = { step: 'buttonText', category }; + await sendMessage(chatId, '✍️ Bitte gib den Button-Text ein:'); + } + + if (selectedList && selectedList.length === 0) { + await sendMessage(chatId, `‼️ Das Inhaltsverzeichnis für ${categoryName} ist leer.`); + } else if (selectedList) { + const buttons = createInlineButtons(selectedList); + await sendInlineKeyboard(chatId, `📚 Inhaltsverzeichnis für ${categoryName}:`, buttons); + } + } + } +} + +// Funktion zum Abfragen neuer Updates +async function getUpdates(offset) { + const url = `${apiUrl}/getUpdates?offset=${offset}&timeout=60`; + const response = await axios.get(url); + const { data } = response; + const updates = data.result; + if (updates.length > 0) { + const lastUpdateId = updates[updates.length - 1].update_id; + processUpdates(updates); + return lastUpdateId + 1; + } + return offset; +} + +// API-Endpunkt +app.get('/api/categories', (req, res) => { + try { + const categories = { + film: filmList, + serien: serienList, + kinderfilme: kinderfilmeList, + anime: animeList, + animeSerien: animeSerienList, + jahreszeitenZauber: jahreszeitenZauberList + }; + res.json(categories); + } catch (err) { + console.error('Fehler beim Abrufen der Kategorien:', err); + res.status(500).json({ error: 'Fehler beim Abrufen der Kategorien.' }); + } +}); + +// Server starten +app.listen(PORT, () => { + console.log(`Server läuft auf http://localhost:${PORT}`); +}); + +// Hauptfunktion zum Starten des Bots +async function startBot() { + let offset = 0; + while (true) { + try { + offset = await getUpdates(offset); + } catch (err) { + console.error('Fehler beim Abrufen der Updates:', err); + } + // Pause von 1 Sekunde zwischen den Anfragen + await new Promise(resolve => setTimeout(resolve, 1000)); + } +} + +// Bot starten +startBot().catch(err => console.error('Fehler beim Starten des Bots:', err)); \ No newline at end of file