neekuro 2.2.0 → 2.3.1
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/CHANGELOG.md +39 -14
- package/README.md +117 -117
- package/package.json +64 -64
- package/sources/classes/SFW.js +26 -5
- package/sources/classes/errors/APIError.js +49 -49
- package/sources/classes/errors/Error.js +21 -21
- package/sources/classes/package/NekoGif.js +46 -46
- package/sources/classes/package/welcome.js +446 -446
- package/sources/classes/user/BaseUser.js +20 -20
- package/sources/classes/user/User.js +34 -34
- package/sources/main/index.js +20 -20
- package/sources/rest/APIClient.js +34 -34
- package/sources/typings/index.d.ts +374 -355
- package/sources/utils/imageLoader.js +38 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.3.1] - 07-10-2026
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- La URL por defecto del API pasa a `https://maplebot.fyi/api/sfw`. El dominio anterior dejo de resolver, asi que las versiones previas no podian obtener ninguna imagen.
|
|
7
|
+
|
|
8
|
+
### Compatibility
|
|
9
|
+
- No cambia ninguna firma. Quien ya fijaba su endpoint con `SFW.setBaseURL()` no se ve afectado.
|
|
10
|
+
|
|
11
|
+
## [2.3.0] - 15-09-2026
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Nuevas subcategorías de `action`: `handhold`, `highfive`, `read` y `wave`.
|
|
15
|
+
- Nuevas subcategorías de `reaction`: `disgust`, `facepalm`, `happy`, `love`, `nervous`, `shrug` y `surprised`.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- El timeout de 10 segundos de las imágenes remotas ahora también cubre la lectura del cuerpo, no solo las cabeceras.
|
|
19
|
+
- Las respuestas descartadas (redirecciones, errores HTTP o formatos inválidos) liberan su conexión.
|
|
20
|
+
- El User-Agent de descarga de imágenes refleja la versión real del paquete.
|
|
21
|
+
- Declaraciones TypeScript: `APIError.determineMessage` es estático, se añade `APIError.fromNetworkError` y se corrige la resolución por defecto documentada (1140 × 520) y el ejemplo de `User.token()`.
|
|
22
|
+
- `SFW` muestra `Desconocido` cuando el anime llega como `Unknown`, no solo cuando viene vacío.
|
|
23
|
+
- `SFW` descarta las URL repetidas de una subcategoría: pesaban doble en el sorteo y podían salir dos veces seguidas.
|
|
24
|
+
|
|
25
|
+
### Compatibility
|
|
26
|
+
- Solo se añaden subcategorías; las existentes no cambian.
|
|
27
|
+
|
|
3
28
|
## [2.2.0] - 28-08-2026
|
|
4
29
|
|
|
5
30
|
### Added
|
|
@@ -34,18 +59,18 @@
|
|
|
34
59
|
- Se conserva la API encadenable de `Welcome`.
|
|
35
60
|
- `Error` continúa disponible como alias de `NekoError`.
|
|
36
61
|
- Las URLs HTTP de imágenes dejan de aceptarse; deben utilizar HTTPS.
|
|
37
|
-
|
|
38
|
-
## [2.0.3] - 07-04-2025
|
|
39
|
-
|
|
40
|
-
### Fixed
|
|
41
|
-
- **Error de Importaciones**
|
|
42
|
-
- Corregido el error de importaciones require('...')`
|
|
43
|
-
- Causaba que no se pudiera usar el paquete
|
|
44
|
-
- Se uso el mismo nombre para todas las importaciones respecto al archivo
|
|
45
|
-
- Afectaba a todos los usuarios que hacian uso de la api
|
|
46
|
-
|
|
47
|
-
**Impacto**:
|
|
48
|
-
- La actualizacion prevee que resuelva el error
|
|
49
|
-
- No requiere cambios en implementaciones existentes
|
|
50
|
-
|
|
62
|
+
|
|
63
|
+
## [2.0.3] - 07-04-2025
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
- **Error de Importaciones**
|
|
67
|
+
- Corregido el error de importaciones require('...')`
|
|
68
|
+
- Causaba que no se pudiera usar el paquete
|
|
69
|
+
- Se uso el mismo nombre para todas las importaciones respecto al archivo
|
|
70
|
+
- Afectaba a todos los usuarios que hacian uso de la api
|
|
71
|
+
|
|
72
|
+
**Impacto**:
|
|
73
|
+
- La actualizacion prevee que resuelva el error
|
|
74
|
+
- No requiere cambios en implementaciones existentes
|
|
75
|
+
|
|
51
76
|
Commit: (1e7380a)
|
package/README.md
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
<center> <h1>NeeKuro</h1> </center>
|
|
2
|
-
<center>de <b>Kmz Kuro</b> en nombre de <b>NexaTDC</b></center>
|
|
3
|
-
<center>creada apartir de <b>cacao_nekoapi</b> y <b>nekoapi.beta</b> en npm.js</center>
|
|
4
|
-
<br>
|
|
5
|
-
<center>
|
|
6
|
-
<img alt="NPM Version" src="https://img.shields.io/npm/v/neekuro?logo=npm&style=flat&color=0d8973">
|
|
7
|
-
<img alt="Downloads" src="https://img.shields.io/npm/dw/neekuro?style=flat&color=bf9308&label=Descargas">
|
|
8
|
-
<img alt="Typescript" src="https://img.shields.io/badge/declaraciones-typescript-blue?logo=typescript">
|
|
9
|
-
<img alt="NPM Version" src="https://img.shields.io/badge/node%20version-%3E=20.12.2-489248?logo=nodedotjs">
|
|
10
|
-
</center>
|
|
11
|
-
|
|
12
|
-
### ¿Qué es "NeeKuro"?
|
|
13
|
-
|
|
14
|
-
NeeKuro es una biblioteca de imágenes con temática de anime para bots de Discord e imagenes de bienvenida.
|
|
15
|
-
|
|
16
|
-
Principalmente se creo con el fin de ser unicamente para <b>Maple Bot</b>. Sin embargo, desde que se decidio hacer a Maple de codigo publico, tambien se decidio que tanto su API como paquete fuesen libres.
|
|
17
|
-
|
|
18
|
-
> notas: el paquete puede contener errores ya que se encuentra en fase beta, la API se hostea de manera gratuita por lo que las solicitudes no siempre pueden estar disponibles.
|
|
19
|
-
|
|
20
|
-
## Instalacion
|
|
21
|
-
|
|
22
|
-
```sh
|
|
23
|
-
npm install neekuro
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Ejemplos
|
|
27
|
-
|
|
28
|
-
NeeKuro es un paquete que requiere de un token para llevar a cabo sus sollicitudes, por lo que requieres de ir a la [API Oficial](https://
|
|
29
|
-
|
|
30
|
-
### primeros pasos
|
|
31
|
-
1 - Instanciamiento de usuario y establecimiento del token.<br>Este paso se requiere ya que con ello se establece globalmente el token por el paquete
|
|
32
|
-
<hr>
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
require('dotenv').config();
|
|
36
|
-
// importacion del paquete neekuro
|
|
37
|
-
const neekuro = require('neekuro');
|
|
38
|
-
|
|
39
|
-
// instanciamiento del usuario
|
|
40
|
-
const user = new neekuro.User();
|
|
41
|
-
|
|
42
|
-
// establecimiento del token
|
|
43
|
-
user.token(process.env['ApiToken'])
|
|
44
|
-
```
|
|
45
|
-
<hr>
|
|
46
|
-
|
|
47
|
-
#### Peticion de imagenes simple
|
|
48
|
-
Una vez estableciste el token puedes comenzar a pedir imagenes
|
|
49
|
-
|
|
50
|
-
```javascript
|
|
51
|
-
|
|
52
|
-
const neekuro = require('neekuro');
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Codigo de usuario
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
// es necesario escribir todo siempre dentro de una funcion asincrona
|
|
1
|
+
<center> <h1>NeeKuro</h1> </center>
|
|
2
|
+
<center>de <b>Kmz Kuro</b> en nombre de <b>NexaTDC</b></center>
|
|
3
|
+
<center>creada apartir de <b>cacao_nekoapi</b> y <b>nekoapi.beta</b> en npm.js</center>
|
|
4
|
+
<br>
|
|
5
|
+
<center>
|
|
6
|
+
<img alt="NPM Version" src="https://img.shields.io/npm/v/neekuro?logo=npm&style=flat&color=0d8973">
|
|
7
|
+
<img alt="Downloads" src="https://img.shields.io/npm/dw/neekuro?style=flat&color=bf9308&label=Descargas">
|
|
8
|
+
<img alt="Typescript" src="https://img.shields.io/badge/declaraciones-typescript-blue?logo=typescript">
|
|
9
|
+
<img alt="NPM Version" src="https://img.shields.io/badge/node%20version-%3E=20.12.2-489248?logo=nodedotjs">
|
|
10
|
+
</center>
|
|
11
|
+
|
|
12
|
+
### ¿Qué es "NeeKuro"?
|
|
13
|
+
|
|
14
|
+
NeeKuro es una biblioteca de imágenes con temática de anime para bots de Discord e imagenes de bienvenida.
|
|
15
|
+
|
|
16
|
+
Principalmente se creo con el fin de ser unicamente para <b>Maple Bot</b>. Sin embargo, desde que se decidio hacer a Maple de codigo publico, tambien se decidio que tanto su API como paquete fuesen libres.
|
|
17
|
+
|
|
18
|
+
> notas: el paquete puede contener errores ya que se encuentra en fase beta, la API se hostea de manera gratuita por lo que las solicitudes no siempre pueden estar disponibles.
|
|
19
|
+
|
|
20
|
+
## Instalacion
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm install neekuro
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Ejemplos
|
|
27
|
+
|
|
28
|
+
NeeKuro es un paquete que requiere de un token para llevar a cabo sus sollicitudes, por lo que requieres de ir a la [API Oficial](https://maplebot.fyi/api/) para poder generar un token.
|
|
29
|
+
|
|
30
|
+
### primeros pasos
|
|
31
|
+
1 - Instanciamiento de usuario y establecimiento del token.<br>Este paso se requiere ya que con ello se establece globalmente el token por el paquete
|
|
32
|
+
<hr>
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
require('dotenv').config();
|
|
36
|
+
// importacion del paquete neekuro
|
|
37
|
+
const neekuro = require('neekuro');
|
|
38
|
+
|
|
39
|
+
// instanciamiento del usuario
|
|
40
|
+
const user = new neekuro.User();
|
|
41
|
+
|
|
42
|
+
// establecimiento del token
|
|
43
|
+
user.token(process.env['ApiToken'])
|
|
44
|
+
```
|
|
45
|
+
<hr>
|
|
46
|
+
|
|
47
|
+
#### Peticion de imagenes simple
|
|
48
|
+
Una vez estableciste el token puedes comenzar a pedir imagenes
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
|
|
52
|
+
const neekuro = require('neekuro');
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Codigo de usuario
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
// es necesario escribir todo siempre dentro de una funcion asincrona
|
|
59
59
|
async function ObtenerImagen() {
|
|
60
|
-
// obtenemos un gif con el metodo getGif de SFW
|
|
61
|
-
const cuddle = await neekuro.SFW.getGif('action', 'cuddle');
|
|
62
|
-
|
|
63
|
-
// imprimimos la url y el anime del gif
|
|
64
|
-
console.log(cuddle.getUrl(), cuddle.getAnime())
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ejecutamos la funcion
|
|
60
|
+
// obtenemos un gif con el metodo getGif de SFW
|
|
61
|
+
const cuddle = await neekuro.SFW.getGif('action', 'cuddle');
|
|
62
|
+
|
|
63
|
+
// imprimimos la url y el anime del gif
|
|
64
|
+
console.log(cuddle.getUrl(), cuddle.getAnime())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ejecutamos la funcion
|
|
68
68
|
ObtenerImagen();
|
|
69
|
-
|
|
70
|
-
// nota: no te aguites por el gif y subcategoria, todo viene en documentado con typescript, solo tienes que completar los pasos :)
|
|
69
|
+
|
|
70
|
+
// nota: no te aguites por el gif y subcategoria, todo viene en documentado con typescript, solo tienes que completar los pasos :)
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
`getGif()` selecciona una imagen nuevamente en cada llamada. Internamente, NeeKuro
|
|
@@ -104,25 +104,25 @@ neekuro.SFW.setBaseURL('https://api.example.com/api/sfw');
|
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
#### Ejemplo de imagenes de bienvenida
|
|
107
|
-
Las imagenes de bienvenida son otra de las alternativas que otorga NeeKuro, puedes hacer una imagen de la siguiente manera:
|
|
108
|
-
```javascript
|
|
109
|
-
// obtenemos directamente la clase del paquete
|
|
110
|
-
const { Welcome } = require('neekuro');
|
|
111
|
-
const fs = require('fs');
|
|
112
|
-
|
|
113
|
-
// Configuración básica, añade un avatar titulo y descripción
|
|
114
|
-
const welcome = new Welcome()
|
|
115
|
-
.setAvatar('https://ejemplo.com/avatar.jpg')
|
|
116
|
-
.setTitle('¡Bienvenido!')
|
|
117
|
-
.setDescription('Al servidor de Discord');
|
|
118
|
-
|
|
119
|
-
// Genera y guarda la imagen
|
|
107
|
+
Las imagenes de bienvenida son otra de las alternativas que otorga NeeKuro, puedes hacer una imagen de la siguiente manera:
|
|
108
|
+
```javascript
|
|
109
|
+
// obtenemos directamente la clase del paquete
|
|
110
|
+
const { Welcome } = require('neekuro');
|
|
111
|
+
const fs = require('fs');
|
|
112
|
+
|
|
113
|
+
// Configuración básica, añade un avatar titulo y descripción
|
|
114
|
+
const welcome = new Welcome()
|
|
115
|
+
.setAvatar('https://ejemplo.com/avatar.jpg')
|
|
116
|
+
.setTitle('¡Bienvenido!')
|
|
117
|
+
.setDescription('Al servidor de Discord');
|
|
118
|
+
|
|
119
|
+
// Genera y guarda la imagen
|
|
120
120
|
welcome.build()
|
|
121
|
-
.then(image => fs.writeFileSync('bienvenida.png', image))
|
|
122
|
-
.then(() => console.log('Imagen creada correctamente!'))
|
|
123
|
-
.catch(err => console.error('Error:', err.message));
|
|
124
|
-
|
|
125
|
-
// nota: como antes, todo viene bien documentado en el paquete, solo sigue los pasos y explora por ti ;3
|
|
121
|
+
.then(image => fs.writeFileSync('bienvenida.png', image))
|
|
122
|
+
.then(() => console.log('Imagen creada correctamente!'))
|
|
123
|
+
.catch(err => console.error('Error:', err.message));
|
|
124
|
+
|
|
125
|
+
// nota: como antes, todo viene bien documentado en el paquete, solo sigue los pasos y explora por ti ;3
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
Las imágenes remotas deben usar HTTPS. El paquete limita cada descarga a 10 MB,
|
|
@@ -158,34 +158,34 @@ pnpm run pack:check
|
|
|
158
158
|
|
|
159
159
|
`pnpm run check` ejecuta las pruebas funcionales locales y comprueba las
|
|
160
160
|
declaraciones TypeScript. Ninguna de estas pruebas consulta la API remota.
|
|
161
|
-
<hr>
|
|
162
|
-
<center>
|
|
163
|
-
<p>Resultado esperado</p>
|
|
164
|
-
<img src="./sources/assets/example.png" style="width: 60%; max-width: 500px;" alt="Texto alternativo">
|
|
165
|
-
</center>
|
|
166
|
-
|
|
167
|
-
## Contenido
|
|
168
|
-
|
|
169
|
-
Lo siguente es lo que contiene (o contendra) el paquete
|
|
170
|
-
|
|
171
|
-
| Categoria | Descripción | |
|
|
172
|
-
|-|-|-|
|
|
173
|
-
| Sfw | Contenido de roleplay no nsfw | en desarrollo
|
|
174
|
-
| Nsfw | Contenido +18 general y roleplay | no comenzada
|
|
175
|
-
|
|
176
|
-
## Finalmente....
|
|
177
|
-
|
|
178
|
-
Tanto la API, paquete y bot se encuentran en desarrollo, ante todo te pedimos la mayor de las paciencias, te aseguraremos que el resultado te gustará! :'3
|
|
179
|
-
|
|
180
|
-
Finalmente te agradecemos tu preferencia y esperamos haber cumplido tus espectativas ;)
|
|
181
|
-
<br><br><hr>
|
|
182
|
-
|
|
183
|
-
### que se tiene planeado?
|
|
184
|
-
|
|
185
|
-
Principalmente terminaremos la categoria acción y reacción para tener la primer subida a NPM de este paquete y asi finalmente tener terminada la categoria SFW. <br> Sin embargo una de las problematicas que se nos presentan son buscar los gifs para la API asi como sus animes <b>es un proceso lento...</b> y agobiante...
|
|
186
|
-
<br>Por eso ahora mas que nunca queremos que nos apoyes en <b>NexaTDC</b>! Con el fin de poder dar al publico lo mas pronto posible los servicios que Maple Bot ofrece.
|
|
187
|
-
|
|
188
|
-
<b><i>No es para mi, es para la comunidad... Si no es para la comunidad, no es para nadie...</i></b>
|
|
189
|
-
<i>- NexaTDC</i>
|
|
190
|
-
<br><br><br><br>
|
|
191
|
-
CC. Creative Commons 2025 - @CacaoNk0027
|
|
161
|
+
<hr>
|
|
162
|
+
<center>
|
|
163
|
+
<p>Resultado esperado</p>
|
|
164
|
+
<img src="./sources/assets/example.png" style="width: 60%; max-width: 500px;" alt="Texto alternativo">
|
|
165
|
+
</center>
|
|
166
|
+
|
|
167
|
+
## Contenido
|
|
168
|
+
|
|
169
|
+
Lo siguente es lo que contiene (o contendra) el paquete
|
|
170
|
+
|
|
171
|
+
| Categoria | Descripción | |
|
|
172
|
+
|-|-|-|
|
|
173
|
+
| Sfw | Contenido de roleplay no nsfw | en desarrollo
|
|
174
|
+
| Nsfw | Contenido +18 general y roleplay | no comenzada
|
|
175
|
+
|
|
176
|
+
## Finalmente....
|
|
177
|
+
|
|
178
|
+
Tanto la API, paquete y bot se encuentran en desarrollo, ante todo te pedimos la mayor de las paciencias, te aseguraremos que el resultado te gustará! :'3
|
|
179
|
+
|
|
180
|
+
Finalmente te agradecemos tu preferencia y esperamos haber cumplido tus espectativas ;)
|
|
181
|
+
<br><br><hr>
|
|
182
|
+
|
|
183
|
+
### que se tiene planeado?
|
|
184
|
+
|
|
185
|
+
Principalmente terminaremos la categoria acción y reacción para tener la primer subida a NPM de este paquete y asi finalmente tener terminada la categoria SFW. <br> Sin embargo una de las problematicas que se nos presentan son buscar los gifs para la API asi como sus animes <b>es un proceso lento...</b> y agobiante...
|
|
186
|
+
<br>Por eso ahora mas que nunca queremos que nos apoyes en <b>NexaTDC</b>! Con el fin de poder dar al publico lo mas pronto posible los servicios que Maple Bot ofrece.
|
|
187
|
+
|
|
188
|
+
<b><i>No es para mi, es para la comunidad... Si no es para la comunidad, no es para nadie...</i></b>
|
|
189
|
+
<i>- NexaTDC</i>
|
|
190
|
+
<br><br><br><br>
|
|
191
|
+
CC. Creative Commons 2025 - @CacaoNk0027
|
package/package.json
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"name": "neekuro",
|
|
4
|
-
"version": "2.
|
|
5
|
-
"description": "Una biblioteca de imágenes con temática de anime para bots de Discord.",
|
|
6
|
-
"main": "sources/main/index.js",
|
|
7
|
-
"types": "sources/typings/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": {
|
|
11
|
-
"types": "./sources/typings/index.d.ts",
|
|
12
|
-
"default": "./sources/main/index.js"
|
|
13
|
-
},
|
|
14
|
-
"require": {
|
|
15
|
-
"types": "./sources/typings/index.d.ts",
|
|
16
|
-
"default": "./sources/main/index.js"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"directories": {
|
|
21
|
-
"test": "test"
|
|
22
|
-
},
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "neekuro",
|
|
4
|
+
"version": "2.3.1",
|
|
5
|
+
"description": "Una biblioteca de imágenes con temática de anime para bots de Discord.",
|
|
6
|
+
"main": "sources/main/index.js",
|
|
7
|
+
"types": "sources/typings/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./sources/typings/index.d.ts",
|
|
12
|
+
"default": "./sources/main/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./sources/typings/index.d.ts",
|
|
16
|
+
"default": "./sources/main/index.js"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"directories": {
|
|
21
|
+
"test": "test"
|
|
22
|
+
},
|
|
23
23
|
"files": [
|
|
24
24
|
"sources",
|
|
25
25
|
"README.md",
|
|
26
26
|
"CHANGELOG.md"
|
|
27
27
|
],
|
|
28
|
-
"contributors": [
|
|
29
|
-
"cacao0027 <kmzkuro@gmail.com>"
|
|
30
|
-
],
|
|
31
|
-
"author": "cacao0027 <kmzkuro@gmail.com>",
|
|
32
|
-
"keywords": [
|
|
33
|
-
"anime",
|
|
34
|
-
"acción",
|
|
35
|
-
"gifs",
|
|
36
|
-
"imagenes",
|
|
37
|
-
"nsfw",
|
|
38
|
-
"sfw",
|
|
39
|
-
"discord",
|
|
40
|
-
"action",
|
|
41
|
-
"images"
|
|
42
|
-
],
|
|
43
|
-
"license": "ISC",
|
|
44
|
-
"packageManager": "pnpm@11.23.0",
|
|
45
|
-
"scripts": {
|
|
46
|
-
"test": "node --test test/*.test.js",
|
|
47
|
-
"check": "node --check sources/main/index.js && node --test test/*.test.js && tsc -p test/tsconfig.json",
|
|
48
|
-
"pack:check": "npm pack --dry-run"
|
|
49
|
-
},
|
|
50
|
-
"engines": {
|
|
51
|
-
"node": ">=20.12.2"
|
|
52
|
-
},
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"canvas": "^3.1.0",
|
|
55
|
-
"hex-color-regex": "^1.1.0"
|
|
56
|
-
},
|
|
57
|
-
"devDependencies": {
|
|
58
|
-
"@types/node": "^24.0.0",
|
|
59
|
-
"typescript": "^5.9.0"
|
|
60
|
-
},
|
|
61
|
-
"repository": {
|
|
62
|
-
"type": "git",
|
|
63
|
-
"url": "git+https://github.com/CacaoNk0027/neekuro_package.git"
|
|
64
|
-
},
|
|
65
|
-
"bugs": {
|
|
66
|
-
"url": "https://github.com/CacaoNk0027/neekuro_package/issues"
|
|
67
|
-
},
|
|
68
|
-
"homepage": "https://github.com/CacaoNk0027/neekuro_package#readme"
|
|
69
|
-
}
|
|
28
|
+
"contributors": [
|
|
29
|
+
"cacao0027 <kmzkuro@gmail.com>"
|
|
30
|
+
],
|
|
31
|
+
"author": "cacao0027 <kmzkuro@gmail.com>",
|
|
32
|
+
"keywords": [
|
|
33
|
+
"anime",
|
|
34
|
+
"acción",
|
|
35
|
+
"gifs",
|
|
36
|
+
"imagenes",
|
|
37
|
+
"nsfw",
|
|
38
|
+
"sfw",
|
|
39
|
+
"discord",
|
|
40
|
+
"action",
|
|
41
|
+
"images"
|
|
42
|
+
],
|
|
43
|
+
"license": "ISC",
|
|
44
|
+
"packageManager": "pnpm@11.23.0",
|
|
45
|
+
"scripts": {
|
|
46
|
+
"test": "node --test test/*.test.js",
|
|
47
|
+
"check": "node --check sources/main/index.js && node --test test/*.test.js && tsc -p test/tsconfig.json",
|
|
48
|
+
"pack:check": "npm pack --dry-run"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.12.2"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"canvas": "^3.1.0",
|
|
55
|
+
"hex-color-regex": "^1.1.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^24.0.0",
|
|
59
|
+
"typescript": "^5.9.0"
|
|
60
|
+
},
|
|
61
|
+
"repository": {
|
|
62
|
+
"type": "git",
|
|
63
|
+
"url": "git+https://github.com/CacaoNk0027/neekuro_package.git"
|
|
64
|
+
},
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/CacaoNk0027/neekuro_package/issues"
|
|
67
|
+
},
|
|
68
|
+
"homepage": "https://github.com/CacaoNk0027/neekuro_package#readme"
|
|
69
|
+
}
|
package/sources/classes/SFW.js
CHANGED
|
@@ -12,7 +12,7 @@ const NekoError = require('./errors/Error.js');
|
|
|
12
12
|
const NekoGif = require('./package/NekoGif.js');
|
|
13
13
|
const { getToken, getTokenVersion } = require('./user/BaseUser.js');
|
|
14
14
|
|
|
15
|
-
const DEFAULT_BASE_URL = 'https://
|
|
15
|
+
const DEFAULT_BASE_URL = 'https://maplebot.fyi/api/sfw';
|
|
16
16
|
const DEFAULT_CACHE_TTL = 5 * 60 * 1000;
|
|
17
17
|
const MAX_CACHE_ENTRIES = 100;
|
|
18
18
|
|
|
@@ -174,9 +174,15 @@ async function requestGifList(category, gif, token) {
|
|
|
174
174
|
throw new NekoError('EmptyResponse', `La API no devolvió GIF para ${category}/${gif}`);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
const items = response.data.map((item, index) => normalizeGif(item, category, gif, index));
|
|
178
|
+
return removeDuplicateURLs(items);
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
const UNKNOWN_ANIME = 'Desconocido';
|
|
182
|
+
// Valores que la base de datos usa para "sin dato". Se tratan igual que un
|
|
183
|
+
// campo vacío para no mostrar, por ejemplo, "Unknown" en un embed en español.
|
|
184
|
+
const PLACEHOLDER_ANIME = new Set(['unknown', 'desconocido']);
|
|
185
|
+
|
|
180
186
|
/**
|
|
181
187
|
* @param {unknown} item
|
|
182
188
|
* @param {string} category
|
|
@@ -189,11 +195,26 @@ function normalizeGif(item, category, gif, index) {
|
|
|
189
195
|
throw new NekoError('InvalidResponse', `El GIF ${index} de ${category}/${gif} no contiene una URL válida`);
|
|
190
196
|
}
|
|
191
197
|
|
|
198
|
+
const anime = typeof item.anime === 'string' ? item.anime.trim() : '';
|
|
192
199
|
return Object.freeze({
|
|
193
200
|
url: item.url.trim(),
|
|
194
|
-
anime:
|
|
195
|
-
|
|
196
|
-
|
|
201
|
+
anime: anime && !PLACEHOLDER_ANIME.has(anime.toLowerCase()) ? anime : UNKNOWN_ANIME
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Conserva la primera aparición de cada URL. Una URL repetida pesa doble en el
|
|
207
|
+
* sorteo y puede salir dos veces seguidas, porque la selección evita repetir
|
|
208
|
+
* posiciones, no URLs.
|
|
209
|
+
* @param {GifData[]} items
|
|
210
|
+
* @returns {GifData[]}
|
|
211
|
+
*/
|
|
212
|
+
function removeDuplicateURLs(items) {
|
|
213
|
+
const seen = new Set();
|
|
214
|
+
return items.filter(item => {
|
|
215
|
+
if (seen.has(item.url)) return false;
|
|
216
|
+
seen.add(item.url);
|
|
217
|
+
return true;
|
|
197
218
|
});
|
|
198
219
|
}
|
|
199
220
|
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {import('../../typings').ApiResponse} ApiResponse
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('../../typings').ApiResponse} ApiResponse
|
|
5
5
|
* @typedef {{url?: string, status?: number}} ResponseLike
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Clase APIError
|
|
10
|
-
* Errores personalizados respecto a la api rest
|
|
11
|
-
* @extends Error
|
|
12
|
-
*/
|
|
13
|
-
class APIError extends Error {
|
|
14
|
-
/**
|
|
15
|
-
* Crea la instancia del error
|
|
16
|
-
* @param {string} endpoint la ruta a la que se realizo la peticion
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Clase APIError
|
|
10
|
+
* Errores personalizados respecto a la api rest
|
|
11
|
+
* @extends Error
|
|
12
|
+
*/
|
|
13
|
+
class APIError extends Error {
|
|
14
|
+
/**
|
|
15
|
+
* Crea la instancia del error
|
|
16
|
+
* @param {string} endpoint la ruta a la que se realizo la peticion
|
|
17
17
|
* @param {ResponseLike} response respuesta HTTP o representación de un error de red
|
|
18
|
-
* @param {ApiResponse} data respuesta de la api
|
|
19
|
-
*/
|
|
18
|
+
* @param {ApiResponse} data respuesta de la api
|
|
19
|
+
*/
|
|
20
20
|
constructor(endpoint, response, data) {
|
|
21
21
|
super(APIError.determineMessage(data));
|
|
22
|
-
|
|
23
|
-
this.name = `NekoREST Error [${endpoint}]`
|
|
24
|
-
/**
|
|
25
|
-
* @type {string}
|
|
26
|
-
*/
|
|
27
|
-
this.url = response?.url ?? 'unknown';
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @type {number}
|
|
31
|
-
*/
|
|
22
|
+
|
|
23
|
+
this.name = `NekoREST Error [${endpoint}]`
|
|
24
|
+
/**
|
|
25
|
+
* @type {string}
|
|
26
|
+
*/
|
|
27
|
+
this.url = response?.url ?? 'unknown';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @type {number}
|
|
31
|
+
*/
|
|
32
32
|
this.statusCode = Number.parseInt(response?.status ?? 500, 10);
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @type {ApiResponse}
|
|
36
|
-
*/
|
|
37
|
-
this.data = data
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Determina el mensaje del error basado en el codigo de la api
|
|
43
|
-
* @param {ApiResponse} response respuesta de la api
|
|
44
|
-
* @returns {string} mensaje de error
|
|
45
|
-
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @type {ApiResponse}
|
|
36
|
+
*/
|
|
37
|
+
this.data = data
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Determina el mensaje del error basado en el codigo de la api
|
|
43
|
+
* @param {ApiResponse} response respuesta de la api
|
|
44
|
+
* @returns {string} mensaje de error
|
|
45
|
+
*/
|
|
46
46
|
static determineMessage(response = {}) {
|
|
47
|
-
if(response.code === 403) {
|
|
48
|
-
return 'TOKEN ERROR: el token que haz proporcionado es invalido'
|
|
49
|
-
} else
|
|
50
|
-
if(response.code === 401) {
|
|
51
|
-
return 'TOKEN ERROR: no se proporciono un token'
|
|
52
|
-
} else {
|
|
53
|
-
return response.message ?? 'descripcion no dada'
|
|
54
|
-
}
|
|
47
|
+
if(response.code === 403) {
|
|
48
|
+
return 'TOKEN ERROR: el token que haz proporcionado es invalido'
|
|
49
|
+
} else
|
|
50
|
+
if(response.code === 401) {
|
|
51
|
+
return 'TOKEN ERROR: no se proporciono un token'
|
|
52
|
+
} else {
|
|
53
|
+
return response.message ?? 'descripcion no dada'
|
|
54
|
+
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
static fromNetworkError(endpoint, url, message) {
|
|
58
58
|
return new APIError(endpoint, { url, status: 503 }, { code: 503, message });
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
module.exports = APIError
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Clase de erorres para la API
|
|
5
|
-
* @extends Error
|
|
6
|
-
*/
|
|
7
|
-
class NekoError extends Error {
|
|
8
|
-
/**
|
|
9
|
-
* Crea una instancia para errores del paquete
|
|
10
|
-
* @param {string} name Corresponde al nombre del error
|
|
11
|
-
* @param {string} message Mensaje de error
|
|
12
|
-
*/
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clase de erorres para la API
|
|
5
|
+
* @extends Error
|
|
6
|
+
*/
|
|
7
|
+
class NekoError extends Error {
|
|
8
|
+
/**
|
|
9
|
+
* Crea una instancia para errores del paquete
|
|
10
|
+
* @param {string} name Corresponde al nombre del error
|
|
11
|
+
* @param {string} message Mensaje de error
|
|
12
|
+
*/
|
|
13
13
|
constructor(name, message) {
|
|
14
14
|
super(message);
|
|
15
|
-
|
|
16
|
-
this.name = `NeeKuro Error [${name}]`
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @type {string}
|
|
20
|
-
*/
|
|
15
|
+
|
|
16
|
+
this.name = `NeeKuro Error [${name}]`
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
21
|
this.message = message
|
|
22
22
|
Error.captureStackTrace?.(this, NekoError);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
26
|
module.exports = NekoError
|