1import { Client, TextChannel, EmbedBuilder } from 'discord.js'
2import { supabase } from '@/configs/supabase'
3import Logger from '@/classes/logger'
4
5export class GiveawayService {
6 private client: Client
7 private interval: NodeJS.Timeout | null = null
8
9 constructor(client: Client) {
10 this.client = client
11 }
12
13 start() {
14 // Check for ended giveaways every minute
15 this.interval = setInterval(() => this.checkGiveaways(), 60000)
16 Logger.log('info', 'Giveaway service started', 'GiveawayService')
17 }
18
19 async checkGiveaways() {
20 const { data: giveaways, error } = await supabase
21 .from('giveaways')
22 .select('*')
23 .eq('ended', false)
24 .lte('ends_at', new Date().toISOString())
25
26 if (error) {
27 Logger.log(
28 'error',
29 `Failed to fetch giveaways: ${error.message}`,
30 'GiveawayService',
31 )
32 return
33 }
34
35 for (const giveaway of giveaways) {
36 try {
37 const channel = (await this.client.channels.fetch(
38 giveaway.channel_id,
39 )) as TextChannel
40 const message = await channel.messages.fetch(giveaway.message_id)
41
42 const reaction = message.reactions.cache.get('🎉')
43 if (!reaction) throw new Error('Reaction not found')
44
45 const users = await reaction.users.fetch()
46 const validParticipants = users.filter((user) => !user.bot)
47
48 if (validParticipants.size < 1) {
49 await channel.send(
50 `No valid participants for giveaway: ${giveaway.prize}`,
51 )
52 continue
53 }
54
55 const winners = validParticipants.random(
56 Math.min(giveaway.winner_count, validParticipants.size),
57 )
58
59 const winnerAnnouncement = new EmbedBuilder()
60 .setTitle('🎉 Giveaway Ended! 🎉')
61 .setDescription(
62 `
63 **Prize:** ${giveaway.prize}
64 **Winners:** ${winners.map((w) => `<@${w.id}>`).join(', ')}
65 `,
66 )
67 .setColor('#00FF00')
68 .setFooter({ text: `Giveaway ID: ${giveaway.message_id}` })
69
70 await channel.send({ embeds: [winnerAnnouncement] })
71
72 // Update giveaway as ended
73 await supabase
74 .from('giveaways')
75 .update({ ended: true })
76 .eq('message_id', giveaway.message_id)
77 } catch (error: any) {
78 Logger.log(
79 'error',
80 `Failed to end giveaway: ${error.message}`,
81 'GiveawayService',
82 )
83 }
84 }
85 }
86
87 stop() {
88 if (this.interval) {
89 clearInterval(this.interval)
90 this.interval = null
91 Logger.log('info', 'Giveaway service stopped', 'GiveawayService')
92 }
93 }
94}
95