@20syldev/api 3.3.1 → 3.3.3

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 (3) hide show
  1. package/README.md +2 -2
  2. package/app.js +26 -17
  3. package/package.json +1 -1
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
- [![Version](https://custom-icon-badges.demolab.com/badge/Version%20:-v3.3.1-6479ee?logo=api.sylvain.pro&labelColor=23272A)](https://github.com/20syldev/api/releases/latest)
5
+ [![Version](https://custom-icon-badges.demolab.com/badge/Version%20:-v3.3.3-6479ee?logo=api.sylvain.pro&labelColor=23272A)](https://github.com/20syldev/api/releases/latest)
6
6
  </div>
7
7
 
8
8
  ---
@@ -46,7 +46,7 @@ Enfin, **exécutez** le script de build, qui installera les **dépendances** et
46
46
  $ npm run build
47
47
  ```
48
48
  ```console
49
- > @20syldev/api@3.3.1 build
49
+ > @20syldev/api@3.3.3 build
50
50
  > npm install && node app.js
51
51
 
52
52
  [...]
package/app.js CHANGED
@@ -39,7 +39,7 @@ const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
39
39
  const logs = [], chat = [], privateChats = {}, sessions = {}, rateLimits = {}, ipLimits = {}, games = {};
40
40
 
41
41
  // Define global variables
42
- let contributions, lastFetch = 0, requests = 0, requestLimit = 50, globalLimit = 10000, resetTime = Date.now() + 60000;
42
+ let contributions, lastFetch = 0, requests = 0, requestLimit, resetTime = Date.now() + 3600000;
43
43
 
44
44
  // ----------- ----------- MAIN FUNCTIONS ----------- ----------- //
45
45
 
@@ -108,14 +108,17 @@ app.use((req, res, next) => {
108
108
  // Too many requests
109
109
  app.use((req, res, next) => {
110
110
  const ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress;
111
- const now = Date.now();
112
111
  const token = req.headers.authorization?.split(' ')[1] || '';
113
112
 
114
- const unlimited = process.env.UNLIMITED_TOKEN_LIST?.split(' ') || [];
113
+ const now = Date.now();
114
+ const minute = Math.floor(now / 60000) % 60;
115
+ const hour = Math.floor(now / 3600000) % 24;
116
+
117
+ const business = process.env.BUSINESS_TOKEN_LIST?.split(' ') || [];
115
118
  const pro = process.env.PRO_TOKEN_LIST?.split(' ') || [];
116
119
  const advanced = process.env.ADVANCED_TOKEN_LIST?.split(' ') || [];
117
120
 
118
- if (token && ![...unlimited, ...pro, ...advanced].includes(token) || token === 'undefined') {
121
+ if (token && ![...business, ...pro, ...advanced].includes(token) || token === 'undefined') {
119
122
  return res.status(401).jsonResponse({
120
123
  message: 'Unauthorized',
121
124
  error: 'Invalid token.',
@@ -123,23 +126,28 @@ app.use((req, res, next) => {
123
126
  });
124
127
  }
125
128
 
126
- if (unlimited.includes(token) && !unlimited.includes('undefined')) requestLimit = Infinity;
127
- else if (pro.includes(token) && !pro.includes('undefined')) requestLimit = 100;
128
- else if (advanced.includes(token) && !advanced.includes('undefined')) requestLimit = 75;
129
-
130
- if (unlimited.includes(token)) return next();
129
+ if (business.includes(token) && !business.includes('undefined')) requestLimit = process.env.BUSINESS_LIMIT;
130
+ else if (pro.includes(token) && !pro.includes('undefined')) requestLimit = process.env.PRO_LIMIT;
131
+ else if (advanced.includes(token) && !advanced.includes('undefined')) requestLimit = process.env.ADVANCED_LIMIT;
132
+ else requestLimit = process.env.DEFAULT_LIMIT;
131
133
 
132
- if (now > resetTime) requests = 0, resetTime = now + 60000;
133
- if (++requests > Math.max(globalLimit / Math.max(1, Object.keys(ipLimits).length), requestLimit)) {
134
+ if (now > resetTime) requests = 0, resetTime = now + 3600000;
135
+ if (++requests > Math.max(process.env.GLOBAL_LIMIT / Math.max(1, Object.keys(ipLimits).length), requestLimit)) {
134
136
  return res.status(429).jsonResponse({ message: 'Too Many Requests' });
135
137
  }
136
138
 
137
- if (!ipLimits[ip]) ipLimits[ip] = [];
138
- ipLimits[ip] = ipLimits[ip].filter(t => now - t < 60000);
139
+ if (!ipLimits[ip]) ipLimits[ip] = {};
140
+ if (!ipLimits[ip][hour]) ipLimits[ip][hour] = {};
141
+ ipLimits[ip][hour][minute] = (ipLimits[ip][hour][minute] || 0) + 1;
139
142
 
140
- if (ipLimits[ip].length >= requestLimit) return res.status(429).jsonResponse({ message: 'Too Many Requests (IP limited)' });
143
+ if (ipLimits[ip][hour][minute] > requestLimit) return res.status(429).jsonResponse({
144
+ message: 'Too Many Requests (IP limited), authenticate to increase the limit.',
145
+ error: `You have exceeded the limit of ${requestLimit} requests per hour.`,
146
+ status: '429'
147
+ });
148
+
149
+ Object.keys(ipLimits[ip]).forEach(h => { if (h != hour) delete ipLimits[ip][h]; });
141
150
 
142
- ipLimits[ip].push(now);
143
151
  next();
144
152
  });
145
153
 
@@ -154,11 +162,12 @@ app.use((req, res, next) => {
154
162
  const timestamp = new Date().toISOString();
155
163
  const method = req.method;
156
164
  const url = req.originalUrl;
157
- const status = res.statusCode === 304 ? 200 : res.statusCode;
158
- const duration = `${Date.now() - startTime}ms`;
159
165
  const platform = req.headers['sec-ch-ua-platform']?.replace(/"/g, '');
160
166
 
161
167
  res.on('finish', () => {
168
+ const status = res.statusCode === 304 ? 200 : res.statusCode;
169
+ const duration = `${Date.now() - startTime}ms`;
170
+
162
171
  logs.push({ timestamp, method, url, status, duration, platform });
163
172
  console.log(`[${new Date().toISOString()}] ${method} ${url} ${res.statusCode} - ${duration} - ${ip}`);
164
173
  if (logs.length > 1000) logs.shift();
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.3.1",
2
+ "version": "3.3.3",
3
3
  "name": "@20syldev/api",
4
4
  "description": "Node.js API with multiple features. Check the documentation at https://docs.sylvain.pro",
5
5
  "main": "app.js",