gufi-cli 0.1.49 → 0.1.51
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/dist/commands/docs.js +1 -5
- package/dist/lib/docs-resolver.d.ts +8 -0
- package/dist/lib/docs-resolver.js +27 -0
- package/dist/lib/security.js +5 -0
- package/dist/mcp.js +56 -43
- package/docs/dev-guide/1-01-architecture.md +358 -0
- package/docs/dev-guide/1-02-multi-tenant.md +415 -0
- package/docs/dev-guide/1-03-column-types.md +594 -0
- package/docs/dev-guide/1-04-json-config.md +442 -0
- package/docs/dev-guide/1-05-authentication.md +427 -0
- package/docs/dev-guide/2-01-api-reference.md +564 -0
- package/docs/dev-guide/2-02-automations.md +508 -0
- package/docs/dev-guide/2-03-gufi-cli.md +568 -0
- package/docs/dev-guide/2-04-realtime.md +401 -0
- package/docs/dev-guide/2-05-permissions.md +497 -0
- package/docs/dev-guide/2-06-integrations-overview.md +104 -0
- package/docs/dev-guide/2-07-stripe.md +173 -0
- package/docs/dev-guide/2-08-nayax.md +297 -0
- package/docs/dev-guide/2-09-ourvend.md +226 -0
- package/docs/dev-guide/2-10-tns.md +177 -0
- package/docs/dev-guide/2-11-custom-http.md +268 -0
- package/docs/dev-guide/3-01-custom-views.md +555 -0
- package/docs/dev-guide/3-02-webhooks-api.md +446 -0
- package/docs/mcp/00-overview.md +329 -0
- package/docs/mcp/01-architecture.md +226 -0
- package/docs/mcp/02-modules.md +285 -0
- package/docs/mcp/03-fields.md +357 -0
- package/docs/mcp/04-views.md +613 -0
- package/docs/mcp/05-automations.md +461 -0
- package/docs/mcp/06-api.md +531 -0
- package/docs/mcp/07-packages.md +246 -0
- package/docs/mcp/08-common-errors.md +284 -0
- package/docs/mcp/09-examples.md +453 -0
- package/docs/mcp/README.md +71 -0
- package/docs/mcp/tool-descriptions.json +64 -0
- package/package.json +3 -2
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Endpoints principales del backend de Gufi.
|
|
4
|
+
|
|
5
|
+
## Autenticacion
|
|
6
|
+
|
|
7
|
+
### Login
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
POST /api/auth/login
|
|
11
|
+
{
|
|
12
|
+
"email": "user@example.com",
|
|
13
|
+
"password": "password123"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Response:
|
|
17
|
+
{
|
|
18
|
+
"accessToken": "eyJ...",
|
|
19
|
+
"refreshToken": "abc...",
|
|
20
|
+
"user": { "id": 16, "email": "...", "name": "..." }
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Refresh token
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
POST /api/auth/refresh
|
|
28
|
+
Headers:
|
|
29
|
+
X-Refresh-Token: {refreshToken}
|
|
30
|
+
|
|
31
|
+
Response:
|
|
32
|
+
{
|
|
33
|
+
"accessToken": "eyJ...",
|
|
34
|
+
"refreshToken": "abc..."
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Headers requeridos
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Authorization: Bearer {accessToken}
|
|
42
|
+
X-Company-ID: {companyId}
|
|
43
|
+
Content-Type: application/json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Companies
|
|
47
|
+
|
|
48
|
+
### Listar companies
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
GET /api/companies
|
|
52
|
+
|
|
53
|
+
Response:
|
|
54
|
+
{
|
|
55
|
+
"items": [
|
|
56
|
+
{ "id": 116, "name": "Mi Empresa", "created_at": "..." }
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Schema de company
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
GET /api/company/schema
|
|
65
|
+
|
|
66
|
+
Response:
|
|
67
|
+
{
|
|
68
|
+
"modules": [
|
|
69
|
+
{
|
|
70
|
+
"id": 360,
|
|
71
|
+
"name": "Ventas",
|
|
72
|
+
"submodules": [...]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Modules
|
|
79
|
+
|
|
80
|
+
### Listar modulos
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
GET /api/company/modules
|
|
84
|
+
|
|
85
|
+
Response:
|
|
86
|
+
[
|
|
87
|
+
{ "id": 360, "name": "ventas", "displayName": "Ventas", "entity_count": 3 }
|
|
88
|
+
]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Obtener modulo
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
GET /api/company/modules/{moduleId}
|
|
95
|
+
|
|
96
|
+
Response:
|
|
97
|
+
{
|
|
98
|
+
"id": 360,
|
|
99
|
+
"name": "ventas",
|
|
100
|
+
"json_definition": {...}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Actualizar modulo
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
PUT /api/company/modules/{moduleId}
|
|
108
|
+
{
|
|
109
|
+
"json_definition": {...}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Crear modulo
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
POST /api/company/modules
|
|
117
|
+
{
|
|
118
|
+
"json_definition": {...}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Tables (CRUD generico)
|
|
123
|
+
|
|
124
|
+
### Listar registros
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
POST /api/tables/{tableName}/list
|
|
128
|
+
{
|
|
129
|
+
"page": 1,
|
|
130
|
+
"perPage": 20,
|
|
131
|
+
"sorters": [{ "field": "created_at", "order": "desc" }],
|
|
132
|
+
"filter": [
|
|
133
|
+
{ "field": "estado", "operator": "eq", "value": "pendiente" }
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
Response:
|
|
138
|
+
{
|
|
139
|
+
"data": [...],
|
|
140
|
+
"meta": { "page": 1, "perPage": 20, "hasMore": true }
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
> **IMPORTANTE**: La paginacion usa `page` y `perPage` directamente en el body,
|
|
145
|
+
> NO `pagination: { current, pageSize }`. Usar el formato incorrecto hace que
|
|
146
|
+
> la API ignore la paginacion y siempre devuelva la primera pagina.
|
|
147
|
+
|
|
148
|
+
### Obtener registro
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
POST /api/tables/{tableName}/getOne
|
|
152
|
+
{
|
|
153
|
+
"id": 123
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
Response:
|
|
157
|
+
{
|
|
158
|
+
"data": { "id": 123, "nombre": "...", ... }
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Crear registro
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
POST /api/tables/{tableName}
|
|
166
|
+
{
|
|
167
|
+
"nombre": "Nuevo",
|
|
168
|
+
"precio": 150,
|
|
169
|
+
"estado": "pendiente"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
Response (objeto directamente, NO envuelto en data):
|
|
173
|
+
{ "id": 124, "nombre": "Nuevo", "precio": 150, ... }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> **IMPORTANTE**: El endpoint de crear devuelve el objeto directamente,
|
|
177
|
+
> NO envuelto en `{ data: {...} }`. Verificar con `'id' in response`, no `'data' in response`.
|
|
178
|
+
|
|
179
|
+
### Actualizar registro
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
PUT /api/tables/{tableName}/{id}
|
|
183
|
+
{
|
|
184
|
+
"estado": "completado",
|
|
185
|
+
"estado__display": "Completado"
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Eliminar registro
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
DELETE /api/tables/{tableName}/{id}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Eliminar multiples
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
POST /api/tables/{tableName}/deleteMany
|
|
199
|
+
{
|
|
200
|
+
"ids": [1, 2, 3]
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Agregaciones (Analytics)
|
|
205
|
+
|
|
206
|
+
Usar `gufi_data` con `action: 'aggregate'` para métricas y agregaciones.
|
|
207
|
+
|
|
208
|
+
### Count total
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
gufi_data({
|
|
212
|
+
action: 'aggregate',
|
|
213
|
+
table: 'ventas.pedidos',
|
|
214
|
+
agg: 'count',
|
|
215
|
+
company_id: '146'
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
// Response: { value: 1250 }
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Sum, Avg, Min, Max
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
// Suma total de ventas
|
|
225
|
+
gufi_data({
|
|
226
|
+
action: 'aggregate',
|
|
227
|
+
table: 'ventas.pedidos',
|
|
228
|
+
agg: 'sum',
|
|
229
|
+
field: 'total',
|
|
230
|
+
company_id: '146'
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// Precio promedio
|
|
234
|
+
gufi_data({
|
|
235
|
+
action: 'aggregate',
|
|
236
|
+
table: 'ventas.productos',
|
|
237
|
+
agg: 'avg',
|
|
238
|
+
field: 'precio',
|
|
239
|
+
company_id: '146'
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Group By
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
// Ventas por cliente
|
|
247
|
+
gufi_data({
|
|
248
|
+
action: 'aggregate',
|
|
249
|
+
table: 'ventas.pedidos',
|
|
250
|
+
agg: 'sum',
|
|
251
|
+
field: 'total',
|
|
252
|
+
groupBy: 'cliente_id',
|
|
253
|
+
limit: 10,
|
|
254
|
+
company_id: '146'
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
// Response:
|
|
258
|
+
// { results: [
|
|
259
|
+
// { group: 'cliente_123', value: 15000 },
|
|
260
|
+
// { group: 'cliente_456', value: 12500 },
|
|
261
|
+
// ...
|
|
262
|
+
// ]}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Con filtros simples
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// Filtrar por campo = valor
|
|
269
|
+
gufi_data({
|
|
270
|
+
action: 'aggregate',
|
|
271
|
+
table: 'ventas.pedidos',
|
|
272
|
+
agg: 'sum',
|
|
273
|
+
field: 'total',
|
|
274
|
+
filter: 'estado=completado',
|
|
275
|
+
company_id: '146'
|
|
276
|
+
})
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Con filtros de fecha
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// Ventas del último mes
|
|
283
|
+
gufi_data({
|
|
284
|
+
action: 'aggregate',
|
|
285
|
+
table: 'ventas.pedidos',
|
|
286
|
+
agg: 'sum',
|
|
287
|
+
field: 'total',
|
|
288
|
+
groupBy: 'cliente_id',
|
|
289
|
+
dateField: 'fecha_venta',
|
|
290
|
+
dateFrom: '2025-12-26T00:00:00Z',
|
|
291
|
+
dateTo: '2026-01-26T23:59:59Z',
|
|
292
|
+
company_id: '146'
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// Top 10 máquinas por ventas del mes
|
|
296
|
+
gufi_data({
|
|
297
|
+
action: 'aggregate',
|
|
298
|
+
table: 'nayax.machine_sales',
|
|
299
|
+
agg: 'sum',
|
|
300
|
+
field: 'settlement_value',
|
|
301
|
+
groupBy: 'machine_id',
|
|
302
|
+
dateField: 'settlement_datetime_gmt',
|
|
303
|
+
dateFrom: '2025-12-26T00:00:00Z',
|
|
304
|
+
dateTo: '2026-01-26T23:59:59Z',
|
|
305
|
+
company_id: '116'
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Parámetros de fecha:**
|
|
310
|
+
- `dateField`: Campo de fecha para filtrar (requerido para filtros de fecha)
|
|
311
|
+
- `dateFrom`: Fecha inicio (ISO string, inclusive >=)
|
|
312
|
+
- `dateTo`: Fecha fin (ISO string, inclusive <=)
|
|
313
|
+
|
|
314
|
+
### Agregaciones disponibles
|
|
315
|
+
|
|
316
|
+
| agg | Descripcion | Requiere field |
|
|
317
|
+
|-----|-------------|----------------|
|
|
318
|
+
| `count` | Cuenta registros | No (opcional) |
|
|
319
|
+
| `sum` | Suma valores | Sí |
|
|
320
|
+
| `avg` | Promedio | Sí |
|
|
321
|
+
| `min` | Valor mínimo | Sí |
|
|
322
|
+
| `max` | Valor máximo | Sí |
|
|
323
|
+
|
|
324
|
+
## Automations
|
|
325
|
+
|
|
326
|
+
### Listar scripts
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
GET /api/automation-scripts
|
|
330
|
+
|
|
331
|
+
Response:
|
|
332
|
+
[
|
|
333
|
+
{ "id": 15, "name": "mi_script", "company_id": 116 }
|
|
334
|
+
]
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Obtener script
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
GET /api/automation-scripts/{name}
|
|
341
|
+
|
|
342
|
+
Response:
|
|
343
|
+
{
|
|
344
|
+
"id": 15,
|
|
345
|
+
"name": "mi_script",
|
|
346
|
+
"js_code": "async function...",
|
|
347
|
+
"description": "..."
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Crear/actualizar script
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
PUT /api/automation-scripts/{name}
|
|
355
|
+
{
|
|
356
|
+
"js_code": "async function mi_script(gufi) {...}",
|
|
357
|
+
"description": "Descripcion"
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Trigger click automation
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
POST /api/automation-scripts/triggerClick
|
|
365
|
+
{
|
|
366
|
+
"table": "m360_t16192",
|
|
367
|
+
"row_id": 123,
|
|
368
|
+
"function_name": "generar_pdf",
|
|
369
|
+
"input": { "formato": "A4" }
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Ver executions
|
|
374
|
+
|
|
375
|
+
```
|
|
376
|
+
GET /api/automation-executions?limit=20&script_name=mi_script
|
|
377
|
+
|
|
378
|
+
Response:
|
|
379
|
+
[
|
|
380
|
+
{
|
|
381
|
+
"id": 456,
|
|
382
|
+
"script_name": "mi_script",
|
|
383
|
+
"status": "completed",
|
|
384
|
+
"duration_ms": 234,
|
|
385
|
+
"created_at": "..."
|
|
386
|
+
}
|
|
387
|
+
]
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Marketplace
|
|
391
|
+
|
|
392
|
+
### Mis packages
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
GET /api/marketplace/developer/packages
|
|
396
|
+
|
|
397
|
+
Response:
|
|
398
|
+
[
|
|
399
|
+
{ "id": 14, "name": "Mi Package", "version": "1.0.0", "published": true }
|
|
400
|
+
]
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Detalle package
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
GET /api/marketplace/packages/{packageId}
|
|
407
|
+
|
|
408
|
+
Response:
|
|
409
|
+
{
|
|
410
|
+
"id": 14,
|
|
411
|
+
"name": "Mi Package",
|
|
412
|
+
"modules": [...],
|
|
413
|
+
"views": [...]
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Archivos de vista
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
GET /api/marketplace/views/{viewId}/files
|
|
421
|
+
|
|
422
|
+
Response:
|
|
423
|
+
{
|
|
424
|
+
"files": [
|
|
425
|
+
{ "path": "index.tsx", "content": "...", "language": "typescript" }
|
|
426
|
+
]
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Actualizar archivos
|
|
431
|
+
|
|
432
|
+
```
|
|
433
|
+
PUT /api/marketplace/views/{viewId}/files
|
|
434
|
+
{
|
|
435
|
+
"files": [
|
|
436
|
+
{ "path": "index.tsx", "content": "..." }
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Files
|
|
442
|
+
|
|
443
|
+
### Upload
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
POST /api/files/upload
|
|
447
|
+
Content-Type: multipart/form-data
|
|
448
|
+
|
|
449
|
+
FormData:
|
|
450
|
+
file: (binary)
|
|
451
|
+
|
|
452
|
+
Response:
|
|
453
|
+
{
|
|
454
|
+
"url": "company_116/abc123_file.pdf",
|
|
455
|
+
"name": "documento.pdf",
|
|
456
|
+
"size": 12345,
|
|
457
|
+
"mime": "application/pdf"
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Download
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
GET /api/files/download?path=company_116/abc123_file.pdf
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Environment Variables
|
|
468
|
+
|
|
469
|
+
### Listar
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
GET /api/cli/env
|
|
473
|
+
|
|
474
|
+
Response:
|
|
475
|
+
[
|
|
476
|
+
{ "key": "SLACK_WEBHOOK", "is_secret": true },
|
|
477
|
+
{ "key": "PUBLIC_URL", "is_secret": false, "value": "https://..." }
|
|
478
|
+
]
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Crear/actualizar
|
|
482
|
+
|
|
483
|
+
```
|
|
484
|
+
POST /api/cli/env
|
|
485
|
+
{
|
|
486
|
+
"key": "NEW_API_KEY",
|
|
487
|
+
"value": "sk-..."
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Eliminar
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
DELETE /api/cli/env/{key}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Operadores de filtro
|
|
498
|
+
|
|
499
|
+
Para usar en `/api/tables/{table}/list`:
|
|
500
|
+
|
|
501
|
+
| Operador | Descripcion | Ejemplo |
|
|
502
|
+
|----------|-------------|---------|
|
|
503
|
+
| `eq` | Igual | `{ "field": "estado", "operator": "eq", "value": "activo" }` |
|
|
504
|
+
| `ne` | No igual | `{ "field": "estado", "operator": "ne", "value": "cancelado" }` |
|
|
505
|
+
| `gt` | Mayor que | `{ "field": "total", "operator": "gt", "value": 100 }` |
|
|
506
|
+
| `gte` | Mayor o igual | `{ "field": "total", "operator": "gte", "value": 100 }` |
|
|
507
|
+
| `lt` | Menor que | `{ "field": "total", "operator": "lt", "value": 1000 }` |
|
|
508
|
+
| `lte` | Menor o igual | `{ "field": "total", "operator": "lte", "value": 1000 }` |
|
|
509
|
+
| `contains` | Contiene texto | `{ "field": "nombre", "operator": "contains", "value": "juan" }` |
|
|
510
|
+
| `in` | En lista | `{ "field": "estado", "operator": "in", "value": ["a", "b"] }` |
|
|
511
|
+
| `null` | Es nulo | `{ "field": "deleted_at", "operator": "null", "value": true }` |
|
|
512
|
+
|
|
513
|
+
## Codigos de error
|
|
514
|
+
|
|
515
|
+
| Codigo | Significado |
|
|
516
|
+
|--------|-------------|
|
|
517
|
+
| 400 | Bad Request - Parametros invalidos |
|
|
518
|
+
| 401 | Unauthorized - Token invalido/expirado |
|
|
519
|
+
| 403 | Forbidden - Sin permisos |
|
|
520
|
+
| 404 | Not Found - Recurso no existe |
|
|
521
|
+
| 409 | Conflict - Ya existe |
|
|
522
|
+
| 429 | Too Many Requests - Rate limit |
|
|
523
|
+
| 500 | Internal Server Error |
|
|
524
|
+
|
|
525
|
+
## Rate limits
|
|
526
|
+
|
|
527
|
+
Por defecto (configurables):
|
|
528
|
+
- Login: 5 intentos/minuto
|
|
529
|
+
- Uploads: 20/minuto
|
|
530
|
+
- AI: 10/minuto
|
|
531
|
+
- General: 100/minuto
|