const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); const { getServerMode, getEmbedColor, EMBED_COLORS } = require('../utils/modeHelper'); const { updateStandaloneXp } = require('../utils/standaloneXp'); const TRIVIA_QUESTIONS = [ { question: "What is the capital of Japan?", answers: ["Tokyo", "Osaka", "Kyoto", "Hiroshima"], correct: 0, category: "Geography" }, { question: "Which planet is known as the Red Planet?", answers: ["Venus", "Mars", "Jupiter", "Saturn"], correct: 1, category: "Science" }, { question: "What year did World War II end?", answers: ["1943", "1944", "1945", "1946"], correct: 2, category: "History" }, { question: "What is the largest mammal on Earth?", answers: ["African Elephant", "Blue Whale", "Giraffe", "Hippopotamus"], correct: 1, category: "Science" }, { question: "Who painted the Mona Lisa?", answers: ["Michelangelo", "Leonardo da Vinci", "Raphael", "Donatello"], correct: 1, category: "Art" }, { question: "What is the chemical symbol for gold?", answers: ["Go", "Gd", "Au", "Ag"], correct: 2, category: "Science" }, { question: "Which programming language was created by Brendan Eich?", answers: ["Python", "Java", "JavaScript", "Ruby"], correct: 2, category: "Technology" }, { question: "What is the smallest country in the world?", answers: ["Monaco", "Vatican City", "San Marino", "Liechtenstein"], correct: 1, category: "Geography" }, { question: "How many bones are in the adult human body?", answers: ["186", "206", "226", "246"], correct: 1, category: "Science" }, { question: "What year was the first iPhone released?", answers: ["2005", "2006", "2007", "2008"], correct: 2, category: "Technology" }, { question: "Which element has the atomic number 1?", answers: ["Helium", "Hydrogen", "Oxygen", "Carbon"], correct: 1, category: "Science" }, { question: "What is the capital of Australia?", answers: ["Sydney", "Melbourne", "Canberra", "Perth"], correct: 2, category: "Geography" }, { question: "Who wrote 'Romeo and Juliet'?", answers: ["Charles Dickens", "William Shakespeare", "Jane Austen", "Mark Twain"], correct: 1, category: "Literature" }, { question: "What is the speed of light in km/s (approximately)?", answers: ["150,000", "200,000", "300,000", "400,000"], correct: 2, category: "Science" }, { question: "Which company created Discord?", answers: ["Hammer & Chisel", "Meta", "Microsoft", "Google"], correct: 0, category: "Technology" } ]; const activeTrivia = new Map(); module.exports = { data: new SlashCommandBuilder() .setName('trivia') .setDescription('Answer trivia questions to earn XP!') .addStringOption(option => option.setName('category') .setDescription('Choose a category (optional)') .setRequired(false) .addChoices( { name: 'All', value: 'all' }, { name: 'Science', value: 'Science' }, { name: 'Geography', value: 'Geography' }, { name: 'History', value: 'History' }, { name: 'Technology', value: 'Technology' }, { name: 'Art', value: 'Art' }, { name: 'Literature', value: 'Literature' } ) ), async execute(interaction, supabase, client) { const category = interaction.options.getString('category') || 'all'; const mode = await getServerMode(supabase, interaction.guildId); const userId = interaction.user.id; const guildId = interaction.guildId; const activeKey = `${guildId}-${userId}`; if (activeTrivia.has(activeKey)) { return interaction.reply({ content: 'You already have an active trivia question! Answer it first.', ephemeral: true }); } let questions = TRIVIA_QUESTIONS; if (category !== 'all') { questions = TRIVIA_QUESTIONS.filter(q => q.category === category); } if (questions.length === 0) { return interaction.reply({ content: 'No questions available for that category.', ephemeral: true }); } const question = questions[Math.floor(Math.random() * questions.length)]; const shuffledIndexes = [0, 1, 2, 3].sort(() => Math.random() - 0.5); const shuffledAnswers = shuffledIndexes.map(i => question.answers[i]); const correctIndex = shuffledIndexes.indexOf(question.correct); activeTrivia.set(activeKey, { correctIndex, question: question.question, startTime: Date.now() }); const embed = new EmbedBuilder() .setColor(getEmbedColor(mode)) .setTitle('🧠 Trivia Time!') .setDescription(`**${question.question}**`) .addFields( { name: '📚 Category', value: question.category, inline: true }, { name: '⏱️ Time Limit', value: '30 seconds', inline: true }, { name: '🎁 Reward', value: '25-50 XP', inline: true } ) .setFooter({ text: 'Click a button to answer!' }) .setTimestamp(); const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId(`trivia_0_${interaction.user.id}`) .setLabel(shuffledAnswers[0]) .setStyle(ButtonStyle.Primary), new ButtonBuilder() .setCustomId(`trivia_1_${interaction.user.id}`) .setLabel(shuffledAnswers[1]) .setStyle(ButtonStyle.Primary), new ButtonBuilder() .setCustomId(`trivia_2_${interaction.user.id}`) .setLabel(shuffledAnswers[2]) .setStyle(ButtonStyle.Primary), new ButtonBuilder() .setCustomId(`trivia_3_${interaction.user.id}`) .setLabel(shuffledAnswers[3]) .setStyle(ButtonStyle.Primary) ); const message = await interaction.reply({ embeds: [embed], components: [row], fetchReply: true }); const collector = message.createMessageComponentCollector({ filter: i => i.customId.startsWith('trivia_') && i.customId.endsWith(`_${interaction.user.id}`), time: 30000, max: 1 }); collector.on('collect', async (i) => { const triviaData = activeTrivia.get(activeKey); if (!triviaData) return; const selectedIndex = parseInt(i.customId.split('_')[1]); const isCorrect = selectedIndex === triviaData.correctIndex; const timeTaken = (Date.now() - triviaData.startTime) / 1000; activeTrivia.delete(activeKey); let xpReward = 0; if (isCorrect) { xpReward = timeTaken < 5 ? 50 : timeTaken < 15 ? 35 : 25; if (mode === 'standalone') { await updateStandaloneXp(supabase, userId, guildId, xpReward, interaction.user.username); } else if (supabase) { try { const { data: profile } = await supabase .from('user_profiles') .select('xp') .eq('discord_id', userId) .maybeSingle(); if (profile) { await supabase .from('user_profiles') .update({ xp: (profile.xp || 0) + xpReward }) .eq('discord_id', userId); } } catch (e) {} } } const resultEmbed = new EmbedBuilder() .setColor(isCorrect ? EMBED_COLORS.success : EMBED_COLORS.error) .setTitle(isCorrect ? '✅ Correct!' : '❌ Incorrect!') .setDescription(isCorrect ? `Great job! You answered in ${timeTaken.toFixed(1)} seconds.` : `The correct answer was: **${question.answers[question.correct]}**` ) .addFields( { name: '❓ Question', value: question.question } ) .setTimestamp(); if (isCorrect) { resultEmbed.addFields({ name: '🎁 XP Earned', value: `+${xpReward} XP`, inline: true }); } const disabledRow = new ActionRowBuilder() .addComponents( ...row.components.map((btn, idx) => ButtonBuilder.from(btn) .setStyle(idx === triviaData.correctIndex ? ButtonStyle.Success : (idx === selectedIndex && !isCorrect) ? ButtonStyle.Danger : ButtonStyle.Secondary) .setDisabled(true) ) ); await i.update({ embeds: [resultEmbed], components: [disabledRow] }); }); collector.on('end', async (collected) => { if (collected.size === 0) { activeTrivia.delete(activeKey); const timeoutEmbed = new EmbedBuilder() .setColor(EMBED_COLORS.warning) .setTitle('⏰ Time\'s Up!') .setDescription(`You didn't answer in time. The correct answer was: **${question.answers[question.correct]}**`) .setTimestamp(); const disabledRow = new ActionRowBuilder() .addComponents( ...row.components.map(btn => ButtonBuilder.from(btn) .setStyle(ButtonStyle.Secondary) .setDisabled(true) ) ); await interaction.editReply({ embeds: [timeoutEmbed], components: [disabledRow] }); } }); }, };