vkashti-bots / reservations_delete.js
reservations_delete.js
Raw
import dotenv from 'dotenv'
dotenv.config()
import { Client, GatewayIntentBits } from 'discord.js'
import cron from 'node-cron'
import { deleteAllMessagesInChannel, logger } from './utils.js'
import { showReservations } from './reservations.js'
import { createClient } from '@supabase/supabase-js'

// Initialize Supabase client
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,
    GatewayIntentBits.MessageContent,
  ],
})

const botToken = process.env.DISCORD_BOT_TOKEN
const reservationsChannelId = process.env.DISCORD_RESERVATIONS_CHANNEL_ID

// Debounce function to prevent excessive updates
let debounceTimer = null;
const DEBOUNCE_DELAY = 3000; // 3 seconds

const debouncedShowDailyReservations = async (channel) => {
  if (debounceTimer) {
    clearTimeout(debounceTimer);
  }
  
  debounceTimer = setTimeout(async () => {
    await showDailyReservations(channel);
    debounceTimer = null;
  }, DEBOUNCE_DELAY);
}

export const showDailyReservations = async (customChannel) => {
  try {
    const channel = customChannel || await client.channels.fetch(reservationsChannelId)
    await deleteAllMessagesInChannel(channel)

    const today = new Date()
    const startDate = new Date(today.setHours(0, 0, 0, 0)).toISOString()
    const endDate = new Date(today.setHours(23, 59, 59, 999)).toISOString()

    showReservations(startDate, endDate, channel)
  } catch (error) {
    console.error('Error during scheduled task:', error)
  }
}

// Function to check if a date is today
function isToday(date) {
  if (!date || isNaN(date.getTime())) {
    return false;
  }
  
  // Convert the input date from UTC to Europe/Sofia timezone
  const sofiaDate = new Date(date.getTime() + (3 * 60 * 60 * 1000)); // Add 3 hours for Sofia timezone
  
  const today = new Date()
  return sofiaDate.getDate() === today.getDate() &&
    sofiaDate.getMonth() === today.getMonth() &&
    sofiaDate.getFullYear() === today.getFullYear()
}

// Function to set up Supabase real-time subscription
function setupRealtimeSubscription() {
  const subscription = supabase
    .channel('reservations_changes')
    .on(
      'postgres_changes',
      {
        event: '*', // Listen to all changes (INSERT, UPDATE, DELETE)
        schema: 'public',
        table: 'reservations'
      },
      async (payload) => {
        try {
          // Log the event
          const eventType = payload.eventType;
          const id = payload.new?.id || payload.old?.id;
          logger(`Reservation ${eventType} detected for ID: ${id}`);
          
          // Get the reservation channel
          const channel = await client.channels.fetch(reservationsChannelId);
          
          // Always refresh the channel on DELETE events
          if (eventType === 'DELETE') {
            logger(`Reservation deleted, updating Discord channel...`);
            await debouncedShowDailyReservations(channel);
            return;
          }
          
          // Check if the change affects today's reservations
          const reservationDate = new Date(payload.new?.from_date || payload.old?.from_date);
          
          if (isToday(reservationDate)) {
            logger(`Today's reservation changed, updating Discord channel...`);
            await debouncedShowDailyReservations(channel);
          }
        } catch (error) {
          console.error('Error handling real-time update:', error);
        }
      }
    )
    .subscribe((status) => {
      logger(`Supabase subscription status: ${status}`);
      
      if (status !== 'SUBSCRIBED') {
        // Attempt to reconnect if subscription fails
        logger('Attempting to reconnect to Supabase in 5 seconds...');
        setTimeout(() => {
          subscription.unsubscribe();
          setupRealtimeSubscription();
        }, 5000);
      }
    });
    
  return subscription;
}

client.once('ready', async () => {
  logger('Reservations bot is ready!')

  // Set up real-time subscription
  setupRealtimeSubscription();

  // Set up daily cron job
  cron.schedule(
    '30 9 * * *',
    async () => {
      await showDailyReservations();
    },
    { timezone: 'Europe/Sofia' }
  )
})

// Start the bot
client.login(botToken)