@20syldev/api 2.8.0 → 2.9.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.
- package/README.md +31 -4
- package/app.js +62 -59
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a href="https://api.sylvain.pro"><img src="https://api.sylvain.pro/favicon.ico" alt="Logo" width="25%" height="auto"/></a>
|
|
3
3
|
|
|
4
4
|
# API Personnelle
|
|
5
|
-
[](https://github.com/20syldev/api/releases/latest)
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -12,12 +12,39 @@ Voici mon API personnelle, disponible sur le domaine [api.sylvain.pro](https://a
|
|
|
12
12
|
L'API est développée avec Node.js et hébergée **24h/7j**. Elle est **simple d'utilisation** et a une **documentation** disponible sur [docs.sylvain.pro](https://docs.sylvain.pro) !
|
|
13
13
|
> *Une limite de **1000** requêtes maximum chaque **10 secondes** est fixée.*
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Installer le paquet de l'API sur votre machine
|
|
16
|
+
```console
|
|
17
|
+
$ sudo apt install nodejs npm
|
|
18
|
+
$ npm install @20syldev/api
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Pour utiliser le **paquet** dans votre projet, **créez** un fichier **JavaScript**. Par exemple, `index.js` :
|
|
22
|
+
```js
|
|
23
|
+
require('@20syldev/api');
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Puis, **démarrez** un serveur [Node.js](http://nodejs.org) pour utiliser l'**API** :
|
|
27
|
+
```console
|
|
28
|
+
$ node index.js
|
|
29
|
+
API is running on
|
|
30
|
+
- http://127.0.0.1:3000
|
|
31
|
+
- http://localhost:3000
|
|
32
|
+
```
|
|
33
|
+
> *Remplacez `index.js` par le nom de votre fichier JavaScript.*
|
|
34
|
+
|
|
35
|
+
## Tester l'API sur votre machine
|
|
36
|
+
**Téléchargez** la [dernière mise à jour](https://github.com/20syldev/api/releases/latest) de l'API, puis **extrayez** le contenu du fichier `.zip` ou `.tar.gz` dans un de vos **répertoires**.
|
|
37
|
+
Ensuite, **déplacez-vous** dans le dossier du projet, via un terminal **Linux**, **Windows** ou **macOS** :
|
|
38
|
+
```console
|
|
39
|
+
$ cd /chemin/vers/le/projet
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Enfin, **exécutez** le script de build, qui installera les **dépendances** et lancera le **serveur** de l'[API](https://api.sylvain.pro) :
|
|
16
43
|
```console
|
|
17
44
|
$ npm run build
|
|
18
45
|
```
|
|
19
46
|
```console
|
|
20
|
-
> @20syldev/api@2.
|
|
47
|
+
> @20syldev/api@2.9.0 build
|
|
21
48
|
> npm install && node app.js
|
|
22
49
|
|
|
23
50
|
[...]
|
|
@@ -28,4 +55,4 @@ API is running on
|
|
|
28
55
|
- http://localhost:3000
|
|
29
56
|
```
|
|
30
57
|
|
|
31
|
-
*Visitez la [documentation](https://docs.sylvain.pro) dédiée, vous y retrouverez des exemples de requêtes et des codes simples pour tester l'[API](https://api.sylvain.pro) !*
|
|
58
|
+
*Visitez la [documentation](https://docs.sylvain.pro) dédiée, vous y retrouverez des exemples de requêtes et des codes simples pour tester l'[API](https://api.sylvain.pro) !*
|
package/app.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const uuid = require('uuid');
|
|
1
|
+
import { createCanvas } from 'canvas';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import { randomBytes, getHashes, createHash } from 'crypto';
|
|
5
|
+
import express, { urlencoded, json } from 'express';
|
|
6
|
+
import { factorial } from 'mathjs';
|
|
7
|
+
import fetch from 'node-fetch';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
import { toDataURL } from 'qrcode';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { v4 } from 'uuid';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
16
15
|
const app = express();
|
|
17
16
|
|
|
18
17
|
// Define allowed versions & endpoints for each version
|
|
@@ -22,6 +21,16 @@ const endpoints = {
|
|
|
22
21
|
v2: ['algorithms', 'captcha', 'chat', 'color', 'convert', 'domain', 'hash', 'infos', 'personal', 'qrcode', 'tic-tac-toe', 'token', 'username', 'website']
|
|
23
22
|
};
|
|
24
23
|
|
|
24
|
+
// Arrowed functions (math & random)
|
|
25
|
+
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
26
|
+
const genID = () => {
|
|
27
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
28
|
+
return Array.from(randomBytes(5)).map(b => chars[b % chars.length]).join('');
|
|
29
|
+
};
|
|
30
|
+
const genIP = () => `${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`;
|
|
31
|
+
const genToken = (chars, length) => Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
|
|
32
|
+
const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
33
|
+
|
|
25
34
|
// Store data
|
|
26
35
|
const logs = [], chat = [], privateChats = {}, sessions = {}, rateLimits = {}, games = {};
|
|
27
36
|
|
|
@@ -30,16 +39,18 @@ let lastFetch = 0, requests = 0, resetTime = Date.now() + 10000;
|
|
|
30
39
|
|
|
31
40
|
// ----------- ----------- MIDDLEWARES SETUP ----------- ----------- //
|
|
32
41
|
|
|
42
|
+
dotenv.config();
|
|
43
|
+
|
|
33
44
|
// CORS & Express setup
|
|
34
45
|
app.use(cors({ methods: ['GET', 'POST'] }));
|
|
35
|
-
app.use(
|
|
36
|
-
app.use(
|
|
46
|
+
app.use(urlencoded({ extended: true }));
|
|
47
|
+
app.use(json());
|
|
37
48
|
|
|
38
49
|
// Set favicon for API
|
|
39
|
-
app.use('/favicon.ico', express.static(
|
|
50
|
+
app.use('/favicon.ico', express.static(join(__dirname, 'src', 'favicon.ico')));
|
|
40
51
|
|
|
41
52
|
// Display robots.txt
|
|
42
|
-
app.use('/robots.txt', express.static(
|
|
53
|
+
app.use('/robots.txt', express.static(join(__dirname, 'robots.txt')));
|
|
43
54
|
|
|
44
55
|
// Return formatted JSON
|
|
45
56
|
app.use((req, res, next) => {
|
|
@@ -104,7 +115,7 @@ app.use('/:version', (req, res, next) => {
|
|
|
104
115
|
return res.status(404).jsonResponse({
|
|
105
116
|
message: 'Not Found',
|
|
106
117
|
error: `Invalid API version (${version}).`,
|
|
107
|
-
documentation:
|
|
118
|
+
documentation: `https://docs.sylvain.pro/${versions.at(-1)}`,
|
|
108
119
|
status: '404'
|
|
109
120
|
});
|
|
110
121
|
}
|
|
@@ -119,7 +130,7 @@ app.use('/:version/:endpoint', (req, res, next) => {
|
|
|
119
130
|
return res.status(404).jsonResponse({
|
|
120
131
|
message: 'Not Found',
|
|
121
132
|
error: `Endpoint '${endpoint}' does not exist in ${version}.`,
|
|
122
|
-
documentation:
|
|
133
|
+
documentation: `https://docs.sylvain.pro/${versions.at(-1)}`,
|
|
123
134
|
status: '404'
|
|
124
135
|
});
|
|
125
136
|
}
|
|
@@ -206,11 +217,12 @@ app.get('/logs', (req, res) => res.jsonResponse(logs));
|
|
|
206
217
|
// Algorithms
|
|
207
218
|
app.get('/:version/algorithms', (req, res) => {
|
|
208
219
|
const { method, value, value2 } = req.query;
|
|
220
|
+
const { version } = req.params;
|
|
209
221
|
|
|
210
222
|
if (!['anagram', 'bubblesort', 'factorial', 'fibonacci', 'gcd', 'isprime', 'palindrome', 'primefactors', 'primelist', 'reverse'].includes(method)) {
|
|
211
223
|
return res.jsonResponse({
|
|
212
224
|
error: 'Please provide a valid algorithm (?method={algorithm})',
|
|
213
|
-
documentation:
|
|
225
|
+
documentation: `https://docs.sylvain.pro/${version}/algorithms`
|
|
214
226
|
});
|
|
215
227
|
}
|
|
216
228
|
if (!value) return res.jsonResponse({ error: 'Please provide a valid value (&value={value})' });
|
|
@@ -233,7 +245,7 @@ app.get('/:version/algorithms', (req, res) => {
|
|
|
233
245
|
|
|
234
246
|
if (method === 'factorial') {
|
|
235
247
|
if (isNaN(value) || value < 0 || value > 170) return res.jsonResponse({ error: 'Please provide a valid number between 0 and 170.' });
|
|
236
|
-
return res.jsonResponse({ answer:
|
|
248
|
+
return res.jsonResponse({ answer: factorial(value) });
|
|
237
249
|
}
|
|
238
250
|
|
|
239
251
|
if (method === 'fibonacci') {
|
|
@@ -243,7 +255,6 @@ app.get('/:version/algorithms', (req, res) => {
|
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
if (method === 'gcd') {
|
|
246
|
-
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
247
258
|
if (!value2) return res.jsonResponse({ error: 'Please provide a second value (&value2={value})' });
|
|
248
259
|
if (isNaN(value) || isNaN(value2)) return res.jsonResponse({ error: 'Invalid numbers.' });
|
|
249
260
|
return res.jsonResponse({ answer: gcd(value, value2) });
|
|
@@ -354,7 +365,7 @@ app.get('/:version/chat/private', (req, res) => {
|
|
|
354
365
|
|
|
355
366
|
// Generate color
|
|
356
367
|
app.get('/:version/color', (req, res) => {
|
|
357
|
-
const r =
|
|
368
|
+
const r = Math.floor(Math.random() * 256), g = Math.floor(Math.random() * 256), b = Math.floor(Math.random() * 256);
|
|
358
369
|
const hsl = (() => {
|
|
359
370
|
const r1 = r / 255, g1 = g / 255, b1 = b / 255, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), l = (max + min) / 2;
|
|
360
371
|
if (max === min) return [0, 0, l * 100];
|
|
@@ -407,17 +418,15 @@ app.get('/:version/convert', (req, res) => {
|
|
|
407
418
|
|
|
408
419
|
// Generate domain informations
|
|
409
420
|
app.get('/:version/domain', (req, res) => {
|
|
410
|
-
const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
411
421
|
const subdomains = ['fr.', 'en.', 'docs.', 'api.', 'projects.', 'app.', 'web.', 'info.', 'dev.', 'shop.', 'blog.', 'support.', 'mail.', 'forum.'];
|
|
412
422
|
const domains = ['example', 'site', 'test', 'demo', 'page', 'store', 'portfolio', 'platform', 'hub', 'network', 'service', 'cloud', 'solutions', 'company'];
|
|
413
423
|
const tlds = ['.com', '.fr', '.eu', '.dev', '.net', '.org', '.io', '.tech', '.biz', '.info', '.co', '.app', '.store', '.online', '.shop', '.tv'];
|
|
414
424
|
|
|
415
425
|
const domain = `${random(domains)}${random(tlds)}`;
|
|
416
426
|
const fulldomain = `${random(subdomains)}${domain}`;
|
|
417
|
-
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
const dns = Array.from({ length: Math.floor(Math.random() * 5) + 1 }, getRandomIp);
|
|
427
|
+
|
|
428
|
+
const ips = Array.from({ length: Math.floor(Math.random() * 3) + 1 }, genIP);
|
|
429
|
+
const dns = Array.from({ length: Math.floor(Math.random() * 5) + 1 }, genIP);
|
|
421
430
|
|
|
422
431
|
res.jsonResponse({
|
|
423
432
|
domain,
|
|
@@ -449,7 +458,7 @@ app.get('/:version/hash', (req, res) => {
|
|
|
449
458
|
// Display API informations
|
|
450
459
|
app.get('/:version/infos', (req, res) => {
|
|
451
460
|
res.jsonResponse({
|
|
452
|
-
endpoints: endpoints.length,
|
|
461
|
+
endpoints: endpoints[versions.at(-1)].length,
|
|
453
462
|
last_version: versions.at(-1),
|
|
454
463
|
documentation: 'https://docs.sylvain.pro',
|
|
455
464
|
github: 'https://github.com/20syldev/api',
|
|
@@ -459,8 +468,6 @@ app.get('/:version/infos', (req, res) => {
|
|
|
459
468
|
|
|
460
469
|
// Generate personal data
|
|
461
470
|
app.get('/:version/personal', (req, res) => {
|
|
462
|
-
const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
463
|
-
|
|
464
471
|
const people = [
|
|
465
472
|
{ name: 'John Doe', social: 'john_doe', email: 'john@example.com', country: 'US' },
|
|
466
473
|
{ name: 'Jane Martin', social: 'jane_martin', email: 'jane@example.com', country: 'FR' },
|
|
@@ -579,7 +586,7 @@ app.get('/:version/qrcode', async (req, res) => {
|
|
|
579
586
|
|
|
580
587
|
if (!url) return res.jsonResponse({ error: 'Please provide a valid url (?url={URL})' });
|
|
581
588
|
|
|
582
|
-
try { res.jsonResponse({ qr: await
|
|
589
|
+
try { res.jsonResponse({ qr: await toDataURL(url) }); }
|
|
583
590
|
catch { res.jsonResponse({ error: 'Error generating QR code.' }); }
|
|
584
591
|
});
|
|
585
592
|
|
|
@@ -604,7 +611,6 @@ app.get('/:version/username', (req, res) => {
|
|
|
604
611
|
const ani = ['Cat', 'Dog', 'Tiger', 'Elephant', 'Monkey', 'Penguin', 'Dolphin', 'Lion', 'Bear', 'Fox', 'Owl', 'Giraffe', 'Zebra', 'Koala', 'Rabbit', 'Squirrel', 'Panda', 'Horse', 'Wolf', 'Eagle'];
|
|
605
612
|
const job = ['Writer', 'Artist', 'Musician', 'Explorer', 'Scientist', 'Engineer', 'Athlete', 'Chef', 'Doctor', 'Teacher', 'Lawyer', 'Entrepreneur', 'Actor', 'Dancer', 'Photographer', 'Architect', 'Pilot', 'Designer', 'Journalist', 'Veterinarian'];
|
|
606
613
|
|
|
607
|
-
const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
608
614
|
const nombre = Math.floor(Math.random() * 100);
|
|
609
615
|
const choix = {
|
|
610
616
|
adj_num: () => random(adj) + nombre,
|
|
@@ -829,12 +835,7 @@ app.post('/:version/tic-tac-toe/fetch', (req, res) => {
|
|
|
829
835
|
|
|
830
836
|
if (!username) return res.jsonResponse({ error: 'Please provide a username (?username={username})' });
|
|
831
837
|
|
|
832
|
-
const
|
|
833
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
834
|
-
return Array.from(crypto.randomBytes(5)).map(b => chars[b % chars.length]).join('');
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
const ID = game || generateId();
|
|
838
|
+
const ID = game || genID();
|
|
838
839
|
const u = username.toLowerCase(), now = Date.now();
|
|
839
840
|
|
|
840
841
|
rateLimits[u] = (rateLimits[u] || []).filter(ts => now - ts < 10000);
|
|
@@ -855,40 +856,42 @@ app.post('/:version/tic-tac-toe/fetch', (req, res) => {
|
|
|
855
856
|
// Generate hash
|
|
856
857
|
app.post('/:version/hash', (req, res) => {
|
|
857
858
|
const { text, method } = req.body;
|
|
859
|
+
const { version } = req.params;
|
|
858
860
|
|
|
859
861
|
if (!text) return res.jsonResponse({ error: 'Please provide a text (?text={text})' });
|
|
860
862
|
if (!method) return res.jsonResponse({
|
|
861
863
|
error: 'Please provide a valid hash algorithm (?method={algorithm})',
|
|
862
|
-
documentation:
|
|
864
|
+
documentation: `https://docs.sylvain.pro/${version}/hash`
|
|
863
865
|
});
|
|
864
866
|
|
|
865
|
-
const methods =
|
|
867
|
+
const methods = getHashes();
|
|
866
868
|
if (!methods.includes(method)) return res.jsonResponse({ error: `Unsupported method. Use one of: ${methods.join(', ')}` });
|
|
867
869
|
|
|
868
|
-
const hash =
|
|
870
|
+
const hash = createHash(method).update(text).digest('hex');
|
|
869
871
|
res.jsonResponse({ method, hash });
|
|
870
872
|
});
|
|
871
873
|
|
|
872
874
|
// Generate Token
|
|
873
875
|
app.post('/:version/token', (req, res) => {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
+
let { len, type } = req.body;
|
|
877
|
+
|
|
878
|
+
len = parseInt(len || 24, 10);
|
|
879
|
+
type = type ? type.toLowerCase() : 'alpha';
|
|
876
880
|
|
|
877
|
-
if (isNaN(
|
|
878
|
-
if (
|
|
879
|
-
if (
|
|
881
|
+
if (isNaN(len) || len < 0) return res.jsonResponse({ error: 'Invalid number.' });
|
|
882
|
+
if (len > 4096) return res.jsonResponse({ error: 'Length cannot exceed 4096.' });
|
|
883
|
+
if (len < 12) return res.jsonResponse({ error: 'Length cannot be less than 12.' });
|
|
880
884
|
|
|
881
|
-
const generateToken = (chars) => Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
|
|
882
885
|
const token = {
|
|
883
|
-
alpha:
|
|
884
|
-
alphanum:
|
|
885
|
-
base64:
|
|
886
|
-
hex:
|
|
887
|
-
num:
|
|
888
|
-
punct:
|
|
889
|
-
urlsafe:
|
|
890
|
-
uuid:
|
|
891
|
-
}[type] ||
|
|
886
|
+
alpha: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', len),
|
|
887
|
+
alphanum: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len),
|
|
888
|
+
base64: randomBytes(len).toString('base64').slice(0, len),
|
|
889
|
+
hex: randomBytes(len).toString('hex').slice(0, len),
|
|
890
|
+
num: genToken('0123456789', len),
|
|
891
|
+
punct: genToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', len),
|
|
892
|
+
urlsafe: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_', len),
|
|
893
|
+
uuid: v4().replace(/-/g, '').slice(0, len)
|
|
894
|
+
}[type] || genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len);
|
|
892
895
|
|
|
893
896
|
res.jsonResponse({ token });
|
|
894
897
|
});
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.9.0",
|
|
3
3
|
"name": "@20syldev/api",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Node.js API with multiple features. Check the documentation at https://docs.sylvain.pro",
|
|
5
5
|
"main": "app.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"start": "node app.js",
|
|
8
9
|
"build": "npm install && node app.js",
|
|
@@ -11,16 +12,16 @@
|
|
|
11
12
|
"upgrade:build": "npm upgrade && npm install && node app.js"
|
|
12
13
|
},
|
|
13
14
|
"dependencies": {
|
|
14
|
-
"canvas": "
|
|
15
|
-
"cors": "
|
|
16
|
-
"dotenv": "
|
|
17
|
-
"express": "
|
|
18
|
-
"mathjs": "
|
|
19
|
-
"node-fetch": "
|
|
20
|
-
"prettier": "
|
|
21
|
-
"qrcode": "
|
|
22
|
-
"random": "
|
|
23
|
-
"uuid": "
|
|
15
|
+
"canvas": "latest",
|
|
16
|
+
"cors": "latest",
|
|
17
|
+
"dotenv": "latest",
|
|
18
|
+
"express": "latest",
|
|
19
|
+
"mathjs": "latest",
|
|
20
|
+
"node-fetch": "latest",
|
|
21
|
+
"prettier": "latest",
|
|
22
|
+
"qrcode": "latest",
|
|
23
|
+
"random": "latest",
|
|
24
|
+
"uuid": "latest"
|
|
24
25
|
},
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|