@20syldev/api 5.2.0 → 5.4.0-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +3 -3
  2. package/dist/app.js +7 -2
  3. package/dist/app.js.map +1 -1
  4. package/dist/config/versions.js +5 -1
  5. package/dist/config/versions.js.map +1 -1
  6. package/dist/constants.js +1 -0
  7. package/dist/constants.js.map +1 -1
  8. package/dist/middleware/ratelimit.js +1 -1
  9. package/dist/middleware/ratelimit.js.map +1 -1
  10. package/dist/modules/v5/address.js +20 -0
  11. package/dist/modules/v5/address.js.map +1 -0
  12. package/dist/modules/v5/algorithms.js +39 -0
  13. package/dist/modules/v5/algorithms.js.map +1 -0
  14. package/dist/modules/v5/asymmetric.js +10 -3
  15. package/dist/modules/v5/asymmetric.js.map +1 -1
  16. package/dist/modules/v5/barcode.js +424 -0
  17. package/dist/modules/v5/barcode.js.map +1 -0
  18. package/dist/modules/v5/case.js +57 -0
  19. package/dist/modules/v5/case.js.map +1 -0
  20. package/dist/modules/v5/chart.js +16 -10
  21. package/dist/modules/v5/chart.js.map +1 -1
  22. package/dist/modules/v5/chat.js +107 -0
  23. package/dist/modules/v5/chat.js.map +1 -0
  24. package/dist/modules/v5/evaluate.js +8 -5
  25. package/dist/modules/v5/evaluate.js.map +1 -1
  26. package/dist/modules/v5/jwt.js +42 -0
  27. package/dist/modules/v5/jwt.js.map +1 -0
  28. package/dist/modules/v5/matrix.js +5 -4
  29. package/dist/modules/v5/matrix.js.map +1 -1
  30. package/dist/modules/v5/otp.js +16 -7
  31. package/dist/modules/v5/otp.js.map +1 -1
  32. package/dist/modules/v5/symmetric.js +36 -19
  33. package/dist/modules/v5/symmetric.js.map +1 -1
  34. package/dist/modules/v5/text.js +12 -0
  35. package/dist/modules/v5/text.js.map +1 -0
  36. package/dist/modules/v5/tic_tac_toe.js +226 -0
  37. package/dist/modules/v5/tic_tac_toe.js.map +1 -0
  38. package/dist/modules/v5.js +9 -1
  39. package/dist/modules/v5.js.map +1 -1
  40. package/dist/routes/get.js +85 -44
  41. package/dist/routes/get.js.map +1 -1
  42. package/dist/routes/index.js +4 -1
  43. package/dist/routes/index.js.map +1 -1
  44. package/dist/routes/post.js +23 -1
  45. package/dist/routes/post.js.map +1 -1
  46. package/dist/utils/helpers.js +6 -1
  47. package/dist/utils/helpers.js.map +1 -1
  48. package/package.json +1 -1
  49. package/dist/modules/v4/colors.js +0 -54
  50. package/dist/modules/v4/colors.js.map +0 -1
  51. package/dist/modules/v4/utils.js +0 -26
  52. package/dist/modules/v4/utils.js.map +0 -1
  53. package/dist/utils/version.js +0 -3
  54. package/dist/utils/version.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"symmetric.js","sourceRoot":"","sources":["../../../src/modules/v5/symmetric.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"symmetric.js","sourceRoot":"","sources":["../../../src/modules/v5/symmetric.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import * as v4text from '../v4/text.js';
2
+ export * from '../v4/text.js';
3
+ /**
4
+ * Converts a number to its written form in the given language.
5
+ */
6
+ export function number(value, lang) {
7
+ const result = v4text.number(value, lang);
8
+ if (lang === 'fr')
9
+ return result.replace(/soixante-onze/g, 'soixante et onze');
10
+ return result;
11
+ }
12
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/modules/v5/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,cAAc,eAAe,CAAC;AAE9B;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,IAAY;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;IAC/E,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,226 @@
1
+ import { randomBytes } from 'crypto';
2
+ import { GAME_CLEANUP_TTL, RATE_LIMIT_MAX, RATE_LIMIT_WINDOW, SESSION_TTL } from '../../constants.js';
3
+ /**
4
+ * Handles Tic-Tac-Toe game actions including playing a move, fetching game state, listing games, and forfeiting.
5
+ *
6
+ * @param action - The action to perform: "play", "fetch", "list", or "forfeit"
7
+ * @param params - Game parameters including username, move, session, game ID, and shared storage
8
+ * @returns Game state or action result depending on the action
9
+ * @throws Error if a required parameter is missing, the action is invalid, or a rate limit is exceeded
10
+ */
11
+ export default function tic_tac_toe(action, params) {
12
+ const storage = params.storage;
13
+ storage.games ??= {};
14
+ storage.sessions ??= {};
15
+ storage.rateLimits ??= {};
16
+ const { games, sessions, rateLimits } = storage;
17
+ if (action === 'list')
18
+ return listGames(games);
19
+ if (!params.username)
20
+ throw new Error('Please provide a username');
21
+ const u = params.username.toLowerCase();
22
+ const now = Date.now();
23
+ rateLimits[u] = (rateLimits[u] ?? []).filter((ts) => now - ts < RATE_LIMIT_WINDOW);
24
+ if (rateLimits[u].length >= RATE_LIMIT_MAX) {
25
+ const remainingTime = Math.ceil((rateLimits[u][0] + RATE_LIMIT_WINDOW - now) / 1000);
26
+ throw new Error(`Rate limit exceeded. Try again in ${remainingTime} seconds.`);
27
+ }
28
+ rateLimits[u].push(now);
29
+ if (action === 'play') {
30
+ return playMove(params, games, sessions, u, now);
31
+ }
32
+ else if (action === 'fetch') {
33
+ return fetchGame(params, games, u);
34
+ }
35
+ else if (action === 'forfeit') {
36
+ return forfeitGame(params, games, sessions);
37
+ }
38
+ else {
39
+ throw new Error('Invalid action. Use "play", "fetch", "list", or "forfeit"');
40
+ }
41
+ }
42
+ function forfeitGame(params, games, sessions) {
43
+ const { game, session } = params;
44
+ if (!game)
45
+ throw new Error('Please provide a valid game ID');
46
+ if (!session)
47
+ throw new Error('Please provide a valid session ID');
48
+ if (!games[game])
49
+ throw new Error('Game not found');
50
+ const u = params.username.toLowerCase();
51
+ if (sessions[u] && sessions[u].user !== session) {
52
+ throw new Error('Session ID mismatch');
53
+ }
54
+ const players = games[game].players;
55
+ if (!players.includes(u))
56
+ throw new Error('You are not a player in this game');
57
+ const winner = players.find((p) => p !== u) ?? null;
58
+ delete games[game];
59
+ delete sessions[u];
60
+ return {
61
+ message: `${params.username} forfeited the game.${winner ? ` ${winner} wins.` : ''}`,
62
+ winner,
63
+ loser: params.username,
64
+ };
65
+ }
66
+ function playMove(params, games, sessions, u, now) {
67
+ const { move, session, game } = params;
68
+ const validMoves = ['1-1', '1-2', '1-3', '2-1', '2-2', '2-3', '3-1', '3-2', '3-3'];
69
+ if (!move)
70
+ throw new Error('Please provide a valid move');
71
+ if (!session)
72
+ throw new Error('Please provide a valid session ID');
73
+ if (!game)
74
+ throw new Error('Please provide a valid game ID');
75
+ if (!validMoves.includes(move))
76
+ throw new Error('Invalid move. Please provide a valid move (e.g., 1-1, 2-2, 3-3).');
77
+ if (sessions[u] && sessions[u].user !== session) {
78
+ throw new Error('Session ID mismatch');
79
+ }
80
+ games[game] = games[game] ?? {
81
+ moves: [],
82
+ players: [],
83
+ private: params.private || false,
84
+ creation: Date.now(),
85
+ };
86
+ const g = games[game];
87
+ const moves = g.moves;
88
+ if (!g.players.includes(u)) {
89
+ if (g.players.length >= 2)
90
+ throw new Error('Game is full, you can only watch.');
91
+ g.players.push(u);
92
+ }
93
+ if (moves.length > 0 && moves[moves.length - 1].username === u) {
94
+ throw new Error('Please wait for the other player to make a move.');
95
+ }
96
+ if (moves.some((play) => play.move === move)) {
97
+ throw new Error('Move already made. Please choose a different move.');
98
+ }
99
+ const play = { username: u, move, session };
100
+ moves.push(play);
101
+ g.last = now;
102
+ const creation = g.creation;
103
+ const result = checkGame(moves);
104
+ if (result.winner || result.tie) {
105
+ setTimeout(() => {
106
+ if (games[game] && games[game].creation === creation)
107
+ delete games[game];
108
+ }, GAME_CLEANUP_TTL);
109
+ return {
110
+ message: `Move sent successfully. ${result.winner ? result.winner + ' wins. ' + result.loser + ' loses.' : "It's a tie."}`,
111
+ ...result,
112
+ };
113
+ }
114
+ setTimeout(() => {
115
+ const cur = games[game];
116
+ if (cur && cur.creation === creation && Date.now() - (cur.last ?? cur.creation) >= SESSION_TTL) {
117
+ delete games[game];
118
+ }
119
+ }, SESSION_TTL);
120
+ sessions[u] = sessions[u] ?? { user: session, last: now };
121
+ sessions[u].last = now;
122
+ setTimeout(() => {
123
+ if (sessions[u] && Date.now() - sessions[u].last >= SESSION_TTL)
124
+ delete sessions[u];
125
+ }, SESSION_TTL);
126
+ return { message: 'Move sent successfully' };
127
+ }
128
+ function fetchGame(params, games, u) {
129
+ const id = params.game || generateGameId();
130
+ if (!games[id]) {
131
+ games[id] = {
132
+ moves: [],
133
+ players: [],
134
+ private: params.private || false,
135
+ creation: Date.now(),
136
+ };
137
+ }
138
+ if (!games[id].players.includes(u)) {
139
+ games[id].players.push(u);
140
+ }
141
+ const moves = games[id].moves;
142
+ const players = games[id].players;
143
+ const privateGame = games[id].private;
144
+ const lastPlayer = moves.length ? moves[moves.length - 1].username : null;
145
+ const turn = players.find((p) => p !== lastPlayer) || players[0];
146
+ const status = players.length >= 2 ? 'ready' : 'waiting';
147
+ const result = moves.length ? checkGame(moves) : {};
148
+ return {
149
+ id,
150
+ moves,
151
+ players,
152
+ turn,
153
+ status,
154
+ private: privateGame,
155
+ ...result,
156
+ };
157
+ }
158
+ function listGames(games) {
159
+ const publicGames = [];
160
+ const now = Date.now();
161
+ for (const [gameId, game] of Object.entries(games)) {
162
+ if (!game.private) {
163
+ const result = game.moves.length ? checkGame(game.moves) : {};
164
+ const isFinished = result.winner || result.tie;
165
+ if (!isFinished) {
166
+ const lastPlayer = game.moves.length ? game.moves[game.moves.length - 1].username : null;
167
+ const turn = game.players.find((p) => p !== lastPlayer) || game.players[0];
168
+ const status = game.players.length >= 2 ? 'ready' : 'waiting';
169
+ publicGames.push({
170
+ id: gameId,
171
+ players: game.players,
172
+ playersCount: game.players.length,
173
+ moves: game.moves.length,
174
+ turn,
175
+ status,
176
+ creation: game.creation || now,
177
+ });
178
+ }
179
+ }
180
+ }
181
+ publicGames.sort((a, b) => b.creation - a.creation);
182
+ return {
183
+ message: 'Public games available',
184
+ count: publicGames.length,
185
+ games: publicGames,
186
+ };
187
+ }
188
+ function generateGameId() {
189
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
190
+ return Array.from(randomBytes(5))
191
+ .map((b) => chars[b % chars.length])
192
+ .join('');
193
+ }
194
+ function checkGame(moves) {
195
+ const board = Array(3)
196
+ .fill(null)
197
+ .map(() => Array(3).fill(null));
198
+ const playerSymbols = {};
199
+ const playersOrder = [];
200
+ moves.forEach(({ username, move }) => {
201
+ if (!playerSymbols[username]) {
202
+ playersOrder.push(username);
203
+ playerSymbols[username] = playersOrder.length === 1 ? 'X' : 'O';
204
+ }
205
+ const [row, col] = move.split('-').map(Number);
206
+ board[row - 1][col - 1] = playerSymbols[username];
207
+ });
208
+ const checkWinner = (symbol) => {
209
+ for (let i = 0; i < 3; i++) {
210
+ if (board[i][0] === symbol && board[i][1] === symbol && board[i][2] === symbol)
211
+ return true;
212
+ if (board[0][i] === symbol && board[1][i] === symbol && board[2][i] === symbol)
213
+ return true;
214
+ }
215
+ if (board[0][0] === symbol && board[1][1] === symbol && board[2][2] === symbol)
216
+ return true;
217
+ if (board[0][2] === symbol && board[1][1] === symbol && board[2][0] === symbol)
218
+ return true;
219
+ return false;
220
+ };
221
+ const winner = Object.keys(playerSymbols).find((player) => checkWinner(playerSymbols[player])) ?? null;
222
+ const isTie = !winner && moves.length === 9;
223
+ const loser = winner && playersOrder.length === 2 ? (playersOrder.find((player) => player !== winner) ?? null) : null;
224
+ return { winner, loser, tie: isTie };
225
+ }
226
+ //# sourceMappingURL=tic_tac_toe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tic_tac_toe.js","sourceRoot":"","sources":["../../../src/modules/v5/tic_tac_toe.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,16 @@
1
- export { address, agent, algorithms, avatar, barcode, captcha, chat, color, convert, credit, cron, dice, domain, encode, geo, hash, hyperplanning, ip, levenshtein, palette, password, personal, placeholder, qrcode, regex, statistics, text, tic_tac_toe, time, token, username, validate, } from './v4.js';
1
+ export { agent, avatar, captcha, color, convert, credit, cron, dice, domain, encode, geo, hash, hyperplanning, ip, levenshtein, palette, password, personal, placeholder, qrcode, regex, statistics, time, token, username, validate, } from './v4.js';
2
+ export { default as address } from './v5/address.js';
3
+ export * as algorithms from './v5/algorithms.js';
2
4
  export { default as asymmetric } from './v5/asymmetric.js';
5
+ export { default as barcode } from './v5/barcode.js';
6
+ export { default as caseConvert } from './v5/case.js';
3
7
  export * as chart from './v5/chart.js';
8
+ export { default as chat } from './v5/chat.js';
4
9
  export { default as evaluate } from './v5/evaluate.js';
10
+ export { default as jwt } from './v5/jwt.js';
5
11
  export * as matrix from './v5/matrix.js';
6
12
  export { default as otp } from './v5/otp.js';
7
13
  export { default as symmetric } from './v5/symmetric.js';
14
+ export * as text from './v5/text.js';
15
+ export { default as tic_tac_toe } from './v5/tic_tac_toe.js';
8
16
  //# sourceMappingURL=v5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"v5.js","sourceRoot":"","sources":["../../src/modules/v5.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,MAAM,EACN,GAAG,EACH,IAAI,EACJ,aAAa,EACb,EAAE,EACF,WAAW,EACX,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,MAAM,EACN,KAAK,EACL,UAAU,EACV,IAAI,EACJ,WAAW,EACX,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"v5.js","sourceRoot":"","sources":["../../src/modules/v5.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,EACL,OAAO,EACP,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,MAAM,EACN,GAAG,EACH,IAAI,EACJ,aAAa,EACb,EAAE,EACF,WAAW,EACX,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,MAAM,EACN,KAAK,EACL,UAAU,EACV,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,UAAU,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
@@ -8,6 +8,14 @@ import { error } from '../utils/response.js';
8
8
  const router = Router();
9
9
  let activity = [];
10
10
  let lastFetch = 0;
11
+ const postOnly = (name) => (req, res) => {
12
+ const available = versions[req.version]?.endpoints.post.some((e) => e.name === name);
13
+ if (!available) {
14
+ error(res, 404, `Endpoint not available in ${req.version}.`, `${req.latest}/${name}`);
15
+ return;
16
+ }
17
+ error(res, 405, 'This endpoint only supports POST requests.');
18
+ };
11
19
  // Display version information
12
20
  router.get('/:version', (req, res) => {
13
21
  const version = req.params.version;
@@ -51,6 +59,10 @@ router.get('/:version/address', (req, res) => {
51
59
  return;
52
60
  }
53
61
  const parsedCount = count !== undefined ? parseInt(count, 10) : 1;
62
+ if (isNaN(parsedCount)) {
63
+ error(res, 400, 'Please provide a valid count (&count={n})', `${version}/address`);
64
+ return;
65
+ }
54
66
  try {
55
67
  const result = addressFn(country, parsedCount);
56
68
  res.jsonResponse(result);
@@ -62,8 +74,12 @@ router.get('/:version/address', (req, res) => {
62
74
  // Parse a User-Agent string
63
75
  router.get('/:version/agent', (req, res) => {
64
76
  const ua = req.query.ua ?? req.headers['user-agent'] ?? '';
77
+ const agentFn = req.module.agent;
78
+ if (!agentFn) {
79
+ error(res, 404, `Endpoint not available in ${req.version}.`, `${req.latest}/agent`);
80
+ return;
81
+ }
65
82
  try {
66
- const agentFn = req.module.agent;
67
83
  const result = agentFn(ua);
68
84
  res.jsonResponse(result);
69
85
  }
@@ -89,8 +105,27 @@ router.get('/:version/algorithms', (req, res) => {
89
105
  }
90
106
  });
91
107
  // GET asymmetric error
92
- router.get('/:version/asymmetric', (_req, res) => {
93
- error(res, 405, 'This endpoint only supports POST requests.');
108
+ router.get('/:version/asymmetric', postOnly('asymmetric'));
109
+ // Convert text to a different case format
110
+ router.get('/:version/case', (req, res) => {
111
+ const { text, to } = req.query;
112
+ const { version } = req.params;
113
+ const caseConvertFn = req.module.caseConvert;
114
+ if (!caseConvertFn) {
115
+ error(res, 404, `Endpoint not available in ${version}.`, `${req.latest}/case`);
116
+ return;
117
+ }
118
+ if (!text || typeof text !== 'string') {
119
+ error(res, 400, 'Please provide a text (?text={text})', `${version}/case`);
120
+ return;
121
+ }
122
+ try {
123
+ const result = caseConvertFn(text, to);
124
+ res.jsonResponse(result);
125
+ }
126
+ catch (err) {
127
+ error(res, 400, err.message, `${req.version}/case`);
128
+ }
94
129
  });
95
130
  // Generate an identicon or pixel-art avatar from a seed
96
131
  router.get('/:version/avatar', (req, res) => {
@@ -100,10 +135,15 @@ router.get('/:version/avatar', (req, res) => {
100
135
  return;
101
136
  }
102
137
  const { seed, size, type, bg, format } = req.query;
138
+ const parsedSize = size !== undefined ? parseInt(size, 10) : undefined;
139
+ if (parsedSize !== undefined && isNaN(parsedSize)) {
140
+ error(res, 400, 'Please provide a valid size (&size={50-2000})', `${req.version}/avatar`);
141
+ return;
142
+ }
103
143
  try {
104
144
  const { contentType, body } = avatarFn({
105
145
  seed: seed,
106
- size: size !== undefined ? parseInt(size, 10) : undefined,
146
+ size: parsedSize,
107
147
  type: type,
108
148
  bg: bg,
109
149
  format: format,
@@ -126,12 +166,18 @@ router.get('/:version/barcode', (req, res) => {
126
166
  error(res, 400, 'Please provide data to encode (?data={string})', `${req.version}/barcode`);
127
167
  return;
128
168
  }
169
+ const parsedWidth = width !== undefined ? parseInt(width, 10) : undefined;
170
+ const parsedHeight = height !== undefined ? parseInt(height, 10) : undefined;
171
+ if ((parsedWidth !== undefined && isNaN(parsedWidth)) || (parsedHeight !== undefined && isNaN(parsedHeight))) {
172
+ error(res, 400, 'Please provide valid dimensions (&width={px}&height={px})', `${req.version}/barcode`);
173
+ return;
174
+ }
129
175
  try {
130
176
  const { contentType, body } = barcodeFn({
131
177
  data: data,
132
178
  type: type,
133
- width: width !== undefined ? parseInt(width, 10) : undefined,
134
- height: height !== undefined ? parseInt(height, 10) : undefined,
179
+ width: parsedWidth,
180
+ height: parsedHeight,
135
181
  format: format,
136
182
  color: color,
137
183
  bg: bg,
@@ -174,14 +220,12 @@ router.get('/:version/captcha', (req, res) => {
174
220
  }
175
221
  });
176
222
  // GET chart error
177
- router.get('/:version/chart', (_req, res) => {
178
- error(res, 405, 'This endpoint only supports POST requests.');
179
- });
223
+ router.get('/:version/chart', postOnly('chart'));
180
224
  // Display stored data
181
225
  router.get('/:version/chat', (req, res) => {
182
226
  try {
183
227
  const messages = req.module.chat('fetch', {
184
- username: 'system',
228
+ username: `reader:${req.ip ?? 'unknown'}`,
185
229
  storage: chatStorage,
186
230
  });
187
231
  res.jsonResponse(messages);
@@ -191,9 +235,7 @@ router.get('/:version/chat', (req, res) => {
191
235
  }
192
236
  });
193
237
  // GET private chat error
194
- router.get('/:version/chat/private', (_req, res) => {
195
- error(res, 405, 'This endpoint only supports POST requests.');
196
- });
238
+ router.get('/:version/chat/private', postOnly('chat'));
197
239
  // Generate color
198
240
  router.get('/:version/color', (req, res) => {
199
241
  try {
@@ -272,8 +314,13 @@ router.get('/:version/cron', (req, res) => {
272
314
  error(res, 400, 'Please provide a cron expression (?expr=* * * * *)', `${version}/cron`);
273
315
  return;
274
316
  }
317
+ const parsedCount = count !== undefined ? parseInt(count, 10) : 5;
318
+ if (isNaN(parsedCount)) {
319
+ error(res, 400, 'Please provide a valid count (&count={n})', `${version}/cron`);
320
+ return;
321
+ }
275
322
  try {
276
- const result = cronFn(expr, count !== undefined ? parseInt(count, 10) : 5, from, timezone ?? 'UTC');
323
+ const result = cronFn(expr, parsedCount, from, timezone ?? 'UTC');
277
324
  res.jsonResponse(result);
278
325
  }
279
326
  catch (err) {
@@ -375,9 +422,7 @@ router.get('/:version/geo', (req, res) => {
375
422
  }
376
423
  });
377
424
  // GET hash error
378
- router.get('/:version/hash', (_req, res) => {
379
- error(res, 405, 'This endpoint only supports POST requests.');
380
- });
425
+ router.get('/:version/hash', postOnly('hash'));
381
426
  // Echo request headers
382
427
  router.get('/:version/headers', (req, res) => {
383
428
  const redacted = new Set(['authorization', 'cookie', 'set-cookie', 'proxy-authorization']);
@@ -385,7 +430,8 @@ router.get('/:version/headers', (req, res) => {
385
430
  for (const [k, v] of Object.entries(req.headers)) {
386
431
  headers[k] = redacted.has(k) ? '[redacted]' : v;
387
432
  }
388
- const filter = req.query.filter;
433
+ const filterParam = req.query.filter;
434
+ const filter = Array.isArray(filterParam) ? filterParam.join(',') : filterParam;
389
435
  if (filter) {
390
436
  const keys = new Set(filter.split(',').map((k) => k.trim().toLowerCase()));
391
437
  headers = Object.fromEntries(Object.entries(headers).filter(([k]) => keys.has(k)));
@@ -399,9 +445,7 @@ router.get('/:version/headers', (req, res) => {
399
445
  });
400
446
  });
401
447
  // GET planning error
402
- router.get('/:version/hyperplanning', (_req, res) => {
403
- error(res, 405, 'This endpoint only supports POST requests.');
404
- });
448
+ router.get('/:version/hyperplanning', postOnly('hyperplanning'));
405
449
  // Display API informations
406
450
  router.get('/:version/infos', (req, res) => {
407
451
  const endpoints = Object.values(versions[req.version].endpoints).flat();
@@ -417,8 +461,12 @@ router.get('/:version/infos', (req, res) => {
417
461
  // Analyze an IP address
418
462
  router.get('/:version/ip', (req, res) => {
419
463
  const address = req.query.address ?? req.ip ?? '';
464
+ const ipFn = req.module.ip;
465
+ if (!ipFn) {
466
+ error(res, 404, `Endpoint not available in ${req.version}.`, `${req.latest}/ip`);
467
+ return;
468
+ }
420
469
  try {
421
- const ipFn = req.module.ip;
422
470
  const result = ipFn(address);
423
471
  res.jsonResponse(result);
424
472
  }
@@ -426,6 +474,8 @@ router.get('/:version/ip', (req, res) => {
426
474
  error(res, 400, err.message, `${req.version}/ip`);
427
475
  }
428
476
  });
477
+ // GET jwt error
478
+ router.get('/:version/jwt', postOnly('jwt'));
429
479
  // Calculate Levenshtein distance
430
480
  router.get('/:version/levenshtein', (req, res) => {
431
481
  const { str1, str2 } = req.query;
@@ -446,13 +496,9 @@ router.get('/:version/levenshtein', (req, res) => {
446
496
  }
447
497
  });
448
498
  // GET matrix error
449
- router.get('/:version/matrix', (_req, res) => {
450
- error(res, 405, 'This endpoint only supports POST requests.');
451
- });
499
+ router.get('/:version/matrix', postOnly('matrix'));
452
500
  // GET otp error
453
- router.get('/:version/otp', (_req, res) => {
454
- error(res, 405, 'This endpoint only supports POST requests.');
455
- });
501
+ router.get('/:version/otp', postOnly('otp'));
456
502
  // Generate a color palette from a base color
457
503
  router.get('/:version/palette', (req, res) => {
458
504
  const { color, type } = req.query;
@@ -617,9 +663,7 @@ router.get('/:version/statistics', (req, res) => {
617
663
  }
618
664
  });
619
665
  // GET symmetric error
620
- router.get('/:version/symmetric', (_req, res) => {
621
- error(res, 405, 'This endpoint only supports POST requests.');
622
- });
666
+ router.get('/:version/symmetric', postOnly('symmetric'));
623
667
  // Text utilities (slug, stats, lorem, number)
624
668
  router.get('/:version/text', (req, res) => {
625
669
  const { method, value, type, count, lang, text } = req.query;
@@ -656,15 +700,9 @@ router.get('/:version/text', (req, res) => {
656
700
  }
657
701
  });
658
702
  // GET tic-tac-toe errors
659
- router.get('/:version/tic-tac-toe', (_req, res) => {
660
- error(res, 405, 'This endpoint only supports POST requests.');
661
- });
662
- router.get('/:version/tic-tac-toe/fetch', (_req, res) => {
663
- error(res, 405, 'This endpoint only supports POST requests.');
664
- });
665
- router.get('/:version/tic-tac-toe/list', (_req, res) => {
666
- error(res, 405, 'This endpoint only supports POST requests.');
667
- });
703
+ router.get('/:version/tic-tac-toe', postOnly('tic_tac_toe'));
704
+ router.get('/:version/tic-tac-toe/fetch', postOnly('tic_tac_toe'));
705
+ router.get('/:version/tic-tac-toe/list', postOnly('tic_tac_toe'));
668
706
  // Display or generate time informations, or compute a countdown
669
707
  router.get('/:version/time', (req, res) => {
670
708
  const { type = 'live', start, end, format, timezone, target } = req.query;
@@ -678,9 +716,7 @@ router.get('/:version/time', (req, res) => {
678
716
  }
679
717
  });
680
718
  // GET token error
681
- router.get('/:version/token', (_req, res) => {
682
- error(res, 405, 'This endpoint only supports POST requests.');
683
- });
719
+ router.get('/:version/token', postOnly('token'));
684
720
  // Generate username
685
721
  router.get('/:version/username', (req, res) => {
686
722
  try {
@@ -818,7 +854,12 @@ router.get('/:version/website', async (req, res) => {
818
854
  tag: env.TAG,
819
855
  active: env.ACTIVE,
820
856
  };
821
- const key = req.query.key;
857
+ const keyParam = req.query.key;
858
+ if (Array.isArray(keyParam)) {
859
+ error(res, 400, 'Invalid key.');
860
+ return;
861
+ }
862
+ const key = keyParam;
822
863
  if (key) {
823
864
  if (['__proto__', 'constructor', 'prototype'].some((p) => key.includes(p))) {
824
865
  error(res, 400, 'Invalid key.');