@soyaxell09/zenbot-scraper 1.0.9 → 1.0.11
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 +107 -187
- package/package.json +10 -4
- package/src/index.js +7 -0
- package/src/nsfw/index.js +14 -0
- package/src/nsfw/phdl.js +147 -0
- package/src/nsfw/phsearch.js +48 -0
- package/src/nsfw/rule34.js +80 -0
- package/src/nsfw/xnxxdl.js +81 -0
- package/src/nsfw/xnxxsearch.js +59 -0
- package/src/nsfw/xvideosdl.js +79 -0
- package/src/nsfw/xvideossearch.js +54 -0
- package/test.js +20 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @soyaxell09/zenbot-scraper
|
|
2
2
|
|
|
3
|
-
Módulo npm de scrapers y herramientas para bots de WhatsApp. Incluye descargadores, buscadores y
|
|
3
|
+
Módulo npm de scrapers y herramientas para bots de WhatsApp. Incluye descargadores, buscadores, utilidades y contenido NSFW.
|
|
4
4
|
|
|
5
5
|
## Instalación
|
|
6
6
|
|
|
@@ -16,7 +16,8 @@ npm install @soyaxell09/zenbot-scraper
|
|
|
16
16
|
src/
|
|
17
17
|
├── scrapers/ → Descargadores de media
|
|
18
18
|
├── search/ → Buscadores
|
|
19
|
-
|
|
19
|
+
├── tools/ → Utilidades
|
|
20
|
+
└── nsfw/ → Contenido adulto
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
---
|
|
@@ -28,11 +29,9 @@ src/
|
|
|
28
29
|
```js
|
|
29
30
|
import { ytSearch, ytDownload, ytInfo } from '@soyaxell09/zenbot-scraper'
|
|
30
31
|
|
|
31
|
-
// Buscar videos
|
|
32
32
|
const results = await ytSearch('bad bunny', 5)
|
|
33
33
|
// → [{ id, title, url, thumbnail, duration, views, channel, published }]
|
|
34
34
|
|
|
35
|
-
// Descargar (URL o texto)
|
|
36
35
|
const video = await ytDownload('https://youtu.be/dQw4w9WgXcQ', 'video', '360p')
|
|
37
36
|
const audio = await ytDownload('nicki nicole wapo traketero', 'mp3')
|
|
38
37
|
// → { title, author, thumbnail, type, url, duration, ... }
|
|
@@ -43,35 +42,13 @@ const audio = await ytDownload('nicki nicole wapo traketero', 'mp3')
|
|
|
43
42
|
```js
|
|
44
43
|
import { ytDownloadV2, ytInfoV2, getFileSizeV2 } from '@soyaxell09/zenbot-scraper'
|
|
45
44
|
|
|
46
|
-
// Ver calidades disponibles
|
|
47
45
|
const info = await ytInfoV2('https://youtu.be/dQw4w9WgXcQ')
|
|
48
46
|
// → { title, uploader, views, thumb, qualities: [{ id, type, quality, size, sizeB, duration }] }
|
|
49
47
|
|
|
50
|
-
// Descargar con calidad específica
|
|
51
48
|
const video = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'video', '1080p')
|
|
52
49
|
const audio = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'mp3', '128k')
|
|
53
50
|
// → { title, uploader, views, thumb, type, quality, size, sizeB, duration, url }
|
|
54
51
|
|
|
55
|
-
// Obtener tamaño de un archivo por URL
|
|
56
|
-
const size = await getFileSizeV2('https://example.com/file.mp4')
|
|
57
|
-
// → '14.5 MB'
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### YouTube v2 (via ytdown.to — más calidades)
|
|
61
|
-
|
|
62
|
-
```js
|
|
63
|
-
import { ytDownloadV2, ytInfoV2, getFileSizeV2 } from '@soyaxell09/zenbot-scraper'
|
|
64
|
-
|
|
65
|
-
// Ver calidades disponibles
|
|
66
|
-
const info = await ytInfoV2('https://youtu.be/dQw4w9WgXcQ')
|
|
67
|
-
// → { title, uploader, views, thumb, qualities: [{ id, type, quality, size, sizeB, duration }] }
|
|
68
|
-
|
|
69
|
-
// Descargar con calidad específica
|
|
70
|
-
const video = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'video', '1080p')
|
|
71
|
-
const audio = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'mp3', '128k')
|
|
72
|
-
// → { title, uploader, views, thumb, type, quality, size, sizeB, duration, url }
|
|
73
|
-
|
|
74
|
-
// Obtener tamaño de un archivo por URL
|
|
75
52
|
const size = await getFileSizeV2('https://example.com/file.mp4')
|
|
76
53
|
// → '14.5 MB'
|
|
77
54
|
```
|
|
@@ -99,29 +76,13 @@ const result = await fbDownload('https://www.facebook.com/watch?v=123')
|
|
|
99
76
|
```js
|
|
100
77
|
import { tweetInfo, tweetDownload } from '@soyaxell09/zenbot-scraper'
|
|
101
78
|
|
|
102
|
-
// Info completa del tweet
|
|
103
79
|
const info = await tweetInfo('https://x.com/user/status/123')
|
|
104
80
|
// → { id, text, lang, createdAt, likes, replies, author: { name, username, avatar }, hashtags, mentions, medias }
|
|
105
81
|
|
|
106
|
-
// Solo media descargable
|
|
107
82
|
const media = await tweetDownload('https://x.com/user/status/123')
|
|
108
83
|
// → { id, text, author, videos: [{ type, url, thumbnail, variants }], photos: [{ type, url, width, height }] }
|
|
109
84
|
```
|
|
110
85
|
|
|
111
|
-
### Twitter / X
|
|
112
|
-
|
|
113
|
-
```js
|
|
114
|
-
import { tweetInfo, tweetDownload } from '@soyaxell09/zenbot-scraper'
|
|
115
|
-
|
|
116
|
-
// Info completa del tweet
|
|
117
|
-
const info = await tweetInfo('https://x.com/user/status/123')
|
|
118
|
-
// → { id, text, createdAt, likes, replies, author: { name, username, avatar }, hashtags, medias }
|
|
119
|
-
|
|
120
|
-
// Solo media descargable
|
|
121
|
-
const media = await tweetDownload('https://x.com/user/status/123')
|
|
122
|
-
// → { id, text, author, videos: [{ type, url, thumbnail }], photos: [{ type, url }] }
|
|
123
|
-
```
|
|
124
|
-
|
|
125
86
|
### MediaFire
|
|
126
87
|
|
|
127
88
|
```js
|
|
@@ -136,35 +97,10 @@ const result = await mediafireInfo('https://www.mediafire.com/file/abc123/archiv
|
|
|
136
97
|
```js
|
|
137
98
|
import { githubInfo, githubRelease, githubContents, githubSearch } from '@soyaxell09/zenbot-scraper'
|
|
138
99
|
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
// → { name, fullName, description, url, stars, forks, language, license, topics, owner, cloneUrl, zipUrl, ... }
|
|
142
|
-
|
|
143
|
-
// Último release
|
|
144
|
-
const release = await githubRelease('facebook/react')
|
|
145
|
-
// → { tag, name, body, publishedAt, url, assets: [{ name, size, downloadUrl, downloads }] }
|
|
146
|
-
|
|
147
|
-
// Contenido de un directorio o archivo
|
|
100
|
+
const info = await githubInfo('facebook/react')
|
|
101
|
+
const release = await githubRelease('facebook/react')
|
|
148
102
|
const contents = await githubContents('facebook/react', 'src')
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// Buscar repositorios o usuarios
|
|
152
|
-
const repos = await githubSearch('whatsapp bot', 'repositories', 5)
|
|
153
|
-
// → [{ name, description, url, stars, forks, language, updatedAt }]
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### APK (APKPure)
|
|
157
|
-
|
|
158
|
-
```js
|
|
159
|
-
import { apkSearch, apkInfo } from '@soyaxell09/zenbot-scraper'
|
|
160
|
-
|
|
161
|
-
// Buscar por nombre
|
|
162
|
-
const results = await apkSearch('whatsapp', 3)
|
|
163
|
-
// → [{ name, developer, pkg, date, icon, appUrl, dlUrl }]
|
|
164
|
-
|
|
165
|
-
// Info por package name
|
|
166
|
-
const info = await apkInfo('com.whatsapp')
|
|
167
|
-
// → { name, developer, pkg, date, icon, download, dlLinks, url }
|
|
103
|
+
const repos = await githubSearch('whatsapp bot', 'repositories', 5)
|
|
168
104
|
```
|
|
169
105
|
|
|
170
106
|
### APK (APKPure)
|
|
@@ -172,36 +108,25 @@ const info = await apkInfo('com.whatsapp')
|
|
|
172
108
|
```js
|
|
173
109
|
import { apkSearch, apkInfo } from '@soyaxell09/zenbot-scraper'
|
|
174
110
|
|
|
175
|
-
// Buscar por nombre
|
|
176
111
|
const results = await apkSearch('whatsapp', 3)
|
|
177
112
|
// → [{ name, developer, pkg, date, icon, appUrl, dlUrl }]
|
|
178
113
|
|
|
179
|
-
// Info por package name
|
|
180
114
|
const info = await apkInfo('com.whatsapp')
|
|
181
115
|
// → { name, developer, pkg, date, icon, download, dlLinks, url }
|
|
182
116
|
```
|
|
183
117
|
|
|
184
|
-
|
|
185
118
|
### Google Drive
|
|
186
119
|
|
|
187
120
|
```js
|
|
188
121
|
import { gdriveInfo, gdriveDownload } from '@soyaxell09/zenbot-scraper'
|
|
189
122
|
|
|
190
|
-
// Info del archivo
|
|
191
123
|
const info = await gdriveInfo('https://drive.google.com/file/d/1ABC.../view')
|
|
192
124
|
// → { fileId, name, download, url }
|
|
193
125
|
|
|
194
|
-
// Descargar archivo (devuelve buffer)
|
|
195
126
|
const file = await gdriveDownload('https://drive.google.com/file/d/1ABC.../view')
|
|
196
127
|
// → { fileId, buffer, contentType, size, url }
|
|
197
|
-
|
|
198
|
-
// También acepta ID directo
|
|
199
|
-
const file2 = await gdriveDownload('1mkfqv5lwuNGpKatPRzPP4r01N6ZFxwBY')
|
|
200
128
|
```
|
|
201
129
|
|
|
202
|
-
> Soporta archivos públicos. Para archivos grandes maneja automáticamente la confirmación del virus scan de Google.
|
|
203
|
-
|
|
204
|
-
|
|
205
130
|
---
|
|
206
131
|
|
|
207
132
|
## 🔍 Search
|
|
@@ -220,12 +145,8 @@ const results = await googleSearch('node.js tutorial', 5)
|
|
|
220
145
|
```js
|
|
221
146
|
import { spotify } from '@soyaxell09/zenbot-scraper'
|
|
222
147
|
|
|
223
|
-
// Buscar tracks
|
|
224
148
|
const tracks = await spotify('bad bunny', 'tracks', 5)
|
|
225
149
|
// → [{ title, artist, album, duration, thumbnail, url, preview }]
|
|
226
|
-
|
|
227
|
-
// Buscar álbumes
|
|
228
|
-
const albums = await spotify('bad bunny', 'albums', 3)
|
|
229
150
|
```
|
|
230
151
|
|
|
231
152
|
### Tenor (GIFs)
|
|
@@ -242,24 +163,12 @@ const gifs = await giphy('funny cat', 5)
|
|
|
242
163
|
```js
|
|
243
164
|
import { pinsearch, pinimg, pinvid } from '@soyaxell09/zenbot-scraper'
|
|
244
165
|
|
|
245
|
-
// Buscar imágenes por texto
|
|
246
166
|
const imgs = await pinsearch('anime wallpaper', 5)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
// Imagen de un pin específico o por texto
|
|
250
|
-
const pin = await pinimg('https://www.pinterest.com/pin/123/')
|
|
251
|
-
const byText = await pinimg('anime wallpaper', 5)
|
|
252
|
-
// → { id, title, description, image, images, url } | [{ index, image, url }]
|
|
253
|
-
|
|
254
|
-
// Buscar videos por texto o URL de pin
|
|
167
|
+
const pin = await pinimg('https://www.pinterest.com/pin/123/')
|
|
255
168
|
const vids = await pinvid('anime', 5)
|
|
256
|
-
const pinVid = await pinvid('https://www.pinterest.com/pin/123/')
|
|
257
|
-
// → [{ index, video, sd, original }]
|
|
258
169
|
```
|
|
259
170
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
### Imágenes de Anime (Wallhaven + Konachan)
|
|
171
|
+
### Imágenes de Anime
|
|
263
172
|
|
|
264
173
|
```js
|
|
265
174
|
import { animeImage } from '@soyaxell09/zenbot-scraper'
|
|
@@ -268,9 +177,7 @@ const results = await animeImage('naruto', 5)
|
|
|
268
177
|
// → [{ image, url, source }]
|
|
269
178
|
```
|
|
270
179
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
### Wallpapers (BestHDWallpaper)
|
|
180
|
+
### Wallpapers
|
|
274
181
|
|
|
275
182
|
```js
|
|
276
183
|
import { wallpaperSearch } from '@soyaxell09/zenbot-scraper'
|
|
@@ -279,45 +186,18 @@ const results = await wallpaperSearch('nature', 10)
|
|
|
279
186
|
// → [{ title, image, url }]
|
|
280
187
|
```
|
|
281
188
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
### Stickers (GetStickerPack)
|
|
189
|
+
### Stickers
|
|
285
190
|
|
|
286
191
|
```js
|
|
287
192
|
import { stickerSearch } from '@soyaxell09/zenbot-scraper'
|
|
288
193
|
|
|
289
|
-
// Buscar packs por texto — devuelve un pack aleatorio con sus stickers
|
|
290
194
|
const result = await stickerSearch('anime', 10)
|
|
291
|
-
// → {
|
|
292
|
-
// status: true,
|
|
293
|
-
// nombre: 'My Hero Academia',
|
|
294
|
-
// creador: '@false_eye',
|
|
295
|
-
// total: 39,
|
|
296
|
-
// fotos: ['https://s3.getstickerpack.com/...webp', ...],
|
|
297
|
-
// url: 'https://getstickerpack.com/stickers/...'
|
|
298
|
-
// }
|
|
195
|
+
// → { status, nombre, creador, total, fotos, url }
|
|
299
196
|
```
|
|
300
197
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
### YouTube v2 (via ytdown.to — más calidades)
|
|
304
|
-
|
|
305
|
-
```js
|
|
306
|
-
import { ytDownloadV2, ytInfoV2, getFileSizeV2 } from '@soyaxell09/zenbot-scraper'
|
|
307
|
-
|
|
308
|
-
// Ver calidades disponibles
|
|
309
|
-
const info = await ytInfoV2('https://youtu.be/dQw4w9WgXcQ')
|
|
310
|
-
// → { title, uploader, views, thumb, qualities: [{ id, type, quality, size, sizeB, duration }] }
|
|
311
|
-
|
|
312
|
-
// Descargar con calidad específica
|
|
313
|
-
const video = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'video', '1080p')
|
|
314
|
-
const audio = await ytDownloadV2('https://youtu.be/dQw4w9WgXcQ', 'mp3', '128k')
|
|
315
|
-
// → { title, uploader, views, thumb, type, quality, size, sizeB, duration, url }
|
|
198
|
+
---
|
|
316
199
|
|
|
317
|
-
|
|
318
|
-
const size = await getFileSizeV2('https://example.com/file.mp4')
|
|
319
|
-
// → '14.5 MB'
|
|
320
|
-
```
|
|
200
|
+
## 🛠️ Tools
|
|
321
201
|
|
|
322
202
|
### TikTok Stalk
|
|
323
203
|
|
|
@@ -325,7 +205,7 @@ const size = await getFileSizeV2('https://example.com/file.mp4')
|
|
|
325
205
|
import { tiktokStalk } from '@soyaxell09/zenbot-scraper'
|
|
326
206
|
|
|
327
207
|
const profile = await tiktokStalk('charlidamelio')
|
|
328
|
-
// → { id, username, nickname, bio, avatar, verified, private, bioLink, stats
|
|
208
|
+
// → { id, username, nickname, bio, avatar, verified, private, bioLink, stats, url }
|
|
329
209
|
```
|
|
330
210
|
|
|
331
211
|
### Letras de canciones
|
|
@@ -333,13 +213,8 @@ const profile = await tiktokStalk('charlidamelio')
|
|
|
333
213
|
```js
|
|
334
214
|
import { lyricsSearch, lyricsGet } from '@soyaxell09/zenbot-scraper'
|
|
335
215
|
|
|
336
|
-
// Buscar por texto libre
|
|
337
216
|
const results = await lyricsSearch('bad bunny tití me preguntó', 3)
|
|
338
|
-
|
|
339
|
-
// lrc = letra sincronizada con timestamps [00:00.00]
|
|
340
|
-
|
|
341
|
-
// Buscar por artista y título
|
|
342
|
-
const song = await lyricsGet('Bad Bunny', 'Tití Me Preguntó')
|
|
217
|
+
const song = await lyricsGet('Bad Bunny', 'Tití Me Preguntó')
|
|
343
218
|
// → { id, title, artist, album, duration, lyrics, lrc }
|
|
344
219
|
```
|
|
345
220
|
|
|
@@ -348,18 +223,11 @@ const song = await lyricsGet('Bad Bunny', 'Tití Me Preguntó')
|
|
|
348
223
|
```js
|
|
349
224
|
import { translate, getLangs } from '@soyaxell09/zenbot-scraper'
|
|
350
225
|
|
|
351
|
-
// Traducir (auto-detecta idioma origen)
|
|
352
226
|
const result = await translate('Hello, how are you?', 'es')
|
|
353
227
|
// → { original, translated, from, to, fromName, toName, source }
|
|
354
228
|
|
|
355
|
-
// Especificar idioma origen
|
|
356
|
-
const result2 = await translate('Hola cómo estás', 'en', 'es')
|
|
357
|
-
|
|
358
|
-
// Ver idiomas disponibles
|
|
359
229
|
const langs = getLangs()
|
|
360
|
-
// → [{ code
|
|
361
|
-
|
|
362
|
-
// Códigos disponibles: es, en, pt, fr, de, it, ja, ko, zh, ru, ar, hi, tr, nl, pl, sv, uk, vi, id
|
|
230
|
+
// → [{ code, name }]
|
|
363
231
|
```
|
|
364
232
|
|
|
365
233
|
### Clima
|
|
@@ -368,7 +236,7 @@ const langs = getLangs()
|
|
|
368
236
|
import { weather } from '@soyaxell09/zenbot-scraper'
|
|
369
237
|
|
|
370
238
|
const w = await weather('Buenos Aires')
|
|
371
|
-
// → { location, temp, feelsLike, humidity, wind, windDir, visibility, pressure, uvIndex, description, forecast
|
|
239
|
+
// → { location, temp, feelsLike, humidity, wind, windDir, visibility, pressure, uvIndex, description, forecast }
|
|
372
240
|
```
|
|
373
241
|
|
|
374
242
|
### QR
|
|
@@ -376,13 +244,8 @@ const w = await weather('Buenos Aires')
|
|
|
376
244
|
```js
|
|
377
245
|
import { qrGenerate, qrRead } from '@soyaxell09/zenbot-scraper'
|
|
378
246
|
|
|
379
|
-
|
|
380
|
-
const qr = await qrGenerate('https://github.com/axeldev09', 300)
|
|
381
|
-
// → { url, buffer, size, text }
|
|
382
|
-
|
|
383
|
-
// Leer QR desde URL de imagen
|
|
247
|
+
const qr = await qrGenerate('https://github.com/axeldev09', 300)
|
|
384
248
|
const result = await qrRead('https://example.com/qr.png')
|
|
385
|
-
// → { text, type }
|
|
386
249
|
```
|
|
387
250
|
|
|
388
251
|
### Acortador de URLs
|
|
@@ -390,13 +253,8 @@ const result = await qrRead('https://example.com/qr.png')
|
|
|
390
253
|
```js
|
|
391
254
|
import { shortenUrl, expandUrl } from '@soyaxell09/zenbot-scraper'
|
|
392
255
|
|
|
393
|
-
|
|
394
|
-
const short = await shortenUrl('https://github.com/axeldev09/zenbot-scraper')
|
|
395
|
-
// → { short: 'https://is.gd/xxxxx', source: 'is.gd' }
|
|
396
|
-
|
|
397
|
-
// Expandir
|
|
256
|
+
const short = await shortenUrl('https://github.com/axeldev09/zenbot-scraper')
|
|
398
257
|
const expanded = await expandUrl('https://is.gd/xxxxx')
|
|
399
|
-
// → { original, expanded }
|
|
400
258
|
```
|
|
401
259
|
|
|
402
260
|
### Noticias
|
|
@@ -404,52 +262,113 @@ const expanded = await expandUrl('https://is.gd/xxxxx')
|
|
|
404
262
|
```js
|
|
405
263
|
import { news, newsCategories } from '@soyaxell09/zenbot-scraper'
|
|
406
264
|
|
|
407
|
-
|
|
408
|
-
const n = await news('es', 5)
|
|
409
|
-
// → { category, source, items: [{ title, description, url, image, published, source }] }
|
|
410
|
-
|
|
411
|
-
// Categorías disponibles
|
|
265
|
+
const n = await news('es', 5)
|
|
412
266
|
const cats = newsCategories()
|
|
413
267
|
// → ['es', 'en', 'pt', 'tech', 'sports', 'science', 'world']
|
|
414
268
|
```
|
|
415
269
|
|
|
416
|
-
---
|
|
417
|
-
|
|
418
|
-
|
|
419
270
|
### Upload (Catbox.moe)
|
|
420
271
|
|
|
421
272
|
```js
|
|
422
273
|
import { upload } from '@soyaxell09/zenbot-scraper'
|
|
423
274
|
|
|
424
|
-
// Por ruta de archivo local
|
|
425
275
|
const r1 = await upload('/sdcard/foto.jpg')
|
|
426
|
-
|
|
276
|
+
const r2 = await upload('https://example.com/image.jpg')
|
|
277
|
+
const r3 = await upload(buffer, 'video.mp4')
|
|
278
|
+
// → { url, filename }
|
|
279
|
+
```
|
|
427
280
|
|
|
428
|
-
|
|
429
|
-
const r2 = await upload('https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg')
|
|
430
|
-
// → { url: 'https://files.catbox.moe/xxxxx.jpg', filename: 'file.jpg' }
|
|
281
|
+
---
|
|
431
282
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
283
|
+
## 🔞 NSFW
|
|
284
|
+
|
|
285
|
+
> ⚠️ Solo para bots con verificación de edad. Usá responsablemente.
|
|
286
|
+
|
|
287
|
+
### XNXX Search
|
|
288
|
+
|
|
289
|
+
```js
|
|
290
|
+
import { xnxxSearch } from '@soyaxell09/zenbot-scraper'
|
|
291
|
+
|
|
292
|
+
const results = await xnxxSearch('query', 10)
|
|
293
|
+
// → [{ title, url, thumb, preview, duration, views, quality, uploader }]
|
|
435
294
|
```
|
|
436
295
|
|
|
437
|
-
|
|
296
|
+
### XNXX Download
|
|
438
297
|
|
|
439
|
-
|
|
298
|
+
```js
|
|
299
|
+
import { xnxxDownload } from '@soyaxell09/zenbot-scraper'
|
|
300
|
+
|
|
301
|
+
const result = await xnxxDownload('https://www.xnxx.com/video-xxx/...')
|
|
302
|
+
// → { title, thumb, uploader, duration, views, uploadDate, download: { low, high, hls } }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### PornHub Search
|
|
440
306
|
|
|
441
307
|
```js
|
|
442
|
-
|
|
443
|
-
|
|
308
|
+
import { phSearch } from '@soyaxell09/zenbot-scraper'
|
|
309
|
+
|
|
310
|
+
const results = await phSearch('query', 10)
|
|
311
|
+
// → [{ title, url, thumb, preview, duration, vkey }]
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### PornHub Download
|
|
315
|
+
|
|
316
|
+
```js
|
|
317
|
+
import { phDownload, phDownloadBuffer } from '@soyaxell09/zenbot-scraper'
|
|
318
|
+
|
|
319
|
+
// Solo info + HLS streams
|
|
320
|
+
const result = await phDownload('https://www.pornhub.com/view_video.php?viewkey=xxx')
|
|
321
|
+
// → { title, thumb, duration, uploadDate, hls: { '1080p', '720p', '480p', '240p' } }
|
|
322
|
+
|
|
323
|
+
// Convertir a mp4 con ffmpeg (requiere ffmpeg instalado)
|
|
324
|
+
const video = await phDownloadBuffer('https://www.pornhub.com/view_video.php?viewkey=xxx', '720')
|
|
325
|
+
// → { title, thumb, duration, uploadDate, buffer, quality }
|
|
326
|
+
// quality: calidad elegida ('720', '480', '360') — máx 5 minutos por descarga
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### XVideos Search
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
import { xvideosSearch } from '@soyaxell09/zenbot-scraper'
|
|
333
|
+
|
|
334
|
+
const results = await xvideosSearch('query', 10)
|
|
335
|
+
// → [{ title, url, thumb, preview, duration, views, quality }]
|
|
336
|
+
```
|
|
444
337
|
|
|
445
|
-
|
|
446
|
-
import { ytDownload, fbDownload } from '@soyaxell09/zenbot-scraper/scrapers'
|
|
338
|
+
### XVideos Download
|
|
447
339
|
|
|
448
|
-
|
|
449
|
-
import {
|
|
340
|
+
```js
|
|
341
|
+
import { xvideosDownload } from '@soyaxell09/zenbot-scraper'
|
|
342
|
+
|
|
343
|
+
const result = await xvideosDownload('https://www.xvideos.com/video.xxx/...')
|
|
344
|
+
// → { title, thumb, duration, views, uploadDate, download: { low, high, hls } }
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Rule34 (yande.re + paheal)
|
|
450
348
|
|
|
451
|
-
|
|
452
|
-
import {
|
|
349
|
+
```js
|
|
350
|
+
import { rule34Search, rule34Random } from '@soyaxell09/zenbot-scraper'
|
|
351
|
+
|
|
352
|
+
// Buscar por tags (usa yande.re, cae a paheal si no hay resultados)
|
|
353
|
+
const results = await rule34Search('cat_girl', 10)
|
|
354
|
+
// → [{ id, url, preview, tags, score, width, height }]
|
|
355
|
+
|
|
356
|
+
// Imagen random (usa paheal, con o sin tags)
|
|
357
|
+
const random = await rule34Random('cat_girl')
|
|
358
|
+
const any = await rule34Random()
|
|
359
|
+
// → { id, url, preview, tags, score, width, height }
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## 📦 Importación por módulo
|
|
365
|
+
|
|
366
|
+
```js
|
|
367
|
+
import { ytDownload, tiktokDownload, translate, weather } from '@soyaxell09/zenbot-scraper'
|
|
368
|
+
import { ytDownload, fbDownload } from '@soyaxell09/zenbot-scraper/scrapers'
|
|
369
|
+
import { googleSearch, spotify } from '@soyaxell09/zenbot-scraper/search'
|
|
370
|
+
import { translate, weather, news } from '@soyaxell09/zenbot-scraper/tools'
|
|
371
|
+
import { xnxxSearch, phSearch, rule34Random } from '@soyaxell09/zenbot-scraper/nsfw'
|
|
453
372
|
```
|
|
454
373
|
|
|
455
374
|
---
|
|
@@ -458,6 +377,7 @@ import { translate, weather, news } from '@soyaxell09/zenbot-scraper/tools'
|
|
|
458
377
|
|
|
459
378
|
- Node.js >= 18.0.0
|
|
460
379
|
- Dependencias: `axios`, `cheerio`, `@distube/ytdl-core`, `form-data`
|
|
380
|
+
- Para `phDownloadBuffer`: requiere `ffmpeg` instalado en el sistema
|
|
461
381
|
|
|
462
382
|
---
|
|
463
383
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soyaxell09/zenbot-scraper",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Scrapers de descarga y búsqueda para bots de WhatsApp — YouTube, TikTok, Facebook, Twitter, Pinterest, MediaFire, GitHub, APK, Google Drive y más.",
|
|
3
|
+
"version": "1.0.11",
|
|
4
|
+
"description": "Scrapers de descarga y búsqueda para bots de WhatsApp — YouTube, TikTok, Facebook, Twitter, Pinterest, MediaFire, GitHub, APK, Google Drive, XNXX, PornHub, XVideos, Rule34 y más.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js",
|
|
9
9
|
"./scrapers": "./src/scrapers/index.js",
|
|
10
10
|
"./search": "./src/search/index.js",
|
|
11
|
-
"./tools": "./src/tools/index.js"
|
|
11
|
+
"./tools": "./src/tools/index.js",
|
|
12
|
+
"./nsfw": "./src/nsfw/index.js"
|
|
12
13
|
},
|
|
13
14
|
"scripts": {
|
|
14
15
|
"test": "node test/index.js"
|
|
@@ -37,7 +38,12 @@
|
|
|
37
38
|
"upload",
|
|
38
39
|
"stickers",
|
|
39
40
|
"gdrive",
|
|
40
|
-
"google-drive"
|
|
41
|
+
"google-drive",
|
|
42
|
+
"xnxx",
|
|
43
|
+
"pornhub",
|
|
44
|
+
"xvideos",
|
|
45
|
+
"rule34",
|
|
46
|
+
"nsfw"
|
|
41
47
|
],
|
|
42
48
|
"author": "AxelDev09",
|
|
43
49
|
"license": "MIT",
|
package/src/index.js
CHANGED
|
@@ -29,3 +29,10 @@ export { qrGenerate, qrRead } from './tools
|
|
|
29
29
|
export { shortenUrl, expandUrl } from './tools/urlshortener.js'
|
|
30
30
|
export { news, newsCategories } from './tools/news.js'
|
|
31
31
|
export { upload } from './tools/upload.js'
|
|
32
|
+
export { xnxxSearch } from './nsfw/xnxxsearch.js'
|
|
33
|
+
export { xnxxDownload } from './nsfw/xnxxdl.js'
|
|
34
|
+
export { phSearch } from './nsfw/phsearch.js'
|
|
35
|
+
export { phDownload, phDownloadBuffer } from './nsfw/phdl.js'
|
|
36
|
+
export { xvideosSearch } from './nsfw/xvideossearch.js'
|
|
37
|
+
export { xvideosDownload } from './nsfw/xvideosdl.js'
|
|
38
|
+
export { rule34Search, rule34Random } from './nsfw/rule34.js'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { xnxxSearch } from './xnxxsearch.js'
|
|
9
|
+
export { xnxxDownload } from './xnxxdl.js'
|
|
10
|
+
export { phSearch } from './phsearch.js'
|
|
11
|
+
export { phDownload, phDownloadBuffer } from './phdl.js'
|
|
12
|
+
export { xvideosSearch } from './xvideossearch.js'
|
|
13
|
+
export { xvideosDownload } from './xvideosdl.js'
|
|
14
|
+
export { rule34Search, rule34Random } from './rule34.js'
|
package/src/nsfw/phdl.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
import { exec } from 'child_process';
|
|
11
|
+
import { promisify } from 'util';
|
|
12
|
+
import { mkdtemp, rm } from 'fs/promises';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { tmpdir } from 'os';
|
|
15
|
+
|
|
16
|
+
const execAsync = promisify(exec);
|
|
17
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
18
|
+
|
|
19
|
+
function parseDuration(iso) {
|
|
20
|
+
if (!iso) return null;
|
|
21
|
+
const match = iso.match(/PT(\d+)H(\d+)M(\d+)S/);
|
|
22
|
+
if (!match) return iso;
|
|
23
|
+
const h = parseInt(match[1]);
|
|
24
|
+
const m = parseInt(match[2]);
|
|
25
|
+
const s = parseInt(match[3]);
|
|
26
|
+
if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
|
|
27
|
+
return `${m}:${String(s).padStart(2, '0')}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function extractMediaDefinitions(s) {
|
|
31
|
+
const start = s.indexOf('mediaDefinitions');
|
|
32
|
+
if (start === -1) return null;
|
|
33
|
+
const arrStart = s.indexOf('[', start);
|
|
34
|
+
if (arrStart === -1) return null;
|
|
35
|
+
let depth = 0, end = -1;
|
|
36
|
+
for (let i = arrStart; i < s.length; i++) {
|
|
37
|
+
if (s[i] === '[') depth++;
|
|
38
|
+
else if (s[i] === ']') { depth--; if (depth === 0) { end = i; break; } }
|
|
39
|
+
}
|
|
40
|
+
try { return JSON.parse(s.slice(arrStart, end + 1).replace(/\\\//g, '/')); }
|
|
41
|
+
catch { return null; }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function phDownload(url) {
|
|
45
|
+
const { data } = await axios.get(url, {
|
|
46
|
+
headers: { 'User-Agent': UA, 'Accept-Language': 'en-US,en;q=0.9' },
|
|
47
|
+
timeout: 12000
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const $ = cheerio.load(data);
|
|
51
|
+
const scripts = $('script').map((_, el) => $(el).html()).get();
|
|
52
|
+
|
|
53
|
+
let mediaDefinitions = null;
|
|
54
|
+
for (const s of scripts) {
|
|
55
|
+
if (!s || !s.includes('mediaDefinitions')) continue;
|
|
56
|
+
mediaDefinitions = extractMediaDefinitions(s);
|
|
57
|
+
if (mediaDefinitions) break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!mediaDefinitions) throw new Error('No se encontraron calidades de video.');
|
|
61
|
+
|
|
62
|
+
const hlss = mediaDefinitions
|
|
63
|
+
.filter(d => d.format === 'hls' && d.videoUrl && d.quality)
|
|
64
|
+
.sort((a, b) => parseInt(b.quality) - parseInt(a.quality));
|
|
65
|
+
|
|
66
|
+
if (!hlss.length) throw new Error('No se encontró stream HLS.');
|
|
67
|
+
|
|
68
|
+
const jsonLd = $('script[type="application/ld+json"]').first().html();
|
|
69
|
+
let title = null, thumb = null, duration = null, uploadDate = null;
|
|
70
|
+
if (jsonLd) {
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(jsonLd);
|
|
73
|
+
title = parsed.name || null;
|
|
74
|
+
thumb = parsed.thumbnailUrl || null;
|
|
75
|
+
duration = parseDuration(parsed.duration);
|
|
76
|
+
uploadDate = parsed.uploadDate?.slice(0, 10) || null;
|
|
77
|
+
} catch {}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!title) title = $('h1.title span').text().trim() || $('h1').first().text().trim() || null;
|
|
81
|
+
|
|
82
|
+
const hls = {};
|
|
83
|
+
for (const d of hlss) {
|
|
84
|
+
hls[`${d.quality}p`] = { quality: `${d.quality}p`, format: 'hls', url: d.videoUrl };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { title, thumb, duration, uploadDate, hls };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function phDownloadBuffer(url, quality = '720') {
|
|
91
|
+
const { data } = await axios.get(url, {
|
|
92
|
+
headers: { 'User-Agent': UA, 'Accept-Language': 'en-US,en;q=0.9' },
|
|
93
|
+
timeout: 12000
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const $ = cheerio.load(data);
|
|
97
|
+
const scripts = $('script').map((_, el) => $(el).html()).get();
|
|
98
|
+
|
|
99
|
+
let mediaDefinitions = null;
|
|
100
|
+
for (const s of scripts) {
|
|
101
|
+
if (!s || !s.includes('mediaDefinitions')) continue;
|
|
102
|
+
mediaDefinitions = extractMediaDefinitions(s);
|
|
103
|
+
if (mediaDefinitions) break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!mediaDefinitions) throw new Error('No se encontraron calidades de video.');
|
|
107
|
+
|
|
108
|
+
const hlss = mediaDefinitions
|
|
109
|
+
.filter(d => d.format === 'hls' && d.videoUrl && d.quality)
|
|
110
|
+
.sort((a, b) => parseInt(b.quality) - parseInt(a.quality));
|
|
111
|
+
|
|
112
|
+
if (!hlss.length) throw new Error('No se encontró stream HLS.');
|
|
113
|
+
|
|
114
|
+
const hlsItem = hlss.find(d => d.quality === quality)
|
|
115
|
+
|| hlss.find(d => d.quality === '480')
|
|
116
|
+
|| hlss.find(d => d.quality === '360')
|
|
117
|
+
|| hlss[0];
|
|
118
|
+
|
|
119
|
+
const jsonLd = $('script[type="application/ld+json"]').first().html();
|
|
120
|
+
let title = null, thumb = null, duration = null, uploadDate = null;
|
|
121
|
+
if (jsonLd) {
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(jsonLd);
|
|
124
|
+
title = parsed.name || null;
|
|
125
|
+
thumb = parsed.thumbnailUrl || null;
|
|
126
|
+
duration = parseDuration(parsed.duration);
|
|
127
|
+
uploadDate = parsed.uploadDate?.slice(0, 10) || null;
|
|
128
|
+
} catch {}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!title) title = $('h1.title span').text().trim() || $('h1').first().text().trim() || null;
|
|
132
|
+
|
|
133
|
+
const tmpDir = await mkdtemp(join(tmpdir(), 'phdl-'));
|
|
134
|
+
const outPath = join(tmpDir, 'video.mp4');
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await execAsync(
|
|
138
|
+
`ffmpeg -v quiet -y -user_agent "${UA}" -headers "Referer: https://www.pornhub.com/\r\n" -i "${hlsItem.videoUrl}" -t 300 -c copy -bsf:a aac_adtstoasc "${outPath}"`,
|
|
139
|
+
{ timeout: 120000 }
|
|
140
|
+
);
|
|
141
|
+
const { readFile } = await import('fs/promises');
|
|
142
|
+
const buffer = await readFile(outPath);
|
|
143
|
+
return { title, thumb, duration, uploadDate, buffer, quality: `${hlsItem.quality}p` };
|
|
144
|
+
} finally {
|
|
145
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
export async function phSearch(query, limit = 10) {
|
|
14
|
+
const { data } = await axios.get(`https://www.pornhub.com/video/search?search=${encodeURIComponent(query)}`, {
|
|
15
|
+
headers: { 'User-Agent': UA, 'Accept-Language': 'en-US,en;q=0.9' },
|
|
16
|
+
timeout: 12000
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const $ = cheerio.load(data);
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
$('li[data-video-vkey]').each((_, el) => {
|
|
23
|
+
if (results.length >= limit) return false;
|
|
24
|
+
|
|
25
|
+
const anchor = $(el).find('a.imageLink').first();
|
|
26
|
+
const img = $(el).find('img.videoThumb').first();
|
|
27
|
+
|
|
28
|
+
const href = anchor.attr('href') || '';
|
|
29
|
+
const title = $(el).find('.title a').first().text().trim();
|
|
30
|
+
const thumb = img.attr('src') || '';
|
|
31
|
+
const preview = anchor.attr('data-webm') || '';
|
|
32
|
+
const duration = $(el).find('.duration').first().text().trim();
|
|
33
|
+
const vkey = $(el).attr('data-video-vkey') || '';
|
|
34
|
+
|
|
35
|
+
if (!title || !href) return;
|
|
36
|
+
|
|
37
|
+
results.push({
|
|
38
|
+
title,
|
|
39
|
+
url: href.startsWith('http') ? href : `https://www.pornhub.com${href}`,
|
|
40
|
+
thumb,
|
|
41
|
+
preview,
|
|
42
|
+
duration,
|
|
43
|
+
vkey
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
async function yandereSearch(tags, limit = 10) {
|
|
14
|
+
const { data } = await axios.get('https://yande.re/post.json', {
|
|
15
|
+
params: { tags, limit },
|
|
16
|
+
headers: { 'User-Agent': UA },
|
|
17
|
+
timeout: 12000
|
|
18
|
+
});
|
|
19
|
+
if (!Array.isArray(data) || !data.length) return [];
|
|
20
|
+
return data.map(p => ({
|
|
21
|
+
id: String(p.id),
|
|
22
|
+
url: p.file_url || '',
|
|
23
|
+
preview: p.preview_url || '',
|
|
24
|
+
tags: p.tags || '',
|
|
25
|
+
score: p.score || 0,
|
|
26
|
+
width: p.width || 0,
|
|
27
|
+
height: p.height || 0
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parsePaheal(xml) {
|
|
32
|
+
const $ = cheerio.load(xml, { xmlMode: true });
|
|
33
|
+
const items = [];
|
|
34
|
+
$('tag').each((_, el) => {
|
|
35
|
+
const file_url = $(el).attr('file_url') || '';
|
|
36
|
+
if (!file_url) return;
|
|
37
|
+
items.push({
|
|
38
|
+
id: $(el).attr('id'),
|
|
39
|
+
url: file_url,
|
|
40
|
+
preview: $(el).attr('preview_url') || '',
|
|
41
|
+
tags: $(el).attr('tags') || '',
|
|
42
|
+
score: parseInt($(el).attr('score')) || 0,
|
|
43
|
+
width: parseInt($(el).attr('width')) || 0,
|
|
44
|
+
height: parseInt($(el).attr('height')) || 0
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
return items;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function pahealSearch(tags, limit = 10) {
|
|
51
|
+
const { data } = await axios.get('https://rule34.paheal.net/api/danbooru/find_posts', {
|
|
52
|
+
params: { tags, limit },
|
|
53
|
+
headers: { 'User-Agent': UA },
|
|
54
|
+
timeout: 12000
|
|
55
|
+
});
|
|
56
|
+
return parsePaheal(data);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function rule34Search(tags, limit = 10) {
|
|
60
|
+
let items = await yandereSearch(tags, limit);
|
|
61
|
+
if (!items.length) items = await pahealSearch(tags, limit);
|
|
62
|
+
if (!items.length) throw new Error('Sin resultados para esos tags.');
|
|
63
|
+
return items;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function rule34Random(tags = null) {
|
|
67
|
+
for (let intento = 0; intento < 3; intento++) {
|
|
68
|
+
const pid = Math.floor(Math.random() * 5);
|
|
69
|
+
const params = { limit: 20, pid };
|
|
70
|
+
if (tags) params.tags = tags;
|
|
71
|
+
const { data } = await axios.get('https://rule34.paheal.net/api/danbooru/find_posts', {
|
|
72
|
+
params,
|
|
73
|
+
headers: { 'User-Agent': UA },
|
|
74
|
+
timeout: 12000
|
|
75
|
+
});
|
|
76
|
+
const items = parsePaheal(data);
|
|
77
|
+
if (items.length) return items[Math.floor(Math.random() * items.length)];
|
|
78
|
+
}
|
|
79
|
+
throw new Error('No se encontraron resultados.');
|
|
80
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
function parseDuration(iso) {
|
|
14
|
+
if (!iso) return null;
|
|
15
|
+
const match = iso.match(/PT(\d+)H(\d+)M(\d+)S/);
|
|
16
|
+
if (!match) return iso;
|
|
17
|
+
const h = parseInt(match[1]);
|
|
18
|
+
const m = parseInt(match[2]);
|
|
19
|
+
const s = parseInt(match[3]);
|
|
20
|
+
if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
|
|
21
|
+
return `${m}:${String(s).padStart(2, '0')}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function xnxxDownload(url) {
|
|
25
|
+
const { data } = await axios.get(url, {
|
|
26
|
+
headers: { 'User-Agent': UA },
|
|
27
|
+
timeout: 12000
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const $ = cheerio.load(data);
|
|
31
|
+
const scripts = $('script').map((_, el) => $(el).html()).get();
|
|
32
|
+
|
|
33
|
+
let playerScript = null;
|
|
34
|
+
for (const s of scripts) {
|
|
35
|
+
if (s && s.includes('html5player') && s.includes('setVideoUrlLow')) {
|
|
36
|
+
playerScript = s;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!playerScript) throw new Error('No se encontró el player del video.');
|
|
42
|
+
|
|
43
|
+
const extract = (key) => {
|
|
44
|
+
const match = playerScript.match(new RegExp(`${key}\\('([^']+)'\\)`));
|
|
45
|
+
return match ? match[1] : null;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const title = extract('setVideoTitle');
|
|
49
|
+
const low = extract('setVideoUrlLow');
|
|
50
|
+
const high = extract('setVideoUrlHigh');
|
|
51
|
+
const hls = extract('setVideoHLS');
|
|
52
|
+
const thumb = extract('setThumbUrl169') || extract('setThumbUrl');
|
|
53
|
+
const uploader = extract('setUploaderName');
|
|
54
|
+
|
|
55
|
+
const jsonLd = $('script[type="application/ld+json"]').first().html();
|
|
56
|
+
let duration = null, views = null, uploadDate = null;
|
|
57
|
+
if (jsonLd) {
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(jsonLd);
|
|
60
|
+
duration = parseDuration(parsed.duration);
|
|
61
|
+
views = parsed.interactionStatistic?.userInteractionCount || null;
|
|
62
|
+
uploadDate = parsed.uploadDate?.slice(0, 10) || null;
|
|
63
|
+
} catch {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!low && !high) throw new Error('No se encontraron URLs de descarga.');
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
title,
|
|
70
|
+
thumb,
|
|
71
|
+
uploader,
|
|
72
|
+
duration,
|
|
73
|
+
views,
|
|
74
|
+
uploadDate,
|
|
75
|
+
download: {
|
|
76
|
+
low: low ? { quality: '240p', url: low } : null,
|
|
77
|
+
high: high ? { quality: '360p', url: high } : null,
|
|
78
|
+
hls: hls ? { quality: 'HLS', url: hls } : null
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
export async function xnxxSearch(query, limit = 10) {
|
|
14
|
+
const { data } = await axios.get(`https://www.xnxx.com/search/${encodeURIComponent(query)}`, {
|
|
15
|
+
headers: { 'User-Agent': UA },
|
|
16
|
+
timeout: 12000
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const $ = cheerio.load(data);
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
$('.mozaique .thumb-block').each((_, el) => {
|
|
23
|
+
if (results.length >= limit) return false;
|
|
24
|
+
|
|
25
|
+
const img = $(el).find('img');
|
|
26
|
+
const anchor = $(el).find('.thumb-inside a').first();
|
|
27
|
+
const titleEl = $(el).find('a[title]').first();
|
|
28
|
+
const metadata = $(el).find('.metadata').text().replace(/\s+/g, ' ').trim();
|
|
29
|
+
const rightEl = $(el).find('.metadata .right').text().replace(/\s+/g, ' ').trim();
|
|
30
|
+
|
|
31
|
+
const href = anchor.attr('href') || titleEl.attr('href') || '';
|
|
32
|
+
const title = titleEl.attr('title') || '';
|
|
33
|
+
const thumb = img.attr('data-src') || '';
|
|
34
|
+
const preview = img.attr('data-pvv') || '';
|
|
35
|
+
const uploader = $(el).find('.uploader .name').text().trim();
|
|
36
|
+
const quality = $(el).find('.video-hd').text().replace(/\s+/g, ' ').trim();
|
|
37
|
+
|
|
38
|
+
const durMatch = metadata.match(/(\d+min|\d+:\d+)/);
|
|
39
|
+
const duration = durMatch ? durMatch[1] : '';
|
|
40
|
+
|
|
41
|
+
const viewsMatch = rightEl.match(/([\d.]+[KMB]?)/);
|
|
42
|
+
const views = viewsMatch ? viewsMatch[1] : '';
|
|
43
|
+
|
|
44
|
+
if (!title || !href) return;
|
|
45
|
+
|
|
46
|
+
results.push({
|
|
47
|
+
title,
|
|
48
|
+
url: `https://www.xnxx.com${href}`,
|
|
49
|
+
thumb,
|
|
50
|
+
preview,
|
|
51
|
+
duration,
|
|
52
|
+
views,
|
|
53
|
+
quality: quality.replace(/-/g, '').trim(),
|
|
54
|
+
uploader
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
function parseDuration(iso) {
|
|
14
|
+
if (!iso) return null;
|
|
15
|
+
const match = iso.match(/PT(\d+)H(\d+)M(\d+)S/);
|
|
16
|
+
if (!match) return iso;
|
|
17
|
+
const h = parseInt(match[1]);
|
|
18
|
+
const m = parseInt(match[2]);
|
|
19
|
+
const s = parseInt(match[3]);
|
|
20
|
+
if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
|
|
21
|
+
return `${m}:${String(s).padStart(2, '0')}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function xvideosDownload(url) {
|
|
25
|
+
const { data } = await axios.get(url, {
|
|
26
|
+
headers: { 'User-Agent': UA },
|
|
27
|
+
timeout: 12000
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const $ = cheerio.load(data);
|
|
31
|
+
const scripts = $('script').map((_, el) => $(el).html()).get();
|
|
32
|
+
|
|
33
|
+
let playerScript = null;
|
|
34
|
+
for (const s of scripts) {
|
|
35
|
+
if (s && s.includes('setVideoUrlLow')) {
|
|
36
|
+
playerScript = s;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const extract = (key) => {
|
|
42
|
+
if (!playerScript) return null;
|
|
43
|
+
const match = playerScript.match(new RegExp(`${key}\\('([^']+)'\\)`));
|
|
44
|
+
return match ? match[1] : null;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const low = extract('setVideoUrlLow');
|
|
48
|
+
const high = extract('setVideoUrlHigh');
|
|
49
|
+
const hls = extract('setVideoHLS');
|
|
50
|
+
const thumb = extract('setThumbUrl169') || extract('setThumbUrl');
|
|
51
|
+
|
|
52
|
+
const jsonLd = $('script[type="application/ld+json"]').first().html();
|
|
53
|
+
let title = null, duration = null, views = null, uploadDate = null, thumbFallback = null;
|
|
54
|
+
if (jsonLd) {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(jsonLd);
|
|
57
|
+
title = parsed.name || null;
|
|
58
|
+
thumbFallback = Array.isArray(parsed.thumbnailUrl) ? parsed.thumbnailUrl[0] : parsed.thumbnailUrl || null;
|
|
59
|
+
duration = parseDuration(parsed.duration);
|
|
60
|
+
views = parsed.interactionStatistic?.userInteractionCount || null;
|
|
61
|
+
uploadDate = parsed.uploadDate?.slice(0, 10) || null;
|
|
62
|
+
} catch {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!low && !high) throw new Error('No se encontraron URLs de descarga.');
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
title,
|
|
69
|
+
thumb: thumb || thumbFallback,
|
|
70
|
+
duration,
|
|
71
|
+
views,
|
|
72
|
+
uploadDate,
|
|
73
|
+
download: {
|
|
74
|
+
low: low ? { quality: '240p', url: low } : null,
|
|
75
|
+
high: high ? { quality: '360p', url: high } : null,
|
|
76
|
+
hls: hls ? { quality: 'HLS', url: hls } : null
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* © Created by AxelDev09 🔥
|
|
3
|
+
* GitHub: https://github.com/AxelDev09
|
|
4
|
+
* Instagram: @axeldev09
|
|
5
|
+
* Deja los créditos we 🗣️
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import * as cheerio from 'cheerio';
|
|
10
|
+
|
|
11
|
+
const UA = 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
12
|
+
|
|
13
|
+
export async function xvideosSearch(query, limit = 10) {
|
|
14
|
+
const { data } = await axios.get(`https://www.xvideos.com/?k=${encodeURIComponent(query)}`, {
|
|
15
|
+
headers: { 'User-Agent': UA },
|
|
16
|
+
timeout: 12000
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const $ = cheerio.load(data);
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
$('.thumb-block').each((_, el) => {
|
|
23
|
+
if (results.length >= limit) return false;
|
|
24
|
+
|
|
25
|
+
const img = $(el).find('img');
|
|
26
|
+
const anchor = $(el).find('.thumb-inside a').first();
|
|
27
|
+
const titleEl = $(el).find('a[title]').first();
|
|
28
|
+
const metadata = $(el).find('.metadata').text().replace(/\s+/g, ' ').trim();
|
|
29
|
+
|
|
30
|
+
const href = anchor.attr('href') || '';
|
|
31
|
+
const title = titleEl.attr('title') || '';
|
|
32
|
+
const thumb = img.attr('data-src') || '';
|
|
33
|
+
const preview = img.attr('data-pvv') || '';
|
|
34
|
+
const duration = $(el).find('.duration').first().text().trim();
|
|
35
|
+
const quality = $(el).find('.video-hd-mark').text().trim();
|
|
36
|
+
|
|
37
|
+
const viewsMatch = metadata.match(/([\d.]+[KMB]?)\s*Views/i);
|
|
38
|
+
const views = viewsMatch ? viewsMatch[1] : '';
|
|
39
|
+
|
|
40
|
+
if (!title || !href) return;
|
|
41
|
+
|
|
42
|
+
results.push({
|
|
43
|
+
title,
|
|
44
|
+
url: `https://www.xvideos.com${href}`,
|
|
45
|
+
thumb,
|
|
46
|
+
preview,
|
|
47
|
+
duration,
|
|
48
|
+
views,
|
|
49
|
+
quality
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return results;
|
|
54
|
+
}
|
package/test.js
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { phDownloadBuffer } from './src/nsfw/phdl.js';
|
|
2
|
+
import { writeFile } from 'fs/promises';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
4
|
+
const URL_TEST = 'https://www.pornhub.com/view_video.php?viewkey=69b03c0796d02';
|
|
5
|
+
const OUT_PATH = '/sdcard/test-phdl.mp4';
|
|
6
|
+
|
|
7
|
+
console.log('🔍 Testeando phDownloadBuffer...\n');
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
console.log('⏳ Fetcheando página y convirtiendo HLS con ffmpeg...');
|
|
11
|
+
const result = await phDownloadBuffer(URL_TEST, '480');
|
|
12
|
+
console.log('✅ Conversión exitosa:\n');
|
|
13
|
+
console.log(` 📹 Título: ${result.title}`);
|
|
14
|
+
console.log(` ⏱️ Duración: ${result.duration || '—'}`);
|
|
15
|
+
console.log(` 🎯 Calidad: ${result.quality}`);
|
|
16
|
+
console.log(` 📦 Buffer: ${(result.buffer.length / 1024 / 1024).toFixed(2)} MB`);
|
|
17
|
+
await writeFile(OUT_PATH, result.buffer);
|
|
18
|
+
console.log(`\n💾 Video guardado en: ${OUT_PATH}`);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.log(`❌ Error: ${e.message}`);
|
|
21
|
+
}
|