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
127 lines
3.7 KiB
JavaScript
127 lines
3.7 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
||
const { getServerMode, getEmbedColor, EMBED_COLORS } = require('../utils/modeHelper');
|
||
const { updateStandaloneXp } = require('../utils/standaloneXp');
|
||
|
||
const SYMBOLS = ['🍒', '🍋', '🍊', '🍇', '⭐', '💎', '7️⃣'];
|
||
const WEIGHTS = [30, 25, 20, 15, 7, 2, 1];
|
||
|
||
const PAYOUTS = {
|
||
'🍒🍒🍒': 5,
|
||
'🍋🍋🍋': 10,
|
||
'🍊🍊🍊': 15,
|
||
'🍇🍇🍇': 20,
|
||
'⭐⭐⭐': 50,
|
||
'💎💎💎': 100,
|
||
'7️⃣7️⃣7️⃣': 250,
|
||
};
|
||
|
||
const slotsCooldowns = new Map();
|
||
const COOLDOWN = 30000;
|
||
|
||
function spin() {
|
||
const totalWeight = WEIGHTS.reduce((a, b) => a + b, 0);
|
||
const random = Math.random() * totalWeight;
|
||
let cumulativeWeight = 0;
|
||
|
||
for (let i = 0; i < SYMBOLS.length; i++) {
|
||
cumulativeWeight += WEIGHTS[i];
|
||
if (random < cumulativeWeight) {
|
||
return SYMBOLS[i];
|
||
}
|
||
}
|
||
return SYMBOLS[0];
|
||
}
|
||
|
||
module.exports = {
|
||
data: new SlashCommandBuilder()
|
||
.setName('slots')
|
||
.setDescription('Try your luck at the slot machine!')
|
||
.addIntegerOption(option =>
|
||
option.setName('bet')
|
||
.setDescription('XP to bet (10-50)')
|
||
.setRequired(false)
|
||
.setMinValue(10)
|
||
.setMaxValue(50)
|
||
),
|
||
|
||
async execute(interaction, supabase, client) {
|
||
const bet = interaction.options.getInteger('bet') || 10;
|
||
const userId = interaction.user.id;
|
||
const guildId = interaction.guildId;
|
||
const mode = await getServerMode(supabase, interaction.guildId);
|
||
|
||
const cooldownKey = `${guildId}-${userId}`;
|
||
const lastSpin = slotsCooldowns.get(cooldownKey);
|
||
if (lastSpin && Date.now() - lastSpin < COOLDOWN) {
|
||
const remaining = Math.ceil((COOLDOWN - (Date.now() - lastSpin)) / 1000);
|
||
return interaction.reply({
|
||
content: `You can spin again in ${remaining} seconds.`,
|
||
ephemeral: true
|
||
});
|
||
}
|
||
|
||
slotsCooldowns.set(cooldownKey, Date.now());
|
||
|
||
const slot1 = spin();
|
||
const slot2 = spin();
|
||
const slot3 = spin();
|
||
const result = `${slot1}${slot2}${slot3}`;
|
||
|
||
const payout = PAYOUTS[result];
|
||
let netGain = 0;
|
||
let resultMessage = '';
|
||
let color = getEmbedColor(mode);
|
||
|
||
if (payout) {
|
||
netGain = bet * payout;
|
||
resultMessage = `🎉 JACKPOT! You won **${netGain} XP**!`;
|
||
color = EMBED_COLORS.success;
|
||
} else if (slot1 === slot2 || slot2 === slot3 || slot1 === slot3) {
|
||
netGain = Math.floor(bet * 0.5);
|
||
resultMessage = `Nice! Two matching! You won **${netGain} XP**!`;
|
||
color = 0xF59E0B;
|
||
} else {
|
||
netGain = -bet;
|
||
resultMessage = `No luck this time. You lost **${bet} XP**.`;
|
||
color = EMBED_COLORS.error;
|
||
}
|
||
|
||
if (netGain !== 0) {
|
||
if (mode === 'standalone') {
|
||
await updateStandaloneXp(supabase, userId, guildId, netGain, interaction.user.username);
|
||
} else if (supabase) {
|
||
try {
|
||
const { data: profile } = await supabase
|
||
.from('user_profiles')
|
||
.select('xp')
|
||
.eq('discord_id', userId)
|
||
.maybeSingle();
|
||
|
||
if (profile) {
|
||
const newXp = Math.max(0, (profile.xp || 0) + netGain);
|
||
await supabase
|
||
.from('user_profiles')
|
||
.update({ xp: newXp })
|
||
.eq('discord_id', userId);
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
|
||
const embed = new EmbedBuilder()
|
||
.setColor(color)
|
||
.setTitle('🎰 Slot Machine')
|
||
.setDescription(`
|
||
╔═══════════╗
|
||
║ ${slot1} ${slot2} ${slot3} ║
|
||
╚═══════════╝
|
||
|
||
${resultMessage}
|
||
`)
|
||
.addFields({ name: '💰 Bet', value: `${bet} XP`, inline: true })
|
||
.setFooter({ text: `${interaction.user.username}` })
|
||
.setTimestamp();
|
||
|
||
await interaction.reply({ embeds: [embed] });
|
||
},
|
||
};
|