DEV Community

Cover image for Code Fully Fledged Trivia Games in Discord.JS
Elitezen
Elitezen

Posted on

Code Fully Fledged Trivia Games in Discord.JS

Trivia is often one of the most engaging group games to play, but programming a trivia match requires patience and a strong knowledge of programming.

Luckily, I have created an NPM module that implements fully fledged and polished trivia games straight out of the box with Discord.JS with just a few lines of code!

Github Repo., includes a condensed form of this article in the README.
NPM Page,
Discord Server

👉 What you will need to get started:

Getting Started

Open a terminal inside your Discord bot's root directory and install discord-trivia with the following command:

npm install discord-trivia
Enter fullscreen mode Exit fullscreen mode

Then, create a new slash command file:

If you still use messages, Click here (support for messages is limited)

const { SlashCommandBuilder } = require('@discordjs/builders');

module.exports = {
 data: new SlashCommandBuilder()
  .setName('Trivia')
  .setDescription('Lets play some trivia!'),
 async execute(interaction) {

 },
};
Enter fullscreen mode Exit fullscreen mode

At the top of your command file require the TriviaManager class from Discord Trivia. Create a new trivia manager instance and name it trivia.

const { TriviaManager } = require('discord-trivia');
const trivia = new TriviaManager();
Enter fullscreen mode Exit fullscreen mode

Then, inside your execute() function create a new game using trivia.createGame(). Use game.start() to start a match as soon as this command is ran. Make sure to add a .catch() callback to catch any errors.

async execute(interaction) {
    // Create the game
    const game = trivia.createGame(interaction); 

    // Start the game
    game
       .start()
       .catch(console.error);
},
Enter fullscreen mode Exit fullscreen mode

Your code so far should look like this:

const { SlashCommandBuilder } = require('@discordjs/builders');
const { TriviaManager } = require('discord-trivia');
const trivia = new TriviaManager();

module.exports = {
 data: new SlashCommandBuilder()
  .setName('Trivia')
  .setDescription('Lets play some trivia!'),
 async execute(interaction) {
        const game = trivia.createGame(interaction); 

        game
           .start()
           .catch(console.error);
 },
};
Enter fullscreen mode Exit fullscreen mode

And that's all! Your bot will start a trivia match within the
channel the command was started 🎉🎉🎉

✨ Customization

The rest of this article will cover customization options such as:

  • Slash Command Options
  • Configuration of what kind of questions to use in a match.
  • Custom Questions.
  • Game options such as points, streak bonuses, game lobby size limits and time during and between rounds.

⭐ Customization Via Slash Command Options

Discord Trivia provides a TrivaCommandBuilder class to help you set up slash commands and provide and manage slash command options.

To setup the builder, start with a fresh trivia slash command.

const { SlashCommandBuilder } = require('@discordjs/builders');
const { TriviaManager } = require('discord-trivia');
const trivia = new TriviaManager();

module.exports = {
 data: new SlashCommandBuilder()
  .setName('Trivia')
  .setDescription('Lets play some trivia!'),
 async execute(interaction) {
        const game = trivia.createGame(interaction); 

        game
           .start()
           .catch(console.error);
 },
};
Enter fullscreen mode Exit fullscreen mode

Require TriviaCommandBuilder along side TriviaManager

const { TriviaManager, TriviaCommandBuilder } = require('discord-trivia');
Enter fullscreen mode Exit fullscreen mode

Create a new instance and name it command, you can pass the command's name and description as options.

const command = new TriviaCommandBuilder({
  name: 'trivia',
  description: 'Lets play some trivia!'
});
Enter fullscreen mode Exit fullscreen mode

replace your current module.exports.data to command.toBuilder()

module.exports = {
 data: command.toBuilder(),
 async execute(interaction) {
        const game = trivia.createGame(interaction); 

        game
           .start()
           .catch(console.error);
 },
};
Enter fullscreen mode Exit fullscreen mode

and finally, pass command.getOptions(interaction) as the second parameter to trivia.createGame()

const game = trivia
   .createGame(interaction, command.getOptions(interaction)); 
Enter fullscreen mode Exit fullscreen mode

Your final code will look like this:

const { SlashCommandBuilder } = require('@discordjs/builders');
const { TriviaManager, TriviaCommandBuilder } = require('discord-trivia'); 
const trivia = new TriviaManager();

const command = new TriviaCommandBuilder({
  name: 'ping',
  description: 'Lets play some trivia!'
});

module.exports = {
 data: command.toBuilder(),
 async execute(interaction) {
        const game = trivia
           .createGame(interaction, command.getOptions(interaction)); 

        game
           .start()
           .catch(console.error);
 },
};
Enter fullscreen mode Exit fullscreen mode

And here is the result for your bot users:

Slash command options

Any chosen options will overwrite the game's defaults, while the remaining will stay as is.

Customization Via Code

Game Questions

Discord Trivia is powered by the Open Trivia Database API (OpenTDB). A "Free to use, user-contributed trivia question database" which supplies all of the questions in a selection of thousands of questions with 23 trivia categories and 3 difficulties.

To start configuring your game, create a variable named gameOptions as an object.

const gameOptions = {};
Enter fullscreen mode Exit fullscreen mode

to configure the questions, we need to override the questionData. For example to recieve 10 Anime and Manga questions in easy difficulty we need to set gameOptions.questionData as such:

const gameOptions = {
   questionData: {
      amount: 10,
      category: 'ENTERTAINMENT_JAPANESE_ANIME_AND_MANGA',
      difficulty: 'easy'
   }
};
Enter fullscreen mode Exit fullscreen mode

To enact these options, pass them as the 2nd parameter to trivia.createGame():

const game = trivia.createGame(interaction, gameOptions);
Enter fullscreen mode Exit fullscreen mode

These new options will be applied when you start the game.

However, Without OpenTDB documentation right next to you it will be hard to write down category names. Just look at the size of 'ENTERTAINMENT_JAPANESE_ANIME_AND_MANGA'!

Let's install a tool to help us navigate the OpenTDB categories, open-trivia-db.

npm install open-trivia-db
Enter fullscreen mode Exit fullscreen mode

require the Category class from open-trivia-db and type Category.allNames., notice how you now get a list of all 23 categories for OpenTDB at your fingertips!

const { Category } = require('open-trivia-db');

Category.allNames.
Enter fullscreen mode Exit fullscreen mode

Intellisense of catgeories

Now pick a category as an option for gameOptions

const gameOptions = {
   questionData: {
      category: Category.allNames.HISTORY
   }
};
Enter fullscreen mode Exit fullscreen mode

⭐ Custom Questions

Custom questions by you and your friends will add extra personality to your game! Here's how to do it:

Create an array named myQuestions, this will hold all of your custom questions.

const myQuestions = [];
Enter fullscreen mode Exit fullscreen mode

Each item in this array will be a custom question. A custom question has the following shape:

{
   value: 'THE QUESTION',
   correctAnswer: 'CORRECT ANSWER',
   incorrectAnswers: ['INC ANS 1', 'INC ANS 2', 'INC ANS 3']
}
Enter fullscreen mode Exit fullscreen mode

Here's how 2 custom question will look in myQuestions:

const myQuestions = [
  {
    value: 'Best Ice Cream Flavor?',
    correctAnswer: 'Shrimp',
    incorrectAnswers: ['Vanilla', 'Chocolate', 'Strawberry']
  },
  {
    value: 'Best Pizza Topping?',
    correctAnswer: 'Chicken Feet',
    incorrectAnswers: ['Pepperoni', 'Chicken', 'Sausage']
  }
];
Enter fullscreen mode Exit fullscreen mode

To enact your custom questions, pass myQuestions as gameOptions.questionData

const gameOptions = {
   questionData: myQuestions
};

const game = trivia.createGame(interaction, gameOptions);
Enter fullscreen mode Exit fullscreen mode

As of the last revision of this article, you can only choose between custom questions or API questions. Stay tuned for updates though!

Game configuration

You can also customize lobby restrictions, how your fast game flows and point and streak handling with the rest of gameOptions.

Here is an example of adjusting all game configurations and what each option changes.

  • minimumPlayerCount: Will not start a match unless the lobby size reaches this value.
  • maximumPlayerCount: Will only let this amount of players join.
  • queueTime: How long to wait for players before starting.
  • timePerQuestion, timeBetweenRounds are self explanatory.
  • minimumPoints, maximumPoints: The minimum and maximum amount of points a player can earn per correct answer.
  • pointsPerStreakAmount: This number multiplied by the streak number will be the bonus points awarded. For example, if Wumpus has a streak of 3 questions and this is set to 20, his bonus for that round will be 60.
  • maximumStreakBonus: The maximum amount of bonus points a streaking player can earn per round.
  • streakDefinitionLevel: The amount of questions needed to be answered correctly in a row for a streak to start.
const gameOptions = {
    minimumPlayerCount: 5,
    maximumPlayerCount: 20,

    queueTime: 20_000,
    timePerQuestion: 15_000,
    timeBetweenRounds: 10_000,

    minimumPoints: 10,
    maximumPoints: 100,
    pointsPerStreakAmount: 20,
    maximumStreakBonus: 100,
    streakDefinitionLevel: 3
}
Enter fullscreen mode Exit fullscreen mode

You can view the defaults by requiring TriviaGame and logging TriviaGame.defaults.

Manager Customization

Lastly, you can customize the following via your TriviaManagerOptions

  • theme: The color of all embeds from this library.
  • showAnswers: Whether or not the game should reveal the answer at the end of each round.
  • image: Am image is displayed in the initial embed for a queue, provide an image URL to override that image.
const trivia = new TriviaManager({
  theme: 'COLOR RESOLVABLE HERE',
  showAnswers: true / false,
  image: 'IMG URL'
});
Enter fullscreen mode Exit fullscreen mode

You can view the defaults by requiring TriviaManager and logging TriviaManager.defaults.

And that's it! For support and feature requests Join Our Discord. Keep an eye on The Discord Trivia Github Repo for updates and changes.

Discussion (0)