'use strict' import { Client, GatewayIntentBits } from 'discord.js' import cron from 'node-cron' import dotenv from 'dotenv' import { getNumberEmoji, logger } from './utils.js' import { createClient } from '@supabase/supabase-js' dotenv.config() if (!process.env.SUPABASE_URL || !process.env.SUPABASE_ANON_KEY) { throw new Error('Missing Supabase environment variables') } const supabase = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY ) const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages], }) const botToken = process.env.DISCORD_BOT_TOKEN const channelId = process.env.DISCORD_CHANNEL_ID // Fetch tasks from Supabase. async function fetchTasksFromSupabase() { console.log('DEBUG: Fetching tasks from Supabase...') const { data, error } = await supabase.from('tasks').select('*') if (error) { console.error('Error fetching tasks from Supabase:', error.message) return [] } console.log(`DEBUG: Retrieved ${data.length} tasks from Supabase.`) return data } // Fetch users with their discord IDs from the database async function fetchUserProfiles(userIds) { if (!userIds || userIds.length === 0) return [] console.log('DEBUG: Fetching user profiles for IDs:', userIds) // Query using user_id which should match the UUID from schedules const { data, error } = await supabase .from('profiles') .select('id, user_id, discord_id') .in('user_id', userIds) if (error) { console.error('Error fetching user profiles:', error.message) return [] } console.log(`DEBUG: Retrieved ${data.length} user profiles.`) console.log('DEBUG: User profiles data:', JSON.stringify(data)) return data } // Modify the fetchCurrentlyWorkingEmployees function to handle timezones correctly. async function fetchCurrentlyWorkingEmployees() { const now = new Date().toISOString() console.log(`DEBUG: Fetching schedules for current time: ${now}`) const { data, error } = await supabase .from('schedules') .select('user_id') .lte('start_time', now) .gte('end_time', now) if (error) { console.error('Error fetching schedules:', error.message) return [] } const userIds = data.map(schedule => schedule.user_id) console.log('DEBUG: User IDs from schedules:', userIds) return userIds } // Determine if a task is due. function isTaskDue(task, today) { const startDate = new Date(task.start_date) if (startDate > today) return false const daysSinceStart = Math.floor((today - startDate) / (1000 * 60 * 60 * 24)) return daysSinceStart % task.interval === 0 } // Modify the sendTasks function async function sendTasks(tasksToSend, currentTime) { console.log(`DEBUG: Preparing to send ${tasksToSend.length} task(s) for ${currentTime}.`) console.log(`DEBUG: Attempting to fetch channel with ID: ${channelId}`) const channel = await client.channels.fetch(channelId) if (!channel) { console.error('Channel not found! Channel ID:', channelId) return } console.log('DEBUG: Channel found successfully:', channel.name) const workingEmployeeIds = await fetchCurrentlyWorkingEmployees() console.log('DEBUG: Currently working employees:', workingEmployeeIds) // Fetch user profiles for working employees const workingEmployees = await fetchUserProfiles(workingEmployeeIds) console.log('DEBUG: Working employees to tag:', workingEmployees) let messageContent = workingEmployees.length > 0 ? `${workingEmployees.filter(emp => emp.discord_id).map(emp => `<@${emp.discord_id}>`).join(' ')}\n\n` : '\n\n' tasksToSend.forEach((task, idx) => { messageContent += `${getNumberEmoji(idx + 1)} ${task.name}\n` }) console.log('DEBUG: Message content:', messageContent) try { const sentMessage = await channel.send(messageContent) console.log('DEBUG: Message sent. Now adding reactions...') for (let i = 1; i <= tasksToSend.length; i++) { const emoji = getNumberEmoji(i) if (emoji) { await sentMessage.react(emoji) console.log(`DEBUG: Added reaction ${emoji}`) } } logger(`Tasks sent for ${currentTime}.`) } catch (err) { console.error('DEBUG: Error sending tasks:', err) } } // Cron job: runs every minute in Sofia time. cron.schedule( '* * * * *', async () => { const now = new Date() const currentTime = now.toLocaleTimeString('en-GB', { timeZone: 'Europe/Sofia', hour12: false, hour: '2-digit', minute: '2-digit', }) console.log(`DEBUG: Cron job triggered at ${currentTime} (Sofia time).`) const allTasks = await fetchTasksFromSupabase() const today = new Date() // Filter tasks that are due and scheduled for the current time. const dueTasks = allTasks.filter((task) => { return isTaskDue(task, today) && task.time === currentTime }) if (dueTasks.length > 0) { console.log( `DEBUG: Found ${dueTasks.length} due task(s) for ${currentTime}.` ) await sendTasks(dueTasks, currentTime) } else { console.log(`DEBUG: No tasks due for ${currentTime}. Enjoy the silence.`) } }, { timezone: 'Europe/Sofia' } ) client.once('ready', () => { logger('Bot is ready.') console.log('DEBUG: Discord client is now ready.') }) client.login(botToken)