2024-08-15 17:40:21 +00:00
|
|
|
|
require('dotenv').config();
|
|
|
|
|
|
|
|
|
|
const TelegramBot = require('node-telegram-bot-api');
|
|
|
|
|
const axios = require('axios');
|
|
|
|
|
const fs = require('fs');
|
|
|
|
|
const yaml = require('yamljs');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const dayjs = require('dayjs');
|
|
|
|
|
const dayOfYear = require('dayjs/plugin/dayOfYear'); // Importiere das Plugin
|
|
|
|
|
const express = require('express');
|
|
|
|
|
const bodyParser = require('body-parser');
|
|
|
|
|
const NodeCache = require('node-cache');
|
|
|
|
|
const schedule = require('node-schedule');
|
|
|
|
|
const moment = require('moment');
|
|
|
|
|
|
|
|
|
|
const CacheDir = path.join(__dirname, 'Cache');
|
|
|
|
|
const cacheFilePath = path.join(CacheDir, 'cache.json');
|
|
|
|
|
|
|
|
|
|
// Setze PROJECT_ROOT auf das aktuelle Verzeichnis
|
|
|
|
|
const PROJECT_ROOT = __dirname;
|
|
|
|
|
|
|
|
|
|
// Konstanten aus .env-Datei
|
|
|
|
|
const BOT_TOKEN = process.env.BOT_TOKEN;
|
|
|
|
|
const PLEX_TOKEN = process.env.PLEX_TOKEN;
|
|
|
|
|
const PLEX_DOMAIN = process.env.PLEX_DOMAIN;
|
|
|
|
|
const PLEX_LIBRARY_URL = `${PLEX_DOMAIN}/library/sections/all?X-Plex-Token=${PLEX_TOKEN}`;
|
|
|
|
|
const USER_YML_PATH = path.resolve(PROJECT_ROOT, process.env.USER_YML_PATH);
|
|
|
|
|
const LOG_DIR = path.resolve(PROJECT_ROOT, process.env.LOG_DIR);
|
|
|
|
|
const ERROR_LOG_PATH = path.resolve(LOG_DIR, process.env.ERROR_LOG_PATH);
|
|
|
|
|
const PORT = process.env.PORT;
|
|
|
|
|
const USER1_ID = process.env.USER1_ID;
|
|
|
|
|
const USER2_ID = process.env.USER2_ID;
|
|
|
|
|
const WEBHOOK_URL = process.env.WEBHOOK_URL;
|
|
|
|
|
|
|
|
|
|
// Debug-Ausgaben für Pfade
|
|
|
|
|
console.log('USER_YML_PATH:', USER_YML_PATH);
|
|
|
|
|
console.log('LOG_DIR:', LOG_DIR);
|
|
|
|
|
console.log('ERROR_LOG_PATH:', ERROR_LOG_PATH);
|
|
|
|
|
|
|
|
|
|
// Sicherstellen, dass Verzeichnisse und Dateien existieren
|
|
|
|
|
if (!fs.existsSync(LOG_DIR)) {
|
|
|
|
|
fs.mkdirSync(LOG_DIR, { recursive: true });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fs.existsSync(USER_YML_PATH)) {
|
|
|
|
|
fs.writeFileSync(USER_YML_PATH, yaml.stringify({}, 4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fs.existsSync(ERROR_LOG_PATH)) {
|
|
|
|
|
fs.writeFileSync(ERROR_LOG_PATH, ''); // Leere Datei erstellen
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Erstelle den Cache-Ordner, falls er nicht existiert
|
|
|
|
|
if (!fs.existsSync(CacheDir)) {
|
|
|
|
|
fs.mkdirSync(CacheDir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialisiere den Cache mit einer bestimmten Lebensdauer (TTL) von 1 Stunde
|
|
|
|
|
const cache = new NodeCache({ stdTTL: 3600 });
|
|
|
|
|
|
|
|
|
|
// Funktion zum Speichern des Caches in eine Datei
|
|
|
|
|
function saveCacheToFile() {
|
|
|
|
|
const cacheData = cache.keys().reduce((acc, key) => {
|
|
|
|
|
acc[key] = cache.get(key);
|
|
|
|
|
return acc;
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
fs.writeFileSync(cacheFilePath, JSON.stringify(cacheData));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Laden des Caches aus einer Datei
|
|
|
|
|
function loadCacheFromFile() {
|
|
|
|
|
if (fs.existsSync(cacheFilePath)) {
|
|
|
|
|
const cacheData = JSON.parse(fs.readFileSync(cacheFilePath));
|
|
|
|
|
for (const [key, value] of Object.entries(cacheData)) {
|
|
|
|
|
cache.set(key, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen von Plex-Daten
|
|
|
|
|
async function fetchPlexData(url) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(url, {
|
|
|
|
|
headers: {
|
|
|
|
|
'X-Plex-Token': PLEX_TOKEN
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return response.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching Plex data: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen aller Filme
|
|
|
|
|
async function fetchAllMovies() {
|
|
|
|
|
try {
|
|
|
|
|
const sectionsData = await fetchPlexData(PLEX_LIBRARY_URL);
|
|
|
|
|
const sections = sectionsData.MediaContainer.Directory;
|
|
|
|
|
|
|
|
|
|
let movies = [];
|
|
|
|
|
|
|
|
|
|
for (const section of sections) {
|
|
|
|
|
const sectionUrl = `${PLEX_DOMAIN}/library/sections/${section.key}/all?X-Plex-Token=${PLEX_TOKEN}`;
|
|
|
|
|
const sectionData = await fetchPlexData(sectionUrl);
|
|
|
|
|
|
|
|
|
|
if (sectionData.MediaContainer && sectionData.MediaContainer.Metadata) {
|
|
|
|
|
const metadata = sectionData.MediaContainer.Metadata;
|
|
|
|
|
movies = movies.concat(metadata.filter(media => media.type === 'movie'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
movies.sort((a, b) => (b.addedAt || 0) - (a.addedAt || 0));
|
|
|
|
|
|
|
|
|
|
return movies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching all movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der Filme mit Caching
|
|
|
|
|
async function fetchMoviesWithCache() {
|
|
|
|
|
const cacheKey = 'allMovies';
|
|
|
|
|
const cachedMovies = cache.get(cacheKey);
|
|
|
|
|
|
|
|
|
|
if (cachedMovies) {
|
|
|
|
|
logMessage('Movies fetched from cache');
|
|
|
|
|
return cachedMovies;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchAllMovies();
|
|
|
|
|
cache.set(cacheKey, movies);
|
|
|
|
|
logMessage('Movies fetched from API and cached');
|
|
|
|
|
return movies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen eines zufälligen Films mit Caching
|
|
|
|
|
async function fetchRandomMovie() {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchMoviesWithCache();
|
|
|
|
|
if (movies.length === 0) return null;
|
|
|
|
|
|
|
|
|
|
const randomIndex = Math.floor(Math.random() * movies.length);
|
|
|
|
|
return movies[randomIndex];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching random movie: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Durchführen der Filmsuche mit Caching
|
|
|
|
|
async function searchMovies(query) {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchMoviesWithCache();
|
|
|
|
|
const results = movies.filter(movie =>
|
|
|
|
|
movie.title.toLowerCase().includes(query.toLowerCase())
|
|
|
|
|
);
|
|
|
|
|
return results;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error searching movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der gut bewerteten Filme mit Caching
|
|
|
|
|
async function fetchTopRatedMovies() {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchMoviesWithCache();
|
|
|
|
|
const ratedMovies = movies.filter(movie => movie.rating && movie.rating > 0);
|
|
|
|
|
ratedMovies.sort((a, b) => (b.rating || 0) - (a.rating || 0));
|
|
|
|
|
return ratedMovies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching top-rated movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen des Films des Tages mit Caching
|
|
|
|
|
async function fetchDailyRecommendation() {
|
|
|
|
|
try {
|
|
|
|
|
const ratedMovies = await fetchTopRatedMovies();
|
|
|
|
|
if (ratedMovies.length === 0) return null;
|
|
|
|
|
|
|
|
|
|
dayjs.extend(dayOfYear); // Füge das Plugin hier hinzu
|
|
|
|
|
const dayOfYear = dayjs().dayOfYear();
|
|
|
|
|
const todayIndex = dayOfYear % ratedMovies.length;
|
|
|
|
|
return ratedMovies[todayIndex];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching daily recommendation: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der letzten 10 hinzugefügten Filme mit Caching
|
|
|
|
|
async function fetchLatest10Movies() {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchMoviesWithCache();
|
|
|
|
|
const sortedMovies = movies
|
|
|
|
|
.filter(movie => movie.addedAt)
|
|
|
|
|
.sort((a, b) => b.addedAt - a.addedAt)
|
|
|
|
|
.slice(0, 10);
|
|
|
|
|
|
|
|
|
|
return sortedMovies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching latest 10 movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum automatischen Aktualisieren des Caches
|
|
|
|
|
async function updateCache() {
|
|
|
|
|
try {
|
|
|
|
|
await fetchMoviesWithCache(); // Stellt sicher, dass der Cache aktualisiert wird
|
|
|
|
|
logMessage('Cache wurde automatisch aktualisiert');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Fehler beim automatischen Aktualisieren des Caches: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lade den Cache beim Start
|
|
|
|
|
(async function start() {
|
|
|
|
|
try {
|
|
|
|
|
await fetchMoviesWithCache(); // Initialisiert den Cache beim Start
|
|
|
|
|
logMessage('Cache beim Start initialisiert');
|
|
|
|
|
|
|
|
|
|
// Speicher den Cache regelmäßig (z.B. jede Stunde)
|
|
|
|
|
schedule.scheduleJob('0 * * * *', saveCacheToFile);
|
|
|
|
|
|
|
|
|
|
// Plane die automatische Aktualisierung des Caches jede Stunde
|
|
|
|
|
schedule.scheduleJob('0 * * * *', updateCache);
|
|
|
|
|
|
|
|
|
|
// Beispiel für die Verwendung von node-schedule
|
|
|
|
|
function checkForNewMovies() {
|
|
|
|
|
// Hier könntest du eine Funktion zum Überprüfen neuer Filme einfügen
|
|
|
|
|
console.log('Checking for new movies...');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Beispiel für geplante Aufgaben
|
|
|
|
|
schedule.scheduleJob('*/1 * * * *', checkForNewMovies);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Fehler beim Start des Bots: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
// Telegram-Bot-Instanz erstellen
|
|
|
|
|
const bot = new TelegramBot(BOT_TOKEN, { polling: true });
|
|
|
|
|
|
|
|
|
|
// Express-Server für Webhooks
|
|
|
|
|
const app = express();
|
|
|
|
|
app.use(bodyParser.json());
|
|
|
|
|
|
|
|
|
|
// Funktion zum Protokollieren von allgemeinen Nachrichten
|
|
|
|
|
function logMessage(message) {
|
|
|
|
|
const today = dayjs().format('YYYY-MM-DD');
|
|
|
|
|
const logFilePath = path.join(LOG_DIR, `${today}.log`);
|
|
|
|
|
fs.appendFileSync(logFilePath, `${dayjs().format('HH:mm:ss')} - ${message}\n`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zur Fehlerprotokollierung
|
|
|
|
|
function logError(error) {
|
|
|
|
|
const errorMessage = `${dayjs().format('HH:mm:ss')} - Error: ${error}\n`;
|
|
|
|
|
fs.appendFileSync(ERROR_LOG_PATH, errorMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// /start-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/start/, (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
const userId = msg.from.id;
|
|
|
|
|
|
|
|
|
|
// Benutzerdaten in user.yml speichern
|
|
|
|
|
let users = yaml.load(USER_YML_PATH);
|
|
|
|
|
users[chatId] = { userId: userId, notifications: true }; // Standardmäßig Benachrichtigungen aktiviert
|
|
|
|
|
fs.writeFileSync(USER_YML_PATH, yaml.stringify(users, 4));
|
|
|
|
|
|
|
|
|
|
const welcomeMessage = `
|
|
|
|
|
Willkommen! Dein Zugang zum Bot wurde erfolgreich eingerichtet.
|
|
|
|
|
|
|
|
|
|
Um die verfügbaren Befehle anzuzeigen, tippe /help.
|
|
|
|
|
`;
|
|
|
|
|
bot.sendMessage(chatId, welcomeMessage);
|
|
|
|
|
|
|
|
|
|
// /start-Befehl protokollieren
|
|
|
|
|
logMessage(`Received /start command from chatId ${chatId} (userId ${userId})`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// /notification-on-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/notification_on/, (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
// Benutzerdaten in user.yml laden
|
|
|
|
|
let users = yaml.load(USER_YML_PATH);
|
|
|
|
|
if (users[chatId]) {
|
|
|
|
|
users[chatId].notifications = true;
|
|
|
|
|
fs.writeFileSync(USER_YML_PATH, yaml.stringify(users, 4));
|
|
|
|
|
bot.sendMessage(chatId, 'Benachrichtigungen wurden aktiviert.');
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Du musst den Bot zuerst mit /start aktivieren.');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// /notification-off-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/notification_off/, (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
// Benutzerdaten in user.yml laden
|
|
|
|
|
let users = yaml.load(USER_YML_PATH);
|
|
|
|
|
if (users[chatId]) {
|
|
|
|
|
users[chatId].notifications = false;
|
|
|
|
|
fs.writeFileSync(USER_YML_PATH, yaml.stringify(users, 4));
|
|
|
|
|
bot.sendMessage(chatId, 'Benachrichtigungen wurden deaktiviert.');
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Du musst den Bot zuerst mit /start aktivieren.');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let lastAddedMovieTime = null; // Variable zum Speichern des Zeitpunkts des letzten Films
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der letzten hinzugefügten Filme
|
|
|
|
|
async function fetchLatestMovies() {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`${PLEX_DOMAIN}/library/recentlyAdded?X-Plex-Token=${PLEX_TOKEN}`);
|
|
|
|
|
const movies = response.data.MediaContainer.Metadata;
|
|
|
|
|
|
|
|
|
|
if (movies && movies.length > 0) {
|
|
|
|
|
return movies;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [];
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`Error fetching latest movies: ${error.message}`);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Überprüfen und Benachrichtigen über neue Filme
|
|
|
|
|
async function checkForNewMovies() {
|
|
|
|
|
const movies = await fetchLatestMovies();
|
|
|
|
|
|
|
|
|
|
if (movies.length > 0) {
|
|
|
|
|
const latestMovie = movies[0];
|
|
|
|
|
|
|
|
|
|
if (!lastAddedMovieTime || dayjs.unix(latestMovie.addedAt).isAfter(lastAddedMovieTime)) {
|
|
|
|
|
// Neuer Film hinzugefügt
|
|
|
|
|
lastAddedMovieTime = dayjs.unix(latestMovie.addedAt);
|
|
|
|
|
|
|
|
|
|
const movieTitle = latestMovie.title || 'Unbekannt';
|
|
|
|
|
const movieSummary = latestMovie.summary || 'Keine Zusammenfassung verfügbar';
|
|
|
|
|
const movieThumb = latestMovie.thumb ? `${PLEX_DOMAIN}${latestMovie.thumb}?X-Plex-Token=${PLEX_TOKEN}` : '';
|
|
|
|
|
|
|
|
|
|
// Kürze die Zusammenfassung, wenn sie zu lang ist
|
|
|
|
|
const maxSummaryLength = 200; // Maximale Länge der Zusammenfassung
|
|
|
|
|
const truncatedSummary = movieSummary.length > maxSummaryLength
|
|
|
|
|
? `${movieSummary.substring(0, maxSummaryLength)}...`
|
|
|
|
|
: movieSummary;
|
|
|
|
|
|
|
|
|
|
const message = `Ein neuer Film wurde hinzugefügt:\n\nTitel: ${movieTitle}\n\nZusammenfassung:\n${truncatedSummary}`;
|
|
|
|
|
|
|
|
|
|
const users = yaml.load(USER_YML_PATH);
|
|
|
|
|
const sendMessages = Object.keys(users).map(chatId => {
|
|
|
|
|
if (users[chatId].notifications) {
|
|
|
|
|
if (movieThumb) {
|
|
|
|
|
// Wenn ein Bild vorhanden ist, sende es mit der Nachricht
|
|
|
|
|
return bot.sendPhoto(chatId, movieThumb, { caption: message }).catch(error => {
|
|
|
|
|
console.error(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// Wenn kein Bild vorhanden ist, sende nur die Nachricht
|
|
|
|
|
return bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
console.error(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}).filter(promise => promise !== undefined);
|
|
|
|
|
|
|
|
|
|
await Promise.all(sendMessages);
|
|
|
|
|
console.log(`Sent new movie message to all users`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Plane die Überprüfung alle 5 Minuten
|
|
|
|
|
schedule.scheduleJob('*/1 * * * *', checkForNewMovies);
|
|
|
|
|
|
|
|
|
|
// Initiale Überprüfung beim Start
|
|
|
|
|
checkForNewMovies();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /latestmovie-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/latestmovie/, async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchAllMovies();
|
|
|
|
|
const sortedMovies = movies
|
|
|
|
|
.filter(movie => movie.addedAt)
|
|
|
|
|
.sort((a, b) => b.addedAt - a.addedAt);
|
|
|
|
|
|
|
|
|
|
const latestMovie = sortedMovies[0];
|
|
|
|
|
if (latestMovie) {
|
|
|
|
|
const movieTitle = latestMovie.title || 'Unbekannt';
|
|
|
|
|
const movieSummary = latestMovie.summary || 'Keine Zusammenfassung verfügbar';
|
|
|
|
|
const addedAtDate = new Date((latestMovie.addedAt || 0) * 1000).toLocaleString(); // Konvertierung von Unix-Zeitstempel in lesbares Datum
|
|
|
|
|
const movieThumb = latestMovie.thumb ? `${PLEX_DOMAIN}${latestMovie.thumb}?X-Plex-Token=${PLEX_TOKEN}` : '';
|
|
|
|
|
|
|
|
|
|
const message = `Der zuletzt hinzugefügte Film ist:\n\nTitel: ${movieTitle}\n\nZusammenfassung: \n${movieSummary}\n\nHinzugefügt am: ${addedAtDate}`;
|
|
|
|
|
|
|
|
|
|
// Bild anzeigen, wenn vorhanden
|
|
|
|
|
if (movieThumb) {
|
|
|
|
|
bot.sendPhoto(chatId, movieThumb, { caption: message }).catch(error => {
|
|
|
|
|
logError(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent latest movie info to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Keine Filme gefunden.').catch(error => {
|
|
|
|
|
logError(`Error sending no movies message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No movies found for chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
bot.sendMessage(chatId, `Fehler beim Abrufen der neuesten Filme. Statuscode: ${error.response.status}`).catch(err => {
|
|
|
|
|
logError(`Error sending error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching latest movie: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
bot.sendMessage(chatId, 'Fehler beim Abrufen der neuesten Filme. Keine Antwort vom Server.').catch(err => {
|
|
|
|
|
logError(`Error sending no response message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching latest movie: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
logError(`Error fetching latest movie: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// /info-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/info/, async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
const plexDomain = process.env.PLEX_DOMAIN;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const {
|
|
|
|
|
movieCount,
|
|
|
|
|
showCount,
|
|
|
|
|
episodeCount,
|
|
|
|
|
seasonCount,
|
|
|
|
|
topGenre,
|
|
|
|
|
totalSize,
|
|
|
|
|
oldestMovie,
|
|
|
|
|
newestMovie
|
|
|
|
|
} = await fetchAllMedia();
|
|
|
|
|
|
|
|
|
|
const message = `In der Bibliothek befinden sich derzeit:\n\n` +
|
|
|
|
|
`📽️ Filme: ${movieCount}\n\n` +
|
|
|
|
|
`📺 Serien: ${showCount}\n\n` +
|
|
|
|
|
`🎞️ Episoden: ${episodeCount}\n\n` +
|
|
|
|
|
`📚 Staffeln: ${seasonCount}\n\n\n` +
|
|
|
|
|
`📊 Top-Genre: ${topGenre}\n\n` +
|
|
|
|
|
`💾 Gesamtgröße: ${totalSize}\n\n\n` +
|
|
|
|
|
`⏳ Ältester Film: ${oldestMovie.title} (${oldestMovie.year})\n\n` +
|
|
|
|
|
`🆕 Neuester Film: ${newestMovie.title} (${newestMovie.year})\n\n\n` +
|
|
|
|
|
`© 2024 M_Viper`;
|
|
|
|
|
|
|
|
|
|
const options = {
|
|
|
|
|
reply_markup: JSON.stringify({
|
|
|
|
|
inline_keyboard: [
|
|
|
|
|
[{ text: 'Zu Plex gehen', url: plexDomain }]
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await bot.sendMessage(chatId, message, options).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent detailed media info, copyright, and Plex button to chatId ${chatId}`);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching media info: ${error.message}`);
|
|
|
|
|
await bot.sendMessage(chatId, 'Fehler beim Abrufen der Medieninformationen.').catch(err => {
|
|
|
|
|
logError(`Error sending media info error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der erweiterten Medieninformationen
|
|
|
|
|
async function fetchAllMedia() {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchAllMovies();
|
|
|
|
|
const shows = await fetchAllShows();
|
|
|
|
|
|
|
|
|
|
const episodeCount = shows.reduce((sum, show) => sum + (show.leafCount || 0), 0);
|
|
|
|
|
const seasonCount = shows.reduce((sum, show) => sum + (show.childCount || 0), 0);
|
|
|
|
|
|
|
|
|
|
const topGenre = findTopGenre(movies.concat(shows));
|
|
|
|
|
const totalSize = await calculateTotalSize(movies.concat(shows));
|
|
|
|
|
const oldestMovie = findOldestMedia(movies);
|
|
|
|
|
const newestMovie = findNewestMedia(movies);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
movieCount: movies.length,
|
|
|
|
|
showCount: shows.length,
|
|
|
|
|
episodeCount: episodeCount,
|
|
|
|
|
seasonCount: seasonCount,
|
|
|
|
|
topGenre: topGenre,
|
|
|
|
|
totalSize: totalSize,
|
|
|
|
|
oldestMovie: oldestMovie,
|
|
|
|
|
newestMovie: newestMovie
|
|
|
|
|
};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching all media: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zur Ermittlung des am häufigsten vorkommenden Genres
|
|
|
|
|
function findTopGenre(mediaArray) {
|
|
|
|
|
const genreCount = {};
|
|
|
|
|
|
|
|
|
|
mediaArray.forEach(media => {
|
|
|
|
|
if (media.Genre) {
|
|
|
|
|
media.Genre.forEach(genre => {
|
|
|
|
|
genreCount[genre.tag] = (genreCount[genre.tag] || 0) + 1;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return Object.keys(genreCount).reduce((a, b) => genreCount[a] > genreCount[b] ? a : b, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zur Berechnung der Gesamtgröße der Mediendateien
|
|
|
|
|
async function calculateTotalSize(mediaArray) {
|
|
|
|
|
let totalSizeBytes = 0;
|
|
|
|
|
|
|
|
|
|
for (const media of mediaArray) {
|
|
|
|
|
if (media.Media && media.Media.length > 0) {
|
|
|
|
|
media.Media.forEach(mediaItem => {
|
|
|
|
|
if (mediaItem.Part && mediaItem.Part.length > 0) {
|
|
|
|
|
mediaItem.Part.forEach(part => {
|
|
|
|
|
if (part.size) {
|
|
|
|
|
const sizeInBytes = parseInt(part.size, 10);
|
|
|
|
|
totalSizeBytes += sizeInBytes;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Log total size in bytes for debugging
|
|
|
|
|
console.log(`Total size in bytes: ${totalSizeBytes}`);
|
|
|
|
|
|
|
|
|
|
// Convert bytes to terabytes (TB) and gigabytes (GB)
|
|
|
|
|
const totalSizeTB = totalSizeBytes / (1024 * 1024 * 1024 * 1024);
|
|
|
|
|
const totalSizeGB = totalSizeBytes / (1024 * 1024 * 1024);
|
|
|
|
|
|
|
|
|
|
// Log sizes in GB and TB
|
|
|
|
|
console.log(`Total size in TB: ${totalSizeTB}`);
|
|
|
|
|
console.log(`Total size in GB: ${totalSizeGB}`);
|
|
|
|
|
|
|
|
|
|
// Determine the appropriate size unit to display
|
|
|
|
|
if (totalSizeTB >= 1) {
|
|
|
|
|
return `${totalSizeTB.toFixed(2)} TB`;
|
|
|
|
|
} else {
|
|
|
|
|
return `${totalSizeGB.toFixed(2)} GB`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Finden des ältesten Mediums
|
|
|
|
|
function findOldestMedia(mediaArray) {
|
|
|
|
|
return mediaArray.reduce((oldest, media) => {
|
|
|
|
|
if (!oldest || (media.year && media.year < oldest.year)) {
|
|
|
|
|
return media;
|
|
|
|
|
}
|
|
|
|
|
return oldest;
|
|
|
|
|
}, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Finden des neuesten Mediums
|
|
|
|
|
function findNewestMedia(mediaArray) {
|
|
|
|
|
return mediaArray.reduce((newest, media) => {
|
|
|
|
|
if (!newest || (media.year && media.year > newest.year)) {
|
|
|
|
|
return media;
|
|
|
|
|
}
|
|
|
|
|
return newest;
|
|
|
|
|
}, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen aller Filme
|
|
|
|
|
async function fetchAllMovies() {
|
|
|
|
|
try {
|
|
|
|
|
const sectionsData = await fetchPlexData(PLEX_LIBRARY_URL);
|
|
|
|
|
const sections = sectionsData.MediaContainer.Directory;
|
|
|
|
|
|
|
|
|
|
let movies = [];
|
|
|
|
|
|
|
|
|
|
for (const section of sections) {
|
|
|
|
|
const sectionUrl = `${process.env.PLEX_DOMAIN}/library/sections/${section.key}/all?X-Plex-Token=${process.env.PLEX_TOKEN}`;
|
|
|
|
|
const sectionData = await fetchPlexData(sectionUrl);
|
|
|
|
|
|
|
|
|
|
if (sectionData.MediaContainer && sectionData.MediaContainer.Metadata) {
|
|
|
|
|
const metadata = sectionData.MediaContainer.Metadata;
|
|
|
|
|
movies = movies.concat(metadata.filter(media => media.type === 'movie'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return movies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching all movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen aller Serien
|
|
|
|
|
async function fetchAllShows() {
|
|
|
|
|
try {
|
|
|
|
|
const sectionsData = await fetchPlexData(PLEX_LIBRARY_URL);
|
|
|
|
|
const sections = sectionsData.MediaContainer.Directory;
|
|
|
|
|
|
|
|
|
|
let shows = [];
|
|
|
|
|
|
|
|
|
|
for (const section of sections) {
|
|
|
|
|
const sectionUrl = `${process.env.PLEX_DOMAIN}/library/sections/${section.key}/all?X-Plex-Token=${process.env.PLEX_TOKEN}`;
|
|
|
|
|
const sectionData = await fetchPlexData(sectionUrl);
|
|
|
|
|
|
|
|
|
|
if (sectionData.MediaContainer && sectionData.MediaContainer.Metadata) {
|
|
|
|
|
const metadata = sectionData.MediaContainer.Metadata;
|
|
|
|
|
shows = shows.concat(metadata.filter(media => media.type === 'show'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return shows;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching all shows: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hilfsfunktion zum Abrufen von Plex-Daten
|
|
|
|
|
async function fetchPlexData(url) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(url);
|
|
|
|
|
return response.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching Plex data: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Erstellen des Inline-Keyboard für die Auswahl von Film oder Serie
|
|
|
|
|
function getTypeKeyboard() {
|
|
|
|
|
return {
|
|
|
|
|
reply_markup: JSON.stringify({
|
|
|
|
|
inline_keyboard: [
|
|
|
|
|
[{ text: 'Film', callback_data: 'type_film' }],
|
|
|
|
|
[{ text: 'Serie', callback_data: 'type_serie' }]
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Senden des Wunsches an zwei Benutzer
|
|
|
|
|
async function sendWish(wish, type, chatId) {
|
2024-08-15 21:37:36 +00:00
|
|
|
|
const message = `✨ **Achtung!** ✨\n\nEin neuer Wunsch ist eingegangen:\n\n🔹 **Typ:** ${type}\n\n🔹 **Titel:**\n${wish}`;
|
2024-08-15 17:40:21 +00:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await Promise.all([
|
|
|
|
|
bot.sendMessage(USER1_ID, message),
|
|
|
|
|
bot.sendMessage(USER2_ID, message),
|
|
|
|
|
]);
|
|
|
|
|
logMessage(`Sent ${type} wish to users ${USER1_ID} and ${USER2_ID}`);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error sending ${type} wish: ${error.message}`);
|
|
|
|
|
console.error(`Error details: ${error}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verarbeite Callback Queries (für die Inline-Buttons)
|
|
|
|
|
bot.on('callback_query', async (query) => {
|
|
|
|
|
const chatId = query.message.chat.id;
|
|
|
|
|
const data = query.data;
|
|
|
|
|
|
|
|
|
|
if (data.startsWith('type_')) {
|
|
|
|
|
// Benutzer hat den Typ ausgewählt (Film oder Serie)
|
|
|
|
|
const type = data === 'type_film' ? 'Film' : 'Serie';
|
|
|
|
|
bot.sendMessage(chatId, `Du hast ${type} ausgewählt. Bitte gib den Titel des ${type} ein.`).catch(error => {
|
|
|
|
|
logError(`Error sending type confirmation message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
userStates[chatId] = { type, waitingForWish: true }; // Setze den Status auf "wartend auf Wunsch"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Markiere die Callback-Abfrage als beantwortet
|
|
|
|
|
bot.answerCallbackQuery(query.id).catch(error => {
|
|
|
|
|
logError(`Error answering callback query: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Verarbeite eingehende Nachrichten
|
|
|
|
|
bot.on('message', async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
const text = msg.text;
|
|
|
|
|
|
|
|
|
|
if (userStates[chatId] && userStates[chatId].waitingForWish) {
|
|
|
|
|
// Verarbeite den Titel des Wunsches
|
|
|
|
|
const wish = text.trim(); // Titel erhalten
|
|
|
|
|
if (wish) {
|
|
|
|
|
const type = userStates[chatId].type;
|
|
|
|
|
await sendWish(wish, type, chatId);
|
|
|
|
|
bot.sendMessage(chatId, `Dein ${type}-Wunsch wurde übermittelt.`).catch(error => {
|
|
|
|
|
logError(`Error sending wish confirmation to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`Received and forwarded ${type} wish from chatId ${chatId}: ${wish}`);
|
|
|
|
|
userStates[chatId].waitingForWish = false; // Benutzerstatus zurücksetzen
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, `Bitte gib den Titel des ${userStates[chatId].type} ein.`).catch(error => {
|
|
|
|
|
logError(`Error sending empty wish message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return; // Beende die Verarbeitung, wenn der Benutzer in der Eingabestimmung ist
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (text.startsWith('/wunsch')) {
|
|
|
|
|
// Benutzer zur Auswahl des Typs (Film oder Serie) auffordern
|
|
|
|
|
bot.sendMessage(chatId, 'Möchtest du einen Film oder eine Serie wünschen? Wähle bitte eine Option:', getTypeKeyboard()).catch(error => {
|
|
|
|
|
logError(`Error sending type request message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
userStates[chatId] = { waitingForType: true }; // Setze den Status auf "wartend auf Typ"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userStates[chatId] && userStates[chatId].waitingForQuery) {
|
|
|
|
|
// Verarbeite Suchabfragen, falls der Benutzer darauf wartet
|
|
|
|
|
const query = text; // Suchbegriff erhalten
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const results = await searchMovies(query);
|
|
|
|
|
if (results.length === 0) {
|
|
|
|
|
bot.sendMessage(chatId, 'Keine Filme gefunden, die deiner Suche entsprechen.').catch(error => {
|
|
|
|
|
logError(`Error sending no results message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No search results found for chatId ${chatId} with query "${query}"`);
|
|
|
|
|
} else {
|
|
|
|
|
// Erstelle Nachrichten für jedes Ergebnis
|
|
|
|
|
for (const movie of results) {
|
|
|
|
|
const { title, summary, thumb } = movie;
|
|
|
|
|
const message = `Titel: ${title}\n\nZusammenfassung: \n\n${summary}`;
|
|
|
|
|
|
|
|
|
|
if (thumb) {
|
|
|
|
|
await bot.sendPhoto(chatId, thumb, { caption: message }).catch(error => {
|
|
|
|
|
logError(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
await bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent search results for query "${query}" to chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
bot.sendMessage(chatId, `Fehler beim Durchführen der Suche. Statuscode: ${error.response.status}`).catch(err => {
|
|
|
|
|
logError(`Error sending search error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error searching movies: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
bot.sendMessage(chatId, 'Fehler beim Durchführen der Suche. Keine Antwort vom Server.').catch(err => {
|
|
|
|
|
logError(`Error sending no response message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error searching movies: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
logError(`Error searching movies: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Benutzerstatus zurücksetzen
|
|
|
|
|
userStates[chatId].waitingForQuery = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// /zufall-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/zufall/, async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const randomMovie = await fetchRandomMovie();
|
|
|
|
|
if (randomMovie) {
|
|
|
|
|
const movieTitle = randomMovie.title || 'Unbekannt';
|
|
|
|
|
const movieSummary = randomMovie.summary || 'Keine Zusammenfassung verfügbar';
|
|
|
|
|
const movieThumb = randomMovie.thumb ? `${PLEX_DOMAIN}${randomMovie.thumb}?X-Plex-Token=${PLEX_TOKEN}` : '';
|
|
|
|
|
|
|
|
|
|
const message = `Hier ist ein zufälliger Film:\n\nTitel: ${movieTitle}\n\nZusammenfassung: \n${movieSummary}`;
|
|
|
|
|
|
|
|
|
|
// Bild anzeigen, wenn vorhanden
|
|
|
|
|
if (movieThumb) {
|
|
|
|
|
bot.sendPhoto(chatId, movieThumb, { caption: message }).catch(error => {
|
|
|
|
|
logError(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent random movie info to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Keine Filme gefunden.').catch(error => {
|
|
|
|
|
logError(`Error sending no movies message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No movies found for chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
bot.sendMessage(chatId, `Fehler beim Abrufen eines zufälligen Films. Statuscode: ${error.response.status}`).catch(err => {
|
|
|
|
|
logError(`Error sending error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching random movie: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
bot.sendMessage(chatId, 'Fehler beim Abrufen eines zufälligen Films. Keine Antwort vom Server.').catch(err => {
|
|
|
|
|
logError(`Error sending no response message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching random movie: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Fehler beim Abrufen eines zufälligen Films. Unbekannter Fehler.').catch(err => {
|
|
|
|
|
logError(`Error sending unknown error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching random movie: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Speichern des Status der Benutzerinteraktionen
|
|
|
|
|
const userStates = {}; // Einfache In-Memory-Datenstruktur
|
|
|
|
|
|
|
|
|
|
// /search-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/search/, (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
// Setze den Status auf "wartet auf Suchbegriff"
|
|
|
|
|
userStates[chatId] = { waitingForQuery: true };
|
|
|
|
|
|
|
|
|
|
const message = 'Bitte gib den Suchbegriff für die Film-Suche ein.';
|
|
|
|
|
|
|
|
|
|
bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending search prompt to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logMessage(`Prompted for search query from chatId ${chatId}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Eingehende Nachrichten verarbeiten
|
|
|
|
|
bot.on('message', async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
const text = msg.text;
|
|
|
|
|
|
|
|
|
|
// Überprüfen, ob der Benutzer auf eine Suchabfrage wartet
|
|
|
|
|
if (userStates[chatId] && userStates[chatId].waitingForQuery) {
|
|
|
|
|
const query = text; // Suchbegriff erhalten
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const results = await searchMovies(query);
|
|
|
|
|
if (results.length === 0) {
|
|
|
|
|
await bot.sendMessage(chatId, 'Keine Filme gefunden, die deiner Suche entsprechen.').catch(error => {
|
|
|
|
|
logError(`Error sending no results message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No search results found for chatId ${chatId} with query "${query}"`);
|
|
|
|
|
} else {
|
|
|
|
|
// Erstelle Nachrichten für jedes Ergebnis
|
|
|
|
|
const messages = results.map(async (movie) => {
|
|
|
|
|
const { title, summary, thumb } = movie;
|
|
|
|
|
const movieThumbUrl = thumb ? `${process.env.PLEX_DOMAIN}${thumb}?X-Plex-Token=${process.env.PLEX_TOKEN}` : '';
|
|
|
|
|
const message = `Titel: ${title}\n\nZusammenfassung: \n\n${summary}`;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (movieThumbUrl) {
|
|
|
|
|
await bot.sendPhoto(chatId, movieThumbUrl, { caption: message });
|
|
|
|
|
logMessage(`Sent photo for movie "${title}" to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
await bot.sendMessage(chatId, message);
|
|
|
|
|
logMessage(`Sent message for movie "${title}" to chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error sending message or photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
// Optional: Sende nur die Textnachricht, wenn das Bild nicht gesendet werden konnte
|
|
|
|
|
await bot.sendMessage(chatId, message).catch(err => {
|
|
|
|
|
logError(`Error sending fallback message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Führe alle Nachrichten-Operationen aus
|
|
|
|
|
await Promise.all(messages);
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent search results for query "${query}" to chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
let errorMessage = 'Fehler beim Durchführen der Suche.';
|
|
|
|
|
|
|
|
|
|
if (error.response) {
|
|
|
|
|
errorMessage += ` Statuscode: ${error.response.status}`;
|
|
|
|
|
logError(`Error searching movies: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
errorMessage += ' Keine Antwort vom Server.';
|
|
|
|
|
logError(`Error searching movies: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
errorMessage += ` Unbekannter Fehler: ${error.message}`;
|
|
|
|
|
logError(`Error searching movies: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await bot.sendMessage(chatId, errorMessage).catch(err => {
|
|
|
|
|
logError(`Error sending search error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Benutzerstatus zurücksetzen
|
|
|
|
|
userStates[chatId].waitingForQuery = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der Filme basierend auf der Suche
|
|
|
|
|
async function searchMovies(query) {
|
|
|
|
|
try {
|
|
|
|
|
// Placeholder für die tatsächliche Implementierung
|
|
|
|
|
// Diese Funktion sollte Filme basierend auf dem Suchbegriff abfragen und zurückgeben
|
|
|
|
|
const movies = await fetchMoviesFromAPI(query); // Ersetze dies durch die echte Implementierung
|
|
|
|
|
return movies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error searching movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der Filme aus der API (placeholder)
|
|
|
|
|
async function fetchMoviesFromAPI(query) {
|
|
|
|
|
try {
|
|
|
|
|
const url = `${process.env.PLEX_DOMAIN}/search?query=${encodeURIComponent(query)}&X-Plex-Token=${process.env.PLEX_TOKEN}`;
|
|
|
|
|
const response = await axios.get(url);
|
|
|
|
|
return response.data.MediaContainer.Metadata; // Oder wie auch immer die API antwortet
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching movies from API: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Array, um empfohlene Filme zu speichern
|
|
|
|
|
const recommendedMovies = [];
|
|
|
|
|
|
|
|
|
|
let dailyMovieCache = {}; // Cache für den Film des Tages
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen des täglichen Films basierend auf dem Datum
|
|
|
|
|
async function fetchDailyRecommendation() {
|
|
|
|
|
try {
|
|
|
|
|
// Berechne das heutige Datum
|
|
|
|
|
const today = moment().format('YYYY-MM-DD');
|
|
|
|
|
|
|
|
|
|
// Überprüfen, ob wir bereits einen Film für heute gespeichert haben
|
|
|
|
|
if (dailyMovieCache[today]) {
|
|
|
|
|
return dailyMovieCache[today];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Anfrage zur Mediathek, um alle Filme abzurufen
|
|
|
|
|
const url = `${process.env.PLEX_DOMAIN}/library/sections/1/all?X-Plex-Token=${process.env.PLEX_TOKEN}`;
|
|
|
|
|
const response = await axios.get(url);
|
|
|
|
|
|
|
|
|
|
const data = response.data;
|
|
|
|
|
if (data && data.MediaContainer && Array.isArray(data.MediaContainer.Metadata) && data.MediaContainer.Metadata.length > 0) {
|
|
|
|
|
// Wähle einen zufälligen Film aus der Liste der Filme aus
|
|
|
|
|
const movies = data.MediaContainer.Metadata;
|
|
|
|
|
const randomIndex = Math.floor(Math.random() * movies.length);
|
|
|
|
|
const selectedMovie = movies[randomIndex];
|
|
|
|
|
|
|
|
|
|
// Speichern des Films für heute im Cache
|
|
|
|
|
dailyMovieCache[today] = selectedMovie;
|
|
|
|
|
return selectedMovie;
|
|
|
|
|
} else {
|
|
|
|
|
// Protokolliere, wenn keine Filme gefunden wurden
|
|
|
|
|
console.log('No movies found in API response or unexpected response format');
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching daily recommendation from API: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// /empfehlung-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/empfehlung/, async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const dailyMovie = await fetchDailyRecommendation();
|
|
|
|
|
if (dailyMovie) {
|
|
|
|
|
// Film empfehlen
|
|
|
|
|
const movieTitle = dailyMovie.title || 'Unbekannt';
|
|
|
|
|
const movieSummary = dailyMovie.summary || 'Keine Zusammenfassung verfügbar';
|
|
|
|
|
const movieThumb = dailyMovie.thumb ? `${process.env.PLEX_DOMAIN}${dailyMovie.thumb}?X-Plex-Token=${process.env.PLEX_TOKEN}` : '';
|
|
|
|
|
|
|
|
|
|
const message = `Hier ist der empfohlene Film des Tages:\n\nTitel: ${movieTitle}\n\nZusammenfassung: \n${movieSummary}`;
|
|
|
|
|
|
|
|
|
|
// Bild anzeigen, wenn vorhanden
|
|
|
|
|
if (movieThumb) {
|
|
|
|
|
await bot.sendPhoto(chatId, movieThumb, { caption: message }).catch(error => {
|
|
|
|
|
logError(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
await bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent daily recommendation to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
await bot.sendMessage(chatId, 'Keine Empfehlungen verfügbar.').catch(error => {
|
|
|
|
|
logError(`Error sending no recommendation message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No daily recommendation found for chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
let errorMessage = 'Fehler beim Abrufen der Empfehlung.';
|
|
|
|
|
|
|
|
|
|
if (error.response) {
|
|
|
|
|
errorMessage += ` Statuscode: ${error.response.status}`;
|
|
|
|
|
logError(`Error fetching daily recommendation: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
errorMessage += ' Keine Antwort vom Server.';
|
|
|
|
|
logError(`Error fetching daily recommendation: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
errorMessage += ` Unbekannter Fehler: ${error.message}`;
|
|
|
|
|
logError(`Error fetching daily recommendation: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await bot.sendMessage(chatId, errorMessage).catch(err => {
|
|
|
|
|
logError(`Error sending daily recommendation error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /help-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/help/, (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
const helpMessage = `📜 **Hier ist eine Liste der verfügbaren Befehle:**\n\n` +
|
|
|
|
|
`👋 /start - Registriert deinen Zugang.\n\n` +
|
|
|
|
|
`🔔 /notification\\_on - Aktiviert Benachrichtigungen für neue Filme.\n\n` +
|
|
|
|
|
`🔕 /notification\\_off - Deaktiviert Benachrichtigungen für neue Filme.\n\n` +
|
|
|
|
|
`🎬 /latestmovie - Zeigt den zuletzt hinzugefügten Film an.\n\n` +
|
|
|
|
|
`📅 /latest10movies - Zeigt die letzten 10 hinzugefügten Filme an.\n\n` +
|
|
|
|
|
`ℹ️ /info - Gibt die Anzahl der Filme und Serien aus.\n\n` +
|
|
|
|
|
`🎲 /zufall - Zeigt einen zufälligen Film an.\n\n` +
|
|
|
|
|
`🔍 /search - Startet die Filmsuche.\n\n` +
|
|
|
|
|
`💭 /wunsch - Nutze diesen Befehl, um einen Filmwunsch zu äußern.\n\n` +
|
|
|
|
|
`🔝 /empfehlung - Film Empfehlung des Tages.\n\n` +
|
|
|
|
|
`❓ /help - Zeigt diese Hilfennachricht an.`;
|
|
|
|
|
|
|
|
|
|
bot.sendMessage(chatId, helpMessage, { parse_mode: 'Markdown' }).catch(error => {
|
|
|
|
|
logError(`Error sending help message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent help message to chatId ${chatId}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Funktion zum Abrufen der letzten 10 hinzugefügten Filme
|
|
|
|
|
async function fetchLatest10Movies() {
|
|
|
|
|
try {
|
|
|
|
|
const movies = await fetchAllMovies();
|
|
|
|
|
const sortedMovies = movies
|
|
|
|
|
.filter(movie => movie.addedAt)
|
|
|
|
|
.sort((a, b) => b.addedAt - a.addedAt)
|
|
|
|
|
.slice(0, 10); // Nimm nur die neuesten 10 Filme
|
|
|
|
|
|
|
|
|
|
return sortedMovies;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error fetching latest 10 movies: ${error.message}`);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// /latest10movies-Befehl verarbeiten
|
|
|
|
|
bot.onText(/\/latest10movies/, async (msg) => {
|
|
|
|
|
const chatId = msg.chat.id;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const latestMovies = await fetchLatest10Movies();
|
|
|
|
|
|
|
|
|
|
if (latestMovies.length > 0) {
|
|
|
|
|
const numberEmojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'];
|
|
|
|
|
const inlineKeyboard = [[], []]; // Zwei Zeilen für das Inline-Keyboard
|
|
|
|
|
let message = 'Letzten 10 hinzugefügten Filme:\n\n';
|
|
|
|
|
|
|
|
|
|
latestMovies.forEach((movie, index) => {
|
|
|
|
|
const numberEmoji = numberEmojis[index] || '';
|
|
|
|
|
message += `${numberEmoji} - ${movie.title || 'Unbekannt'}\n\n`;
|
|
|
|
|
|
|
|
|
|
// Ordne die Schaltflächen in zwei Zeilen an (5 pro Zeile)
|
|
|
|
|
const rowIndex = index < 5 ? 0 : 1;
|
|
|
|
|
inlineKeyboard[rowIndex].push({ text: numberEmoji, callback_data: `movie_${index}` });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Füge die Anweisung unter den Filmnamen hinzu
|
|
|
|
|
message += '\nKlicke auf die Zahl, um nähere Informationen zu bekommen.';
|
|
|
|
|
|
|
|
|
|
bot.sendMessage(chatId, message, {
|
|
|
|
|
reply_markup: {
|
|
|
|
|
inline_keyboard: inlineKeyboard
|
|
|
|
|
}
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent latest 10 movies info to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Keine Filme gefunden.').catch(error => {
|
|
|
|
|
logError(`Error sending no movies message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
logMessage(`No movies found for chatId ${chatId}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
handleError(chatId, error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Inline-Knopf-Ereignis für Film auswählen verarbeiten
|
|
|
|
|
bot.on('callback_query', async (callbackQuery) => {
|
|
|
|
|
const chatId = callbackQuery.message.chat.id;
|
|
|
|
|
const data = callbackQuery.data;
|
|
|
|
|
|
|
|
|
|
if (data.startsWith('movie_')) {
|
|
|
|
|
const movieIndex = parseInt(data.split('_')[1], 10);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const latestMovies = await fetchLatest10Movies();
|
|
|
|
|
const selectedMovie = latestMovies[movieIndex];
|
|
|
|
|
|
|
|
|
|
if (selectedMovie) {
|
|
|
|
|
const movieDetails = `
|
|
|
|
|
🎬 *Titel*: ${selectedMovie.title || 'Unbekannt'}\n\n
|
|
|
|
|
📝 *Zusammenfassung*: \n${selectedMovie.summary || 'Keine Zusammenfassung verfügbar.'}\n\n
|
|
|
|
|
📅 *Hinzugefügt am*: ${dayjs(selectedMovie.addedAt * 1000).format('DD.MM.YYYY')}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
if (selectedMovie.thumb) {
|
|
|
|
|
const imageUrl = `${PLEX_DOMAIN}${selectedMovie.thumb}?X-Plex-Token=${PLEX_TOKEN}`;
|
|
|
|
|
bot.sendPhoto(chatId, imageUrl, { caption: movieDetails, parse_mode: 'Markdown' }).catch(error => {
|
|
|
|
|
logError(`Error sending photo to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, movieDetails, { parse_mode: 'Markdown' }).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logMessage(`Sent movie details for movie index ${movieIndex} to chatId ${chatId}`);
|
|
|
|
|
} else {
|
|
|
|
|
bot.sendMessage(chatId, 'Film nicht gefunden.').catch(error => {
|
|
|
|
|
logError(`Error sending movie not found message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
handleError(chatId, error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function handleError(chatId, error) {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
bot.sendMessage(chatId, `Fehler beim Abrufen der Daten. Statuscode: ${error.response.status}`).catch(err => {
|
|
|
|
|
logError(`Error sending error message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching data: ${error.response.status} - ${error.response.statusText}`);
|
|
|
|
|
} else if (error.request) {
|
|
|
|
|
bot.sendMessage(chatId, 'Fehler beim Abrufen der Daten. Keine Antwort vom Server.').catch(err => {
|
|
|
|
|
logError(`Error sending no response message to chatId ${chatId}: ${err.message}`);
|
|
|
|
|
});
|
|
|
|
|
logError(`Error fetching data: No response from server`);
|
|
|
|
|
} else {
|
|
|
|
|
logError(`Error fetching data: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Funktion zum Verarbeiten von Webhook-Anfragen
|
|
|
|
|
app.post('/mywebhook', async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const event = req.body;
|
|
|
|
|
logDebug(`Received webhook event: ${JSON.stringify(event, null, 2)}`);
|
|
|
|
|
|
|
|
|
|
if (event.type === 'library.new' && event.Metadata) {
|
|
|
|
|
const addedMovie = event.Metadata;
|
|
|
|
|
const movieTitle = addedMovie.title || 'Unbekannt';
|
|
|
|
|
const message = `Ein neuer Film wurde hinzugefügt:\n\nTitel: ${movieTitle}`;
|
|
|
|
|
|
|
|
|
|
const users = yaml.load(USER_YML_PATH);
|
|
|
|
|
const sendMessages = Object.keys(users).map(chatId =>
|
|
|
|
|
bot.sendMessage(chatId, message).catch(error => {
|
|
|
|
|
logError(`Error sending message to chatId ${chatId}: ${error.message}`);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await Promise.all(sendMessages);
|
|
|
|
|
logMessage(`Sent new movie message to all users`);
|
|
|
|
|
} else {
|
|
|
|
|
logDebug(`Unhandled event type or missing metadata: ${event.type}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.sendStatus(200);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logError(`Error processing webhook: ${error.message}`);
|
|
|
|
|
res.sendStatus(500);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Express-Server starten
|
|
|
|
|
app.listen(PORT, () => {
|
|
|
|
|
console.log(`Webhook server running on port ${PORT}`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Log-Rotation
|
|
|
|
|
function rotateLogs() {
|
|
|
|
|
const today = format(new Date(), 'yyyy-MM-dd');
|
|
|
|
|
const logFilePath = path.join(LOG_DIR, `${today}.log`);
|
|
|
|
|
|
|
|
|
|
// Lösche die Log-Datei von gestern, wenn sie existiert
|
|
|
|
|
const yesterday = format(new Date(Date.now() - 24 * 60 * 60 * 1000), 'yyyy-MM-dd');
|
|
|
|
|
const oldLogFilePath = path.join(LOG_DIR, `${yesterday}.log`);
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(oldLogFilePath)) {
|
|
|
|
|
fs.unlinkSync(oldLogFilePath); // Lösche die alte Logdatei
|
|
|
|
|
logMessage(`Deleted old log file: ${yesterday}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logs täglich um Mitternacht rotieren
|
|
|
|
|
function scheduleDailyRotation() {
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const millisTillMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0, 0) - now;
|
|
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
rotateLogs(); // Rotieren der Logs um Mitternacht
|
|
|
|
|
setInterval(rotateLogs, 24 * 60 * 60 * 1000); // Danach täglich wiederholen
|
|
|
|
|
}, millisTillMidnight);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Starte die tägliche Rotation
|
|
|
|
|
scheduleDailyRotation();
|
|
|
|
|
|
|
|
|
|
console.log('Bot is running...');
|