@20syldev/api 3.5.0 → 4.0.0

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 (180) hide show
  1. package/.prettierrc +7 -0
  2. package/README.md +32 -33
  3. package/dist/app.js +36 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/config/env.js +73 -0
  6. package/dist/config/env.js.map +1 -0
  7. package/dist/config/versions.js +72 -0
  8. package/dist/config/versions.js.map +1 -0
  9. package/dist/constants.js +42 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/middleware/cors.js +15 -0
  12. package/dist/middleware/cors.js.map +1 -0
  13. package/dist/middleware/error.js +6 -0
  14. package/dist/middleware/error.js.map +1 -0
  15. package/dist/middleware/json.js +8 -0
  16. package/dist/middleware/json.js.map +1 -0
  17. package/dist/middleware/logger.js +26 -0
  18. package/dist/middleware/logger.js.map +1 -0
  19. package/dist/middleware/ratelimit.js +58 -0
  20. package/dist/middleware/ratelimit.js.map +1 -0
  21. package/dist/middleware/version.js +30 -0
  22. package/dist/middleware/version.js.map +1 -0
  23. package/dist/modules/v3/algorithms.js +221 -0
  24. package/dist/modules/v3/algorithms.js.map +1 -0
  25. package/{modules → dist/modules}/v3/captcha.js +4 -13
  26. package/dist/modules/v3/captcha.js.map +1 -0
  27. package/dist/modules/v3/chat.js +103 -0
  28. package/dist/modules/v3/chat.js.map +1 -0
  29. package/{modules → dist/modules}/v3/color.js +12 -13
  30. package/dist/modules/v3/color.js.map +1 -0
  31. package/dist/modules/v3/convert.js +41 -0
  32. package/dist/modules/v3/convert.js.map +1 -0
  33. package/dist/modules/v3/domain.js +83 -0
  34. package/dist/modules/v3/domain.js.map +1 -0
  35. package/dist/modules/v3/hash.js +16 -0
  36. package/dist/modules/v3/hash.js.map +1 -0
  37. package/dist/modules/v3/hyperplanning.js +50 -0
  38. package/dist/modules/v3/hyperplanning.js.map +1 -0
  39. package/dist/modules/v3/levenshtein.js +38 -0
  40. package/dist/modules/v3/levenshtein.js.map +1 -0
  41. package/dist/modules/v3/personal.js +129 -0
  42. package/dist/modules/v3/personal.js.map +1 -0
  43. package/dist/modules/v3/qrcode.js +21 -0
  44. package/dist/modules/v3/qrcode.js.map +1 -0
  45. package/dist/modules/v3/tic_tac_toe.js +221 -0
  46. package/dist/modules/v3/tic_tac_toe.js.map +1 -0
  47. package/dist/modules/v3/time.js +88 -0
  48. package/dist/modules/v3/time.js.map +1 -0
  49. package/{modules → dist/modules}/v3/token.js +10 -11
  50. package/dist/modules/v3/token.js.map +1 -0
  51. package/dist/modules/v3/username.js +92 -0
  52. package/dist/modules/v3/username.js.map +1 -0
  53. package/dist/modules/v3/utils.js +70 -0
  54. package/dist/modules/v3/utils.js.map +1 -0
  55. package/dist/modules/v3.js +16 -0
  56. package/dist/modules/v3.js.map +1 -0
  57. package/dist/modules/v4/algorithms.js +200 -0
  58. package/dist/modules/v4/algorithms.js.map +1 -0
  59. package/dist/modules/v4/captcha.js +35 -0
  60. package/dist/modules/v4/captcha.js.map +1 -0
  61. package/dist/modules/v4/chat.js +92 -0
  62. package/dist/modules/v4/chat.js.map +1 -0
  63. package/dist/modules/v4/color.js +43 -0
  64. package/dist/modules/v4/color.js.map +1 -0
  65. package/dist/modules/v4/convert.js +33 -0
  66. package/dist/modules/v4/convert.js.map +1 -0
  67. package/dist/modules/v4/dice.js +30 -0
  68. package/dist/modules/v4/dice.js.map +1 -0
  69. package/dist/modules/v4/domain.js +78 -0
  70. package/dist/modules/v4/domain.js.map +1 -0
  71. package/dist/modules/v4/encode.js +165 -0
  72. package/dist/modules/v4/encode.js.map +1 -0
  73. package/dist/modules/v4/geo.js +41 -0
  74. package/dist/modules/v4/geo.js.map +1 -0
  75. package/dist/modules/v4/hash.js +9 -0
  76. package/dist/modules/v4/hash.js.map +1 -0
  77. package/dist/modules/v4/hyperplanning.js +42 -0
  78. package/dist/modules/v4/hyperplanning.js.map +1 -0
  79. package/dist/modules/v4/levenshtein.js +29 -0
  80. package/dist/modules/v4/levenshtein.js.map +1 -0
  81. package/dist/modules/v4/palette.js +89 -0
  82. package/dist/modules/v4/palette.js.map +1 -0
  83. package/dist/modules/v4/personal.js +125 -0
  84. package/dist/modules/v4/personal.js.map +1 -0
  85. package/dist/modules/v4/placeholder.js +96 -0
  86. package/dist/modules/v4/placeholder.js.map +1 -0
  87. package/dist/modules/v4/qrcode.js +12 -0
  88. package/dist/modules/v4/qrcode.js.map +1 -0
  89. package/dist/modules/v4/statistics.js +41 -0
  90. package/dist/modules/v4/statistics.js.map +1 -0
  91. package/dist/modules/v4/text.js +293 -0
  92. package/dist/modules/v4/text.js.map +1 -0
  93. package/dist/modules/v4/tic_tac_toe.js +206 -0
  94. package/dist/modules/v4/tic_tac_toe.js.map +1 -0
  95. package/dist/modules/v4/time.js +73 -0
  96. package/dist/modules/v4/time.js.map +1 -0
  97. package/dist/modules/v4/token.js +36 -0
  98. package/dist/modules/v4/token.js.map +1 -0
  99. package/dist/modules/v4/username.js +87 -0
  100. package/dist/modules/v4/username.js.map +1 -0
  101. package/dist/modules/v4/utils.js +26 -0
  102. package/dist/modules/v4/utils.js.map +1 -0
  103. package/dist/modules/v4/validate.js +54 -0
  104. package/dist/modules/v4/validate.js.map +1 -0
  105. package/dist/modules/v4.js +18 -0
  106. package/dist/modules/v4.js.map +1 -0
  107. package/dist/routes/delete.js +65 -0
  108. package/dist/routes/delete.js.map +1 -0
  109. package/dist/routes/get.js +441 -0
  110. package/dist/routes/get.js.map +1 -0
  111. package/dist/routes/index.js +50 -0
  112. package/dist/routes/index.js.map +1 -0
  113. package/dist/routes/patch.js +41 -0
  114. package/dist/routes/patch.js.map +1 -0
  115. package/dist/routes/post.js +185 -0
  116. package/dist/routes/post.js.map +1 -0
  117. package/dist/storage/index.js +13 -0
  118. package/dist/storage/index.js.map +1 -0
  119. package/dist/types/storage.js +2 -0
  120. package/dist/types/storage.js.map +1 -0
  121. package/dist/utils/response.js +10 -0
  122. package/dist/utils/response.js.map +1 -0
  123. package/dist/utils/version.js +3 -0
  124. package/dist/utils/version.js.map +1 -0
  125. package/eslint.config.js +20 -0
  126. package/package.json +30 -15
  127. package/src/app.ts +44 -0
  128. package/src/config/env.ts +81 -0
  129. package/src/config/versions.ts +80 -0
  130. package/src/constants.ts +28 -0
  131. package/src/middleware/cors.ts +17 -0
  132. package/src/middleware/error.ts +7 -0
  133. package/src/middleware/json.ts +9 -0
  134. package/src/middleware/logger.ts +31 -0
  135. package/src/middleware/ratelimit.ts +66 -0
  136. package/src/middleware/version.ts +39 -0
  137. package/{modules → src/modules}/v3/algorithms.js +1 -1
  138. package/src/modules/v3/captcha.js +60 -0
  139. package/{modules → src/modules}/v3/chat.js +6 -4
  140. package/src/modules/v3/color.js +60 -0
  141. package/{modules → src/modules}/v3/convert.js +5 -5
  142. package/{modules → src/modules}/v3/domain.js +51 -4
  143. package/{modules → src/modules}/v3/hash.js +1 -1
  144. package/{modules → src/modules}/v3/hyperplanning.js +11 -10
  145. package/{modules → src/modules}/v3/levenshtein.js +3 -3
  146. package/{modules → src/modules}/v3/personal.js +20 -8
  147. package/{modules → src/modules}/v3/qrcode.js +1 -1
  148. package/{modules → src/modules}/v3/tic_tac_toe.js +24 -18
  149. package/{modules → src/modules}/v3/time.js +22 -11
  150. package/src/modules/v3/token.js +54 -0
  151. package/src/modules/v3/username.js +94 -0
  152. package/{modules → src/modules}/v3/utils.js +2 -2
  153. package/{modules → src/modules}/v3.js +1 -1
  154. package/src/modules/v4/algorithms.ts +155 -0
  155. package/src/modules/v4/captcha.ts +49 -0
  156. package/src/modules/v4/chat.ts +99 -0
  157. package/src/modules/v4/color.ts +64 -0
  158. package/src/modules/v4/convert.ts +38 -0
  159. package/src/modules/v4/domain.ts +81 -0
  160. package/src/modules/v4/hash.ts +9 -0
  161. package/src/modules/v4/hyperplanning.ts +58 -0
  162. package/src/modules/v4/levenshtein.ts +38 -0
  163. package/src/modules/v4/personal.ts +147 -0
  164. package/src/modules/v4/qrcode.ts +11 -0
  165. package/src/modules/v4/tic_tac_toe.ts +223 -0
  166. package/src/modules/v4/time.ts +92 -0
  167. package/src/modules/v4/token.ts +43 -0
  168. package/src/modules/v4/username.ts +89 -0
  169. package/src/modules/v4/utils.ts +38 -0
  170. package/src/modules/v4.ts +15 -0
  171. package/src/routes/get.ts +461 -0
  172. package/src/routes/index.ts +58 -0
  173. package/src/routes/post.ts +200 -0
  174. package/src/storage/index.ts +16 -0
  175. package/src/types/express.d.ts +17 -0
  176. package/src/types/storage.ts +48 -0
  177. package/src/utils/response.ts +11 -0
  178. package/tsconfig.json +17 -0
  179. package/app.js +0 -865
  180. package/modules/v3/username.js +0 -32
@@ -0,0 +1,66 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import { env } from '../config/env.js';
3
+ import { ipLimits } from '../storage/index.js';
4
+ import { SESSION_TTL } from '../constants.js';
5
+ import { error } from '../utils/response.js';
6
+
7
+ let requests = 0;
8
+ let resetTime = Date.now() + SESSION_TTL;
9
+
10
+ export function rateLimitMiddleware(req: Request, res: Response, next: NextFunction): void {
11
+ const ip = (req.headers['cf-connecting-ip'] as string) || req.socket.remoteAddress || '';
12
+ const token = req.headers.authorization?.split(' ')[1] || '';
13
+
14
+ const now = Date.now();
15
+ const minute = String(Math.floor(now / 60000) % 60);
16
+ const hour = String(Math.floor(now / 3600000) % 24);
17
+
18
+ if (
19
+ (token && ![...env.BUSINESS_TOKEN_LIST, ...env.PRO_TOKEN_LIST, ...env.ADVANCED_TOKEN_LIST].includes(token)) ||
20
+ token === 'undefined'
21
+ ) {
22
+ error(res, 401, 'Invalid token.');
23
+ return;
24
+ }
25
+
26
+ let requestLimit: number;
27
+ if (env.BUSINESS_TOKEN_LIST.includes(token) && !env.BUSINESS_TOKEN_LIST.includes('undefined')) {
28
+ requestLimit = env.BUSINESS_LIMIT;
29
+ } else if (env.PRO_TOKEN_LIST.includes(token) && !env.PRO_TOKEN_LIST.includes('undefined')) {
30
+ requestLimit = env.PRO_LIMIT;
31
+ } else if (env.ADVANCED_TOKEN_LIST.includes(token) && !env.ADVANCED_TOKEN_LIST.includes('undefined')) {
32
+ requestLimit = env.ADVANCED_LIMIT;
33
+ } else {
34
+ requestLimit = env.DEFAULT_LIMIT;
35
+ }
36
+
37
+ if (now > resetTime) {
38
+ requests = 0;
39
+ resetTime = now + SESSION_TTL;
40
+ }
41
+
42
+ if (++requests > Math.max(env.GLOBAL_LIMIT, requestLimit)) {
43
+ error(res, 429, 'Global rate limit exceeded.');
44
+ return;
45
+ }
46
+
47
+ if (['__proto__', 'constructor', 'prototype'].includes(ip)) {
48
+ error(res, 400, 'Invalid IP address.');
49
+ return;
50
+ }
51
+
52
+ if (!ipLimits[ip]) ipLimits[ip] = {};
53
+ if (!ipLimits[ip]![hour]) ipLimits[ip]![hour] = {};
54
+ ipLimits[ip]![hour]![minute] = (ipLimits[ip]![hour]![minute] ?? 0) + 1;
55
+
56
+ if (ipLimits[ip]![hour]![minute]! > requestLimit) {
57
+ error(res, 429, `You have exceeded the limit of ${requestLimit} requests per hour.`);
58
+ return;
59
+ }
60
+
61
+ Object.keys(ipLimits[ip]!).forEach((h) => {
62
+ if (h != hour) delete ipLimits[ip]![h];
63
+ });
64
+
65
+ next();
66
+ }
@@ -0,0 +1,39 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import { versions } from '../config/versions.js';
3
+ import { error } from '../utils/response.js';
4
+
5
+ export function versionCheckMiddleware(req: Request, res: Response, next: NextFunction): void {
6
+ const version = req.params.version as string;
7
+ const latest = Object.keys(versions).pop()!;
8
+
9
+ req.version = version;
10
+ req.latest = latest;
11
+
12
+ if (!versions[version]) {
13
+ error(res, 404, `Invalid API version (${version}).`, latest);
14
+ return;
15
+ }
16
+
17
+ req.module = versions[version]!.modules;
18
+
19
+ if (!req.module) {
20
+ error(res, 404, `Module not found for version ${version}.`, latest);
21
+ return;
22
+ }
23
+
24
+ next();
25
+ }
26
+
27
+ export function endpointCheckMiddleware(req: Request, res: Response, next: NextFunction): void {
28
+ const version = req.params.version as string;
29
+ const endpoint = req.params.endpoint as string;
30
+
31
+ req.version = version;
32
+ req.endpoint = endpoint;
33
+
34
+ if (!endpoint) {
35
+ error(res, 404, `Endpoint '${endpoint}' does not exist in ${req.version}.`);
36
+ return;
37
+ }
38
+ next();
39
+ }
@@ -215,4 +215,4 @@ export function reverse(value) {
215
215
  if (typeof value !== 'string') throw new Error('Value must be a string');
216
216
 
217
217
  return value.split('').reverse().join('');
218
- }
218
+ }
@@ -0,0 +1,60 @@
1
+ import { createCanvas } from 'canvas';
2
+
3
+ /**
4
+ * Generate a captcha image from the provided text
5
+ *
6
+ * @param {string} text - Text to render in the captcha image
7
+ * @returns {Buffer} - PNG image buffer of the rendered captcha
8
+ * @throws {Error} - If text is not provided
9
+ */
10
+ export default function captcha(text) {
11
+ if (!text) throw new Error('Text is required to generate a captcha.');
12
+
13
+ const size = 60,
14
+ font = '60px Comic Sans Ms',
15
+ width = text.length * size,
16
+ height = 120;
17
+ const canvas = createCanvas(width, height),
18
+ ctx = canvas.getContext('2d');
19
+
20
+ // Set white background
21
+ ctx.fillStyle = 'white';
22
+ ctx.fillRect(0, 0, width, height);
23
+
24
+ // Add random lines for noise
25
+ for (let i = 0; i < 20; i++) {
26
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
27
+ ctx.beginPath();
28
+ ctx.moveTo(Math.random() * width, Math.random() * height);
29
+ ctx.lineTo(Math.random() * width, Math.random() * height);
30
+ ctx.lineWidth = Math.random() * 2;
31
+ ctx.stroke();
32
+ }
33
+
34
+ let x = (canvas.width + 20 - width) / 2;
35
+
36
+ // Draw each character with random rotation and color
37
+ for (let i = 0; i < text.length; i++) {
38
+ const offsetX = Math.cos(i * 0.3) * 10,
39
+ y = height / 2.5 + Math.floor(Math.random() * (height / 2));
40
+
41
+ ctx.font = font;
42
+ ctx.fillStyle = `rgb(${Math.floor(Math.random() * 192)}, ${Math.floor(Math.random() * 192)}, ${Math.floor(Math.random() * 192)})`;
43
+
44
+ ctx.save();
45
+ ctx.translate(x + size / 2, y);
46
+ ctx.rotate((Math.random() - 0.5) * 0.5);
47
+ ctx.fillText(text[i], -size / 2 + offsetX, 0);
48
+ ctx.restore();
49
+
50
+ x += size;
51
+ }
52
+
53
+ // Add noise dots
54
+ for (let i = 0; i < 200; i++) {
55
+ ctx.fillStyle = 'black';
56
+ ctx.fillRect(Math.floor(Math.random() * width), Math.floor(Math.random() * height), 1.2, 1.2);
57
+ }
58
+
59
+ return canvas.toBuffer('image/png');
60
+ }
@@ -1,4 +1,4 @@
1
- import { checkRateLimit } from "./utils.js";
1
+ import { checkRateLimit } from './utils.js';
2
2
 
3
3
  /**
4
4
  * Manages a chat system with public and private messages
@@ -61,14 +61,16 @@ function sendMessage(params, messages, privateChats, sessions, u, now) {
61
61
  const msg = {
62
62
  username: params.username,
63
63
  message,
64
- timestamp: params.timestamp || new Date().toISOString()
64
+ timestamp: params.timestamp || new Date().toISOString(),
65
65
  };
66
66
 
67
67
  // Store message based on whether it's private or public
68
68
  if (token) {
69
69
  privateChats[token] = privateChats[token] || [];
70
70
  privateChats[token].push(msg);
71
- setTimeout(() => { delete privateChats[token]; }, 3600000);
71
+ setTimeout(() => {
72
+ delete privateChats[token];
73
+ }, 3600000);
72
74
  } else {
73
75
  messages.push(msg);
74
76
  setTimeout(() => messages.splice(messages.indexOf(msg), 1), 3600000);
@@ -106,4 +108,4 @@ function getPrivateChat(params, privateChats) {
106
108
  function fetchMessages(messages) {
107
109
  if (messages.length > 0) return messages;
108
110
  throw new Error('No messages stored.');
109
- }
111
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Generate a random color in multiple formats
3
+ *
4
+ * @returns {Object} Color in various formats (hex, rgb, hsl, hsv, hwb, cmyk)
5
+ */
6
+ export default function color() {
7
+ const r = Math.floor(Math.random() * 256),
8
+ g = Math.floor(Math.random() * 256),
9
+ b = Math.floor(Math.random() * 256);
10
+
11
+ const hsl = (() => {
12
+ const r1 = r / 255,
13
+ g1 = g / 255,
14
+ b1 = b / 255,
15
+ max = Math.max(r1, g1, b1),
16
+ min = Math.min(r1, g1, b1),
17
+ l = (max + min) / 2;
18
+ if (max === min) return [0, 0, l * 100];
19
+ const d = max - min,
20
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
21
+ let h = { [r1]: (g1 - b1) / d + (g1 < b1 ? 6 : 0), [g1]: (b1 - r1) / d + 2, [b1]: (r1 - g1) / d + 4 }[max];
22
+ return [(h * 60) % 360, s * 100, l * 100];
23
+ })();
24
+
25
+ const hsv = (() => {
26
+ const max = Math.max(r, g, b),
27
+ min = Math.min(r, g, b),
28
+ v = max / 255,
29
+ s = max ? (max - min) / max : 0;
30
+ let h =
31
+ max === min
32
+ ? 0
33
+ : { [r]: (g - b) / (max - min), [g]: 2 + (b - r) / (max - min), [b]: 4 + (r - g) / (max - min) }[max];
34
+ return [(h * 60) % 360, s * 100, v * 100];
35
+ })();
36
+
37
+ const hwb = (() => {
38
+ const [h] = hsv,
39
+ whiteness = Math.min(r, g, b) / 255,
40
+ blackness = 1 - Math.max(r, g, b) / 255;
41
+ return [h, whiteness * 100, blackness * 100];
42
+ })();
43
+
44
+ const cmyk = (() => {
45
+ const k = 1 - Math.max(r, g, b) / 255,
46
+ c = (1 - r / 255 - k) / (1 - k) || 0,
47
+ m = (1 - g / 255 - k) / (1 - k) || 0,
48
+ y = (1 - b / 255 - k) / (1 - k) || 0;
49
+ return [c, m, y, k].map((x) => x * 100);
50
+ })();
51
+
52
+ return {
53
+ hex: `#${[r, g, b].map((x) => x.toString(16).padStart(2, '0')).join('')}`,
54
+ rgb: `rgb(${r}, ${g}, ${b})`,
55
+ hsl: `hsl(${hsl[0].toFixed(1)}, ${hsl[1].toFixed(1)}%, ${hsl[2].toFixed(1)}%)`,
56
+ hsv: `hsv(${hsv[0].toFixed(1)}, ${hsv[1].toFixed(1)}%, ${hsv[2].toFixed(1)}%)`,
57
+ hwb: `hwb(${hwb[0].toFixed(1)}, ${hwb[1].toFixed(1)}%, ${hwb[2].toFixed(1)}%)`,
58
+ cmyk: `cmyk(${cmyk.map((x) => x.toFixed(1)).join('%, ')}%)`,
59
+ };
60
+ }
@@ -11,15 +11,15 @@ export default function convert(value, from, to) {
11
11
  const conversions = {
12
12
  celsius: {
13
13
  fahrenheit: (val) => (val * 9) / 5 + 32,
14
- kelvin: (val) => val + 273.15
14
+ kelvin: (val) => val + 273.15,
15
15
  },
16
16
  fahrenheit: {
17
17
  celsius: (val) => ((val - 32) * 5) / 9,
18
- kelvin: (val) => ((val - 32) * 5) / 9 + 273.15
18
+ kelvin: (val) => ((val - 32) * 5) / 9 + 273.15,
19
19
  },
20
20
  kelvin: {
21
21
  celsius: (val) => val - 273.15,
22
- fahrenheit: (val) => ((val - 273.15) * 9) / 5 + 32
22
+ fahrenheit: (val) => ((val - 273.15) * 9) / 5 + 32,
23
23
  },
24
24
  };
25
25
 
@@ -34,6 +34,6 @@ export default function convert(value, from, to) {
34
34
  from,
35
35
  to,
36
36
  value: parseFloat(value),
37
- result: convert(parseFloat(value))
37
+ result: convert(parseFloat(value)),
38
38
  };
39
- }
39
+ }
@@ -6,9 +6,56 @@ import { random, genIP } from './utils.js';
6
6
  * @returns {Object} Domain details including DNS, hosting, and SEO metrics
7
7
  */
8
8
  export default function domain() {
9
- const subdomains = ['fr.', 'en.', 'docs.', 'api.', 'projects.', 'app.', 'web.', 'info.', 'dev.', 'shop.', 'blog.', 'support.', 'mail.', 'forum.'];
10
- const domains = ['example', 'site', 'test', 'demo', 'page', 'store', 'portfolio', 'platform', 'hub', 'network', 'service', 'cloud', 'solutions', 'company'];
11
- const tlds = ['.com', '.fr', '.eu', '.dev', '.net', '.org', '.io', '.tech', '.biz', '.info', '.co', '.app', '.store', '.online', '.shop', '.tv'];
9
+ const subdomains = [
10
+ 'fr.',
11
+ 'en.',
12
+ 'docs.',
13
+ 'api.',
14
+ 'projects.',
15
+ 'app.',
16
+ 'web.',
17
+ 'info.',
18
+ 'dev.',
19
+ 'shop.',
20
+ 'blog.',
21
+ 'support.',
22
+ 'mail.',
23
+ 'forum.',
24
+ ];
25
+ const domains = [
26
+ 'example',
27
+ 'site',
28
+ 'test',
29
+ 'demo',
30
+ 'page',
31
+ 'store',
32
+ 'portfolio',
33
+ 'platform',
34
+ 'hub',
35
+ 'network',
36
+ 'service',
37
+ 'cloud',
38
+ 'solutions',
39
+ 'company',
40
+ ];
41
+ const tlds = [
42
+ '.com',
43
+ '.fr',
44
+ '.eu',
45
+ '.dev',
46
+ '.net',
47
+ '.org',
48
+ '.io',
49
+ '.tech',
50
+ '.biz',
51
+ '.info',
52
+ '.co',
53
+ '.app',
54
+ '.store',
55
+ '.online',
56
+ '.shop',
57
+ '.tv',
58
+ ];
12
59
 
13
60
  const domain = `${random(domains)}${random(tlds)}`;
14
61
  const fulldomain = `${random(subdomains)}${domain}`;
@@ -36,4 +83,4 @@ export default function domain() {
36
83
  creation_date: new Date(Date.now() - Math.floor(Math.random() * 10000000000)).toISOString(),
37
84
  expiration_date: new Date(Date.now() + Math.floor(Math.random() * 10000000000)).toISOString(),
38
85
  };
39
- }
86
+ }
@@ -13,4 +13,4 @@ export default function hash(text, method) {
13
13
 
14
14
  const hash = createHash(method).update(text).digest('hex');
15
15
  return { method, hash };
16
- }
16
+ }
@@ -1,6 +1,5 @@
1
1
  import { formatDate } from './utils.js';
2
2
  import ical from 'ical.js';
3
- import fetch from 'node-fetch';
4
3
 
5
4
  /**
6
5
  * Parse an ICS calendar file and extract event information
@@ -19,24 +18,26 @@ export default async function hyperplanning(url, detail) {
19
18
 
20
19
  const events = new ical.Component(ical.parse(await response.text()))
21
20
  .getAllSubcomponents('vevent')
22
- .map(e => {
21
+ .map((e) => {
23
22
  const evt = new ical.Event(e);
24
- const summary = (evt.summary || '').split(' ').filter(part => part !== '-');
23
+ const summary = (evt.summary || '').split(' ').filter((part) => part !== '-');
25
24
  const start = formatDate(evt.startDate.toJSDate());
26
25
  const end = formatDate(evt.endDate.toJSDate());
27
26
 
28
27
  if (detail === 'full') {
29
- const desc = (evt.description || '').split('\n').map(l => l.trim());
30
- const extract = (p) => (desc.find(l => l.startsWith(p)) || '').replace(p, '').trim();
28
+ const desc = (evt.description || '').split('\n').map((l) => l.trim());
29
+ const extract = (p) => (desc.find((l) => l.startsWith(p)) || '').replace(p, '').trim();
31
30
 
32
31
  return {
33
32
  summary,
34
33
  subject: extract('Matière :'),
35
34
  teacher: extract('Enseignant :'),
36
- classes: extract('Promotions :').split(', ').map(c => c.trim()),
35
+ classes: extract('Promotions :')
36
+ .split(', ')
37
+ .map((c) => c.trim()),
37
38
  type: extract('Salle :') || undefined,
38
39
  start,
39
- end
40
+ end,
40
41
  };
41
42
  }
42
43
 
@@ -45,11 +46,11 @@ export default async function hyperplanning(url, detail) {
45
46
  return {
46
47
  summary: evt.summary || '',
47
48
  start,
48
- end
49
+ end,
49
50
  };
50
51
  })
51
52
  .sort((a, b) => new Date(a.start) - new Date(b.start))
52
- .filter(e => new Date(e.end) >= new Date());
53
+ .filter((e) => new Date(e.end) >= new Date());
53
54
 
54
55
  return events;
55
- }
56
+ }
@@ -33,7 +33,7 @@ export default function levenshtein(str1, str2) {
33
33
  m[i][j] = Math.min(
34
34
  m[i - 1][j] + 1,
35
35
  m[i][j - 1] + 1,
36
- m[i - 1][j - 1] + (str1[i - 1] !== str2[j - 1] ? 1 : 0)
36
+ m[i - 1][j - 1] + (str1[i - 1] !== str2[j - 1] ? 1 : 0),
37
37
  );
38
38
  }
39
39
  }
@@ -41,6 +41,6 @@ export default function levenshtein(str1, str2) {
41
41
  return {
42
42
  str1,
43
43
  str2,
44
- distance: m[str1.length][str2.length]
44
+ distance: m[str1.length][str2.length],
45
45
  };
46
- }
46
+ }
@@ -16,7 +16,7 @@ export default function personal() {
16
16
  { name: 'Daniel Brown', social: 'daniel_brown', email: 'daniel@example.com', country: 'JP' },
17
17
  { name: 'Sophia Wilson', social: 'sophia_wilson', email: 'sophia@example.com', country: 'BR' },
18
18
  { name: 'James Taylor', social: 'james_taylor', email: 'james@example.com', country: 'CA' },
19
- { name: 'Olivia Thomas', social: 'olivia_thomas', email: 'olivia@example.com', country: 'AU' }
19
+ { name: 'Olivia Thomas', social: 'olivia_thomas', email: 'olivia@example.com', country: 'AU' },
20
20
  ];
21
21
 
22
22
  const countries = {
@@ -29,12 +29,24 @@ export default function personal() {
29
29
  JP: { tel: '080-1234-5678', code: '81', lang: 'Japanese' },
30
30
  BR: { tel: '(11) 98765-4321', code: '55', lang: 'Portuguese' },
31
31
  CA: { tel: '416-123-4567', code: '1', lang: 'English' },
32
- AU: { tel: '0412 345 678', code: '61', lang: 'English' }
32
+ AU: { tel: '0412 345 678', code: '61', lang: 'English' },
33
33
  };
34
34
 
35
35
  const jobs = ['Writer', 'Artist', 'Musician', 'Explorer', 'Scientist', 'Engineer', 'Athlete', 'Doctor'];
36
36
  const hobbies = ['Reading', 'Traveling', 'Gaming', 'Cooking', 'Fitness', 'Music', 'Photography', 'Writing'];
37
- const cities = ['New York', 'Paris', 'London', 'Madrid', 'Berlin', 'Rome', 'Tokyo', 'Los Angeles', 'Sydney', 'São Paulo', 'Toronto'];
37
+ const cities = [
38
+ 'New York',
39
+ 'Paris',
40
+ 'London',
41
+ 'Madrid',
42
+ 'Berlin',
43
+ 'Rome',
44
+ 'Tokyo',
45
+ 'Los Angeles',
46
+ 'Sydney',
47
+ 'São Paulo',
48
+ 'Toronto',
49
+ ];
38
50
  const streets = ['Main St', '2nd Ave', 'Broadway', 'Park Lane', 'Elm St', 'Sunset Blvd', 'Maple St', 'Highland Rd'];
39
51
 
40
52
  const card = Array.from({ length: 4 }, () => randomNumber(1000, 9999)).join(' ');
@@ -66,7 +78,7 @@ export default function personal() {
66
78
  let emergencyContact = random(people);
67
79
  while (
68
80
  emergencyContact.email === person.email ||
69
- emergencyContacts.some(e => e.email === emergencyContact.email)
81
+ emergencyContacts.some((e) => e.email === emergencyContact.email)
70
82
  ) {
71
83
  emergencyContact = random(people);
72
84
  }
@@ -74,7 +86,7 @@ export default function personal() {
74
86
  emergencyContacts.push({
75
87
  name: emergencyContact.name,
76
88
  relationship: random(['Spouse', 'Parent', 'Sibling', 'Friend']),
77
- phone: `+${countries[country].code} ${emergencyPhone}`
89
+ phone: `+${countries[country].code} ${emergencyPhone}`,
78
90
  });
79
91
  }
80
92
 
@@ -113,15 +125,15 @@ export default function personal() {
113
125
  twitter: `@${social}`,
114
126
  facebook: `facebook.com/${social}`,
115
127
  linkedin: `linkedin.com/in/${social}`,
116
- instagram: `instagram.com/${social}`
128
+ instagram: `instagram.com/${social}`,
117
129
  },
118
130
  year_income: `${yearIncome} USD/year`,
119
131
  month_income: `${(yearIncome / 12).toFixed(2)} USD/month`,
120
- education: random(['High School', 'Bachelor\'s', 'Master\'s', 'PhD']),
132
+ education: random(['High School', "Bachelor's", "Master's", 'PhD']),
121
133
  work_experience: `${randomNumber(0, 20)} years`,
122
134
  health_status: random(['Healthy', 'Minor Issues', 'Chronic Conditions']),
123
135
  emergency_contacts: emergencyContacts,
124
136
  subscriptions,
125
137
  pets,
126
138
  };
127
- }
139
+ }
@@ -17,4 +17,4 @@ export default async function qrcode(url) {
17
17
  } catch (error) {
18
18
  throw new Error(`Failed to generate QR code: ${error.message}`);
19
19
  }
20
- }
20
+ }
@@ -30,7 +30,7 @@ export default function tic_tac_toe(action, params = {}) {
30
30
  const now = Date.now();
31
31
 
32
32
  // Rate limiting
33
- rateLimits[u] = (rateLimits[u] || []).filter(ts => now - ts < 10000);
33
+ rateLimits[u] = (rateLimits[u] || []).filter((ts) => now - ts < 10000);
34
34
  if (rateLimits[u].length > 50) {
35
35
  const remainingTime = Math.ceil((rateLimits[u][0] + 10000 - now) / 1000);
36
36
  throw new Error(`Rate limit exceeded. Try again in ${remainingTime} seconds.`);
@@ -70,12 +70,12 @@ function playMove(params, games, sessions, u, now) {
70
70
  moves: [],
71
71
  players: [],
72
72
  private: params.private || false,
73
- creation: Date.now()
73
+ creation: Date.now(),
74
74
  };
75
75
  const moves = games[game].moves;
76
76
 
77
77
  // Check if game is full
78
- const players = [...new Set(moves.map(play => play.username))];
78
+ const players = [...new Set(moves.map((play) => play.username))];
79
79
  if (players.length >= 2 && !players.includes(params.username)) {
80
80
  throw new Error('Game is full, you can only watch.');
81
81
  }
@@ -86,7 +86,7 @@ function playMove(params, games, sessions, u, now) {
86
86
  }
87
87
 
88
88
  // Check if move is already made
89
- if (moves.some(play => play.move === move)) {
89
+ if (moves.some((play) => play.move === move)) {
90
90
  throw new Error('Move already made. Please choose a different move.');
91
91
  }
92
92
 
@@ -99,8 +99,8 @@ function playMove(params, games, sessions, u, now) {
99
99
  if (result.winner || result.tie) {
100
100
  setTimeout(() => delete games[game], 600000);
101
101
  return {
102
- message: `Move sent successfully. ${result.winner ? result.winner + ' wins. ' + result.loser + ' loses.' : 'It\'s a tie.'}`,
103
- ...result
102
+ message: `Move sent successfully. ${result.winner ? result.winner + ' wins. ' + result.loser + ' loses.' : "It's a tie."}`,
103
+ ...result,
104
104
  };
105
105
  }
106
106
 
@@ -110,7 +110,9 @@ function playMove(params, games, sessions, u, now) {
110
110
  // Update session
111
111
  sessions[u] = sessions[u] || { user: session, last: now };
112
112
  sessions[u].last = now;
113
- setTimeout(() => { if (now - sessions[u].last >= 3600000) delete sessions[u]; }, 3600000);
113
+ setTimeout(() => {
114
+ if (now - sessions[u].last >= 3600000) delete sessions[u];
115
+ }, 3600000);
114
116
 
115
117
  return { message: 'Move sent successfully' };
116
118
  }
@@ -125,7 +127,7 @@ function fetchGame(params, games, u) {
125
127
  moves: [],
126
128
  players: [],
127
129
  private: params.private || false,
128
- creation: Date.now()
130
+ creation: Date.now(),
129
131
  };
130
132
  }
131
133
  if (!games[id].players.includes(u)) {
@@ -136,7 +138,7 @@ function fetchGame(params, games, u) {
136
138
  const players = games[id].players;
137
139
  const privateGame = games[id].private;
138
140
  const lastPlayer = moves.length ? moves[moves.length - 1].username : null;
139
- const turn = players.find(p => p !== lastPlayer) || players[0];
141
+ const turn = players.find((p) => p !== lastPlayer) || players[0];
140
142
  const status = players.length >= 2 ? 'ready' : 'waiting';
141
143
  const result = moves.length ? checkGame(moves) : {};
142
144
 
@@ -147,7 +149,7 @@ function fetchGame(params, games, u) {
147
149
  turn,
148
150
  status,
149
151
  private: privateGame,
150
- ...result
152
+ ...result,
151
153
  };
152
154
  }
153
155
 
@@ -167,7 +169,7 @@ function listGames(games) {
167
169
  // Only include active games (not finished)
168
170
  if (!isFinished) {
169
171
  const lastPlayer = game.moves.length ? game.moves[game.moves.length - 1].username : null;
170
- const turn = game.players.find(p => p !== lastPlayer) || game.players[0];
172
+ const turn = game.players.find((p) => p !== lastPlayer) || game.players[0];
171
173
  const status = game.players.length >= 2 ? 'ready' : 'waiting';
172
174
 
173
175
  publicGames.push({
@@ -177,7 +179,7 @@ function listGames(games) {
177
179
  moves: game.moves.length,
178
180
  turn,
179
181
  status,
180
- creation: game.creation || now
182
+ creation: game.creation || now,
181
183
  });
182
184
  }
183
185
  }
@@ -189,7 +191,7 @@ function listGames(games) {
189
191
  return {
190
192
  message: 'Public games available',
191
193
  count: publicGames.length,
192
- games: publicGames
194
+ games: publicGames,
193
195
  };
194
196
  }
195
197
 
@@ -198,14 +200,18 @@ function listGames(games) {
198
200
  */
199
201
  function generateGameId() {
200
202
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
201
- return Array.from(randomBytes(5)).map(b => chars[b % chars.length]).join('');
203
+ return Array.from(randomBytes(5))
204
+ .map((b) => chars[b % chars.length])
205
+ .join('');
202
206
  }
203
207
 
204
208
  /**
205
209
  * Check the game result
206
210
  */
207
211
  function checkGame(moves) {
208
- let board = Array(3).fill().map(() => Array(3).fill(null));
212
+ let board = Array(3)
213
+ .fill()
214
+ .map(() => Array(3).fill(null));
209
215
  let playerSymbols = {};
210
216
  let playersOrder = [];
211
217
 
@@ -228,9 +234,9 @@ function checkGame(moves) {
228
234
  return false;
229
235
  };
230
236
 
231
- let winner = Object.keys(playerSymbols).find(player => checkWinner(playerSymbols[player]));
237
+ let winner = Object.keys(playerSymbols).find((player) => checkWinner(playerSymbols[player]));
232
238
  let isTie = !winner && moves.length === 9;
233
- let loser = winner && playersOrder.length === 2 ? playersOrder.find(player => player !== winner) : null;
239
+ let loser = winner && playersOrder.length === 2 ? playersOrder.find((player) => player !== winner) : null;
234
240
 
235
241
  return { winner, loser, tie: isTie };
236
- }
242
+ }