mirror of
https://github.com/aydenjahola/discord-multipurpose-bot.git
synced 2024-11-22 08:45:55 +00:00
fix a bug where if the user enocouters an error it would still wouild be makred as ongoing trivia
This commit is contained in:
parent
50bfb9c6e3
commit
d693d2f714
1 changed files with 156 additions and 141 deletions
|
@ -43,152 +43,167 @@ module.exports = {
|
|||
// Add the user to the set of active trivia players
|
||||
ongoingTrivia.add(userId);
|
||||
|
||||
const categoryId = interaction.options.getString("category");
|
||||
const categoryName = categoryId === "15" ? "Video Games" : "Anime & Manga";
|
||||
try {
|
||||
const categoryId = interaction.options.getString("category");
|
||||
const categoryName =
|
||||
categoryId === "15" ? "Video Games" : "Anime & Manga";
|
||||
|
||||
// Fetch a trivia question from the cache or the API
|
||||
let triviaQuestion = await TriviaQuestion.findOne({
|
||||
last_served: { $lt: new Date(Date.now() - QUESTION_EXPIRY) }, // Fetch questions not served recently
|
||||
category: categoryName, // Filter by category
|
||||
}).sort({ last_served: 1 });
|
||||
|
||||
if (!triviaQuestion || Date.now() - lastApiCall >= API_INTERVAL) {
|
||||
// Fetch a new trivia question from OTDB
|
||||
const response = await axios.get(
|
||||
`https://opentdb.com/api.php?amount=1&category=${categoryId}`
|
||||
);
|
||||
|
||||
triviaQuestion = response.data.results[0];
|
||||
lastApiCall = Date.now();
|
||||
|
||||
// Save the new trivia question to MongoDB
|
||||
await TriviaQuestion.create({
|
||||
question: decode(triviaQuestion.question),
|
||||
correct_answer: decode(triviaQuestion.correct_answer),
|
||||
incorrect_answers: triviaQuestion.incorrect_answers.map(decode),
|
||||
category: categoryName, // Include the category
|
||||
last_served: null, // Initially not served
|
||||
});
|
||||
|
||||
// Fetch the newly created question
|
||||
triviaQuestion = await TriviaQuestion.findOne({
|
||||
question: decode(triviaQuestion.question),
|
||||
// Fetch a trivia question from the cache or the API
|
||||
let triviaQuestion = await TriviaQuestion.findOne({
|
||||
last_served: { $lt: new Date(Date.now() - QUESTION_EXPIRY) }, // Fetch questions not served recently
|
||||
category: categoryName, // Filter by category
|
||||
});
|
||||
}
|
||||
}).sort({ last_served: 1 });
|
||||
|
||||
if (triviaQuestion) {
|
||||
triviaQuestion.last_served = new Date();
|
||||
await triviaQuestion.save();
|
||||
}
|
||||
|
||||
const question = decode(triviaQuestion.question);
|
||||
const correctAnswer = decode(triviaQuestion.correct_answer);
|
||||
const incorrectAnswers = triviaQuestion.incorrect_answers.map(decode);
|
||||
let allAnswers = [...incorrectAnswers, correctAnswer];
|
||||
|
||||
// Handle True/False questions specifically
|
||||
if (triviaQuestion.type === "boolean") {
|
||||
allAnswers = ["True", "False"];
|
||||
}
|
||||
|
||||
allAnswers = allAnswers.sort(() => Math.random() - 0.5); // Shuffle answers
|
||||
|
||||
// Create a mapping of numbers to answers
|
||||
const answerMap = allAnswers.reduce((map, answer, index) => {
|
||||
map[index + 1] = answer;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Create an embed with the trivia question and numbered options
|
||||
const triviaEmbed = new EmbedBuilder()
|
||||
.setColor("#0099ff")
|
||||
.setTitle("Trivia Question")
|
||||
.setDescription(question)
|
||||
.addFields(
|
||||
Object.entries(answerMap).map(([number, answer]) => ({
|
||||
name: `Option ${number}`,
|
||||
value: answer,
|
||||
inline: true,
|
||||
}))
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: `${guild.name} | Answer within ${timeLimit / 1000} seconds`,
|
||||
iconURL: guild.iconURL(),
|
||||
});
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [triviaEmbed],
|
||||
});
|
||||
|
||||
// Create a message collector specific to the user
|
||||
const answerFilter = (response) => {
|
||||
const userInput = response.content.trim();
|
||||
const userAnswerNumber = parseInt(userInput, 10);
|
||||
const userAnswerText =
|
||||
allAnswers.includes(userInput) ||
|
||||
(answerMap[userAnswerNumber] &&
|
||||
answerMap[userAnswerNumber] === correctAnswer);
|
||||
|
||||
// Check if the input is a number within valid range or a text that matches one of the options
|
||||
return (
|
||||
response.author.id === userId &&
|
||||
(userAnswerText || (userAnswerNumber >= 1 && userAnswerNumber <= 4))
|
||||
);
|
||||
};
|
||||
|
||||
const answerCollector = interaction.channel.createMessageCollector({
|
||||
filter: answerFilter,
|
||||
max: 1,
|
||||
time: timeLimit,
|
||||
});
|
||||
|
||||
answerCollector.on("collect", async (message) => {
|
||||
const userInput = message.content.trim();
|
||||
const userAnswerNumber = parseInt(userInput, 10);
|
||||
const userAnswer = answerMap[userAnswerNumber] || userInput;
|
||||
|
||||
let resultMessage = "Incorrect! Better luck next time.";
|
||||
|
||||
if (userAnswer === correctAnswer) {
|
||||
resultMessage = "Correct!";
|
||||
}
|
||||
|
||||
// Update leaderboard
|
||||
let userScore = await Leaderboard.findOne({ userId });
|
||||
if (!userScore) {
|
||||
userScore = new Leaderboard({
|
||||
userId,
|
||||
username,
|
||||
gamesPlayed: 1,
|
||||
correctAnswers: userAnswer === correctAnswer ? 1 : 0,
|
||||
});
|
||||
} else {
|
||||
userScore.gamesPlayed += 1;
|
||||
if (userAnswer === correctAnswer) {
|
||||
userScore.correctAnswers += 1;
|
||||
}
|
||||
}
|
||||
await userScore.save();
|
||||
|
||||
await interaction.followUp(
|
||||
`${resultMessage} <@${userId}> You've answered ${userScore.correctAnswers} questions correctly out of ${userScore.gamesPlayed} games.`
|
||||
);
|
||||
|
||||
// Remove user from the ongoing trivia set once the game is finished
|
||||
ongoingTrivia.delete(userId);
|
||||
});
|
||||
|
||||
answerCollector.on("end", (collected, reason) => {
|
||||
if (reason === "time") {
|
||||
interaction.followUp(
|
||||
`<@${userId}> Time's up! You didn't answer in time.`
|
||||
if (!triviaQuestion || Date.now() - lastApiCall >= API_INTERVAL) {
|
||||
// Fetch a new trivia question from OTDB
|
||||
const response = await axios.get(
|
||||
`https://opentdb.com/api.php?amount=1&category=${categoryId}`
|
||||
);
|
||||
|
||||
// Remove user from the ongoing trivia set when the game times out
|
||||
ongoingTrivia.delete(userId);
|
||||
triviaQuestion = response.data.results[0];
|
||||
lastApiCall = Date.now();
|
||||
|
||||
// Save the new trivia question to MongoDB
|
||||
await TriviaQuestion.create({
|
||||
question: decode(triviaQuestion.question),
|
||||
correct_answer: decode(triviaQuestion.correct_answer),
|
||||
incorrect_answers: triviaQuestion.incorrect_answers.map(decode),
|
||||
category: categoryName, // Include the category
|
||||
last_served: null, // Initially not served
|
||||
});
|
||||
|
||||
// Fetch the newly created question
|
||||
triviaQuestion = await TriviaQuestion.findOne({
|
||||
question: decode(triviaQuestion.question),
|
||||
category: categoryName, // Filter by category
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (triviaQuestion) {
|
||||
triviaQuestion.last_served = new Date();
|
||||
await triviaQuestion.save();
|
||||
}
|
||||
|
||||
const question = decode(triviaQuestion.question);
|
||||
const correctAnswer = decode(triviaQuestion.correct_answer);
|
||||
const incorrectAnswers = triviaQuestion.incorrect_answers.map(decode);
|
||||
let allAnswers = [...incorrectAnswers, correctAnswer];
|
||||
|
||||
// Handle True/False questions specifically
|
||||
if (triviaQuestion.type === "boolean") {
|
||||
allAnswers = ["True", "False"];
|
||||
}
|
||||
|
||||
allAnswers = allAnswers.sort(() => Math.random() - 0.5); // Shuffle answers
|
||||
|
||||
// Create a mapping of numbers to answers
|
||||
const answerMap = allAnswers.reduce((map, answer, index) => {
|
||||
map[index + 1] = answer;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Create an embed with the trivia question and numbered options
|
||||
const triviaEmbed = new EmbedBuilder()
|
||||
.setColor("#0099ff")
|
||||
.setTitle("Trivia Question")
|
||||
.setDescription(question)
|
||||
.addFields(
|
||||
Object.entries(answerMap).map(([number, answer]) => ({
|
||||
name: `Option ${number}`,
|
||||
value: answer,
|
||||
inline: true,
|
||||
}))
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: `${guild.name} | Answer within ${timeLimit / 1000} seconds`,
|
||||
iconURL: guild.iconURL(),
|
||||
});
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [triviaEmbed],
|
||||
});
|
||||
|
||||
// Create a message collector specific to the user
|
||||
const answerFilter = (response) => {
|
||||
const userInput = response.content.trim();
|
||||
const userAnswerNumber = parseInt(userInput, 10);
|
||||
const userAnswerText =
|
||||
allAnswers.includes(userInput) ||
|
||||
(answerMap[userAnswerNumber] &&
|
||||
answerMap[userAnswerNumber] === correctAnswer);
|
||||
|
||||
// Check if the input is a number within valid range or a text that matches one of the options
|
||||
return (
|
||||
response.author.id === userId &&
|
||||
(userAnswerText || (userAnswerNumber >= 1 && userAnswerNumber <= 4))
|
||||
);
|
||||
};
|
||||
|
||||
const answerCollector = interaction.channel.createMessageCollector({
|
||||
filter: answerFilter,
|
||||
max: 1,
|
||||
time: timeLimit,
|
||||
});
|
||||
|
||||
answerCollector.on("collect", async (message) => {
|
||||
const userInput = message.content.trim();
|
||||
const userAnswerNumber = parseInt(userInput, 10);
|
||||
const userAnswer = answerMap[userAnswerNumber] || userInput;
|
||||
|
||||
let resultMessage = "Incorrect! Better luck next time.";
|
||||
|
||||
if (userAnswer === correctAnswer) {
|
||||
resultMessage = "Correct!";
|
||||
}
|
||||
|
||||
// Update leaderboard
|
||||
let userScore = await Leaderboard.findOne({ userId });
|
||||
if (!userScore) {
|
||||
userScore = new Leaderboard({
|
||||
userId,
|
||||
username,
|
||||
gamesPlayed: 1,
|
||||
correctAnswers: userAnswer === correctAnswer ? 1 : 0,
|
||||
});
|
||||
} else {
|
||||
userScore.gamesPlayed += 1;
|
||||
if (userAnswer === correctAnswer) {
|
||||
userScore.correctAnswers += 1;
|
||||
}
|
||||
}
|
||||
await userScore.save();
|
||||
|
||||
await interaction.followUp(
|
||||
`${resultMessage} <@${userId}> You've answered ${userScore.correctAnswers} questions correctly out of ${userScore.gamesPlayed} games.`
|
||||
);
|
||||
|
||||
// Remove user from the ongoing trivia set once the game is finished
|
||||
ongoingTrivia.delete(userId);
|
||||
});
|
||||
|
||||
answerCollector.on("end", (collected, reason) => {
|
||||
if (reason === "time") {
|
||||
interaction.followUp(
|
||||
`<@${userId}> Time's up! You didn't answer in time.`
|
||||
);
|
||||
|
||||
// Remove user from the ongoing trivia set when the game times out
|
||||
ongoingTrivia.delete(userId);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching trivia question:", error);
|
||||
|
||||
// Inform the user about the error and let them retry
|
||||
await interaction.reply({
|
||||
content:
|
||||
"There was an error fetching your trivia question. Please try again later.",
|
||||
ephemeral: true,
|
||||
});
|
||||
|
||||
// Remove the user from the ongoing trivia set in case of an error
|
||||
ongoingTrivia.delete(userId);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue