Skip to content

Commit afb1bf4

Browse files
author
Elitezen
committed
Completed Initial Source for 2.0.0
1 parent 3875407 commit afb1bf4

File tree

17 files changed

+388
-154
lines changed

17 files changed

+388
-154
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
# Changelog
22

3+
# 2.0.0
4+
- The library received a massive rework through many quality of life changes.
5+
6+
- 'Static' and 'Pretty' category names are no more, developers will no longer have to worry about converting through these formats.
7+
8+
- All QuestionOption option types now have respective enums to work with.
9+
10+
- `Category` is now just a class with various static methods for working with categories.
11+
312
## 1.0.2
413
- Switched from https module to Node Fetch API

README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
![OpenTriviaDB](https://i.imgur.com/QBhF5aY.png)
2+
3+
![version](https://img.shields.io/npm/v/open-trivia-db)
4+
![downloads](https://img.shields.io/npm/dm/open-trivia-db)
5+
![minisize](https://img.shields.io/bundlephobia/min/open-trivia-db)
6+
![types](https://img.shields.io/npm/types/open-trivia-db)
7+
8+
`open-trivia-db` is a small and simple library for interacting with the [OpenTDB](https://opentdb.com/) API.
9+
10+
Live Demo: https://replit.com/@Elitezenv/open-trivia-db-DEMO?v=1
11+
12+
## Updates (2.0.0)
13+
- The library received a massive rework through many quality of life changes.
14+
15+
- 'Static' and 'Pretty' category names are no more, developers will no longer have to worry about converting through these formats.
16+
17+
- All QuestionOption option types now have respective enums to work with.
18+
19+
- `Category` is now just a class with various static methods for working with categories.
20+
21+
22+
## Example Code
23+
```js
24+
import { getQuestions, CategoryNames } from "open-trivia-db";
25+
26+
const questions = await getQuestions({
27+
amount: 10,
28+
category: CategoryNames.Animals,
29+
difficulty: QuestionDifficulties.Easy,
30+
})
31+
```
32+
33+
## Result
34+
```js
35+
[
36+
{
37+
value: 'How many teeth does an adult rabbit have?',
38+
category: { id: 27, name: 'Animals', getData: [Function: getData] },
39+
type: 'multiple',
40+
difficulty: 'easy',
41+
correctAnswer: '28',
42+
incorrectAnswers: [ '30', '26', '24' ],
43+
allAnswers: [ '24', '28', '30', '26' ],
44+
checkAnswer: [Function: checkAnswer]
45+
}
46+
...
47+
]
48+
```
49+
50+
# Guide
51+
## Getting Questions
52+
53+
Questions can be fetched via the `getQuestions()` function by supplying options such as `amount`, `category`, `difficulty`, `type`, `session` and `encode`.
54+
55+
`type`: The kind of questions, such as multiple choice (`"multiple"`) or true/false (`"boolean"`).
56+
57+
`session`: A session instance or session token. [Learn about sessions](#sessions)
58+
59+
`encode`: The encoding of the questions such as `base64`, `urlLegacy`, `url3968` or `none` which is the default.
60+
61+
You can apply options via their respective enums.
62+
63+
The result will be an array of questions.
64+
65+
```js
66+
import {
67+
CategoryNames,
68+
QuestionDifficulties,
69+
QuestionTypes,
70+
QuestionEncodings
71+
} from "open-trivia-db";
72+
73+
getQuestions({
74+
amount: 50,
75+
category: CategoryNames["Entertainment: Japanese Anime & Manga"],
76+
difficulty: QuestionDifficulties.Hard,
77+
type: QuestionTypes.Multiple,
78+
encode: QuestionEncodings.None
79+
})
80+
```
81+
82+
## Getting Categories and Category Data
83+
<hr>
84+
85+
A category resolvable can either be a category name or id. Category id's range from 9-32 inclusive, for there are 23 categories.
86+
87+
To jump between resolvables, use `Category.idByName()` and `Category.nameById()`.
88+
89+
```js
90+
import { Category, CategoryNames } from "open-trivia-db";
91+
92+
Category.idByName('Art'); // 25
93+
Category.nameById(25); // 'Art'
94+
```
95+
96+
### Getting a Category's Data
97+
Use `Category.getCategory()` to get a category's data such as name, id, and question counts.
98+
99+
```js
100+
import { Category, CategoryNames } from "open-trivia-db"
101+
102+
Category.getCategory(CategoryNames.Geography)
103+
.then(console.log)
104+
```
105+
106+
```js
107+
{
108+
id: 22,
109+
name: 'Geography',
110+
questionCount: {
111+
total: 275,
112+
easy: 80, medium: 139, hard: 56
113+
}
114+
}
115+
```
116+
117+
You can also complete a category's data through a question via `Question.category.getData()`
118+
119+
```js
120+
const targetQuestion = questions[0] // from getQuestions()
121+
122+
targetQuestion.category.getData()
123+
.then(console.log)
124+
```
125+
126+
## Sessions
127+
A session ensures you are not supplied a question more than once throughout it's lifetime.
128+
129+
Initialize a session and supply the instance into `getQuestions()`. Make sure to await or resolve `Session.start()`.
130+
```js
131+
import { Session } from "open-trivia-db"
132+
133+
const mySession = new Session();
134+
await mySession.start();
135+
136+
getQuestions({
137+
session: mySession
138+
})
139+
```
140+
141+
`getQuestions()` will return an error once your session has served every single question in OpenTDB. Don't worry, theres thousands of questions! You will likely never come accross a session's end. However, if you wish to reset your session, use `Session.reset()`.
142+
143+
```js
144+
await mySession.reset();
145+
```
146+
147+
<hr>

dist/index.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
export {};
1+
import Category from "./src/classes/Category";
2+
import Constructor from "./src/classes/Constructor";
3+
import OpenTDBError from "./src/classes/OpenTDBError";
4+
import Session from "./src/classes/Session";
5+
import Util from "./src/classes/Util";
6+
import getCategory from "./src/functions/getCategory";
7+
import getQuestions from "./src/functions/getQuestions";
8+
import { CategoryNames, QuestionDifficulties, QuestionEncodings, QuestionTypes, Routes } from "./src/typings/enums";
9+
import type { CategoryData, ErrorResponse, MinifiedCategoryData, Question, QuestionOptions, RawQuestion, RawCategoryResponse, RawQuestionResponse, RawSessionStartResponse } from "./src/typings/interfaces";
10+
import type { CategoryNameType, CategoryResolvable, Dictionary, ErrorCode, QuestionDifficultyType, QuestionEncodingType, QuestionTypeType, ResponseCode, SimpleDictionary, ExtendedDictionary } from "./src/typings/types";
11+
export { Category, Constructor, OpenTDBError, Session, Util, getCategory, getQuestions, CategoryNames, QuestionDifficulties, QuestionEncodings, QuestionTypes, Routes, CategoryData, ErrorResponse, MinifiedCategoryData, Question, QuestionOptions, RawQuestion, RawCategoryResponse, RawQuestionResponse, RawSessionStartResponse, CategoryNameType, CategoryResolvable, Dictionary, ErrorCode, QuestionDifficultyType, QuestionEncodingType, QuestionTypeType, ResponseCode, SimpleDictionary, ExtendedDictionary };

dist/index.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.Routes = exports.QuestionTypes = exports.QuestionEncodings = exports.QuestionDifficulties = exports.CategoryNames = exports.getQuestions = exports.getCategory = exports.Util = exports.Session = exports.OpenTDBError = exports.Constructor = exports.Category = void 0;
34
const Category_1 = require("./src/classes/Category");
4-
async function test() {
5-
try {
6-
await Category_1.default.getCategory(8);
7-
}
8-
catch (err) {
9-
throw err;
10-
}
11-
}
12-
test();
5+
exports.Category = Category_1.default;
6+
const Constructor_1 = require("./src/classes/Constructor");
7+
exports.Constructor = Constructor_1.default;
8+
const OpenTDBError_1 = require("./src/classes/OpenTDBError");
9+
exports.OpenTDBError = OpenTDBError_1.default;
10+
const Session_1 = require("./src/classes/Session");
11+
exports.Session = Session_1.default;
12+
const Util_1 = require("./src/classes/Util");
13+
exports.Util = Util_1.default;
14+
const getCategory_1 = require("./src/functions/getCategory");
15+
exports.getCategory = getCategory_1.default;
16+
const getQuestions_1 = require("./src/functions/getQuestions");
17+
exports.getQuestions = getQuestions_1.default;
18+
const enums_1 = require("./src/typings/enums");
19+
Object.defineProperty(exports, "CategoryNames", { enumerable: true, get: function () { return enums_1.CategoryNames; } });
20+
Object.defineProperty(exports, "QuestionDifficulties", { enumerable: true, get: function () { return enums_1.QuestionDifficulties; } });
21+
Object.defineProperty(exports, "QuestionEncodings", { enumerable: true, get: function () { return enums_1.QuestionEncodings; } });
22+
Object.defineProperty(exports, "QuestionTypes", { enumerable: true, get: function () { return enums_1.QuestionTypes; } });
23+
Object.defineProperty(exports, "Routes", { enumerable: true, get: function () { return enums_1.Routes; } });

index.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
import Category from "./src/classes/Category";
2+
import Constructor from "./src/classes/Constructor";
3+
import OpenTDBError from "./src/classes/OpenTDBError";
4+
import Session from "./src/classes/Session";
5+
import Util from "./src/classes/Util";
26

3-
async function test() {
4-
try {
5-
await Category.getCategory(8)
6-
} catch (err) {
7-
throw err;
8-
}
9-
}
7+
import getCategory from "./src/functions/getCategory";
8+
import getQuestions from "./src/functions/getQuestions";
109

11-
test();
10+
import { CategoryNames, QuestionDifficulties, QuestionEncodings, QuestionTypes, Routes } from "./src/typings/enums";
11+
import type { CategoryData, ErrorResponse, MinifiedCategoryData, Question, QuestionOptions, RawQuestion, RawCategoryResponse, RawQuestionResponse, RawSessionStartResponse } from "./src/typings/interfaces";
12+
import type { CategoryNameType, CategoryResolvable, Dictionary, ErrorCode, QuestionDifficultyType, QuestionEncodingType, QuestionTypeType, ResponseCode, SimpleDictionary, ExtendedDictionary } from "./src/typings/types";
13+
14+
export {
15+
Category,
16+
Constructor,
17+
OpenTDBError,
18+
Session,
19+
Util,
20+
getCategory,
21+
getQuestions,
22+
CategoryNames, QuestionDifficulties, QuestionEncodings, QuestionTypes, Routes,
23+
CategoryData, ErrorResponse, MinifiedCategoryData, Question, QuestionOptions, RawQuestion, RawCategoryResponse, RawQuestionResponse, RawSessionStartResponse,
24+
CategoryNameType, CategoryResolvable, Dictionary, ErrorCode, QuestionDifficultyType, QuestionEncodingType, QuestionTypeType, ResponseCode, SimpleDictionary, ExtendedDictionary
25+
}

src/Classes/Category.ts

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,72 @@ import type { CategoryNameType } from "../typings/types";
33
import getCategory from "../functions/getCategory";
44
import Util from "./Util";
55

6+
/**
7+
* @class Class for anything trivia category related.
8+
*/
69
export default class Category {
7-
static allNames = Object.keys(CategoryNames).filter((key) => isNaN(+key));
10+
/**
11+
* An array of all category names. Use `Category.random()` for a random pick.
12+
*/
13+
static allNames: CategoryNameType[] = Object.keys(CategoryNames).filter(
14+
(key) => isNaN(+key)
15+
) as CategoryNameType[];
816

17+
/**
18+
* Decodes a URLLegacy, URL3968 or Base64 category name.
19+
* @param {string} str string to decode.
20+
* @returns {string} The decoded category name.
21+
*/
22+
static decodeEncodedCategoryName(str: string): CategoryNameType | null {
23+
return (
24+
[
25+
Util.decodeBase64<CategoryNameType>(str),
26+
Util.decodeUrl3968<CategoryNameType>(str),
27+
Util.decodeUrlLegacy<CategoryNameType>(str),
28+
].find((str) => Category.allNames.includes(str)) || null
29+
);
30+
}
31+
32+
/**
33+
* Fetches a trivia category's data. Duplicate of `getCategory()`.
34+
* @param {CategoryResolvable} arg An argument resolving to a trivia category.
35+
* @returns {Promise<CategoryData>} The data of the category.
36+
*/
937
static getCategory = getCategory;
1038

11-
static idByName(name: string) {
39+
/**
40+
* Returns a category id when given it's name.
41+
* @param {CategoryNameType} name The name of the category.
42+
* @returns {number | null} The id if resolvable.
43+
*/
44+
static idByName(name: CategoryNameType): number | null {
1245
const id = Category.allNames.indexOf(name);
1346
return id > -1 ? id + 9 : null;
1447
}
1548

49+
/**
50+
* Returns a category name when given it's id.
51+
* @param {number} id The id of the category.
52+
* @returns {CategoryNameType | null} The name if resolvable.
53+
*/
1654
static nameById(id: number): CategoryNameType | null {
1755
const name = Category.allNames[id - 9];
1856
return name !== undefined ? (name as CategoryNameType) : null;
1957
}
2058

21-
static decodeEncodedCategoryName(str: string): CategoryNameType | null {
22-
return (
23-
[
24-
Util.decodeBase64<CategoryNameType>(str),
25-
Util.decodeUrl3968<CategoryNameType>(str),
26-
Util.decodeUrlLegacy<CategoryNameType>(str),
27-
].find((str) => Category.allNames.includes(str)) || null
28-
);
59+
/**
60+
* Picks a random category name or id.
61+
* @param {'name' | 'id'} resolvableType The kind of resolvable to return (default `'name'`).
62+
* @returns {CategoryNameType | number} A random category id or name.
63+
*/
64+
static random(resolvableType: "name"): CategoryNameType;
65+
static random(resolvableType: "id"): number;
66+
static random(resolvableType?: "name" | "id"): CategoryNameType | number {
67+
if (resolvableType === undefined) resolvableType = "name";
68+
69+
const name =
70+
Category.allNames[Math.floor(Math.random() * Category.allNames.length)];
71+
if (resolvableType === "id") return Category.idByName(name)!;
72+
return name;
2973
}
30-
}
74+
}

src/Classes/Constructor.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import type {
33
Question,
44
RawCategoryResponse,
55
RawQuestion,
6-
} from "../typings/interface";
6+
} from "../typings/interfaces";
77
import Category from "./Category";
88
import Util from "./Util";
99

10+
/**
11+
* @class Class for transforming raw API data to developer friendly data.
12+
* @private
13+
*/
1014
export default class Constructor {
1115
static category(rawCategoryData: RawCategoryResponse): CategoryData {
1216
return {

src/Classes/OpenTDBError.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import type { ErrorResponse } from "../typings/interface";
1+
import type { ErrorResponse } from "../typings/interfaces";
22

3+
/**
4+
* @class OpenTDB error constructor
5+
* @private
6+
*/
37
export default class OpenTDBError extends TypeError {
48
constructor(error: ErrorResponse) {
5-
console.log(error);
69
super(error.text);
710
this.name = `OpenTDBError [${error.header}]`;
811
}

0 commit comments

Comments
 (0)