opentdb

  Source   Edit

This package is a wrapper around opentdb which provides a database of trivia questions.

This package adds procs that can be used ontop of HttpClient/AsyncHttpClient to get questions from it

Example: cmd: -r:off

import opentdb
let client = newHttpClient()

# See getQuestions for more options such as difficulty and categories
for question in client.getQuestions():
  echo question

close client
Using a token is recommended so that you get unique questions in each call (until you run out of questions)

Example: cmd: -r:off

import opentdb
let client = newHttpClient()
var token = client.createToken()
while true:
  try:
    for question in client.getQuestions(token=token):
      echo question.question, "?"
      echo "Answer: ", question.correct_answer
  except TokenEmpty:
    client.resetToken(token)

Types

Category {.pure.} = enum
  Any = (8, "Any Category"), General = (9, "General Knowledge"),
  Books = (10, "Entertainment: Books"), Film = (11, "Entertainment: Film"),
  Music = (12, "Entertainment: Music"),
  Theatre = (13, "Entertainment: Musicals & Theatres"),
  TV = (14, "Entertainment: Television"),
  VideoGames = (15, "Entertainment: Video Games"),
  BoardGames = (16, "Entertainment: Board Games"),
  Nature = (17, "Science & Nature"), Computers = (18, "Science: Computers"),
  Maths = (19, "Science: Mathematics"), Mythology = (20, "Mythology"),
  Sports = (21, "Sports"), Geography = (22, "Geography"),
  History = (23, "History"), Politics = (24, "Politics"), Art = (25, "Art"),
  Celebrities = (26, "Celebrities"), Animals = (27, "Animals"),
  Vehicles = (28, "Vehicles"), Comics = (29, "Entertainment: Comics"),
  Gadgets = (30, "Science: Gadgets"),
  Anime = (31, "Entertainment: Japanese Anime & Manga"),
  Cartoons = (32, "Entertainment: Cartoon & Animations")
  Source   Edit
Difficulty {.pure.} = enum
  Any = "", Easy = "easy", Medium = "medium", Hard = "hard"
  Source   Edit
GlobalCount = object
  total_num_of_questions*: int
  total_num_of_pending_questions*: int
  total_num_of_verified_questions*: int
  total_num_of_rejected_questions*: int
Contains total counts for everything in openTDB's database   Source   Edit
NoResults = IOError
Thrown when you ask for too many questions   Source   Edit
Question = object
  category: Category
  kind*: QuestionType
  difficulty*: Difficulty
  question*: string
  correct_answer*: string
  incorrect_answers*: seq[string]
Contains info for a question
  • correct_answer: The right answer for the question
  • incorrect_answers: The possible answers that are wrong
  Source   Edit
QuestionCount = object
  total_question_count*: int
  total_easy_question_count*: int
  total_medium_question_count*: int
  total_hard_question_count*: int
Contains counts for number of questions in a single Category   Source   Edit
QuestionType = enum
  MultipleChoice = "multiple", Boolean = "boolean", Both = ""
  • multiple: Multiple choice questions
  • Boolean: yes/no questions
  • Both: Both of those
  Source   Edit
TokenEmpty = IOError
Thrown when token has run out of questions and needs to be reset (with resetToken)   Source   Edit
TokenNotFound = IOError
Thown when token provided isn't valid. Tokens must be made with createToken   Source   Edit

Consts

BASE_URL = "https://opentdb.com/"
  Source   Edit
URL_API = "https://opentdb.com/api.php"
  Source   Edit
URL_COUNT = "https://opentdb.com/api_count.php?category="
  Source   Edit
URL_COUNT_GLOBAL = "https://opentdb.com/api_count_global.php"
  Source   Edit
URL_TOKEN_API = "https://opentdb.com/api_token.php"
  Source   Edit

Procs

proc createToken(client: AsyncHttpClient): Future[string] {.
    ...raises: [Exception, ValueError],
    tags: [RootEffect, TimeEffect, ReadIOEffect, WriteIOEffect].}
Creates a token which makes sure you do not get the same questions twice After a while you will run out of responses and will need to reset the token

Example: cmd: -r:off

let 
  client = newHttpClient()
  token = client.createToken()
# Token assures that you won't get the same questions twice
for qA in client.getQuestions(token=token):
  for qB in client.getQuestions(token=token):
    assert qA != qB
  Source   Edit
proc createToken(client: HttpClient): string {....raises: [ValueError,
    HttpRequestError, LibraryError, Exception, OSError, SslError, IOError,
    TimeoutError, ProtocolError, KeyError, JsonParsingError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect, TimeEffect].}
  Source   Edit
proc getQuestions(client: AsyncHttpClient; category = Category.Any;
                  difficulty = Difficulty.Any; questionType = Both;
                  amount: Natural = 10; token = ""): Future[seq[Question]] {.
    ...raises: [Exception, ValueError],
    tags: [RootEffect, TimeEffect, ReadIOEffect, WriteIOEffect].}
Gets questions from https://opentdb.com

Example: cmd: -r:off

let client = newHttpClient()
# Get questions with default parameters
let questions = client.getQuestions()
# Get questions that are easy
let easyQuestions = client.getQuestions(difficulty=Easy)
# Get questions in relation to TV
let tvQuestions = client.getQuestions(category=TV)
# Get 100 questions
let hundredQuestions = client.getQuestions(amount=100)
# You can also combine them
let combinationQuestions = client.getQuestions(difficulty=Easy, category=TV, amount=100)
  Source   Edit
proc getQuestions(client: HttpClient; category = Category.Any;
                  difficulty = Difficulty.Any; questionType = Both;
                  amount: Natural = 10; token = ""): seq[Question] {....raises: [
    ValueError, HttpRequestError, LibraryError, Exception, OSError, SslError,
    IOError, TimeoutError, ProtocolError, KeyError, JsonParsingError,
    JsonKindError], tags: [RootEffect, ReadIOEffect, WriteIOEffect, TimeEffect].}
  Source   Edit
proc resetToken(client: AsyncHttpClient; token: string): owned(Future[void]) {.
    ...raises: [Exception], tags: [RootEffect, TimeEffect, ReadIOEffect].}
Resets a token so it can reuse questions

Example: cmd: -r:off

import httpclient
let client = newHttpClient()
let token = client.createToken()
# Run code that uses up all the questions
client.resetToken(token)
  Source   Edit
proc resetToken(client: HttpClient; token: string) {....raises: [ValueError,
    HttpRequestError, LibraryError, Exception, OSError, SslError, IOError,
    TimeoutError, ProtocolError, KeyError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect, TimeEffect].}
  Source   Edit
proc size(client: AsyncHttpClient; category: Category): Future[QuestionCount] {.
    ...raises: [Exception, ValueError],
    tags: [RootEffect, TimeEffect, ReadIOEffect, WriteIOEffect].}
Returns the numbers of questions in a category

Example: cmd: -r:off

import httpclient
let client = newHttpClient()
echo client.size(TV).totalQuestionCount
  Source   Edit
proc size(client: HttpClient; category: Category): QuestionCount {....raises: [
    ValueError, HttpRequestError, LibraryError, Exception, OSError, SslError,
    IOError, TimeoutError, ProtocolError, KeyError, JsonKindError,
    JsonParsingError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect, TimeEffect].}
  Source   Edit
proc totalSize(client: AsyncHttpClient): Future[GlobalCount] {.
    ...raises: [Exception, ValueError],
    tags: [RootEffect, TimeEffect, ReadIOEffect, WriteIOEffect].}
Returns the number of questions in total that opentdb has

Example: cmd: -r:off

let client = newHttpClient()
echo client.totalSize().totalNumOfQuestions
  Source   Edit
proc totalSize(client: HttpClient): GlobalCount {....raises: [ValueError,
    HttpRequestError, LibraryError, Exception, OSError, SslError, IOError,
    TimeoutError, ProtocolError, KeyError, JsonKindError, JsonParsingError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect, TimeEffect].}
  Source   Edit