import { botDatabase } from './database'; import { logger } from './logger'; import { GroupSettings, ReminderTime, reminderTimeToMinutes } from '../types/groups'; class GroupStateManager { async init(): Promise { // Database is initialized separately logger.info('Group state manager initialized (using SQLite database)'); } /** * Get group settings */ async getGroup(groupId: number): Promise { return botDatabase.getGroup(groupId); } /** * Register a new group */ async registerGroup( groupId: number, groupTitle: string, addedBy: number ): Promise { return botDatabase.registerGroup(groupId, groupTitle, addedBy); } /** * Remove a group */ async removeGroup(groupId: number): Promise { botDatabase.removeGroup(groupId); } /** * Save group settings */ async saveGroup(settings: GroupSettings): Promise { botDatabase.saveGroup(settings); logger.debug('Group settings saved', { groupId: settings.groupId }); } /** * Update a group setting */ async updateSetting( groupId: number, setting: | 'enabled' | 'drawAnnouncements' | 'reminders' | 'newJackpotAnnouncement' | 'ticketPurchaseAllowed' | 'reminder1Enabled' | 'reminder2Enabled' | 'reminder3Enabled', value: boolean ): Promise { return botDatabase.updateGroupSetting(groupId, setting, value); } /** * Update reminder time for a slot */ async updateReminderTime( groupId: number, slot: 1 | 2 | 3, time: ReminderTime ): Promise { return botDatabase.updateReminderTime(groupId, slot, time); } /** * Update announcement delay */ async updateAnnouncementDelay( groupId: number, seconds: number ): Promise { return botDatabase.updateAnnouncementDelay(groupId, seconds); } /** * Update new jackpot announcement delay */ async updateNewJackpotDelay( groupId: number, minutes: number ): Promise { return botDatabase.updateNewJackpotDelay(groupId, minutes); } /** * Get groups with specific feature enabled */ async getGroupsWithFeature( feature: 'enabled' | 'drawAnnouncements' | 'reminders' | 'newJackpotAnnouncement' ): Promise { if (feature === 'newJackpotAnnouncement') { const allGroups = await this.getAllGroups(); return allGroups.filter(g => g.enabled && g.newJackpotAnnouncement); } return botDatabase.getGroupsWithFeature(feature as 'enabled' | 'drawAnnouncements' | 'reminders'); } /** * Get all groups */ async getAllGroups(): Promise { return botDatabase.getAllGroups(); } /** * Get groups that need reminders for a specific draw time */ async getGroupsNeedingReminders(drawTime: Date): Promise> { const allGroups = await this.getGroupsWithFeature('reminders'); const now = new Date(); const minutesUntilDraw = (drawTime.getTime() - now.getTime()) / (1000 * 60); const results: Array<{ settings: GroupSettings; reminderSlot: 1 | 2 | 3 }> = []; for (const group of allGroups) { // Check each reminder slot if (group.reminder1Enabled) { const reminderMinutes = reminderTimeToMinutes(group.reminder1Time); if (Math.abs(minutesUntilDraw - reminderMinutes) < 1) { results.push({ settings: group, reminderSlot: 1 }); } } if (group.reminder2Enabled) { const reminderMinutes = reminderTimeToMinutes(group.reminder2Time); if (Math.abs(minutesUntilDraw - reminderMinutes) < 1) { results.push({ settings: group, reminderSlot: 2 }); } } if (group.reminder3Enabled) { const reminderMinutes = reminderTimeToMinutes(group.reminder3Time); if (Math.abs(minutesUntilDraw - reminderMinutes) < 1) { results.push({ settings: group, reminderSlot: 3 }); } } } return results; } /** * Add time to a reminder */ async addReminderTime( groupId: number, slot: 1 | 2 | 3, amount: number, unit: 'minutes' | 'hours' | 'days' ): Promise { const group = await this.getGroup(groupId); if (!group) return null; const timeKey = `reminder${slot}Time` as 'reminder1Time' | 'reminder2Time' | 'reminder3Time'; const currentTime = group[timeKey]; // Convert everything to minutes, add, then convert back let totalMinutes = reminderTimeToMinutes(currentTime); switch (unit) { case 'minutes': totalMinutes += amount; break; case 'hours': totalMinutes += amount * 60; break; case 'days': totalMinutes += amount * 24 * 60; break; } // Ensure minimum of 1 minute totalMinutes = Math.max(1, totalMinutes); // Convert back to best unit const newTime = this.minutesToReminderTime(totalMinutes); return this.updateReminderTime(groupId, slot, newTime); } /** * Remove time from a reminder */ async removeReminderTime( groupId: number, slot: 1 | 2 | 3, amount: number, unit: 'minutes' | 'hours' | 'days' ): Promise { return this.addReminderTime(groupId, slot, -amount, unit); } /** * Convert total minutes to the best ReminderTime representation */ private minutesToReminderTime(totalMinutes: number): ReminderTime { // Use days if evenly divisible and >= 1 day if (totalMinutes >= 1440 && totalMinutes % 1440 === 0) { return { value: totalMinutes / 1440, unit: 'days' }; } // Use hours if evenly divisible and >= 1 hour if (totalMinutes >= 60 && totalMinutes % 60 === 0) { return { value: totalMinutes / 60, unit: 'hours' }; } // Use minutes return { value: totalMinutes, unit: 'minutes' }; } /** * Shutdown */ async close(): Promise { // Database close is handled separately logger.info('Group state manager closed'); } } export const groupStateManager = new GroupStateManager(); export default groupStateManager;