@20syldev/api 3.4.9 → 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
@@ -11,16 +11,27 @@
11
11
  */
12
12
  export default function time(type = 'live', start, end, format, timezone) {
13
13
  const validFormats = [
14
- 'iso', 'utc', 'timestamp', 'locale', 'date', 'time',
15
- 'year', 'month', 'day', 'hour', 'minute', 'second',
16
- 'ms', 'dayOfWeek', 'dayOfYear', 'weekNumber',
17
- 'timezone', 'timezoneOffset'
14
+ 'iso',
15
+ 'utc',
16
+ 'timestamp',
17
+ 'locale',
18
+ 'date',
19
+ 'time',
20
+ 'year',
21
+ 'month',
22
+ 'day',
23
+ 'hour',
24
+ 'minute',
25
+ 'second',
26
+ 'ms',
27
+ 'dayOfWeek',
28
+ 'dayOfYear',
29
+ 'weekNumber',
30
+ 'timezone',
31
+ 'timezoneOffset',
18
32
  ];
19
33
 
20
- const validTimezones = [
21
- 'UTC', 'America/New_York', 'Europe/Paris',
22
- 'Asia/Tokyo', 'Australia/Sydney'
23
- ];
34
+ const validTimezones = ['UTC', 'America/New_York', 'Europe/Paris', 'Asia/Tokyo', 'Australia/Sydney'];
24
35
 
25
36
  // Input validation
26
37
  if (type !== 'live' && type !== 'random') {
@@ -61,9 +72,9 @@ export default function time(type = 'live', start, end, format, timezone) {
61
72
  ms: date.getMilliseconds(),
62
73
  dayOfWeek: date.getDay(),
63
74
  dayOfYear: Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 86400000),
64
- weekNumber: Math.ceil((((date - new Date(date.getFullYear(), 0, 0)) / 86400000) + 1) / 7),
75
+ weekNumber: Math.ceil(((date - new Date(date.getFullYear(), 0, 0)) / 86400000 + 1) / 7),
65
76
  timezone: tz,
66
- timezoneOffset: date.getTimezoneOffset()
77
+ timezoneOffset: date.getTimezoneOffset(),
67
78
  };
68
79
  };
69
80
 
@@ -84,4 +95,4 @@ export default function time(type = 'live', start, end, format, timezone) {
84
95
  const formats = getTimeFormats(now, tz);
85
96
 
86
97
  return format ? { date: formats[format] } : formats;
87
- }
98
+ }
@@ -0,0 +1,54 @@
1
+ import { randomBytes } from 'crypto';
2
+ import { v4 } from 'uuid';
3
+
4
+ /**
5
+ * Generate a random token of specified length and type.
6
+ *
7
+ * @param {number} len - Length of the token
8
+ * @param {string} type - Type of token to generate
9
+ * @returns {string} - The generated token
10
+ * @throws {Error} - If inputs are invalid
11
+ */
12
+ export default function token(len, type = 'alphanum') {
13
+ // Input validation
14
+ if (isNaN(len) || len < 12) {
15
+ throw new Error('Length must be a number greater than or equal to 12');
16
+ }
17
+
18
+ if (len > 4096) {
19
+ throw new Error('Length cannot exceed 4096');
20
+ }
21
+
22
+ // Helper function to generate token from character set
23
+ const genToken = (chars, length) => {
24
+ return Array.from({ length }, () => {
25
+ return chars[Math.floor(Math.random() * chars.length)];
26
+ }).join('');
27
+ };
28
+
29
+ // Token type definitions
30
+ const tokenTypes = {
31
+ alpha: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', len),
32
+ alphanum: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len),
33
+ base64: () =>
34
+ randomBytes(Math.ceil(len * 0.75))
35
+ .toString('base64')
36
+ .slice(0, len),
37
+ hex: () =>
38
+ randomBytes(Math.ceil(len * 0.5))
39
+ .toString('hex')
40
+ .slice(0, len),
41
+ num: () => genToken('0123456789', len),
42
+ punct: () => genToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', len),
43
+ urlsafe: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_', len),
44
+ uuid: () => v4().replace(/-/g, '').slice(0, len),
45
+ };
46
+
47
+ // Generate token based on type or default to alphanum
48
+ if (!tokenTypes[type.toLowerCase()]) {
49
+ throw new Error(`Invalid token type. Valid types: ${Object.keys(tokenTypes).join(', ')}`);
50
+ }
51
+
52
+ // Generate token based on type or default to alphanum
53
+ return (tokenTypes[type.toLowerCase()] || tokenTypes.alphanum)();
54
+ }
@@ -0,0 +1,94 @@
1
+ import { random, randomNumber } from './utils.js';
2
+
3
+ /**
4
+ * Generate a random username with related information
5
+ *
6
+ * @returns {Object} Object containing username and component parts
7
+ */
8
+ export default function username() {
9
+ const adj = [
10
+ 'Happy',
11
+ 'Silly',
12
+ 'Clever',
13
+ 'Creative',
14
+ 'Brave',
15
+ 'Gentle',
16
+ 'Kind',
17
+ 'Funny',
18
+ 'Wise',
19
+ 'Charming',
20
+ 'Sincere',
21
+ 'Resourceful',
22
+ 'Patient',
23
+ 'Energetic',
24
+ 'Adventurous',
25
+ 'Ambitious',
26
+ 'Courageous',
27
+ 'Courteous',
28
+ 'Determined',
29
+ ];
30
+ const ani = [
31
+ 'Cat',
32
+ 'Dog',
33
+ 'Tiger',
34
+ 'Elephant',
35
+ 'Monkey',
36
+ 'Penguin',
37
+ 'Dolphin',
38
+ 'Lion',
39
+ 'Bear',
40
+ 'Fox',
41
+ 'Owl',
42
+ 'Giraffe',
43
+ 'Zebra',
44
+ 'Koala',
45
+ 'Rabbit',
46
+ 'Squirrel',
47
+ 'Panda',
48
+ 'Horse',
49
+ 'Wolf',
50
+ 'Eagle',
51
+ ];
52
+ const job = [
53
+ 'Writer',
54
+ 'Artist',
55
+ 'Musician',
56
+ 'Explorer',
57
+ 'Scientist',
58
+ 'Engineer',
59
+ 'Athlete',
60
+ 'Chef',
61
+ 'Doctor',
62
+ 'Teacher',
63
+ 'Lawyer',
64
+ 'Entrepreneur',
65
+ 'Actor',
66
+ 'Dancer',
67
+ 'Photographer',
68
+ 'Architect',
69
+ 'Pilot',
70
+ 'Designer',
71
+ 'Journalist',
72
+ 'Veterinarian',
73
+ ];
74
+
75
+ const nombre = randomNumber(0, 99);
76
+ const choix = {
77
+ adj_num: () => random(adj) + nombre,
78
+ ani_num: () => random(ani) + nombre,
79
+ pro_num: () => random(job) + nombre,
80
+ adj_ani: () => random(adj) + random(ani),
81
+ adj_ani_num: () => random(adj) + random(ani) + nombre,
82
+ adj_pro: () => random(adj) + random(job),
83
+ pro_ani: () => random(job) + random(ani),
84
+ pro_ani_num: () => random(job) + random(ani) + nombre,
85
+ };
86
+
87
+ return {
88
+ username: choix[random(Object.keys(choix))](),
89
+ number: nombre,
90
+ adjective: random(adj),
91
+ animal: random(ani),
92
+ job: random(job),
93
+ };
94
+ }
@@ -65,7 +65,7 @@ export function envList(key) {
65
65
  * @throws {Error} - If rate limit is exceeded
66
66
  */
67
67
  export function checkRateLimit(rateLimits, userId, timestamp, window = 10000, limit = 50) {
68
- rateLimits[userId] = (rateLimits[userId] || []).filter(ts => timestamp - ts < window);
68
+ rateLimits[userId] = (rateLimits[userId] || []).filter((ts) => timestamp - ts < window);
69
69
 
70
70
  if (rateLimits[userId].length > limit) {
71
71
  const remainingTime = Math.ceil((rateLimits[userId][0] + window - timestamp) / 1000);
@@ -74,4 +74,4 @@ export function checkRateLimit(rateLimits, userId, timestamp, window = 10000, li
74
74
 
75
75
  rateLimits[userId].push(timestamp);
76
76
  return false;
77
- }
77
+ }
@@ -12,4 +12,4 @@ export { default as qrcode } from './v3/qrcode.js';
12
12
  export { default as tic_tac_toe } from './v3/tic_tac_toe.js';
13
13
  export { default as time } from './v3/time.js';
14
14
  export { default as token } from './v3/token.js';
15
- export { default as username } from './v3/username.js';
15
+ export { default as username } from './v3/username.js';
@@ -0,0 +1,155 @@
1
+ import { MAX_FACTORIAL, MAX_GCD_VALUE, MAX_PRIME_LIST, MAX_STRING_LENGTH } from '../../constants.js';
2
+
3
+ export function anagram(value: string, value2: string): boolean {
4
+ if (!value) throw new Error('First value is required');
5
+ if (!value2) throw new Error('Second value is required');
6
+
7
+ if (typeof value !== 'string') throw new Error('First value must be a string');
8
+ if (typeof value2 !== 'string') throw new Error('Second value must be a string');
9
+
10
+ if (value.length < 2) throw new Error('First value must be at least two characters long');
11
+ if (value.length > MAX_STRING_LENGTH) throw new Error('First value must be less than 1000 characters long');
12
+
13
+ if (value2.length < 2) throw new Error('Second value must be at least two characters long');
14
+ if (value2.length > MAX_STRING_LENGTH) throw new Error('Second value must be less than 1000 characters long');
15
+
16
+ return value.split('').sort().join('') === value2.split('').sort().join('');
17
+ }
18
+
19
+ export function bubblesort(value: string): number[] {
20
+ if (!value) throw new Error('A value is required');
21
+
22
+ if (typeof value !== 'string') throw new Error('Value must be a string');
23
+
24
+ const arr = value.split(',').map(Number);
25
+
26
+ if (arr.some(isNaN)) throw new Error('Array must contain only numbers');
27
+ if (arr.length < 2) throw new Error('Array must contain at least two numbers');
28
+ if (arr.length > MAX_STRING_LENGTH) throw new Error('Array must contain less than 1000 numbers');
29
+
30
+ for (let i = 0; i < arr.length - 1; i++) {
31
+ for (let j = 0; j < arr.length - i - 1; j++) {
32
+ if (arr[j]! > arr[j + 1]!) [arr[j], arr[j + 1]] = [arr[j + 1]!, arr[j]!];
33
+ }
34
+ }
35
+
36
+ return arr;
37
+ }
38
+
39
+ export function factorial(value: string | number): number {
40
+ const num = Number(value);
41
+ if (isNaN(num)) throw new Error('Value must be a number');
42
+ if (num < 0) throw new Error('Number must be positive');
43
+ if (num > MAX_FACTORIAL) throw new Error('Number must be between 0 and 170');
44
+
45
+ return num <= 1 ? 1 : num * factorial(num - 1);
46
+ }
47
+
48
+ export function fibonacci(value: string | number): number[] {
49
+ const num = Number(value);
50
+ if (isNaN(num)) throw new Error('Value must be a number');
51
+ if (num < 0) throw new Error('Number must be positive');
52
+ if (num > 1000) throw new Error('Number must be between 0 and 1000');
53
+
54
+ const fib = [0, 1];
55
+
56
+ for (let i = 2; i < num; i++) {
57
+ fib.push(fib[i - 1]! + fib[i - 2]!);
58
+ }
59
+
60
+ return fib.slice(0, num);
61
+ }
62
+
63
+ export function gcd(value: string | number, value2: string | number): number {
64
+ let a = Number(value);
65
+ let b = Number(value2);
66
+ if (isNaN(a)) throw new Error('First value must be a number');
67
+ if (isNaN(b)) throw new Error('Second value must be a number');
68
+
69
+ if (a <= 0) throw new Error('First number must be strictly positive');
70
+ if (b <= 0) throw new Error('Second number must be strictly positive');
71
+
72
+ if (a > MAX_GCD_VALUE) throw new Error('First number must be between 0 and 100000');
73
+ if (b > MAX_GCD_VALUE) throw new Error('Second number must be between 0 and 100000');
74
+
75
+ a = Math.abs(a);
76
+ b = Math.abs(b);
77
+
78
+ while (b) [a, b] = [b, a % b];
79
+
80
+ return a;
81
+ }
82
+
83
+ export function isprime(value: string | number): boolean {
84
+ const num = Number(value);
85
+ if (isNaN(num)) throw new Error('Value must be a number');
86
+ if (num < 1) throw new Error('Number must be positive');
87
+ if (num > MAX_GCD_VALUE) throw new Error('Number must be between 1 and 100000');
88
+
89
+ for (let i = 2; i <= Math.sqrt(num); i++) {
90
+ if (num % i === 0) return false;
91
+ }
92
+
93
+ return true;
94
+ }
95
+
96
+ export function palindrome(value: string): boolean {
97
+ if (!value) throw new Error('A value is required');
98
+
99
+ if (typeof value !== 'string') throw new Error('Value must be a string');
100
+
101
+ if (value.length < 2) throw new Error('Value must be at least two characters long');
102
+ if (value.length > MAX_STRING_LENGTH) throw new Error('Value must be less than 1000 characters long');
103
+
104
+ return value === value.split('').reverse().join('');
105
+ }
106
+
107
+ export function primefactors(value: string | number): number[] {
108
+ let num = Number(value);
109
+ if (isNaN(num)) throw new Error('Value must be a number');
110
+ if (num < 2) throw new Error('Number must be positive and greater than 1');
111
+ if (num > MAX_GCD_VALUE) throw new Error('Number must be between 2 and 100000');
112
+
113
+ const factors: number[] = [];
114
+
115
+ for (let i = 2; i <= num; i++) {
116
+ while (num % i === 0) {
117
+ factors.push(i);
118
+ num /= i;
119
+ }
120
+ }
121
+
122
+ return factors;
123
+ }
124
+
125
+ export function primelist(value: string | number): number[] {
126
+ const num = Number(value);
127
+ if (isNaN(num)) throw new Error('Value must be a number');
128
+ if (num < 2) throw new Error('Number must be positive and greater than 1');
129
+ if (num > MAX_PRIME_LIST) throw new Error('Number must be between 2 and 10000');
130
+
131
+ const primes: number[] = [];
132
+
133
+ for (let i = 2; i <= num; i++) {
134
+ let isPrime = true;
135
+
136
+ for (let j = 2; j <= Math.sqrt(i); j++) {
137
+ if (i % j === 0) {
138
+ isPrime = false;
139
+ break;
140
+ }
141
+ }
142
+
143
+ if (isPrime) primes.push(i);
144
+ }
145
+
146
+ return primes;
147
+ }
148
+
149
+ export function reverse(value: string): string {
150
+ if (!value) throw new Error('A value is required');
151
+
152
+ if (typeof value !== 'string') throw new Error('Value must be a string');
153
+
154
+ return value.split('').reverse().join('');
155
+ }
@@ -0,0 +1,49 @@
1
+ import { createCanvas } from 'canvas';
2
+
3
+ export default function captcha(text: string): Buffer {
4
+ if (!text) throw new Error('Text is required to generate a captcha.');
5
+
6
+ const size = 60,
7
+ font = '60px Comic Sans Ms',
8
+ width = text.length * size,
9
+ height = 120;
10
+ const canvas = createCanvas(width, height),
11
+ ctx = canvas.getContext('2d');
12
+
13
+ ctx.fillStyle = 'white';
14
+ ctx.fillRect(0, 0, width, height);
15
+
16
+ for (let i = 0; i < 20; i++) {
17
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
18
+ ctx.beginPath();
19
+ ctx.moveTo(Math.random() * width, Math.random() * height);
20
+ ctx.lineTo(Math.random() * width, Math.random() * height);
21
+ ctx.lineWidth = Math.random() * 2;
22
+ ctx.stroke();
23
+ }
24
+
25
+ let x = (canvas.width + 20 - width) / 2;
26
+
27
+ for (let i = 0; i < text.length; i++) {
28
+ const offsetX = Math.cos(i * 0.3) * 10,
29
+ y = height / 2.5 + Math.floor(Math.random() * (height / 2));
30
+
31
+ ctx.font = font;
32
+ ctx.fillStyle = `rgb(${Math.floor(Math.random() * 192)}, ${Math.floor(Math.random() * 192)}, ${Math.floor(Math.random() * 192)})`;
33
+
34
+ ctx.save();
35
+ ctx.translate(x + size / 2, y);
36
+ ctx.rotate((Math.random() - 0.5) * 0.5);
37
+ ctx.fillText(text[i]!, -size / 2 + offsetX, 0);
38
+ ctx.restore();
39
+
40
+ x += size;
41
+ }
42
+
43
+ for (let i = 0; i < 200; i++) {
44
+ ctx.fillStyle = 'black';
45
+ ctx.fillRect(Math.floor(Math.random() * width), Math.floor(Math.random() * height), 1.2, 1.2);
46
+ }
47
+
48
+ return canvas.toBuffer('image/png');
49
+ }
@@ -0,0 +1,99 @@
1
+ import { checkRateLimit } from './utils.js';
2
+ import { SESSION_TTL } from '../../constants.js';
3
+ import type { ChatStorage, ChatMessage } from '../../types/storage.js';
4
+
5
+ interface ChatParams {
6
+ username: string;
7
+ message?: string;
8
+ timestamp?: string;
9
+ session?: string;
10
+ token?: string;
11
+ storage: ChatStorage;
12
+ }
13
+
14
+ export default function chat(action: string, params: ChatParams): ChatMessage[] | ChatMessage | { message: string } {
15
+ const storage = params.storage;
16
+
17
+ storage.messages ??= [];
18
+ storage.privateChats ??= {};
19
+ storage.sessions ??= {};
20
+ storage.rateLimits ??= {};
21
+
22
+ const { messages, privateChats, sessions, rateLimits } = storage;
23
+
24
+ if (!params.username) throw new Error('Please provide a username');
25
+
26
+ const u = params.username.toLowerCase();
27
+ const now = Date.now();
28
+
29
+ checkRateLimit(rateLimits, u, now);
30
+
31
+ if (action === 'message') {
32
+ return sendMessage(params, messages, privateChats, sessions, u, now);
33
+ } else if (action === 'private') {
34
+ return getPrivateChat(params, privateChats);
35
+ } else if (action === 'fetch') {
36
+ return fetchMessages(messages);
37
+ } else {
38
+ throw new Error('Invalid action. Use "message", "private", or "fetch"');
39
+ }
40
+ }
41
+
42
+ function sendMessage(
43
+ params: ChatParams,
44
+ messages: ChatMessage[],
45
+ privateChats: Record<string, ChatMessage[]>,
46
+ sessions: Record<string, { user: string; last: number }>,
47
+ u: string,
48
+ now: number,
49
+ ): { message: string } {
50
+ const { message, session, token } = params;
51
+
52
+ if (!message) throw new Error('Please provide a message');
53
+ if (!session) throw new Error('Please provide a valid session ID');
54
+
55
+ if (sessions[u] && sessions[u].user !== session) {
56
+ throw new Error('Session ID mismatch');
57
+ }
58
+
59
+ const msg: ChatMessage = {
60
+ username: params.username,
61
+ message,
62
+ timestamp: params.timestamp || new Date().toISOString(),
63
+ };
64
+
65
+ if (token) {
66
+ privateChats[token] = privateChats[token] || [];
67
+ privateChats[token]!.push(msg);
68
+ setTimeout(() => {
69
+ delete privateChats[token];
70
+ }, SESSION_TTL);
71
+ } else {
72
+ messages.push(msg);
73
+ setTimeout(() => messages.splice(messages.indexOf(msg), 1), SESSION_TTL);
74
+ }
75
+
76
+ sessions[u] = sessions[u] || { user: session, last: now };
77
+ sessions[u]!.last = now;
78
+
79
+ setTimeout(() => {
80
+ if (sessions[u] && now - sessions[u].last >= SESSION_TTL) delete sessions[u];
81
+ }, SESSION_TTL);
82
+
83
+ return { message: 'Message sent successfully' };
84
+ }
85
+
86
+ function getPrivateChat(params: ChatParams, privateChats: Record<string, ChatMessage[]>): ChatMessage[] {
87
+ const { token } = params;
88
+
89
+ if (!token) throw new Error('Please provide a valid token');
90
+
91
+ if (privateChats[token]) return privateChats[token];
92
+
93
+ throw new Error('Invalid or expired token.');
94
+ }
95
+
96
+ function fetchMessages(messages: ChatMessage[]): ChatMessage[] {
97
+ if (messages.length > 0) return messages;
98
+ throw new Error('No messages stored.');
99
+ }
@@ -0,0 +1,64 @@
1
+ export default function color(): Record<string, string> {
2
+ const r = Math.floor(Math.random() * 256),
3
+ g = Math.floor(Math.random() * 256),
4
+ b = Math.floor(Math.random() * 256);
5
+
6
+ const hsl = ((): [number, number, number] => {
7
+ const r1 = r / 255,
8
+ g1 = g / 255,
9
+ b1 = b / 255,
10
+ max = Math.max(r1, g1, b1),
11
+ min = Math.min(r1, g1, b1),
12
+ l = (max + min) / 2;
13
+ if (max === min) return [0, 0, l * 100];
14
+ const d = max - min,
15
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
16
+ const h =
17
+ {
18
+ [r1]: (g1 - b1) / d + (g1 < b1 ? 6 : 0),
19
+ [g1]: (b1 - r1) / d + 2,
20
+ [b1]: (r1 - g1) / d + 4,
21
+ }[max] ?? 0;
22
+ return [(h * 60) % 360, s * 100, l * 100];
23
+ })();
24
+
25
+ const hsv = ((): [number, number, number] => {
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
+ const h =
31
+ max === min
32
+ ? 0
33
+ : ({
34
+ [r]: (g - b) / (max - min),
35
+ [g]: 2 + (b - r) / (max - min),
36
+ [b]: 4 + (r - g) / (max - min),
37
+ }[max] ?? 0);
38
+ return [(h * 60) % 360, s * 100, v * 100];
39
+ })();
40
+
41
+ const hwb = ((): [number, number, number] => {
42
+ const [h] = hsv,
43
+ whiteness = Math.min(r, g, b) / 255,
44
+ blackness = 1 - Math.max(r, g, b) / 255;
45
+ return [h, whiteness * 100, blackness * 100];
46
+ })();
47
+
48
+ const cmyk = ((): [number, number, number, number] => {
49
+ const k = 1 - Math.max(r, g, b) / 255,
50
+ c = (1 - r / 255 - k) / (1 - k) || 0,
51
+ m = (1 - g / 255 - k) / (1 - k) || 0,
52
+ y = (1 - b / 255 - k) / (1 - k) || 0;
53
+ return [c * 100, m * 100, y * 100, k * 100];
54
+ })();
55
+
56
+ return {
57
+ hex: `#${[r, g, b].map((x) => x.toString(16).padStart(2, '0')).join('')}`,
58
+ rgb: `rgb(${r}, ${g}, ${b})`,
59
+ hsl: `hsl(${hsl[0].toFixed(1)}, ${hsl[1].toFixed(1)}%, ${hsl[2].toFixed(1)}%)`,
60
+ hsv: `hsv(${hsv[0].toFixed(1)}, ${hsv[1].toFixed(1)}%, ${hsv[2].toFixed(1)}%)`,
61
+ hwb: `hwb(${hwb[0].toFixed(1)}, ${hwb[1].toFixed(1)}%, ${hwb[2].toFixed(1)}%)`,
62
+ cmyk: `cmyk(${cmyk.map((x) => x.toFixed(1)).join('%, ')}%)`,
63
+ };
64
+ }
@@ -0,0 +1,38 @@
1
+ import { MIN_TEMPERATURE, MAX_TEMPERATURE } from '../../constants.js';
2
+
3
+ type ConversionFn = (val: number) => number;
4
+
5
+ const conversions: Record<string, Record<string, ConversionFn>> = {
6
+ celsius: {
7
+ fahrenheit: (val) => (val * 9) / 5 + 32,
8
+ kelvin: (val) => val + 273.15,
9
+ },
10
+ fahrenheit: {
11
+ celsius: (val) => ((val - 32) * 5) / 9,
12
+ kelvin: (val) => ((val - 32) * 5) / 9 + 273.15,
13
+ },
14
+ kelvin: {
15
+ celsius: (val) => val - 273.15,
16
+ fahrenheit: (val) => ((val - 273.15) * 9) / 5 + 32,
17
+ },
18
+ };
19
+
20
+ export default function convert(
21
+ value: string | number,
22
+ from: string,
23
+ to: string,
24
+ ): { from: string; to: string; value: number; result: number } {
25
+ const convertFn = conversions[from.toLowerCase()]?.[to.toLowerCase()];
26
+
27
+ if (!convertFn) throw new Error('Invalid conversion unit');
28
+ if (isNaN(Number(value))) throw new Error('Value must be a number');
29
+ if (Number(value) < MIN_TEMPERATURE) throw new Error('Value must be greater than absolute zero');
30
+ if (Number(value) > MAX_TEMPERATURE) throw new Error('Value must be less than 1,000,000');
31
+
32
+ return {
33
+ from,
34
+ to,
35
+ value: parseFloat(String(value)),
36
+ result: convertFn(parseFloat(String(value))),
37
+ };
38
+ }