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 ;
2024-08-18 14:18:05 +00:00
const AUTHORIZED _USER _ID = process . env . AUTHORIZED _USER _ID ;
2024-09-01 15:04:00 +00:00
const errorLogPath = process . env . ERROR _LOG _PATH ;
2024-08-15 17:40:21 +00:00
// 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 ) ;
}
2024-08-18 14:18:05 +00:00
// Handler für den /admin-Befehl
bot . onText ( /\/admin/ , ( msg ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
// Prüfe, ob der Benutzer autorisiert ist
if ( userId . toString ( ) === USER1 _ID || userId . toString ( ) === USER2 _ID ) {
bot . sendMessage ( chatId , 'Bitte gib die Nachricht ein, die du an alle Benutzer senden möchtest:' , {
reply _markup : {
force _reply : true
}
} ) . then ( ( ) => {
bot . once ( 'message' , async ( msg ) => {
if ( msg . chat . id === chatId && msg . text ) {
const messageText = msg . text ;
// Sende die Nachricht an alle Benutzer
const users = yaml . load ( USER _YML _PATH ) ;
const sendMessages = Object . keys ( users ) . map ( userChatId => {
return bot . sendMessage ( userChatId , ` ❗️ Systemnachricht \n \n " ${ messageText } " ` ) . catch ( error => {
logError ( ` Fehler beim Senden der Systemnachricht an chatId ${ userChatId } : ${ error . message } ` ) ;
} ) ;
} ) . filter ( promise => promise !== undefined ) ;
await Promise . all ( sendMessages ) ;
bot . sendMessage ( chatId , 'Nachricht wurde an alle Benutzer gesendet.' ) . catch ( error => {
logError ( ` Fehler beim Senden der Bestätigung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
}
} ) ;
} ) . catch ( error => {
logError ( ` Fehler beim Senden der Nachrichteneingabeaufforderung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . sendMessage ( chatId , '❌ Du bist nicht autorisiert, diesen Befehl auszuführen.' ) ;
}
} ) ;
// Pfad zur Cache-Datei
const CACHE _FILE _PATH = path . join ( 'Cache' , 'cache-series.json' ) ;
// Funktion zum Speichern des Caches in eine Datei
function saveSeriesCache ( series ) {
fs . writeFileSync ( CACHE _FILE _PATH , JSON . stringify ( series , null , 2 ) ) ;
}
// Funktion zum Laden des Caches aus einer Datei
function loadSeriesCache ( ) {
if ( fs . existsSync ( CACHE _FILE _PATH ) ) {
return JSON . parse ( fs . readFileSync ( CACHE _FILE _PATH ) ) ;
}
return null ;
}
// Funktion zum Abrufen aller Serien
async function fetchAllSeries ( ) {
try {
const sectionsData = await fetchPlexData ( PLEX _LIBRARY _URL ) ;
const sections = sectionsData . MediaContainer . Directory ;
let series = [ ] ;
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 ;
series = series . concat ( metadata . filter ( media => media . type === 'show' ) ) ;
}
}
series . sort ( ( a , b ) => ( b . addedAt || 0 ) - ( a . addedAt || 0 ) ) ;
return series ;
} catch ( error ) {
logError ( ` Error fetching all series: ${ error . message } ` ) ;
throw error ;
}
}
// Funktion zum Abrufen der Serien mit Caching
async function fetchSeriesWithCache ( ) {
const cachedSeries = loadSeriesCache ( ) ;
if ( cachedSeries ) {
logMessage ( 'Series fetched from cache' ) ;
return cachedSeries ;
}
try {
const series = await fetchAllSeries ( ) ;
saveSeriesCache ( series ) ;
logMessage ( 'Series fetched from API and cached' ) ;
return series ;
} catch ( error ) {
logError ( ` Error fetching series: ${ error . message } ` ) ;
throw error ;
}
}
// Automatische Cache-Aktualisierung jede Stunde
schedule . scheduleJob ( '0 * * * *' , async ( ) => {
try {
const series = await fetchAllSeries ( ) ;
saveSeriesCache ( series ) ;
logMessage ( 'Series cache updated automatically' ) ;
} catch ( error ) {
logError ( ` Error updating series cache: ${ error . message } ` ) ;
}
} ) ;
// Handler für den /serien-Befehl
bot . onText ( /\/serien/ , async ( msg ) => {
const chatId = msg . chat . id ;
try {
const series = await fetchSeriesWithCache ( ) ;
const seriesList = series . map ( ( s , index ) => ` ${ index + 1 } . ${ s . title } ` ) . join ( '\n' ) ;
bot . sendMessage ( chatId , ` Hier sind die Serien in deiner Plex-Mediathek: \n \n ${ seriesList } ` , {
reply _markup : {
inline _keyboard : [
[ { text : 'Weitere Informationen' , callback _data : 'get_series_info' } ]
]
}
} ) ;
} catch ( error ) {
bot . sendMessage ( chatId , 'Fehler beim Abrufen der Serien. Bitte versuche es später erneut.' ) ;
logError ( ` Error handling /serien command: ${ error . message } ` ) ;
}
} ) ;
// Handler für die Callback-Abfragen von Inline-Buttons
bot . on ( 'callback_query' , async ( query ) => {
const chatId = query . message . chat . id ;
if ( query . data . startsWith ( 'get_series_info' ) ) {
try {
const series = await fetchSeriesWithCache ( ) ;
const responseMessage = ` Bitte gib die Nummer der Serie ein, um weitere Informationen zu erhalten. ` ;
bot . sendMessage ( chatId , responseMessage , {
reply _markup : {
force _reply : true
}
} ) . then ( ( ) => {
bot . once ( 'message' , async ( msg ) => {
if ( msg . chat . id === chatId && msg . text ) {
const seriesNumber = parseInt ( msg . text , 10 ) ;
if ( ! isNaN ( seriesNumber ) && seriesNumber > 0 && seriesNumber <= series . length ) {
const seriesInfo = series [ seriesNumber - 1 ] ;
const { title , summary , thumb , addedAt } = seriesInfo ;
const imageUrl = ` ${ PLEX _DOMAIN } ${ thumb } ?X-Plex-Token= ${ PLEX _TOKEN } ` ;
// Formatieren des Hinzufügungsdatums
const addedDate = addedAt ? dayjs ( addedAt * 1000 ) . format ( 'DD.MM.YYYY' ) : 'Unbekannt' ; // Umrechnung von Unix-Zeitstempel in Millisekunden
const caption = ` 📺 *Titel:* ${ title } \n \n ` +
` 📝 *Beschreibung:* \n ${ summary } \n \n ` +
` 📅 *Hinzugefügt am:* ${ addedDate } ` ;
bot . sendPhoto ( chatId , imageUrl , { caption , parse _mode : 'Markdown' } ) ;
} else {
bot . sendMessage ( chatId , 'Ungültige Nummer. Bitte gib eine gültige Nummer ein.' ) ;
}
}
} ) ;
} ) . catch ( error => {
logError ( ` Fehler beim Senden der Eingabeaufforderung: ${ error . message } ` ) ;
} ) ;
} catch ( error ) {
bot . sendMessage ( chatId , 'Fehler beim Abrufen der Serieninformationen. Bitte versuche es später erneut.' ) ;
logError ( ` Error handling callback query: ${ error . message } ` ) ;
}
}
} ) ;
// Umgebungsvariable für die Chat-ID der Entwickler
const DEV _CHAT _ID = parseInt ( process . env . DEV _CHAT _ID , 10 ) ;
// Funktion zum Erstellen des Inline-Keyboards
function getDevOptionsKeyboard ( ) {
return {
reply _markup : {
inline _keyboard : [
[ { text : '💡 Funktionswunsch' , callback _data : 'dev_request' } ] ,
[ { text : '🐞 Bug melden' , callback _data : 'dev_bug' } ]
]
}
} ;
}
// Handler für den /dev-Befehl
bot . onText ( /\/dev/ , ( msg ) => {
const chatId = msg . chat . id ;
const message = '🔧 *Dev-Feedback* - Bitte wählen Sie eine der folgenden Optionen, um Ihr Feedback zu übermitteln:' ;
bot . sendMessage ( chatId , message , {
parse _mode : 'Markdown' ,
... getDevOptionsKeyboard ( )
} ) ;
} ) ;
// Handler für Callback-Queries im /dev-Befehl
bot . on ( 'callback_query' , ( query ) => {
console . log ( 'Callback-Query-Daten:' , query . data ) ; // Debugging-Ausgabe
const chatId = query . message . chat . id ;
const data = query . data ;
let responseText = '' ;
let replyMarkup ;
switch ( data ) {
case 'dev_request' :
responseText = '✏️ *Bitte geben Sie Ihren Funktionswunsch ein:*' ;
replyMarkup = {
reply _markup : {
force _reply : true
}
} ;
break ;
case 'dev_bug' :
responseText = '✏️ *Bitte beschreiben Sie den Bug, den Sie melden möchten:*' ;
replyMarkup = {
reply _markup : {
force _reply : true
}
} ;
break ;
default :
// Kein Popup oder Nachricht senden, wenn die Auswahl unbekannt ist
return ;
}
bot . sendMessage ( chatId , responseText , { parse _mode : 'Markdown' , ... replyMarkup } ) ;
} ) ;
// Handler für die Antworten auf die Feedback-Anfrage
bot . on ( 'message' , async ( msg ) => {
if ( msg . reply _to _message && ( msg . reply _to _message . text . includes ( 'Bitte geben Sie Ihren Funktionswunsch ein:' ) ||
msg . reply _to _message . text . includes ( 'Bitte beschreiben Sie den Bug, den Sie melden möchten:' ) ) ) {
const chatId = msg . chat . id ;
const text = msg . text ;
const userName = msg . from . first _name + ( msg . from . last _name ? ` ${ msg . from . last _name } ` : '' ) ;
const userId = msg . from . id ;
const messageType = msg . reply _to _message . text . includes ( 'Funktionswunsch' ) ? 'Funktionswunsch' : 'Bug' ;
const devMessage = ` 📩 * ${ messageType } * \n \n ` +
` von: ${ userName } ( ${ userId } ) \n \n ` +
` " ${ text } " ` ;
try {
console . log ( 'Sende Nachricht an Entwickler-Chat-ID:' , DEV _CHAT _ID ) ; // Debugging-Ausgabe
await bot . sendMessage ( DEV _CHAT _ID , devMessage , { parse _mode : 'Markdown' } ) ;
console . log ( 'Nachricht erfolgreich gesendet.' ) ;
bot . sendMessage ( chatId , '✅ Ihre Nachricht wurde erfolgreich gesendet! Vielen Dank für Ihr Feedback.' ) ;
} catch ( error ) {
console . error ( 'Fehler beim Senden der Nachricht:' , error ) ;
bot . sendMessage ( chatId , '🚫 Etwas ist schiefgelaufen. Ihre Nachricht konnte nicht gesendet werden.' ) ;
}
}
} ) ;
// Handler für den /bot-Befehl
bot . onText ( /\/bot/ , ( msg ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
// Überprüfe, ob der Benutzer autorisiert ist
if ( userId . toString ( ) === USER1 _ID || userId . toString ( ) === USER2 _ID ) {
try {
// Bot-Version
2024-09-01 15:04:00 +00:00
const botVersion = "1.5.2" ; // Hier kannst du die tatsächliche Version dynamisch einfügen
2024-08-18 14:18:05 +00:00
// Laufzeit des Prozesses in Sekunden
const uptime = process . uptime ( ) ;
const hours = Math . floor ( uptime / 3600 ) ;
const minutes = Math . floor ( ( uptime % 3600 ) / 60 ) ;
const seconds = Math . floor ( uptime % 60 ) ;
const runtime = ` ${ String ( hours ) . padStart ( 2 , '0' ) } : ${ String ( minutes ) . padStart ( 2 , '0' ) } : ${ String ( seconds ) . padStart ( 2 , '0' ) } ` ;
// Benutzeranzahl
const users = yaml . load ( USER _YML _PATH ) ;
const userCount = Object . keys ( users ) . length ;
// Letzter Neustart des Bots
const lastRestart = dayjs ( ) . format ( 'YYYY-MM-DD HH:mm:ss' ) ;
// Speicherbelegung
const memoryUsage = process . memoryUsage ( ) ;
const memoryStats = ` Heap Total: ${ Math . round ( memoryUsage . heapTotal / 1024 / 1024 ) } MB, Heap Used: ${ Math . round ( memoryUsage . heapUsed / 1024 / 1024 ) } MB ` ;
// Cache-Status
const cacheKeys = cache . keys ( ) . length ;
const cacheStats = cache . getStats ( ) ; // Hole die vollständigen Cache-Stats
const cacheTTL = cacheStats . stdTTL || 0 ; // Setze Default-Wert auf 0, falls nicht definiert
// Fehlerprotokoll-Status
const errorLogCount = fs . existsSync ( ERROR _LOG _PATH ) ? fs . readFileSync ( ERROR _LOG _PATH , 'utf8' ) . split ( '\n' ) . length - 1 : 0 ;
// Aktuelle Aufgaben
const currentTasks = `
- Cache wird jede Stunde aktualisiert \ n
- Geplante Überprüfungen neuer Filme alle 1 Minute \ n
` ;
// Bot Token und Webhook URL (falls vorhanden)
const botToken = BOT _TOKEN ;
const webhookStatus = WEBHOOK _URL ? "Aktiv" : "Inaktiv" ;
// Nachricht erstellen
const infoMessage = `
📊 * Bot Informationen * \ n \ n
🆙 * Version : * $ { botVersion } \ n
⏱ ️ * Laufzeit : * $ { runtime } \ n
👥 * Benutzeranzahl : * $ { userCount } \ n
🔄 * Letzter Neustart : * $ { lastRestart } \ n
💾 * Speicherbelegung : * $ { memoryStats } \ n
🔑 * Bot Token : * $ { botToken . slice ( 0 , 10 ) } ... ( gekürzt für Sicherheit ) \ n
🌐 * Webhook URL : * $ { webhookStatus } \ n
🔑 * Cache Keys : * $ { cacheKeys } \ n
⏳ * Cache TTL : * $ { cacheTTL } Sekunden \ n
📝 * Fehlerprotokoll - Anzahl : * $ { errorLogCount } \ n \ n
🛠 ️ * Aktuelle Aufgaben : * \ n
$ { currentTasks . trim ( ) }
` ;
// Nachricht senden
bot . sendMessage ( chatId , infoMessage , { parse _mode : 'Markdown' } ) . catch ( error => {
logError ( ` Fehler beim Senden der Bot-Informationen an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} catch ( error ) {
// Fehlerprotokollierung für unerwartete Fehler
logError ( ` Fehler beim Abrufen von Bot-Informationen: ${ error . message } ` ) ;
bot . sendMessage ( chatId , 'Fehler beim Abrufen der Bot-Informationen.' ) . catch ( err => {
logError ( ` Fehler beim Senden der Fehlermeldung an chatId ${ chatId } : ${ err . message } ` ) ;
} ) ;
}
} else {
bot . sendMessage ( chatId , '❌ Du bist nicht autorisiert, diesen Befehl auszuführen.' ) ;
}
} ) ;
// Handler für den /logs-Befehl
bot . onText ( /\/logs(?: (\d+))?/ , ( msg , match ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
if ( userId . toString ( ) === USER1 _ID || userId . toString ( ) === USER2 _ID ) {
const count = match [ 1 ] ? parseInt ( match [ 1 ] , 10 ) : 10 ;
const recentErrors = getRecentErrors ( count ) . join ( '\n' ) ;
const message = recentErrors . length > 0 ? ` Fehlermeldungen: \n ${ recentErrors } ` : 'Keine Fehlermeldungen vorhanden.' ;
bot . sendMessage ( chatId , message ) . catch ( error => {
logError ( ` Fehler beim Senden der Logs an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . sendMessage ( chatId , '❌ Du bist nicht autorisiert, diesen Befehl auszuführen.' ) ;
}
} ) ;
// Definiere den Pfad zur feedback.yml
const FEEDBACK _FILE _PATH = path . resolve ( _ _dirname , 'Log' , 'feedback.yml' ) ;
// Handler für den /log_delete-Befehl
bot . onText ( /\/log_delete/ , ( msg ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
if ( userId . toString ( ) === USER1 _ID || userId . toString ( ) === USER2 _ID ) {
const inlineKeyboard = [
[ { text : 'Error Log Löschen' , callback _data : 'delete_error_log' } ] ,
[ { text : 'User Log Löschen' , callback _data : 'delete_user_log' } ] ,
[ { text : 'Feedback Log Löschen' , callback _data : 'delete_feedback_log' } ] // Neuer Button
] ;
bot . sendMessage ( chatId , 'Wähle, welches Log du löschen möchtest:' , {
reply _markup : {
inline _keyboard : inlineKeyboard
}
} ) . catch ( error => {
logError ( ` Fehler beim Senden der Log-Lösch-Nachricht an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . sendMessage ( chatId , '❌ Du bist nicht autorisiert, diesen Befehl auszuführen.' ) ;
}
} ) ;
// Handler für Inline-Button-Callbacks
bot . on ( 'callback_query' , async ( callbackQuery ) => {
const chatId = callbackQuery . message . chat . id ;
const userId = callbackQuery . from . id ;
const data = callbackQuery . data ;
if ( data === 'delete_error_log' ) {
// Lösche das gesamte Error Log
if ( fs . existsSync ( ERROR _LOG _PATH ) ) {
fs . unlinkSync ( ERROR _LOG _PATH ) ; // Lösche die Error Log Datei komplett
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Error Log wurde gelöscht.' } ) ;
bot . sendMessage ( chatId , 'Das Error Log wurde erfolgreich gelöscht.' ) . catch ( error => {
logError ( ` Fehler beim Senden der Bestätigung für das Löschen des Error Logs an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Error Log existiert nicht.' } ) ;
}
} else if ( data === 'delete_user_log' ) {
// Lösche alle User Logs im LOG_DIR
try {
const files = fs . readdirSync ( LOG _DIR ) ;
const userLogFiles = files . filter ( file => / ^ \ d { 4 } - \ d { 2 } - \ d { 2 } \ . log$ / . test ( file ) ) ;
if ( userLogFiles . length > 0 ) {
userLogFiles . forEach ( file => fs . unlinkSync ( path . join ( LOG _DIR , file ) ) ) ; // Lösche jede User Log Datei
bot . answerCallbackQuery ( callbackQuery . id , { text : 'User Logs wurden gelöscht.' } ) ;
bot . sendMessage ( chatId , 'Alle User Logs wurden erfolgreich gelöscht.' ) . catch ( error => {
logError ( ` Fehler beim Senden der Bestätigung für das Löschen der User Logs an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Keine User Logs zum Löschen gefunden.' } ) ;
}
} catch ( error ) {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Fehler beim Löschen der User Logs.' } ) ;
logError ( ` Fehler beim Löschen der User Logs: ${ error . message } ` ) ;
}
} else if ( data === 'delete_feedback_log' ) {
// Lösche die Feedback-Datei
if ( fs . existsSync ( FEEDBACK _FILE _PATH ) ) {
fs . unlinkSync ( FEEDBACK _FILE _PATH ) ; // Lösche die Feedback-Datei komplett
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Feedback Log wurde gelöscht.' } ) ;
bot . sendMessage ( chatId , 'Das Feedback Log wurde erfolgreich gelöscht.' ) . catch ( error => {
logError ( ` Fehler beim Senden der Bestätigung für das Löschen des Feedback Logs an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Feedback Log existiert nicht.' } ) ;
}
} else {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Unbekannte Auswahl.' } ) ;
}
} ) ;
// Handler für den /user-Befehl
bot . onText ( /\/user/ , ( msg ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
// Überprüfen, ob der Benutzer autorisiert ist
if ( userId . toString ( ) === USER1 _ID || userId . toString ( ) === USER2 _ID ) {
try {
// Lade die Benutzer aus der YAML-Datei
const users = yaml . load ( USER _YML _PATH ) ;
let responseMessage = "Benutzerinformationen:\n\n" ;
// Gehe durch die Benutzer und baue die Antwortnachricht auf
for ( const [ id , user ] of Object . entries ( users ) ) {
const name = user . username || 'Unbekannt' ;
const notificationsStatus = user . notifications ? 'Aktiv' : 'Inaktiv' ;
responseMessage += ` Name: ${ name } \n ID: ${ id } \n Benachrichtigung Status: ${ notificationsStatus } \n \n ` ; // Zwei Leerzeilen für Abstand
}
// Sende die Antwortnachricht
bot . sendMessage ( chatId , responseMessage . trim ( ) ) . catch ( error => {
logError ( ` Fehler beim Senden der Benutzerinformationen an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} catch ( error ) {
// Fehlerprotokollierung für unerwartete Fehler
logError ( ` Fehler beim Abrufen der Benutzerinformationen: ${ error . message } ` ) ;
bot . sendMessage ( chatId , 'Fehler beim Abrufen der Benutzerinformationen.' ) . catch ( err => {
logError ( ` Fehler beim Senden der Fehlermeldung an chatId ${ chatId } : ${ err . message } ` ) ;
} ) ;
}
} else {
bot . sendMessage ( chatId , '❌ Du bist nicht autorisiert, diesen Befehl auszuführen.' ) ;
}
} ) ;
// Maximale Länge einer Telegram-Nachricht in Zeichen
const MAX _MESSAGE _LENGTH = 4096 ;
// Hilfsfunktion zum Aufteilen einer Nachricht in kleinere Teile
function splitMessage ( message ) {
const messages = [ ] ;
while ( message . length > MAX _MESSAGE _LENGTH ) {
let splitIndex = message . lastIndexOf ( '\n' , MAX _MESSAGE _LENGTH ) ;
if ( splitIndex === - 1 ) {
splitIndex = MAX _MESSAGE _LENGTH ; // Wenn kein neuer Zeilenumbruch gefunden wird, einfach am Limit aufteilen
}
messages . push ( message . substring ( 0 , splitIndex ) ) ;
message = message . substring ( splitIndex ) ;
}
if ( message . length > 0 ) {
messages . push ( message ) ;
}
return messages ;
}
// Handler für den /top_rated-Befehl
bot . onText ( /\/top_rated/ , async ( msg ) => {
const chatId = msg . chat . id ;
try {
const movies = await fetchTopRatedMovies ( ) ;
if ( movies . length > 0 ) {
// Begrenze die Anzahl der angezeigten Filme auf 20
2024-09-01 15:04:00 +00:00
const topMovies = movies . slice ( 0 , 15 ) ;
2024-08-18 14:18:05 +00:00
let message = '🌟 *Top 15 Am besten bewertete Filme:*\n\n' ;
topMovies . forEach ( ( movie , index ) => {
message += ` 🎬 * ${ index + 1 } . ${ movie . title } * \n ` +
` ⭐ Bewertung: ${ movie . rating . toFixed ( 1 ) } \n \n ` ;
} ) ;
// Teile die Nachricht in kleinere Teile auf, wenn sie zu lang ist
const messageParts = splitMessage ( message ) ;
for ( const part of messageParts ) {
await bot . sendMessage ( chatId , part , { parse _mode : 'Markdown' } ) ;
}
} else {
await bot . sendMessage ( chatId , '🚫 Keine gut bewerteten Filme gefunden.' ) ;
}
} catch ( error ) {
logError ( ` Fehler beim Abrufen der besten Filme für chatId ${ chatId } : ${ error . message } ` ) ;
await bot . sendMessage ( chatId , 'Beim Abrufen der besten Filme ist ein Fehler aufgetreten.' ) ;
}
} ) ;
// Handler für Inline-Button-Callbacks
bot . on ( 'callback_query' , ( callbackQuery ) => {
const chatId = callbackQuery . message . chat . id ;
const userId = callbackQuery . from . id ;
const data = callbackQuery . data ;
if ( data . startsWith ( 'delete_log_' ) ) {
const index = parseInt ( data . split ( '_' ) [ 2 ] , 10 ) ;
const recentErrors = getRecentErrors ( ) ;
if ( index >= 0 && index < recentErrors . length ) {
recentErrors . splice ( index , 1 ) ; // Lösche den ausgewählten Eintrag
fs . writeFileSync ( ERROR _LOG _PATH , recentErrors . join ( '\n' ) , 'utf8' ) ;
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Fehlermeldung gelöscht.' } ) ;
bot . sendMessage ( chatId , 'Die Fehlermeldung wurde gelöscht.' ) . catch ( error => {
logError ( ` Fehler beim Senden der Bestätigungsnachricht über das Löschen der Fehlermeldung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
} else {
bot . answerCallbackQuery ( callbackQuery . id , { text : 'Ungültiger Index.' } ) ;
}
}
} ) ;
// Funktion zum Abrufen der letzten Fehlermeldungen
function getRecentErrors ( count = 10 ) {
if ( ! fs . existsSync ( ERROR _LOG _PATH ) ) return [ ] ;
const logLines = fs . readFileSync ( ERROR _LOG _PATH , 'utf8' ) . trim ( ) . split ( '\n' ) ;
return logLines . slice ( - count ) ;
}
// Funktion zum Protokollieren von Fehlern
function logError ( error ) {
const errorMessage = ` ${ dayjs ( ) . format ( 'HH:mm:ss' ) } - Error: ${ error } \n ` ;
fs . appendFileSync ( ERROR _LOG _PATH , errorMessage ) ;
}
2024-08-15 17:40:21 +00:00
// /start-Befehl verarbeiten
bot . onText ( /\/start/ , ( msg ) => {
const chatId = msg . chat . id ;
const userId = msg . from . id ;
2024-08-18 14:18:05 +00:00
const username = msg . from . username || 'Unbekannt' ; // Benutzername, falls vorhanden, sonst 'Unbekannt'
2024-08-15 17:40:21 +00:00
// Benutzerdaten in user.yml speichern
let users = yaml . load ( USER _YML _PATH ) ;
2024-09-01 15:04:00 +00:00
users [ chatId ] = { userId : userId , username : username , notifications : false } ; // Standardmäßig Benachrichtigungen deaktiviert
2024-08-15 17:40:21 +00:00
fs . writeFileSync ( USER _YML _PATH , yaml . stringify ( users , 4 ) ) ;
const welcomeMessage = `
2024-09-01 15:04:00 +00:00
👋 Willkommen $ { username } !
Dein Zugang zum Bot wurde erfolgreich eingerichtet . ✅
2024-08-15 17:40:21 +00:00
2024-09-01 15:04:00 +00:00
Um die verfügbaren Befehle anzuzeigen , tippe 👉 / help .
🔔 Hinweis : Benachrichtigungen über neue Filme sind standardmäßig deaktiviert .
Um sie zu aktivieren , tippe 👉 / notification _on .
2024-08-15 17:40:21 +00:00
` ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , welcomeMessage ) ;
2024-08-15 17:40:21 +00:00
// /start-Befehl protokollieren
2024-08-18 14:18:05 +00:00
logMessage ( ` Received /start command from chatId ${ chatId } (userId ${ userId } , username ${ username } ) ` ) ;
2024-08-15 17:40:21 +00:00
} ) ;
// /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 [ ] ;
}
}
2024-08-18 14:18:05 +00:00
// Funktion zum Überprüfen und Benachrichtigen über neue Filme
async function checkForNewMovies ( ) {
try {
const movies = await fetchLatest10Movies ( ) ; // Verwende fetchLatest10Movies, um die letzten 10 Filme zu erhalten
if ( movies . length > 0 ) {
const latestMovie = movies [ 0 ] ;
if ( ! lastAddedMovieTime || dayjs . unix ( latestMovie . addedAt ) . isAfter ( lastAddedMovieTime ) ) {
// Neuer Film wurde hinzugefügt und ist neuer als der zuletzt gesendete Film
lastAddedMovieTime = dayjs . unix ( latestMovie . addedAt ) ; // Update the last added movie time
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 \n Titel: ${ movieTitle } \n \n Zusammenfassung: \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 } ` ) ;
} ) ;
}
2024-08-15 17:40:21 +00:00
}
2024-08-18 14:18:05 +00:00
} ) . filter ( promise => promise !== undefined ) ;
2024-08-15 17:40:21 +00:00
2024-08-18 14:18:05 +00:00
await Promise . all ( sendMessages ) ;
console . log ( ` Sent new movie message to all users ` ) ;
// Speichern der letzten gesendeten Zeit in einer Datei, um Wiederholungen zu vermeiden
fs . writeFileSync ( 'lastAddedMovieTime.json' , JSON . stringify ( { time : lastAddedMovieTime . unix ( ) } ) ) ;
}
2024-08-15 17:40:21 +00:00
}
2024-08-18 14:18:05 +00:00
} catch ( error ) {
logError ( ` Error checking for new movies: ${ error . message } ` ) ;
2024-08-15 17:40:21 +00:00
}
}
2024-08-18 14:18:05 +00:00
// Lade den letzten gesendeten Film-Zeitstempel beim Start des Bots
if ( fs . existsSync ( 'lastAddedMovieTime.json' ) ) {
const lastAddedMovieData = JSON . parse ( fs . readFileSync ( 'lastAddedMovieTime.json' ) ) ;
lastAddedMovieTime = dayjs . unix ( lastAddedMovieData . time ) ;
}
// Plane die kontinuierliche Überprüfung alle 1 Minute
2024-08-15 17:40:21 +00:00
schedule . scheduleJob ( '*/1 * * * *' , checkForNewMovies ) ;
// Initiale Überprüfung beim Start
checkForNewMovies ( ) ;
// /latestmovie-Befehl verarbeiten
bot . onText ( /\/latestmovie/ , async ( msg ) => {
const chatId = msg . chat . id ;
2024-09-01 15:04:00 +00:00
2024-08-15 17:40:21 +00:00
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 \n Titel: ${ movieTitle } \n \n Zusammenfassung: \n ${ movieSummary } \n \n Hinzugefü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 ;
2024-09-01 15:04:00 +00:00
const messageId = msg . message _id ;
2024-08-18 14:18:05 +00:00
const plexDomain = PLEX _DOMAIN ;
2024-08-15 17:40:21 +00:00
try {
2024-08-18 14:18:05 +00:00
// Überprüfe den Serverstatus
const serverStatus = await checkServerStatus ( ) ;
2024-08-15 17:40:21 +00:00
const {
movieCount ,
showCount ,
episodeCount ,
seasonCount ,
topGenre ,
totalSize ,
oldestMovie ,
newestMovie
} = await fetchAllMedia ( ) ;
2024-08-18 14:18:05 +00:00
// Serverstatus Text
const serverStatusText = serverStatus
? '🟢 Server Status: Online'
: '🔴 Server Status: Offline' ;
const message = ` ${ serverStatusText } \n \n ` +
` *In der Bibliothek befinden sich derzeit:* \n \n ` +
2024-08-15 17:40:21 +00:00
` 📽️ Filme: ${ movieCount } \n \n ` +
` 📺 Serien: ${ showCount } \n \n ` +
` 🎞️ Episoden: ${ episodeCount } \n \n ` +
` 📚 Staffeln: ${ seasonCount } \n \n \n ` +
` 📊 Top-Genre: ${ topGenre } \n \n ` +
2024-09-01 15:04:00 +00:00
` 💾 Gesamtgröße-Filme: ${ totalSize } \n \n ` +
` 💾 Gesamtgröße-Serien: 1.70TB \n \n \n ` +
2024-08-15 17:40:21 +00:00
` ⏳ Ältester Film: ${ oldestMovie . title } ( ${ oldestMovie . year } ) \n \n ` +
` 🆕 Neuester Film: ${ newestMovie . title } ( ${ newestMovie . year } ) \n \n \n ` +
` © 2024 M_Viper ` ;
2024-08-18 14:18:05 +00:00
2024-08-15 17:40:21 +00:00
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 } ` ) ;
} ) ;
2024-09-01 15:04:00 +00:00
// Ursprüngliche Nachricht löschen (den /info-Befehl)
await bot . deleteMessage ( chatId , messageId ) . catch ( error => {
logError ( ` Error deleting message from chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
2024-08-15 17:40:21 +00:00
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 } ` ) ;
} ) ;
}
} ) ;
2024-08-18 14:18:05 +00:00
// Funktion zum Überprüfen des Serverstatus
async function checkServerStatus ( ) {
try {
const response = await axios . get ( ` ${ PLEX _DOMAIN } /status ` , {
headers : { 'X-Plex-Token' : PLEX _TOKEN }
} ) ;
return response . status === 200 ; // Server ist online, wenn Status 200 zurückgegeben wird
} catch ( error ) {
console . error ( ` Server is offline or unreachable: ${ error . message } ` ) ;
return false ; // Server ist offline oder nicht erreichbar
}
}
// 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 from ${ url } : ${ error . message } ` ) ;
throw error ;
}
}
2024-08-15 17:40:21 +00:00
// 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 {
2024-08-18 14:18:05 +00:00
const sectionsData = await fetchPlexData ( ` ${ PLEX _DOMAIN } /library/sections?X-Plex-Token= ${ PLEX _TOKEN } ` ) ;
2024-08-15 17:40:21 +00:00
const sections = sectionsData . MediaContainer . Directory ;
let movies = [ ] ;
for ( const section of sections ) {
2024-08-18 14:18:05 +00:00
const sectionUrl = ` ${ PLEX _DOMAIN } /library/sections/ ${ section . key } /all?X-Plex-Token= ${ PLEX _TOKEN } ` ;
2024-08-15 17:40:21 +00:00
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 {
2024-08-18 14:18:05 +00:00
const sectionsData = await fetchPlexData ( ` ${ PLEX _DOMAIN } /library/sections?X-Plex-Token= ${ PLEX _TOKEN } ` ) ;
2024-08-15 17:40:21 +00:00
const sections = sectionsData . MediaContainer . Directory ;
let shows = [ ] ;
for ( const section of sections ) {
2024-08-18 14:18:05 +00:00
const sectionUrl = ` ${ PLEX _DOMAIN } /library/sections/ ${ section . key } /all?X-Plex-Token= ${ PLEX _TOKEN } ` ;
2024-08-15 17:40:21 +00:00
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 ;
}
}
2024-08-18 14:18:05 +00:00
// Fehlerprotokollierung
function logError ( message ) {
fs . appendFile ( path . join ( _ _dirname , 'Log' , 'error.log' ) , ` ${ new Date ( ) . toISOString ( ) } - ${ message } \n ` , err => {
if ( err ) {
console . error ( ` Failed to log error: ${ err . message } ` ) ;
}
} ) ;
}
// Erfolgsprotokollierung
function logMessage ( message ) {
fs . appendFile ( path . join ( _ _dirname , 'Log' , 'message.log' ) , ` ${ new Date ( ) . toISOString ( ) } - ${ message } \n ` , err => {
if ( err ) {
console . error ( ` Failed to log message: ${ err . message } ` ) ;
}
} ) ;
}
2024-08-15 17:40:21 +00:00
// 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' } ]
]
} )
} ;
}
2024-09-01 15:04:00 +00:00
2024-08-15 17:40:21 +00:00
// 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 \n Ein 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 \n Zusammenfassung: \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 \n Titel: ${ movieTitle } \n \n Zusammenfassung: \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 \n Zusammenfassung: \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 ;
}
}
2024-08-18 14:18:05 +00:00
async function fetchRandomKidsMovie ( ) {
try {
const movies = await fetchAllMovies ( ) ;
const kidsGenres = [ "Kids" , "Family" , "Kinderfilme" , "Animation" , "Cartoon" , "Familienfilm" ] ;
// Filter movies by checking if any of the genres match the kidsGenres list
const kidsMovies = movies . filter ( movie =>
movie . Genre && movie . Genre . some ( genre => kidsGenres . includes ( genre . tag ) )
) ;
if ( kidsMovies . length > 0 ) {
// Select a random movie from the filtered list
const randomIndex = Math . floor ( Math . random ( ) * kidsMovies . length ) ;
return kidsMovies [ randomIndex ] ;
} else {
logError ( "No kids movies found with the specified genres." ) ;
return null ;
}
} catch ( error ) {
logError ( ` Error fetching random kids movie: ${ error . message } ` ) ;
throw error ;
}
}
2024-08-15 17:40:21 +00:00
// /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 \n Titel: ${ movieTitle } \n \n Zusammenfassung: \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 } ` ) ;
} ) ;
}
} ) ;
2024-09-01 15:04:00 +00:00
2024-08-18 14:18:05 +00:00
// Session-Management für Feedback
const feedbackSessions = { } ;
2024-08-15 17:40:21 +00:00
2024-08-18 14:18:05 +00:00
// Fehlerprotokollierungsfunktion
function logError ( error ) {
const errorMessage = ` ${ dayjs ( ) . format ( 'HH:mm:ss' ) } - Error: ${ error } \n ` ;
fs . appendFileSync ( ERROR _LOG _PATH , errorMessage ) ;
}
// Speichert Feedback in der Datei
function saveFeedbackToFile ( feedbackData ) {
// Wenn die Datei nicht existiert, erstelle sie mit dem Header
if ( ! fs . existsSync ( feedbackFilePath ) ) {
fs . writeFileSync ( feedbackFilePath , 'timestamp - chatId: feedback\n' ) ;
}
const feedback = ` ${ feedbackData . timestamp } - chatId ${ feedbackData . chatId } : ${ feedbackData . feedback } \n ` ;
fs . appendFileSync ( feedbackFilePath , feedback ) ;
}
// Sendet Feedback an Administratoren
function sendFeedbackToAdmins ( userId , feedback ) {
const adminChatIds = [ USER1 _ID , USER2 _ID ] ; // Hier sollten die IDs der Administratoren festgelegt werden
2024-09-01 15:04:00 +00:00
const message = ` 📢 Neues Feedback: \n \n Von userId: " ${ userId } " \n \n " ${ feedback } " ` ;
2024-08-18 14:18:05 +00:00
adminChatIds . forEach ( adminChatId => {
bot . sendMessage ( adminChatId , message ) . catch ( error => {
logError ( ` Fehler beim Senden von Feedback an Admin chatId ${ adminChatId } : ${ error . message } ` ) ;
} ) ;
} ) ;
}
2024-09-01 15:04:00 +00:00
const feedbackFilePath = path . join ( _ _dirname , 'feedback.log' ) ; // Überprüfe, ob dieser Pfad korrekt ist
// Fehlerprotokollierungsfunktion
function logError ( error ) {
const errorMessage = ` ${ new Date ( ) . toISOString ( ) } - Error: ${ error . message || error } \n ` ;
try {
fs . appendFileSync ( errorLogPath , errorMessage ) ;
} catch ( err ) {
console . error ( 'Fehler beim Schreiben in die Fehlerprotokolldatei:' , err . message ) ;
}
}
// Funktion, die überprüft, ob ein Benutzer autorisiert ist
function isUserAuthorized ( userId ) {
const authorizedUsers = [ process . env . USER1 _ID , process . env . USER2 _ID ] ;
return authorizedUsers . includes ( userId . toString ( ) ) ;
}
// Funktion, die überprüft, ob ein Benutzer autorisiert ist
function isUserAuthorized ( userId ) {
const authorizedUsers = [ process . env . USER1 _ID , process . env . USER2 _ID ] ;
return authorizedUsers . includes ( userId . toString ( ) ) ;
}
// Speichert Feedback in der Datei
function saveFeedbackToFile ( { chatId , feedback , timestamp } ) {
const feedbackEntry = ` ${ timestamp } - chatId ${ chatId } : ${ feedback } \n ` ;
try {
if ( ! fs . existsSync ( feedbackFilePath ) ) {
fs . writeFileSync ( feedbackFilePath , 'timestamp - chatId: feedback\n' ) ;
}
fs . appendFileSync ( feedbackFilePath , feedbackEntry ) ;
} catch ( err ) {
logError ( ` Fehler beim Speichern des Feedbacks: ${ err . message } ` ) ;
}
}
// Sendet Feedback an Administratoren
function sendFeedbackToAdmins ( userId , feedback ) {
const adminChatIds = [ process . env . USER1 _ID , process . env . USER2 _ID ] ;
const message = `
✨ * Neues Feedback * ✨
🆔 * User ID : * $ { userId }
═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═
📌 * Zusammenfassung : * 📌
$ { feedback }
` ;
adminChatIds . forEach ( adminChatId => {
bot . sendMessage ( adminChatId , message )
. catch ( error => {
logError ( ` Fehler beim Senden von Feedback an Admin chatId ${ adminChatId } : ${ error . message } ` ) ;
} ) ;
} ) ;
}
2024-08-18 14:18:05 +00:00
// Handler für den /feedback Befehl
bot . onText ( /\/feedback/ , ( msg ) => {
const chatId = msg . chat . id ;
// Startet eine Feedback-Sitzung
feedbackSessions [ chatId ] = { waitingForFeedback : true } ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , '✍️ Bitte gib dein Feedback ein. Du kannst den Befehl `/cancel` verwenden, um das Feedback zu abbrechen.' , { parse _mode : 'Markdown' } )
. catch ( error => {
logError ( ` Fehler beim Senden der Feedback-Aufforderung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
} ) ;
// Handler für den /cancel Befehl
bot . onText ( /\/cancel/ , ( msg ) => {
const chatId = msg . chat . id ;
if ( feedbackSessions [ chatId ] ) {
delete feedbackSessions [ chatId ] ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , 'Feedback wurde abgebrochen.' , { parse _mode : 'Markdown' } )
. catch ( error => {
logError ( ` Fehler beim Senden der Abbruch-Nachricht an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
}
} ) ;
// Handler für Nachrichten
bot . on ( 'message' , ( msg ) => {
const chatId = msg . chat . id ;
if ( feedbackSessions [ chatId ] && msg . text && msg . text !== '/cancel' ) {
const feedback = msg . text ;
const userId = msg . from . id ; // Die userId des Feedbackers
2024-09-01 15:04:00 +00:00
saveFeedbackToFile ( { chatId , feedback , timestamp : dayjs ( ) . format ( 'YYYY-MM-DD HH:mm:ss' ) } ) ;
2024-08-18 14:18:05 +00:00
sendFeedbackToAdmins ( userId , feedback ) ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , '👍 Danke für dein Feedback!' , { parse _mode : 'Markdown' } )
. catch ( error => {
logError ( ` Fehler beim Senden der Bestätigung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
delete feedbackSessions [ chatId ] ;
}
} ) ;
2024-09-01 15:04:00 +00:00
// Beispiel zur erweiterten Fehlerbehandlung im Bot
bot . on ( 'polling_error' , ( error ) => {
logError ( ` Polling Error: ${ error . code } - ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
// Handler für den /f_log Befehl
bot . onText ( /\/f_log/ , ( msg ) => {
2024-08-15 17:40:21 +00:00
const chatId = msg . chat . id ;
2024-08-18 14:18:05 +00:00
const userId = msg . from . id ;
2024-08-15 17:40:21 +00:00
2024-08-18 14:18:05 +00:00
if ( isUserAuthorized ( userId ) ) {
try {
if ( fs . existsSync ( feedbackFilePath ) ) {
const tempFilePath = path . join ( _ _dirname , 'feedback_log.txt' ) ;
const feedbackData = fs . readFileSync ( feedbackFilePath , 'utf8' ) ;
fs . writeFileSync ( tempFilePath , feedbackData ) ;
2024-09-01 15:04:00 +00:00
bot . sendDocument ( chatId , tempFilePath )
. then ( ( ) => {
fs . unlinkSync ( tempFilePath ) ;
console . log ( 'Feedback-Log-Datei erfolgreich gesendet und gelöscht.' ) ;
} )
. catch ( error => {
logError ( ` Fehler beim Senden der feedback_log.txt an chatId ${ chatId } : ${ error . message } ` ) ;
bot . sendMessage ( chatId , '❌ Fehler beim Senden der Feedback-Log-Datei.' )
. catch ( err => {
logError ( ` Fehler beim Senden der Fehlermeldung an chatId ${ chatId } : ${ err . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
} ) ;
} else {
const errMsg = ` Keine Feedback-Datei gefunden unter ${ feedbackFilePath } . ` ;
console . log ( errMsg ) ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , ` ❌ ${ errMsg } ` )
. catch ( error => {
logError ( ` Fehler beim Senden der Fehlermeldung an chatId ${ chatId } : ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
}
} catch ( error ) {
logError ( ` Fehler beim Senden der Feedback-Log-Datei: ${ error . message } ` ) ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , '❌ Fehler beim Senden der Feedback-Log-Datei.' )
. catch ( err => {
logError ( ` Fehler beim Senden der Fehlermeldung an chatId ${ chatId } : ${ err . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
}
} else {
const errMsg = ` Unberechtigter Zugriff auf /f_log von userId ${ userId } . ` ;
console . log ( errMsg ) ;
2024-09-01 15:04:00 +00:00
bot . sendMessage ( chatId , ` ❌ ${ errMsg } ` )
. catch ( error => {
logError ( ` Unberechtigter Zugriff auf /f_log von userId ${ userId } : ${ error . message } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
}
} ) ;
// Funktion zum Erstellen der Hilfennachricht
function createHelpMessage ( chatId ) {
// Basis-Hilfe-Nachricht für alle Benutzer
let helpMessage = ` 📜 *Hier ist eine Liste der verfügbaren Befehle:* \n \n ` +
2024-08-15 17:40:21 +00:00
` 👋 /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 ` +
2024-08-18 14:18:05 +00:00
` 📺 /serien - Zeigt eine Liste aller Serien an. \n \n ` +
2024-08-15 17:40:21 +00:00
` 🎬 /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 ` +
2024-08-18 14:18:05 +00:00
` ⭐ /top \\ _rated - Zeigt die am besten bewerteten Filme an. \n \n ` +
2024-08-15 17:40:21 +00:00
` 💭 /wunsch - Nutze diesen Befehl, um einen Filmwunsch zu äußern. \n \n ` +
` 🔝 /empfehlung - Film Empfehlung des Tages. \n \n ` +
2024-08-18 14:18:05 +00:00
` 💬 /feedback - Gib Feedback zum Bot. \n \n ` +
` 🔧 /dev - Funktionswunsch oder Bug melden. \n \n ` +
` ❓ /help - Zeigt diese Hilfennachricht an. \n \n \n ` ;
const additionalCommands = ` *👨💻 Admin Befehle* \n \n ` +
` 🤖 /bot - Zeigt Informationen über den Bot. \n \n ` +
2024-09-01 15:04:00 +00:00
` 🛠️ /admin - sendet eine Nachricht an alle Nutzer. \n \n ` +
2024-08-18 14:18:05 +00:00
` 👤 /user - Zeigt Benutzerinformationen an. \n \n ` +
` 📝 /logs - Zeigt die letzten Fehlermeldungen an. \n \n ` +
` 🗑️ /log \\ _delete - Löscht Logs. \n \n ` +
` 📝 /f \\ _log - Sendet die Feedback als .txt-Datei. ` ;
// Debug-Ausgaben zur Überprüfung
console . log ( ` Received chatId: ${ chatId } ` ) ;
console . log ( ` Configured USER1_ID: ${ USER1 _ID } ` ) ;
console . log ( ` Configured USER2_ID: ${ USER2 _ID } ` ) ;
// Nur Benutzer in der .env-Datei erhalten die zusätzlichen Befehle
if ( chatId . toString ( ) === USER1 _ID || chatId . toString ( ) === USER2 _ID ) {
helpMessage += additionalCommands ;
}
return helpMessage ;
}
// /help-Befehl verarbeiten
bot . onText ( /\/help/ , ( msg ) => {
const chatId = msg . chat . id ;
const helpMessage = createHelpMessage ( chatId ) ;
2024-08-15 17:40:21 +00:00
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 } ` ) ;
} ) ;
2024-08-18 14:18:05 +00:00
// 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 ;
}
}
2024-08-15 17:40:21 +00:00
// 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 ;
}
}
2024-09-01 15:04:00 +00:00
// 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 ;
}
}
// Maximal zulässige Länge der Bildunterschrift (in Zeichen)
const MAX _CAPTION _LENGTH = 1024 ; // Telegrams Beschränkung für Bildunterschriften
// Funktion zum Kürzen der Zusammenfassung
function truncateSummary ( summary , maxLength ) {
if ( summary . length > maxLength ) {
return summary . slice ( 0 , maxLength ) + '...' ; // Kürzen und "..." hinzufügen
}
return summary ;
}
// Funktion zum Erstellen der Bildunterschrift
function createCaption ( title , summary , addedAt ) {
// Initiale Bildunterschrift ohne Kürzung
let caption = `
🎬 Titel : $ { title || 'Unbekannt' }
📝 Zusammenfassung :
$ { summary || 'Keine Zusammenfassung verfügbar.' }
📅 Hinzugefügt am : $ { dayjs ( addedAt * 1000 ) . format ( 'DD.MM.YYYY' ) }
` ;
// Überprüfen, ob die Bildunterschrift zu lang ist
if ( caption . length > MAX _CAPTION _LENGTH ) {
// Berechnen der maximalen Länge für die Zusammenfassung
const maxSummaryLength = MAX _CAPTION _LENGTH - ( caption . length - summary . length ) ;
// Kürzen der Zusammenfassung auf die berechnete Länge
const truncatedSummary = truncateSummary ( summary , maxSummaryLength ) ;
// Neu zusammenstellen der Bildunterschrift mit der gekürzten Zusammenfassung
caption = `
🎬 Titel : $ { title || 'Unbekannt' }
📝 Zusammenfassung :
$ { truncatedSummary }
📅 Hinzugefügt am : $ { dayjs ( addedAt * 1000 ) . format ( 'DD.MM.YYYY' ) }
` ;
}
return caption ;
}
2024-08-15 17:40:21 +00:00
// /latest10movies-Befehl verarbeiten
bot . onText ( /\/latest10movies/ , async ( msg ) => {
const chatId = msg . chat . id ;
try {
const latestMovies = await fetchLatest10Movies ( ) ;
if ( latestMovies . length > 0 ) {
2024-09-01 15:04:00 +00:00
const numberEmojis = [ '1️ ⃣' , '2️ ⃣' , '3️ ⃣' , '4️ ⃣' , '5️ ⃣' , '6️ ⃣' , '7️ ⃣' , '8️ ⃣' , '9️ ⃣' , '🔟' ] ;
2024-08-15 17:40:21 +00:00
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 ) {
2024-09-01 15:04:00 +00:00
// Bildunterschrift erstellen und kürzen, falls nötig
const movieDetails = createCaption ( selectedMovie . title , selectedMovie . summary , selectedMovie . addedAt ) ;
2024-08-15 17:40:21 +00:00
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 } ` ) ;
}
}
2024-09-01 15:04:00 +00:00
2024-08-15 17:40:21 +00:00
// 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 \n Titel: ${ 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 ( ) ;
2024-08-18 14:18:05 +00:00
console . log ( 'Bot is running...' ) ;