trivia: maybe next time I should read api docs proeprly, add session token so we aboid reapeated question

This commit is contained in:
Ayden Jahola 2024-09-08 18:34:21 +01:00
parent 2c079eb173
commit 83fc8d207e
No known key found for this signature in database
GPG key ID: 71DD90AE4AE92742
2 changed files with 92 additions and 38 deletions

View file

@ -1,8 +1,9 @@
const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
const axios = require("axios"); const axios = require("axios");
const { decode } = require("html-entities");
const TriviaQuestion = require("../../models/TriviaQuestion"); const TriviaQuestion = require("../../models/TriviaQuestion");
const Leaderboard = require("../../models/Leaderboard"); const Leaderboard = require("../../models/Leaderboard");
const { decode } = require("html-entities"); const TriviaSession = require("../../models/TriviaSession");
const API_INTERVAL = 5000; // 5 seconds const API_INTERVAL = 5000; // 5 seconds
const QUESTION_EXPIRY = 30 * 24 * 60 * 60 * 1000; // 1 month const QUESTION_EXPIRY = 30 * 24 * 60 * 60 * 1000; // 1 month
@ -26,11 +27,58 @@ const CATEGORY_MAP = {
20: "Mythology", 20: "Mythology",
}; };
// Fetch or create a new session token from the database
const getSessionToken = async () => {
let session = await TriviaSession.findOne();
if (!session) {
// If no token exists, request a new one
const response = await axios.get(
"https://opentdb.com/api_token.php?command=request"
);
const newToken = response.data.token;
session = new TriviaSession({
token: newToken,
});
await session.save();
}
return session.token;
};
// Reset the session token if it's exhausted and update the database
const resetSessionToken = async () => {
let session = await TriviaSession.findOne();
if (!session) {
// If there's no session, create a new one as fallback
return await getSessionToken();
}
// Reset the session token
const response = await axios.get(
`https://opentdb.com/api_token.php?command=reset&token=${session.token}`
);
const newToken = response.data.token;
// Update token in the database
session.token = newToken;
session.last_updated = new Date();
await session.save();
return newToken;
};
const fetchTriviaQuestion = async (categoryId, categoryName) => { const fetchTriviaQuestion = async (categoryId, categoryName) => {
try { try {
let triviaQuestion; let triviaQuestion;
let source = "API"; // Default to API let source = "API"; // Default to API
// Get session token before making API call
let sessionToken = await getSessionToken();
// Attempt to find a question in the database that hasn't been served recently // Attempt to find a question in the database that hasn't been served recently
triviaQuestion = await TriviaQuestion.findOne({ triviaQuestion = await TriviaQuestion.findOne({
last_served: { $lt: new Date(Date.now() - QUESTION_EXPIRY) }, last_served: { $lt: new Date(Date.now() - QUESTION_EXPIRY) },
@ -40,24 +88,44 @@ const fetchTriviaQuestion = async (categoryId, categoryName) => {
if (!triviaQuestion || Date.now() - LAST_API_CALL.time >= API_INTERVAL) { if (!triviaQuestion || Date.now() - LAST_API_CALL.time >= API_INTERVAL) {
// If no question was found in the database or API cooldown is over, fetch from API // If no question was found in the database or API cooldown is over, fetch from API
const response = await axios.get( const response = await axios.get(
`https://opentdb.com/api.php?amount=1&category=${categoryId}` `https://opentdb.com/api.php?amount=1&category=${categoryId}&token=${sessionToken}`
); );
const apiQuestion = response.data.results[0]; const apiQuestion = response.data.results[0];
// Save the API question in the database // Check if the token is exhausted (response code 4 indicates this)
await TriviaQuestion.create({ if (response.data.response_code === 4) {
question: decode(apiQuestion.question), sessionToken = await resetSessionToken(); // Reset session token
correct_answer: decode(apiQuestion.correct_answer), // Retry fetching the question with the new token
incorrect_answers: apiQuestion.incorrect_answers.map(decode), const retryResponse = await axios.get(
category: categoryName, `https://opentdb.com/api.php?amount=1&category=${categoryId}&token=${sessionToken}`
last_served: null, );
}); const retryApiQuestion = retryResponse.data.results[0];
await TriviaQuestion.create({
question: decode(retryApiQuestion.question),
correct_answer: decode(retryApiQuestion.correct_answer),
incorrect_answers: retryApiQuestion.incorrect_answers.map(decode),
category: categoryName,
last_served: null,
});
// Re-fetch it from the database to return the saved question object triviaQuestion = await TriviaQuestion.findOne({
triviaQuestion = await TriviaQuestion.findOne({ question: decode(retryApiQuestion.question),
question: decode(apiQuestion.question), category: categoryName,
category: categoryName, });
}); } else {
await TriviaQuestion.create({
question: decode(apiQuestion.question),
correct_answer: decode(apiQuestion.correct_answer),
incorrect_answers: apiQuestion.incorrect_answers.map(decode),
category: categoryName,
last_served: null,
});
triviaQuestion = await TriviaQuestion.findOne({
question: decode(apiQuestion.question),
category: categoryName,
});
}
LAST_API_CALL.time = Date.now(); // Update the last API call time LAST_API_CALL.time = Date.now(); // Update the last API call time
} else { } else {
@ -78,29 +146,6 @@ const fetchTriviaQuestion = async (categoryId, categoryName) => {
} }
}; };
const getShuffledQuestions = async (categoryName) => {
try {
const questions = await TriviaQuestion.find({
category: categoryName,
}).sort({ last_served: 1 });
if (questions.length === 0) {
return [];
}
questions.forEach(async (question) => {
question.last_served = new Date();
await question.save();
});
// Shuffle questions
return questions.sort(() => Math.random() - 0.5);
} catch (error) {
console.error("Error fetching or shuffling questions:", error);
throw new Error("Error fetching questions from database");
}
};
const createTriviaEmbed = ( const createTriviaEmbed = (
categoryName, categoryName,
question, question,

9
models/TriviaSession.js Normal file
View file

@ -0,0 +1,9 @@
const mongoose = require("mongoose");
const triviaSessionSchema = new mongoose.Schema({
token: { type: String, required: true },
last_updated: { type: Date, default: Date.now },
status: { type: String, enum: ["active", "inactive"], default: "active" }, // Add status field
});
module.exports = mongoose.model("TriviaSession", triviaSessionSchema);