Introduces a new server mode configuration system (Federation/Standalone) with associated command changes, dynamic status rotation for the bot, and adds new commands and features. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: b08e6ba5-7498-4b9f-b1c9-7dc11b362ddd Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/R9PkDi8 Replit-Helium-Checkpoint-Created: true
193 lines
6.1 KiB
JavaScript
193 lines
6.1 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
const { getServerMode, getEmbedColor, EMBED_COLORS } = require('../utils/modeHelper');
|
|
|
|
const activeReminders = new Map();
|
|
|
|
function parseTime(timeStr) {
|
|
const regex = /^(\d+)(s|m|h|d)$/i;
|
|
const match = timeStr.match(regex);
|
|
if (!match) return null;
|
|
|
|
const value = parseInt(match[1]);
|
|
const unit = match[2].toLowerCase();
|
|
|
|
const multipliers = {
|
|
's': 1000,
|
|
'm': 60 * 1000,
|
|
'h': 60 * 60 * 1000,
|
|
'd': 24 * 60 * 60 * 1000
|
|
};
|
|
|
|
return value * multipliers[unit];
|
|
}
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('remind')
|
|
.setDescription('Set a personal reminder')
|
|
.addSubcommand(subcommand =>
|
|
subcommand
|
|
.setName('set')
|
|
.setDescription('Set a new reminder')
|
|
.addStringOption(option =>
|
|
option.setName('time')
|
|
.setDescription('When to remind (e.g., 30m, 2h, 1d)')
|
|
.setRequired(true)
|
|
)
|
|
.addStringOption(option =>
|
|
option.setName('message')
|
|
.setDescription('What to remind you about')
|
|
.setRequired(true)
|
|
.setMaxLength(500)
|
|
)
|
|
)
|
|
.addSubcommand(subcommand =>
|
|
subcommand
|
|
.setName('list')
|
|
.setDescription('List your active reminders')
|
|
)
|
|
.addSubcommand(subcommand =>
|
|
subcommand
|
|
.setName('cancel')
|
|
.setDescription('Cancel a reminder')
|
|
.addStringOption(option =>
|
|
option.setName('id')
|
|
.setDescription('The reminder ID to cancel')
|
|
.setRequired(true)
|
|
)
|
|
),
|
|
|
|
async execute(interaction, supabase, client) {
|
|
const subcommand = interaction.options.getSubcommand();
|
|
const mode = await getServerMode(supabase, interaction.guildId);
|
|
const userId = interaction.user.id;
|
|
|
|
if (subcommand === 'set') {
|
|
const timeStr = interaction.options.getString('time');
|
|
const message = interaction.options.getString('message');
|
|
|
|
const duration = parseTime(timeStr);
|
|
if (!duration) {
|
|
return interaction.reply({
|
|
content: 'Invalid time format. Use formats like: 30s, 5m, 2h, 1d',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
if (duration < 10000) {
|
|
return interaction.reply({
|
|
content: 'Reminder must be at least 10 seconds in the future.',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
if (duration > 30 * 24 * 60 * 60 * 1000) {
|
|
return interaction.reply({
|
|
content: 'Reminder cannot be more than 30 days in the future.',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
const reminderId = `${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
|
|
const reminderTime = Date.now() + duration;
|
|
|
|
const timeout = setTimeout(async () => {
|
|
try {
|
|
const user = await client.users.fetch(userId);
|
|
const reminderEmbed = new EmbedBuilder()
|
|
.setColor(EMBED_COLORS.warning)
|
|
.setTitle('⏰ Reminder!')
|
|
.setDescription(message)
|
|
.addFields({
|
|
name: '📍 Set',
|
|
value: `<t:${Math.floor((reminderTime - duration) / 1000)}:R>`
|
|
})
|
|
.setTimestamp();
|
|
|
|
await user.send({ embeds: [reminderEmbed] });
|
|
} catch (e) {
|
|
try {
|
|
const channel = await client.channels.fetch(interaction.channelId);
|
|
await channel.send({
|
|
content: `<@${userId}> ⏰ **Reminder:** ${message}`
|
|
});
|
|
} catch (e2) {}
|
|
}
|
|
|
|
const userReminders = activeReminders.get(userId) || [];
|
|
activeReminders.set(userId, userReminders.filter(r => r.id !== reminderId));
|
|
}, duration);
|
|
|
|
const userReminders = activeReminders.get(userId) || [];
|
|
userReminders.push({
|
|
id: reminderId,
|
|
message,
|
|
time: reminderTime,
|
|
timeout,
|
|
channelId: interaction.channelId
|
|
});
|
|
activeReminders.set(userId, userReminders);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(EMBED_COLORS.success)
|
|
.setTitle('⏰ Reminder Set!')
|
|
.setDescription(`I'll remind you: **${message}**`)
|
|
.addFields(
|
|
{ name: '⏱️ In', value: timeStr, inline: true },
|
|
{ name: '📅 At', value: `<t:${Math.floor(reminderTime / 1000)}:f>`, inline: true },
|
|
{ name: '🆔 ID', value: `\`${reminderId}\``, inline: true }
|
|
)
|
|
.setTimestamp();
|
|
|
|
await interaction.reply({ embeds: [embed], ephemeral: true });
|
|
}
|
|
|
|
else if (subcommand === 'list') {
|
|
const userReminders = activeReminders.get(userId) || [];
|
|
|
|
if (userReminders.length === 0) {
|
|
return interaction.reply({
|
|
content: 'You have no active reminders.',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
const list = userReminders.map((r, i) => {
|
|
return `${i + 1}. **${r.message.substring(0, 50)}${r.message.length > 50 ? '...' : ''}**\n ⏰ <t:${Math.floor(r.time / 1000)}:R> | ID: \`${r.id}\``;
|
|
}).join('\n\n');
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(getEmbedColor(mode))
|
|
.setTitle('⏰ Your Reminders')
|
|
.setDescription(list)
|
|
.setFooter({ text: `${userReminders.length} active reminder(s)` })
|
|
.setTimestamp();
|
|
|
|
await interaction.reply({ embeds: [embed], ephemeral: true });
|
|
}
|
|
|
|
else if (subcommand === 'cancel') {
|
|
const reminderId = interaction.options.getString('id');
|
|
const userReminders = activeReminders.get(userId) || [];
|
|
|
|
const reminder = userReminders.find(r => r.id === reminderId);
|
|
if (!reminder) {
|
|
return interaction.reply({
|
|
content: 'Reminder not found. Use `/remind list` to see your reminders.',
|
|
ephemeral: true
|
|
});
|
|
}
|
|
|
|
clearTimeout(reminder.timeout);
|
|
activeReminders.set(userId, userReminders.filter(r => r.id !== reminderId));
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(EMBED_COLORS.success)
|
|
.setTitle('🗑️ Reminder Cancelled')
|
|
.setDescription(`Cancelled reminder: **${reminder.message.substring(0, 100)}**`)
|
|
.setTimestamp();
|
|
|
|
await interaction.reply({ embeds: [embed], ephemeral: true });
|
|
}
|
|
},
|
|
};
|