-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.js
100 lines (85 loc) · 2.34 KB
/
api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { AbusiveClientError, NotAvailable, Untranslatable } from './errors';
const mutex = { current: false };
/**
* @typedef {{ translation: string, quality: number }} Translation
* @typedef {Record<string, Array<null | Translation>>} TranslatableValues
*
*/
export class ExternalApi {
/**
* @param {Readonly<TranslatableValues>} values
*/
constructor(values = {}) {
/** @type {TranslatableValues} */
this.values = JSON.parse(JSON.stringify(values));
}
/**
* Register a word for translation
*
* @param {string} value
* @param {string | null} translation
* @param {number | undefined} quality
*
* @returns {this}
*/
register(value, translation, quality = undefined) {
if (typeof this.values[value] === 'undefined') {
this.values[value] = [];
}
this.values[value].push(translation ? { translation, quality } : null);
return this;
}
/**
* @param {string} text
* @returns {Promise<Translation>}
*/
fetch(text) {
// Check if client is banned
if (mutex.current) {
return rejectWithRandomDelay(new AbusiveClientError());
}
if (this.values[text] && this.values[text][0]) {
return resolveWithRandomDelay(this.values[text][0]);
}
if (this.values[text]) {
return rejectWithRandomDelay(new NotAvailable(text));
}
return rejectWithRandomDelay(new Untranslatable());
}
/**
* @param {string} text
* @param {(err?: Error) => void} callback
*/
request(text, callback) {
if (this.values[text] && this.values[text][0]) {
mutex.current = true;
callback(new AbusiveClientError());
return;
}
if (this.values[text]) {
this.values[text].shift();
// If it's now available, yay, otherwise, nay
setTimeout(
() => callback(this.values[text][0] ? undefined : makeRandomError()),
1
);
return;
}
callback(new Untranslatable());
}
}
function resolveWithRandomDelay(value) {
const timeout = Math.random() * 100;
return new Promise((resolve) => {
setTimeout(() => resolve(value), timeout);
});
}
function rejectWithRandomDelay(value) {
const timeout = Math.random() * 100;
return new Promise((_, reject) => {
setTimeout(() => reject(value), timeout);
});
}
function makeRandomError() {
return new Error(`Error code ${Math.ceil(Math.random() * 10000)}`);
}