summaryrefslogtreecommitdiff
path: root/src/bot.js
blob: cd7c2dbf0dc84ff084a16437f547fc7f98365e98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
const { Client, GatewayIntentBits } = require('discord.js');
require('dotenv').config();

const commands = require('./commands/definitions');
const { registerCommands } = require('./utils/commandRegistry');
const { handlePlay } = require('./handlers/playCommand');
const { handlePause, handleResume, handleSkip, handleClear, handleLoop, handleQuit } = require('./handlers/controlCommands');
const { handleQueue } = require('./handlers/queueCommand');
const { handleVolume } = require('./handlers/volumeCommand');
const { handleSeek } = require('./handlers/seekCommand');

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates,
  ],
});

const queues = new Map();

client.once('ready', async () => {
  console.log(`Bot ready: ${client.user.tag}`);
  console.log(`Ready at: ${new Date().toISOString()}`);
  await registerCommands(commands, process.env.DISCORD_TOKEN, process.env.CLIENT_ID);
  
  setInterval(() => {
    const activeQueues = queues.size;
    console.log(`[HEARTBEAT] ${new Date().toISOString()} - Active queues: ${activeQueues}`);
  }, 5 * 60 * 1000);
});

function handleError(error, context = 'Unknown') {
  const timestamp = new Date().toISOString();
  console.error(`[ERROR] ${timestamp} - Context: ${context}`);
  console.error(error);
  
  if (error.stack) {
    console.error('Stack trace:', error.stack);
  }
}

async function handleInteractionError(interaction, error, commandName) {
  handleError(error, `Command: ${commandName}`);
  
  try {
    const reply = interaction.deferred || interaction.replied ? 'editReply' : 'reply';
    await interaction[reply]({
      content: 'An error occurred while executing this command!',
      ephemeral: true
    }).catch(() => {});
  } catch (replyError) {
    console.error('Failed to send error message to user:', replyError);
  }
}

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  try {
    switch (interaction.commandName) {
      case 'play':
        await handlePlay(interaction, queues);
        break;
      case 'pause':
        handlePause(interaction, queues);
        break;
      case 'resume':
        handleResume(interaction, queues);
        break;
      case 'skip':
        handleSkip(interaction, queues);
        break;
      case 'clear':
        handleClear(interaction, queues);
        break;
      case 'loop':
        handleLoop(interaction, queues);
        break;
      case 'quit':
        handleQuit(interaction, queues);
        break;
      case 'queue':
        handleQueue(interaction, queues);
        break;
      case 'volume':
        handleVolume(interaction, queues);
        break;
      case 'seek':
        handleSeek(interaction, queues);
        break;
    }
  } catch (error) {
    await handleInteractionError(interaction, error, interaction.commandName);
  }
});

process.on('unhandledRejection', (error) => {
  handleError(error, 'Unhandled Promise Rejection');
});

process.on('uncaughtException', (error) => {
  handleError(error, 'Uncaught Exception');
});

client.on('error', (error) => {
  handleError(error, 'Discord Client Error');
});

client.on('warn', (info) => {
  console.warn(`[WARN] ${new Date().toISOString()} - ${info}`);
});

client.login(process.env.DISCORD_TOKEN);