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.
This commit is contained in:
Matthias Lotz 2025-11-30 11:20:10 +01:00
parent 8cceb8e9a3
commit 489e2166bb
5 changed files with 156 additions and 1 deletions

View File

@ -39,6 +39,9 @@
{
"name": "Admin - Cleanup"
},
{
"name": "Admin - Telegram"
},
{
"name": "Admin - Monitoring"
},
@ -1726,6 +1729,46 @@
}
}
},
"/api/admin/telegram/warning": {
"post": {
"tags": [
"Admin - Telegram"
],
"summary": "Manually trigger Telegram deletion warning",
"description": "Sends deletion warning to Telegram for testing (normally runs daily at 09:00)",
"responses": {
"200": {
"description": "Warning sent successfully",
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"example": true
},
"groupsWarned": {
"type": "number",
"example": 2
},
"message": {
"type": "string",
"example": "Deletion warning sent for 2 groups"
}
},
"xml": {
"name": "main"
}
}
},
"403": {
"description": "Forbidden"
},
"500": {
"description": "Internal Server Error"
}
}
}
},
"/api/admin/cleanup/preview": {
"get": {
"tags": [

View File

@ -237,6 +237,46 @@ router.post('/cleanup/trigger', async (req, res) => {
}
});
router.post('/telegram/warning', async (req, res) => {
/*
#swagger.tags = ['Admin - Telegram']
#swagger.summary = 'Manually trigger Telegram deletion warning'
#swagger.description = 'Sends deletion warning to Telegram for testing (normally runs daily at 09:00)'
#swagger.responses[200] = {
description: 'Warning sent successfully',
schema: {
success: true,
groupsWarned: 2,
message: 'Deletion warning sent for 2 groups'
}
}
*/
try {
const schedulerService = req.app.get('schedulerService');
if (!schedulerService) {
return res.status(500).json({
success: false,
message: 'Scheduler service not available'
});
}
const result = await schedulerService.triggerTelegramWarningNow();
res.json({
success: true,
groupsWarned: result.groupCount,
message: result.message
});
} catch (error) {
console.error('[Admin API] Error triggering Telegram warning:', error);
res.status(500).json({
error: 'Internal server error',
message: error.message
});
}
});
router.get('/cleanup/preview', async (req, res) => {
/*
#swagger.tags = ['Admin - Cleanup']

View File

@ -82,6 +82,9 @@ class Server {
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();

View File

@ -1,9 +1,11 @@
const cron = require('node-cron');
const GroupCleanupService = require('./GroupCleanupService');
const TelegramNotificationService = require('./TelegramNotificationService');
class SchedulerService {
constructor() {
this.tasks = [];
this.telegramService = new TelegramNotificationService();
}
start() {
@ -30,7 +32,35 @@ class SchedulerService {
this.tasks.push(cleanupTask);
console.log('✓ Scheduler started - Daily cleanup at 10:00 AM (Europe/Berlin)');
// Telegram Warning-Job: Jeden Tag um 09:00 Uhr (1 Stunde vor Cleanup)
const telegramWarningTask = cron.schedule('0 9 * * *', async () => {
console.log('[Scheduler] Running daily Telegram deletion warning at 09:00 AM...');
try {
if (this.telegramService.isAvailable()) {
const groupsForDeletion = await GroupCleanupService.findGroupsForDeletion();
if (groupsForDeletion && groupsForDeletion.length > 0) {
await this.telegramService.sendDeletionWarning(groupsForDeletion);
console.log(`[Scheduler] Sent deletion warning for ${groupsForDeletion.length} groups`);
} else {
console.log('[Scheduler] No groups pending deletion');
}
} else {
console.log('[Scheduler] Telegram service not available, skipping warning');
}
} catch (error) {
console.error('[Scheduler] Telegram warning task failed:', error);
}
}, {
scheduled: true,
timezone: "Europe/Berlin"
});
this.tasks.push(telegramWarningTask);
console.log('✓ Scheduler started:');
console.log(' - Daily cleanup at 10:00 AM (Europe/Berlin)');
console.log(' - Daily Telegram warning at 09:00 AM (Europe/Berlin)');
// Für Development: Manueller Trigger
if (process.env.NODE_ENV === 'development') {
@ -50,6 +80,42 @@ class SchedulerService {
console.log('[Scheduler] Manual cleanup triggered...');
return await GroupCleanupService.performScheduledCleanup();
}
// Für Development: Manueller Telegram-Warning-Trigger
async triggerTelegramWarningNow() {
console.log('[Scheduler] Manual Telegram warning triggered...');
try {
if (!this.telegramService.isAvailable()) {
console.log('[Scheduler] Telegram service not available');
return { success: false, message: 'Telegram service not available' };
}
const groupsForDeletion = await GroupCleanupService.findGroupsForDeletion();
if (!groupsForDeletion || groupsForDeletion.length === 0) {
console.log('[Scheduler] No groups pending deletion');
return { success: true, message: 'No groups pending deletion', groupCount: 0 };
}
await this.telegramService.sendDeletionWarning(groupsForDeletion);
console.log(`[Scheduler] Sent deletion warning for ${groupsForDeletion.length} groups`);
return {
success: true,
message: `Warning sent for ${groupsForDeletion.length} groups`,
groupCount: groupsForDeletion.length,
groups: groupsForDeletion.map(g => ({
groupId: g.groupId,
name: g.name,
year: g.year,
uploadDate: g.uploadDate
}))
};
} catch (error) {
console.error('[Scheduler] Manual Telegram warning failed:', error);
return { success: false, message: error.message };
}
}
}
module.exports = new SchedulerService();

View File

@ -46,6 +46,9 @@ services:
- ENABLE_HOST_RESTRICTION=true
- TRUST_PROXY_HOPS=0
- PUBLIC_UPLOAD_RATE_LIMIT=20
- TELEGRAM_ENABLED=true
- TELEGRAM_BOT_TOKEN=8496813818:AAHShJP_cqOuWIW66ROUCxa-1C83CCCZmqU
- TELEGRAM_CHAT_ID=-1003064825033
networks:
- dev-internal
command: [ "npm", "run", "server" ]