Project-Image-Uploader/backend/src/server.js
matthias.lotz 489e2166bb feat(telegram): add daily deletion warning cron job (Phase 5)
- 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.
2025-11-30 11:20:10 +01:00

125 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;