- Added Telegram warning cron job at 09:00 (1 hour before cleanup) - Integrated with GroupCleanupService.findGroupsForDeletion() - Sends sendDeletionWarning() notification for groups pending deletion - Added manual trigger method triggerTelegramWarningNow() for development - Added POST /api/admin/telegram/warning endpoint for manual testing - Fixed SchedulerService singleton instance in server.js app.set() - Added Telegram ENV vars to docker-compose.yml environment section Tested successfully with test data showing warning message in Telegram.
125 lines
4.5 KiB
JavaScript
125 lines
4.5 KiB
JavaScript
const express = require('express');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const initiateResources = require('./utils/initiate-resources');
|
||
const dbManager = require('./database/DatabaseManager');
|
||
const SchedulerService = require('./services/SchedulerService');
|
||
const TelegramNotificationService = require('./services/TelegramNotificationService');
|
||
|
||
// Singleton-Instanz des Telegram Service
|
||
const telegramService = new TelegramNotificationService();
|
||
|
||
// Dev: Swagger UI (mount only in non-production) — require lazily
|
||
let swaggerUi = null;
|
||
try {
|
||
swaggerUi = require('swagger-ui-express');
|
||
} catch (e) {
|
||
swaggerUi = null;
|
||
}
|
||
|
||
class Server {
|
||
_port;
|
||
_app;
|
||
|
||
constructor(port) {
|
||
this._port = port;
|
||
this._app = express();
|
||
const trustProxyHops = Number.parseInt(process.env.TRUST_PROXY_HOPS ?? '1', 10);
|
||
if (!Number.isNaN(trustProxyHops) && trustProxyHops > 0) {
|
||
this._app.set('trust proxy', trustProxyHops);
|
||
}
|
||
}
|
||
|
||
async generateOpenApiSpecIfNeeded() {
|
||
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const generateOpenApi = require('./generate-openapi');
|
||
console.log('🔄 Generating OpenAPI specification...');
|
||
await generateOpenApi();
|
||
console.log('✓ OpenAPI spec generated');
|
||
} catch (error) {
|
||
console.warn('⚠️ Failed to generate OpenAPI spec:', error.message);
|
||
}
|
||
}
|
||
|
||
loadSwaggerDocument() {
|
||
try {
|
||
const specPath = path.join(__dirname, '..', 'docs', 'openapi.json');
|
||
const raw = fs.readFileSync(specPath, 'utf8');
|
||
return JSON.parse(raw);
|
||
} catch (error) {
|
||
console.warn('⚠️ Unable to load Swagger document:', error.message);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async start() {
|
||
try {
|
||
await this.generateOpenApiSpecIfNeeded();
|
||
|
||
// Initialisiere Datenbank
|
||
console.log('🔄 Initialisiere Datenbank...');
|
||
await dbManager.initialize();
|
||
console.log('✓ Datenbank bereit');
|
||
|
||
// Starte Express Server
|
||
initiateResources(this._app);
|
||
this._app.use('/upload', express.static( __dirname + '/upload'));
|
||
this._app.use('/api/previews', express.static( __dirname + '/data/previews'));
|
||
|
||
// Mount Swagger UI in dev only when available
|
||
if (process.env.NODE_ENV !== 'production' && swaggerUi) {
|
||
const swaggerDocument = this.loadSwaggerDocument();
|
||
if (swaggerDocument) {
|
||
this._app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
||
console.log('ℹ️ Swagger UI mounted at /api/docs (dev only)');
|
||
}
|
||
}
|
||
this._app.listen(this._port, () => {
|
||
console.log(`✅ Server läuft auf Port ${this._port}`);
|
||
console.log(`📊 SQLite Datenbank aktiv`);
|
||
|
||
// Speichere SchedulerService in app für Admin-Endpoints
|
||
this._app.set('schedulerService', SchedulerService);
|
||
|
||
// Starte Scheduler für automatisches Cleanup
|
||
SchedulerService.start();
|
||
|
||
// Teste Telegram-Service (nur in Development)
|
||
if (process.env.NODE_ENV === 'development' && telegramService.isAvailable()) {
|
||
telegramService.sendTestMessage()
|
||
.catch(err => console.error('[Telegram] Test message failed:', err.message));
|
||
}
|
||
});
|
||
} catch (error) {
|
||
console.error('💥 Fehler beim Serverstart:', error);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// Expose app for testing
|
||
getApp() {
|
||
return this._app;
|
||
}
|
||
|
||
// Initialize app without listening (for tests)
|
||
async initializeApp() {
|
||
await dbManager.initialize();
|
||
initiateResources(this._app);
|
||
this._app.use('/upload', express.static( __dirname + '/upload'));
|
||
this._app.use('/api/previews', express.static( __dirname + '/data/previews'));
|
||
|
||
if (process.env.NODE_ENV !== 'production' && swaggerUi) {
|
||
const swaggerDocument = this.loadSwaggerDocument();
|
||
if (swaggerDocument) {
|
||
this._app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
||
}
|
||
}
|
||
return this._app;
|
||
}
|
||
}
|
||
|
||
module.exports = Server; |