node-csfd-api 4.0.0-next.0 → 4.0.0-next.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/README.md +317 -209
- package/fetchers/fetch.polyfill.js +0 -2
- package/fetchers/fetch.polyfill.js.map +1 -1
- package/fetchers/index.js +1 -1
- package/fetchers/index.js.map +1 -1
- package/fetchers/index.mjs +1 -1
- package/fetchers/index.mjs.map +1 -1
- package/helpers/movie.helper.js.map +1 -1
- package/helpers/movie.helper.mjs.map +1 -1
- package/helpers/search-user.helper.js +0 -2
- package/helpers/search-user.helper.js.map +1 -1
- package/package.json +3 -3
- package/services/cinema.service.js +0 -2
- package/services/cinema.service.js.map +1 -1
- package/services/creator.service.js +0 -2
- package/services/creator.service.js.map +1 -1
- package/services/movie.service.js +0 -2
- package/services/movie.service.js.map +1 -1
- package/services/search.service.js +0 -2
- package/services/search.service.js.map +1 -1
- package/services/user-ratings.service.js +0 -2
- package/services/user-ratings.service.js.map +1 -1
- package/services/user-reviews.service.js +0 -2
- package/services/user-reviews.service.js.map +1 -1
- package/_virtual/rolldown_runtime.js +0 -25
package/README.md
CHANGED
|
@@ -1,52 +1,103 @@
|
|
|
1
1
|
[](https://badge.fury.io/js/node-csfd-api)
|
|
2
|
-
[](https://www.npmjs.com/node-csfd-api)
|
|
3
3
|
[](https://github.com/bartholomej/node-csfd-api/actions)
|
|
4
|
-
[](https://codecov.io/gh/bartholomej/node-csfd-api)
|
|
5
|
+
[](https://www.npmjs.com/node-csfd-api)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
<div align="center">
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
# CSFD API 🎬 2025
|
|
10
|
+
|
|
11
|
+
#### Modern TypeScript NPM library for scraping **Czech Movie Database (csfd.cz)** _(unofficial)_
|
|
12
|
+
|
|
13
|
+
[Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-usage-examples) • [Docker](#-docker-support)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ✨ Features
|
|
20
|
+
|
|
21
|
+
- 🎯 **Type-safe** - Full TypeScript support with type definitions
|
|
22
|
+
- 🧪 **Well-tested** - ~100% code coverage
|
|
23
|
+
- 🚀 **Universal** - Works in Node.js, browsers, and serverless environments
|
|
24
|
+
- 🐳 **Docker ready** - Pre-built Docker images available
|
|
25
|
+
- 🔄 **Modern API** - Promise-based with async/await support
|
|
26
|
+
- 📦 **One dependency** - Lightweight and efficient
|
|
27
|
+
|
|
28
|
+
### Supported Platforms
|
|
29
|
+
|
|
30
|
+
- Node.js (ESM & CommonJS)
|
|
31
|
+
- Browsers (with CORS considerations)
|
|
32
|
+
- Docker containers
|
|
33
|
+
- Serverless (Firebase Functions, AWS Lambda, CloudFlare Workers, etc.)
|
|
34
|
+
- Chrome Extensions
|
|
35
|
+
- React Native (Yes, with Expo too!)
|
|
36
|
+
|
|
37
|
+
## 📦 Installation
|
|
24
38
|
|
|
25
39
|
```bash
|
|
26
40
|
npm install node-csfd-api
|
|
27
41
|
# yarn add node-csfd-api
|
|
42
|
+
# pnpm add node-csfd-api
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚀 Quick Start
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { csfd } from 'node-csfd-api';
|
|
49
|
+
|
|
50
|
+
// Fetch movie details
|
|
51
|
+
const movie = await csfd.movie(535121);
|
|
52
|
+
console.log(movie.title); // "Na špatné straně"
|
|
53
|
+
|
|
54
|
+
// Search for content
|
|
55
|
+
const results = await csfd.search('Tarantino');
|
|
56
|
+
console.log(results.movies, results.tvSeries, results.users);
|
|
57
|
+
|
|
58
|
+
// Get creator info
|
|
59
|
+
const creator = await csfd.creator(2120);
|
|
60
|
+
console.log(creator.name); // "Quentin Tarantino"
|
|
61
|
+
|
|
62
|
+
// Get user ratings
|
|
63
|
+
const ratings = await csfd.userRatings('912');
|
|
64
|
+
console.log(ratings);
|
|
65
|
+
|
|
66
|
+
// Get user reviews
|
|
67
|
+
const reviews = await csfd.userReviews('195357-verbal');
|
|
68
|
+
console.log(reviews);
|
|
28
69
|
```
|
|
29
70
|
|
|
30
|
-
##
|
|
71
|
+
## 📖 Table of Contents
|
|
72
|
+
|
|
73
|
+
- [Movie Details](#movie)
|
|
74
|
+
- [Search](#search)
|
|
75
|
+
- [Creators](#creators)
|
|
76
|
+
- [User Ratings](#user-ratings)
|
|
77
|
+
- [User Reviews](#user-reviews)
|
|
78
|
+
- [Docker Support](#-docker-support)
|
|
79
|
+
- [Development](#-development)
|
|
31
80
|
|
|
32
|
-
|
|
33
|
-
- [User Ratings](#User-Ratings)
|
|
34
|
-
- [User Reviews](#User-Reviews)
|
|
35
|
-
- [Search](#Search)
|
|
36
|
-
- [Creators](#Creators)
|
|
81
|
+
## 📚 API Reference
|
|
37
82
|
|
|
38
83
|
### Movie
|
|
39
84
|
|
|
40
|
-
>
|
|
85
|
+
> Retrieve comprehensive information about a movie or TV series by its ČSFD ID.
|
|
41
86
|
|
|
42
|
-
|
|
87
|
+
**Method:** `csfd.movie(id: number): Promise<Movie>`
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
43
90
|
import { csfd } from 'node-csfd-api';
|
|
44
91
|
|
|
92
|
+
// Using async/await
|
|
93
|
+
const movie = await csfd.movie(535121);
|
|
94
|
+
|
|
95
|
+
// Alternatively, using promises
|
|
45
96
|
csfd.movie(535121).then((movie) => console.log(movie));
|
|
46
97
|
```
|
|
47
98
|
|
|
48
99
|
<details>
|
|
49
|
-
<summary
|
|
100
|
+
<summary>🔎 Click here to see full result example</summary>
|
|
50
101
|
|
|
51
102
|
```javascript
|
|
52
103
|
{
|
|
@@ -144,16 +195,23 @@ csfd.movie(535121).then((movie) => console.log(movie));
|
|
|
144
195
|
|
|
145
196
|
### Search
|
|
146
197
|
|
|
147
|
-
> Search movies,
|
|
198
|
+
> Search for movies, TV series, and users across the ČSFD database.
|
|
148
199
|
|
|
149
|
-
|
|
200
|
+
**Method:** `csfd.search(query: string): Promise<SearchResults>`
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
150
203
|
import { csfd } from 'node-csfd-api';
|
|
151
204
|
|
|
152
|
-
csfd.search('bart')
|
|
205
|
+
const results = await csfd.search('bart');
|
|
206
|
+
|
|
207
|
+
// Access different result types
|
|
208
|
+
console.log(results.movies); // Array of movies
|
|
209
|
+
console.log(results.tvSeries); // Array of TV series
|
|
210
|
+
console.log(results.users); // Array of users
|
|
153
211
|
```
|
|
154
212
|
|
|
155
213
|
<details>
|
|
156
|
-
<summary
|
|
214
|
+
<summary>🔎 Click here to see full result example</summary>
|
|
157
215
|
|
|
158
216
|
```javascript
|
|
159
217
|
[
|
|
@@ -208,16 +266,24 @@ users: [
|
|
|
208
266
|
|
|
209
267
|
### Creators
|
|
210
268
|
|
|
211
|
-
> Get creator
|
|
269
|
+
> Get detailed information about a creator including their biography and filmography.
|
|
212
270
|
|
|
213
|
-
|
|
271
|
+
**Method:** `csfd.creator(id: number): Promise<Creator>`
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
214
274
|
import { csfd } from 'node-csfd-api';
|
|
215
275
|
|
|
216
|
-
csfd.creator(2120)
|
|
276
|
+
const creator = await csfd.creator(2120); // Quentin Tarantino
|
|
277
|
+
|
|
278
|
+
console.log(creator.name); // Name
|
|
279
|
+
console.log(creator.bio); // Biography
|
|
280
|
+
console.log(creator.films); // Filmography
|
|
281
|
+
console.log(creator.birthday); // Birth date
|
|
282
|
+
// ... many more properties, see example
|
|
217
283
|
```
|
|
218
284
|
|
|
219
285
|
<details>
|
|
220
|
-
<summary
|
|
286
|
+
<summary>🔎 Click here to see full result example</summary>
|
|
221
287
|
|
|
222
288
|
```javascript
|
|
223
289
|
{
|
|
@@ -298,49 +364,45 @@ csfd.creator(2120).then((creator) => console.log(creator));
|
|
|
298
364
|
|
|
299
365
|
### User Ratings
|
|
300
366
|
|
|
301
|
-
|
|
367
|
+
> Retrieve user ratings from their ČSFD profile.
|
|
302
368
|
|
|
303
|
-
|
|
369
|
+
**Method:** `csfd.userRatings(username: string, options?: UserRatingsOptions): Promise<Rating[]>`
|
|
304
370
|
|
|
305
|
-
|
|
371
|
+
#### Basic Usage
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
306
374
|
import { csfd } from 'node-csfd-api';
|
|
307
375
|
|
|
308
|
-
|
|
376
|
+
// Get last page of ratings (~50 items)
|
|
377
|
+
const ratings = await csfd.userRatings('912-bart');
|
|
309
378
|
```
|
|
310
379
|
|
|
311
|
-
####
|
|
380
|
+
#### Advanced Options
|
|
312
381
|
|
|
313
|
-
|
|
382
|
+
```typescript
|
|
383
|
+
// Get specific page
|
|
384
|
+
const page2 = await csfd.userRatings('912-bart', { page: 2 });
|
|
314
385
|
|
|
315
|
-
Get
|
|
386
|
+
// Get all ratings (use with caution - rate limiting applies)
|
|
387
|
+
const allRatings = await csfd.userRatings('912-bart', {
|
|
388
|
+
allPages: true,
|
|
389
|
+
allPagesDelay: 2000 // 2 second delay between requests
|
|
390
|
+
});
|
|
316
391
|
|
|
317
|
-
|
|
318
|
-
|
|
392
|
+
// Filter by content type
|
|
393
|
+
const onlyMovies = await csfd.userRatings('912-bart', {
|
|
394
|
+
includesOnly: ['film']
|
|
395
|
+
});
|
|
319
396
|
|
|
320
|
-
csfd
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
allPageDelay: 2000 // Make delay 2000ms on each page request
|
|
324
|
-
})
|
|
325
|
-
.then((ratings) => console.log(ratings));
|
|
397
|
+
const excludeEpisodes = await csfd.userRatings('912-bart', {
|
|
398
|
+
exclude: ['epizoda', 'série']
|
|
399
|
+
});
|
|
326
400
|
```
|
|
327
401
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
Get [second page of my ratings](https://www.csfd.cz/uzivatel/912-bart/hodnoceni/?page=2)
|
|
331
|
-
|
|
332
|
-
```javascript
|
|
333
|
-
import { csfd } from 'node-csfd-api';
|
|
334
|
-
|
|
335
|
-
csfd
|
|
336
|
-
.userRatings('912-bart', {
|
|
337
|
-
page: 2 // Get specific page
|
|
338
|
-
})
|
|
339
|
-
.then((ratings) => console.log(ratings));
|
|
340
|
-
```
|
|
402
|
+
> ⚠️ **Rate Limiting Warning**: When fetching all pages, use appropriate delays to avoid detection. Consider implementing exponential backoff for large datasets.
|
|
341
403
|
|
|
342
404
|
<details>
|
|
343
|
-
<summary
|
|
405
|
+
<summary>🔎 Click here to see full result example</summary>
|
|
344
406
|
|
|
345
407
|
```javascript
|
|
346
408
|
[
|
|
@@ -367,63 +429,56 @@ csfd
|
|
|
367
429
|
|
|
368
430
|
</details>
|
|
369
431
|
|
|
370
|
-
####
|
|
432
|
+
#### UserRatingsOptions
|
|
371
433
|
|
|
372
|
-
| Option
|
|
373
|
-
|
|
|
374
|
-
|
|
|
375
|
-
|
|
|
376
|
-
|
|
|
377
|
-
|
|
|
378
|
-
|
|
|
434
|
+
| Option | Type | Default | Description |
|
|
435
|
+
| --------------- | ----------------- | ------- | ---------------------------------------------------------------- |
|
|
436
|
+
| `includesOnly` | `CSFDFilmTypes[]` | `null` | Include only specific content types (e.g., `['film', 'seriál']`) |
|
|
437
|
+
| `exclude` | `CSFDFilmTypes[]` | `null` | Exclude specific content types (e.g., `['epizoda']`) |
|
|
438
|
+
| `allPages` | `boolean` | `false` | Fetch all pages of ratings |
|
|
439
|
+
| `allPagesDelay` | `number` | `0` | Delay between page requests in milliseconds |
|
|
440
|
+
| `page` | `number` | `1` | Fetch specific page number |
|
|
379
441
|
|
|
380
|
-
|
|
442
|
+
> 📝 **Note**: `includesOnly` and `exclude` are mutually exclusive. If both are provided, `includesOnly` takes precedence.
|
|
443
|
+
>
|
|
444
|
+
> 🔗 See [CSFDFilmTypes definition](https://github.com/bartholomej/node-csfd-api/blob/master/src/dto/global.ts)
|
|
381
445
|
|
|
382
446
|
### User Reviews
|
|
383
447
|
|
|
384
|
-
|
|
448
|
+
> Retrieve detailed user reviews from their ČSFD profile.
|
|
385
449
|
|
|
386
|
-
|
|
450
|
+
**Method:** `csfd.userReviews(userId: number | string, options?: UserReviewsOptions): Promise<Review[]>`
|
|
387
451
|
|
|
388
|
-
|
|
389
|
-
import { csfd } from 'node-csfd-api';
|
|
452
|
+
#### Basic Usage
|
|
390
453
|
|
|
391
|
-
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
#### All reviews (all pages)
|
|
395
|
-
|
|
396
|
-
> Warning: Use it wisely. Can be detected and banned. Consider using it together with `allPagesDelay` attribute.
|
|
397
|
-
|
|
398
|
-
Get [all user reviews](https://www.csfd.cz/uzivatel/195357-verbal/recenze/)
|
|
399
|
-
|
|
400
|
-
```javascript
|
|
454
|
+
```typescript
|
|
401
455
|
import { csfd } from 'node-csfd-api';
|
|
402
456
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
allPages: true, // Download all pages (one by one)
|
|
406
|
-
allPagesDelay: 2000 // Make delay 2000ms on each page request
|
|
407
|
-
})
|
|
408
|
-
.then((reviews) => console.log(reviews));
|
|
457
|
+
// Get latest reviews
|
|
458
|
+
const reviews = await csfd.userReviews(195357);
|
|
409
459
|
```
|
|
410
460
|
|
|
411
|
-
####
|
|
461
|
+
#### Advanced Options
|
|
412
462
|
|
|
413
|
-
|
|
463
|
+
```typescript
|
|
464
|
+
// Get specific page
|
|
465
|
+
const page2 = await csfd.userReviews(195357, { page: 2 });
|
|
414
466
|
|
|
415
|
-
|
|
416
|
-
|
|
467
|
+
// Get all reviews with rate limiting
|
|
468
|
+
const allReviews = await csfd.userReviews(195357, {
|
|
469
|
+
allPages: true,
|
|
470
|
+
allPagesDelay: 2000
|
|
471
|
+
});
|
|
417
472
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
473
|
+
// Filter by content type
|
|
474
|
+
const filtered = await csfd.userReviews(195357, {
|
|
475
|
+
includesOnly: ['film'],
|
|
476
|
+
exclude: ['epizoda']
|
|
477
|
+
});
|
|
423
478
|
```
|
|
424
479
|
|
|
425
480
|
<details>
|
|
426
|
-
<summary
|
|
481
|
+
<summary>🔎 Click here to see full result example</summary>
|
|
427
482
|
|
|
428
483
|
```javascript
|
|
429
484
|
[
|
|
@@ -458,166 +513,219 @@ csfd
|
|
|
458
513
|
|
|
459
514
|
</details>
|
|
460
515
|
|
|
461
|
-
####
|
|
462
|
-
|
|
463
|
-
| Option | Type | Default | Description |
|
|
464
|
-
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------ |
|
|
465
|
-
| **includesOnly** | [CSFDFilmTypes[]](https://github.com/bartholomej/node-csfd-api/blob/8fa5f9cbc7e7f2b62b0bd2c2b5a24c9a63444f6a/src/interfaces/global.ts#L25) | null | Including only film types. eg. `['seriál', 'koncert']` |
|
|
466
|
-
| **exclude** | [CSFDFilmTypes[]](https://github.com/bartholomej/node-csfd-api/blob/8fa5f9cbc7e7f2b62b0bd2c2b5a24c9a63444f6a/src/interfaces/global.ts#L25) | null | Excluding film types eg. `['epizoda', 'série']` |
|
|
467
|
-
| **allPages** | boolean | false | Get all pages |
|
|
468
|
-
| **allPagesDelay** | number | 0 | Delay on each page request. In milliseconds |
|
|
469
|
-
| **page** | number | 1 | Specific page number to fetch (e.g., 2 for page 2) |
|
|
470
|
-
|
|
471
|
-
_Note: You can not use both parameters `includesOnly` and `excludes`. Parameter `includesOnly` has a priority._
|
|
516
|
+
#### UserReviewsOptions
|
|
472
517
|
|
|
473
|
-
|
|
518
|
+
Same options as [UserRatingsOptions](#userrationsoptions).
|
|
474
519
|
|
|
475
|
-
|
|
520
|
+
## 🐳 Docker Support
|
|
476
521
|
|
|
477
|
-
|
|
522
|
+
Run the CSFD API as a standalone REST service using Docker.
|
|
478
523
|
|
|
479
|
-
###
|
|
524
|
+
### Using Pre-built Image
|
|
480
525
|
|
|
481
526
|
```bash
|
|
527
|
+
# Pull the latest image
|
|
482
528
|
docker pull bartholomej/node-csfd-api
|
|
483
|
-
```
|
|
484
529
|
|
|
485
|
-
|
|
530
|
+
# Run the container
|
|
531
|
+
docker run -p 3000:3000 bartholomej/node-csfd-api
|
|
532
|
+
```
|
|
486
533
|
|
|
487
|
-
|
|
534
|
+
### Building Your Own Image
|
|
488
535
|
|
|
489
536
|
```bash
|
|
537
|
+
# Build the image
|
|
490
538
|
docker build -t node-csfd-api .
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
> Run image on port 3000
|
|
494
539
|
|
|
495
|
-
|
|
540
|
+
# Run the container
|
|
496
541
|
docker run -p 3000:3000 node-csfd-api
|
|
497
542
|
```
|
|
498
543
|
|
|
499
|
-
|
|
544
|
+
### REST API Endpoints
|
|
500
545
|
|
|
501
|
-
|
|
546
|
+
Once running, access the API at `http://localhost:3000`:
|
|
502
547
|
|
|
503
|
-
|
|
548
|
+
| Endpoint | Description | Example |
|
|
549
|
+
| ------------------------- | ----------------- | ------------------------ |
|
|
550
|
+
| `/movie/:id` | Get movie details | `/movie/535121` |
|
|
551
|
+
| `/search/:query` | Search content | `/search/tarantino` |
|
|
552
|
+
| `/creator/:id` | Get creator info | `/creator/2120` |
|
|
553
|
+
| `/user-ratings/:username` | Get user ratings | `/user-ratings/912-bart` |
|
|
554
|
+
| `/user-reviews/:userId` | Get user reviews | `/user-reviews/195357` |
|
|
504
555
|
|
|
505
|
-
|
|
506
|
-
- `/search/quentin+tarantino`
|
|
507
|
-
- `/creator/2120`
|
|
508
|
-
- `/user-ratings/912-bart`
|
|
509
|
-
- `/user-reviews/195357`
|
|
556
|
+
**Docker Hub:** [bartholomej/node-csfd-api](https://hub.docker.com/r/bartholomej/node-csfd-api)
|
|
510
557
|
|
|
511
|
-
##
|
|
558
|
+
## 🌟 Real-World Usage
|
|
512
559
|
|
|
513
|
-
|
|
560
|
+
This library powers several production applications:
|
|
514
561
|
|
|
515
|
-
|
|
516
|
-
- [Dafilms: chrome extension](https://chrome.google.com/webstore/detail/dafilms/hgcgneddmgflnbmhkjnefiobjgobbmdm) ([code](https://github.com/bartholomej/dafilms-ext))
|
|
517
|
-
- [Kviff.tv: chrome extension](https://chrome.google.com/webstore/detail/kvifftv-%20-csfd/ihpngekoejodiligajlppbeedofhnmfm) ([code](https://github.com/bartholomej/kviff-ext))
|
|
562
|
+
### Browser Extensions
|
|
518
563
|
|
|
519
|
-
|
|
564
|
+
- **[Netflix ČSFD Extension](https://chrome.google.com/webstore/detail/netflix-csfd/eomgekccbddnlpmehgdjmlphndjgnlni)** - Shows ČSFD ratings on Netflix ([source](https://github.com/bartholomej/netflix-csfd-ext))
|
|
565
|
+
- **[Dafilms Extension](https://chrome.google.com/webstore/detail/dafilms/hgcgneddmgflnbmhkjnefiobjgobbmdm)** - ČSFD integration for Dafilms ([source](https://github.com/bartholomej/dafilms-ext))
|
|
566
|
+
- **[Kviff.tv Extension](https://chrome.google.com/webstore/detail/kvifftv-%20-csfd/ihpngekoejodiligajlppbeedofhnmfm)** - ČSFD ratings for Kviff.tv ([source](https://github.com/bartholomej/kviff-ext))
|
|
520
567
|
|
|
521
|
-
|
|
568
|
+
### Web Applications
|
|
522
569
|
|
|
523
|
-
|
|
570
|
+
- **[bartweb.cz](https://bartweb.cz)** - Personal website using Firebase Functions for "Last Seen" movie tracking
|
|
524
571
|
|
|
525
|
-
|
|
572
|
+
### Mobile Applications
|
|
573
|
+
|
|
574
|
+
- **[KinoKlub](https://play.google.com/store/apps/details?id=com.aquasoup)** - React Native app for AeroFilms cinema chain (Android & iOS)
|
|
526
575
|
|
|
527
576
|
## 🔮 Roadmap
|
|
528
577
|
|
|
529
|
-
###
|
|
530
|
-
|
|
531
|
-
-
|
|
532
|
-
-
|
|
533
|
-
-
|
|
534
|
-
-
|
|
535
|
-
-
|
|
536
|
-
-
|
|
537
|
-
|
|
538
|
-
-
|
|
539
|
-
|
|
540
|
-
-
|
|
541
|
-
|
|
542
|
-
-
|
|
543
|
-
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
- [x] Producers
|
|
553
|
-
- [x] Film editors
|
|
554
|
-
- [x] Costume designers
|
|
555
|
-
- [x] Production designers
|
|
556
|
-
- [x] Premieres
|
|
557
|
-
- [x] Related movies
|
|
558
|
-
- [x] Similar movies
|
|
559
|
-
- [x] Trivia
|
|
560
|
-
- [x] Photo from movie (random)
|
|
561
|
-
- [ ] Reviews (from movie page)
|
|
562
|
-
- [ ] OST
|
|
563
|
-
- [ ] Search
|
|
564
|
-
- [x] Movies
|
|
565
|
-
- [x] Users
|
|
566
|
-
- [x] TV Series
|
|
567
|
-
- [ ] Creators
|
|
568
|
-
- [x] Creators
|
|
569
|
-
- [x] Bio
|
|
570
|
-
- [x] Movies (TODO categories)
|
|
571
|
-
- [x] User Ratings
|
|
572
|
-
- [x] Last ratings
|
|
573
|
-
- [x] All pages
|
|
574
|
-
- [x] User Reviews
|
|
575
|
-
- [x] Last reviews
|
|
576
|
-
- [x] All pages
|
|
577
|
-
- [ ] Filter by type
|
|
578
|
+
### Completed Features ✅
|
|
579
|
+
|
|
580
|
+
- **Movies & TV Series**
|
|
581
|
+
- Basic info (title, year, rating, poster, duration)
|
|
582
|
+
- Detailed metadata (genres, origins, VOD platforms)
|
|
583
|
+
- Cast & crew (directors, actors, writers, composers, producers, etc.)
|
|
584
|
+
- Related content (similar movies, trivia)
|
|
585
|
+
- Alternative titles, premieres, tags
|
|
586
|
+
- **Search**
|
|
587
|
+
- Movies, TV series, and users
|
|
588
|
+
- **Creators**
|
|
589
|
+
- Biography and filmography
|
|
590
|
+
- **User Data**
|
|
591
|
+
- Ratings with pagination and filtering
|
|
592
|
+
- Reviews with pagination and filtering
|
|
593
|
+
|
|
594
|
+
### Planned Features 🚧
|
|
595
|
+
|
|
596
|
+
- [ ] Movie: reviews from movie detail page
|
|
597
|
+
- [ ] Movie: Original soundtracks (OST) information
|
|
598
|
+
- [ ] Search: Creator search functionality
|
|
599
|
+
- [ ] Server: Caching layer for improved performance
|
|
600
|
+
- [ ] Server: Rate limiting helpers
|
|
578
601
|
|
|
579
602
|
## 🛠️ Development
|
|
580
603
|
|
|
581
|
-
###
|
|
604
|
+
### Prerequisites
|
|
605
|
+
|
|
606
|
+
- Node.js 18+
|
|
607
|
+
- yarn/npm/pnpm/...
|
|
608
|
+
|
|
609
|
+
### Setup
|
|
582
610
|
|
|
583
611
|
```bash
|
|
612
|
+
# Clone the repository
|
|
613
|
+
git clone https://github.com/bartholomej/node-csfd-api.git
|
|
614
|
+
cd node-csfd-api
|
|
615
|
+
|
|
616
|
+
# Install dependencies
|
|
617
|
+
yarn install
|
|
618
|
+
|
|
619
|
+
# Run tests
|
|
620
|
+
yarn test
|
|
621
|
+
|
|
622
|
+
# Run tests with coverage
|
|
623
|
+
yarn test:coverage
|
|
624
|
+
|
|
625
|
+
# Start development mode
|
|
584
626
|
yarn start
|
|
627
|
+
|
|
628
|
+
# Run the demo
|
|
629
|
+
yarn demo
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Project Structure
|
|
633
|
+
|
|
634
|
+
```text
|
|
635
|
+
src/
|
|
636
|
+
├── dto/ # Data transfer objects & types
|
|
637
|
+
├── fetchers/ # HTTP request handlers
|
|
638
|
+
├── helpers/ # Parsing & data transformation
|
|
639
|
+
├── services/ # Main API service classes
|
|
640
|
+
└── index.ts # Public API exports
|
|
585
641
|
```
|
|
586
642
|
|
|
587
|
-
###
|
|
643
|
+
### Testing
|
|
588
644
|
|
|
589
|
-
|
|
645
|
+
The project maintains ~100% code coverage. Tests are located in the `tests/` directory.
|
|
590
646
|
|
|
591
647
|
```bash
|
|
592
|
-
|
|
648
|
+
# Run all tests
|
|
649
|
+
yarn test
|
|
650
|
+
|
|
651
|
+
# Run tests in watch mode
|
|
652
|
+
yarn test:watch
|
|
653
|
+
|
|
654
|
+
# Generate coverage report
|
|
655
|
+
yarn test:coverage
|
|
593
656
|
```
|
|
594
657
|
|
|
595
|
-
## 🤝
|
|
658
|
+
## 🤝 Contributing
|
|
659
|
+
|
|
660
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
661
|
+
|
|
662
|
+
### How to Contribute
|
|
663
|
+
|
|
664
|
+
1. **Fork the repository**
|
|
665
|
+
2. **Create a feature branch** (`git checkout -b feature/amazing-feature`)
|
|
666
|
+
3. **Make your changes**
|
|
667
|
+
4. **Add tests** for new functionality
|
|
668
|
+
5. **Ensure tests pass** (`yarn test`)
|
|
669
|
+
6. **Commit your changes** (`git commit -m 'Add amazing feature'`)
|
|
670
|
+
7. **Push to the branch** (`git push origin feature/amazing-feature`)
|
|
671
|
+
8. **Open a Pull Request**
|
|
596
672
|
|
|
597
|
-
|
|
673
|
+
### Guidelines
|
|
598
674
|
|
|
599
|
-
|
|
675
|
+
- Write clear, concise commit messages
|
|
676
|
+
- Add tests for new features
|
|
677
|
+
- Update documentation as needed
|
|
678
|
+
- Follow the existing code style
|
|
679
|
+
- Ensure all tests pass before submitting PR
|
|
600
680
|
|
|
601
|
-
|
|
681
|
+
### Reporting Issues
|
|
602
682
|
|
|
603
|
-
|
|
683
|
+
Found a bug? Have a feature request? Please [open an issue](https://github.com/bartholomej/node-csfd-api/issues) with:
|
|
604
684
|
|
|
605
|
-
|
|
685
|
+
- Clear description of the problem
|
|
686
|
+
- Steps to reproduce (for bugs)
|
|
687
|
+
- Expected vs actual behavior
|
|
688
|
+
- Environment details (Node version, OS, etc.)
|
|
606
689
|
|
|
607
|
-
##
|
|
690
|
+
## ⭐️ Support
|
|
608
691
|
|
|
609
|
-
|
|
692
|
+
If you find this project useful and you are brave enough consider [making a donation](https://github.com/sponsors/bartholomej) for some 🍺 or 🍵 ;)
|
|
693
|
+
|
|
694
|
+
- Giving it a ⭐️ on [GitHub](https://github.com/bartholomej/node-csfd-api)
|
|
695
|
+
- Sharing it with others who might benefit
|
|
696
|
+
- [Sponsoring the project](https://github.com/sponsors/bartholomej) to support ongoing development
|
|
697
|
+
|
|
698
|
+
Your support helps maintain and improve this library! 🙏
|
|
699
|
+
|
|
700
|
+
## 🔒 Privacy & Security
|
|
701
|
+
|
|
702
|
+
**This library does not collect, store, or transmit any user data.**
|
|
703
|
+
|
|
704
|
+
All requests are made directly from your application to ČSFD.cz. No intermediary servers are involved, and no data is logged or stored by this library.
|
|
610
705
|
|
|
611
706
|
I physically can't. I have nowhere to store it. I don't even have a server database to store it. So even if Justin Bieber asked nicely to see your data, I wouldn't have anything to show him.
|
|
612
707
|
|
|
613
|
-
|
|
708
|
+
### Important Notes
|
|
709
|
+
|
|
710
|
+
- This is a **scraping library** - use it responsibly and respect ❤️ ČSFD's terms of service
|
|
711
|
+
- Implement appropriate rate limiting in production
|
|
712
|
+
- Consider caching responses to minimize server load
|
|
713
|
+
- Be aware of CORS restrictions when using in browsers
|
|
614
714
|
|
|
615
715
|
## 📝 License
|
|
616
716
|
|
|
617
|
-
|
|
717
|
+
MIT © 2020 - 2025 [Lukas Bartak](http://bartweb.cz)
|
|
718
|
+
|
|
719
|
+
See [LICENSE](LICENSE) for full details.
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
<div align="center">
|
|
724
|
+
|
|
725
|
+
**Built with ❤️ by [Lukas Bartak](https://bartweb.cz)**
|
|
618
726
|
|
|
619
|
-
|
|
727
|
+
Powered by nature 🗻, wind 💨, tea 🍵 and beer 🍺
|
|
620
728
|
|
|
621
|
-
|
|
729
|
+
[⭐ Star on GitHub](https://github.com/bartholomej/node-csfd-api) • [📦 NPM Package](https://www.npmjs.com/node-csfd-api) • [🐳 Docker Hub](https://hub.docker.com/r/bartholomej/node-csfd-api)
|
|
622
730
|
|
|
623
|
-
|
|
731
|
+
</div>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
let cross_fetch = require("cross-fetch");
|
|
3
|
-
cross_fetch = require_rolldown_runtime.__toESM(cross_fetch);
|
|
4
2
|
|
|
5
3
|
//#region src/fetchers/fetch.polyfill.ts
|
|
6
4
|
const fetchSafe = typeof fetch === "function" && fetch || typeof global === "object" && global.fetch || typeof window !== "undefined" && window.fetch || cross_fetch.fetch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.polyfill.js","names":["crossFetch"],"sources":["../../src/fetchers/fetch.polyfill.ts"],"sourcesContent":["// Check if `fetch` is available in global scope (nodejs 18+) or in window (browser). If not, use cross-fetch polyfill.\nimport { fetch as crossFetch } from 'cross-fetch';\nexport const fetchSafe =\n (typeof fetch === 'function' && fetch) || // ServiceWorker fetch (Cloud Functions + Chrome extension)\n (typeof global === 'object' && global.fetch) || // Node.js 18+ fetch\n (typeof window !== 'undefined' && window.fetch) || // Browser fetch\n crossFetch; // Polyfill fetch\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.polyfill.js","names":["crossFetch"],"sources":["../../src/fetchers/fetch.polyfill.ts"],"sourcesContent":["// Check if `fetch` is available in global scope (nodejs 18+) or in window (browser). If not, use cross-fetch polyfill.\nimport { fetch as crossFetch } from 'cross-fetch';\nexport const fetchSafe =\n (typeof fetch === 'function' && fetch) || // ServiceWorker fetch (Cloud Functions + Chrome extension)\n (typeof global === 'object' && global.fetch) || // Node.js 18+ fetch\n (typeof window !== 'undefined' && window.fetch) || // Browser fetch\n crossFetch; // Polyfill fetch\n"],"mappings":";;;AAEA,MAAa,YACV,OAAO,UAAU,cAAc,SAC/B,OAAO,WAAW,YAAY,OAAO,SACrC,OAAO,WAAW,eAAe,OAAO,SACzCA"}
|
package/fetchers/index.js
CHANGED
|
@@ -12,7 +12,7 @@ const fetchPage = async (url, optionsRequest) => {
|
|
|
12
12
|
try {
|
|
13
13
|
const mergedHeaders = new Headers(defaultHeaders);
|
|
14
14
|
if (optionsRequest?.headers) new Headers(optionsRequest.headers).forEach((value, key) => mergedHeaders.set(key, value));
|
|
15
|
-
const { headers: _
|
|
15
|
+
const { headers: _, ...restOptions } = optionsRequest || {};
|
|
16
16
|
const response = await require_fetch_polyfill.fetchSafe(url, {
|
|
17
17
|
credentials: "omit",
|
|
18
18
|
...restOptions,
|
package/fetchers/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["USER_AGENTS: string[]","fetchSafe","e: unknown"],"sources":["../../src/fetchers/index.ts"],"sourcesContent":["import { fetchSafe } from './fetch.polyfill';\n\nconst USER_AGENTS: string[] = [\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',\n 'Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36',\n 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36'\n];\n\nconst defaultHeaders = {\n 'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],\n};\n\nexport const fetchPage = async (url: string, optionsRequest?: RequestInit): Promise<string> => {\n try {\n const mergedHeaders = new Headers(defaultHeaders);\n if (optionsRequest?.headers) {\n const reqHeaders = new Headers(optionsRequest.headers);\n reqHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n const { headers: _, ...restOptions } = optionsRequest || {};\n\n const response = await fetchSafe(url, { credentials: 'omit', ...restOptions, headers: mergedHeaders });\n if (response.status >= 400 && response.status < 600) {\n throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);\n }\n return await response.text();\n } catch (e: unknown) {\n if (e instanceof Error) {\n console.error(e.message);\n } else {\n console.error(String(e));\n }\n return 'Error';\n }\n};\n"],"mappings":";;;AAEA,MAAMA,cAAwB;CAC5B;CACA;CACA;CACA;CACD;AAED,MAAM,iBAAiB,EACrB,cAAc,YAAY,KAAK,MAAM,KAAK,QAAQ,GAAG,YAAY,OAAO,GACzE;AAED,MAAa,YAAY,OAAO,KAAa,mBAAkD;AAC7F,KAAI;EACF,MAAM,gBAAgB,IAAI,QAAQ,eAAe;AACjD,MAAI,gBAAgB,QAElB,CADmB,IAAI,QAAQ,eAAe,QAAQ,CAC3C,SAAS,OAAO,QAAQ,cAAc,IAAI,KAAK,MAAM,CAAC;EAEnE,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"index.js","names":["USER_AGENTS: string[]","fetchSafe","e: unknown"],"sources":["../../src/fetchers/index.ts"],"sourcesContent":["import { fetchSafe } from './fetch.polyfill';\n\nconst USER_AGENTS: string[] = [\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',\n 'Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36',\n 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36'\n];\n\nconst defaultHeaders = {\n 'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],\n};\n\nexport const fetchPage = async (url: string, optionsRequest?: RequestInit): Promise<string> => {\n try {\n const mergedHeaders = new Headers(defaultHeaders);\n if (optionsRequest?.headers) {\n const reqHeaders = new Headers(optionsRequest.headers);\n reqHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n const { headers: _, ...restOptions } = optionsRequest || {};\n\n const response = await fetchSafe(url, { credentials: 'omit', ...restOptions, headers: mergedHeaders });\n if (response.status >= 400 && response.status < 600) {\n throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);\n }\n return await response.text();\n } catch (e: unknown) {\n if (e instanceof Error) {\n console.error(e.message);\n } else {\n console.error(String(e));\n }\n return 'Error';\n }\n};\n"],"mappings":";;;AAEA,MAAMA,cAAwB;CAC5B;CACA;CACA;CACA;CACD;AAED,MAAM,iBAAiB,EACrB,cAAc,YAAY,KAAK,MAAM,KAAK,QAAQ,GAAG,YAAY,OAAO,GACzE;AAED,MAAa,YAAY,OAAO,KAAa,mBAAkD;AAC7F,KAAI;EACF,MAAM,gBAAgB,IAAI,QAAQ,eAAe;AACjD,MAAI,gBAAgB,QAElB,CADmB,IAAI,QAAQ,eAAe,QAAQ,CAC3C,SAAS,OAAO,QAAQ,cAAc,IAAI,KAAK,MAAM,CAAC;EAEnE,MAAM,EAAE,SAAS,GAAG,GAAG,gBAAgB,kBAAkB,EAAE;EAE3D,MAAM,WAAW,MAAMC,iCAAU,KAAK;GAAE,aAAa;GAAQ,GAAG;GAAa,SAAS;GAAe,CAAC;AACtG,MAAI,SAAS,UAAU,OAAO,SAAS,SAAS,IAC9C,OAAM,IAAI,MAAM,+BAA+B,SAAS,OAAO,YAAY,MAAM;AAEnF,SAAO,MAAM,SAAS,MAAM;UACrBC,GAAY;AACnB,MAAI,aAAa,MACf,SAAQ,MAAM,EAAE,QAAQ;MAExB,SAAQ,MAAM,OAAO,EAAE,CAAC;AAE1B,SAAO"}
|
package/fetchers/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const fetchPage = async (url, optionsRequest) => {
|
|
|
12
12
|
try {
|
|
13
13
|
const mergedHeaders = new Headers(defaultHeaders);
|
|
14
14
|
if (optionsRequest?.headers) new Headers(optionsRequest.headers).forEach((value, key) => mergedHeaders.set(key, value));
|
|
15
|
-
const { headers: _
|
|
15
|
+
const { headers: _, ...restOptions } = optionsRequest || {};
|
|
16
16
|
const response = await fetchSafe(url, {
|
|
17
17
|
credentials: "omit",
|
|
18
18
|
...restOptions,
|
package/fetchers/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["USER_AGENTS: string[]","e: unknown"],"sources":["../../src/fetchers/index.ts"],"sourcesContent":["import { fetchSafe } from './fetch.polyfill';\n\nconst USER_AGENTS: string[] = [\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',\n 'Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36',\n 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36'\n];\n\nconst defaultHeaders = {\n 'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],\n};\n\nexport const fetchPage = async (url: string, optionsRequest?: RequestInit): Promise<string> => {\n try {\n const mergedHeaders = new Headers(defaultHeaders);\n if (optionsRequest?.headers) {\n const reqHeaders = new Headers(optionsRequest.headers);\n reqHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n const { headers: _, ...restOptions } = optionsRequest || {};\n\n const response = await fetchSafe(url, { credentials: 'omit', ...restOptions, headers: mergedHeaders });\n if (response.status >= 400 && response.status < 600) {\n throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);\n }\n return await response.text();\n } catch (e: unknown) {\n if (e instanceof Error) {\n console.error(e.message);\n } else {\n console.error(String(e));\n }\n return 'Error';\n }\n};\n"],"mappings":";;;AAEA,MAAMA,cAAwB;CAC5B;CACA;CACA;CACA;CACD;AAED,MAAM,iBAAiB,EACrB,cAAc,YAAY,KAAK,MAAM,KAAK,QAAQ,GAAG,YAAY,OAAO,GACzE;AAED,MAAa,YAAY,OAAO,KAAa,mBAAkD;AAC7F,KAAI;EACF,MAAM,gBAAgB,IAAI,QAAQ,eAAe;AACjD,MAAI,gBAAgB,QAElB,CADmB,IAAI,QAAQ,eAAe,QAAQ,CAC3C,SAAS,OAAO,QAAQ,cAAc,IAAI,KAAK,MAAM,CAAC;EAEnE,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["USER_AGENTS: string[]","e: unknown"],"sources":["../../src/fetchers/index.ts"],"sourcesContent":["import { fetchSafe } from './fetch.polyfill';\n\nconst USER_AGENTS: string[] = [\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',\n 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',\n 'Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36',\n 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36'\n];\n\nconst defaultHeaders = {\n 'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],\n};\n\nexport const fetchPage = async (url: string, optionsRequest?: RequestInit): Promise<string> => {\n try {\n const mergedHeaders = new Headers(defaultHeaders);\n if (optionsRequest?.headers) {\n const reqHeaders = new Headers(optionsRequest.headers);\n reqHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n const { headers: _, ...restOptions } = optionsRequest || {};\n\n const response = await fetchSafe(url, { credentials: 'omit', ...restOptions, headers: mergedHeaders });\n if (response.status >= 400 && response.status < 600) {\n throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);\n }\n return await response.text();\n } catch (e: unknown) {\n if (e instanceof Error) {\n console.error(e.message);\n } else {\n console.error(String(e));\n }\n return 'Error';\n }\n};\n"],"mappings":";;;AAEA,MAAMA,cAAwB;CAC5B;CACA;CACA;CACA;CACD;AAED,MAAM,iBAAiB,EACrB,cAAc,YAAY,KAAK,MAAM,KAAK,QAAQ,GAAG,YAAY,OAAO,GACzE;AAED,MAAa,YAAY,OAAO,KAAa,mBAAkD;AAC7F,KAAI;EACF,MAAM,gBAAgB,IAAI,QAAQ,eAAe;AACjD,MAAI,gBAAgB,QAElB,CADmB,IAAI,QAAQ,eAAe,QAAQ,CAC3C,SAAS,OAAO,QAAQ,cAAc,IAAI,KAAK,MAAM,CAAC;EAEnE,MAAM,EAAE,SAAS,GAAG,GAAG,gBAAgB,kBAAkB,EAAE;EAE3D,MAAM,WAAW,MAAM,UAAU,KAAK;GAAE,aAAa;GAAQ,GAAG;GAAa,SAAS;GAAe,CAAC;AACtG,MAAI,SAAS,UAAU,OAAO,SAAS,SAAS,IAC9C,OAAM,IAAI,MAAM,+BAA+B,SAAS,OAAO,YAAY,MAAM;AAEnF,SAAO,MAAM,SAAS,MAAM;UACrBC,GAAY;AACnB,MAAI,aAAa,MACf,SAAQ,MAAM,EAAE,QAAQ;MAExB,SAAQ,MAAM,OAAO,EAAE,CAAC;AAE1B,SAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"movie.helper.js","names":["labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>>","getColor","parseISO8601Duration","el","addProtocol","parseIdFromUrl","vods: CSFDVod[]","movieListItem: CSFDMovieListItem[]","premiere: CSFDPremiere[]"],"sources":["../../src/helpers/movie.helper.ts"],"sourcesContent":["import { HTMLElement } from 'node-html-parser';\nimport { CSFDColorRating } from '../dto/global';\nimport {\n CSFDBoxContent,\n CSFDCreatorGroups,\n CSFDCreatorGroupsEnglish,\n CSFDCreatorGroupsSlovak,\n CSFDGenres,\n CSFDMovieCreator,\n CSFDMovieListItem,\n CSFDPremiere,\n CSFDTitlesOther,\n CSFDVod,\n CSFDVodService\n} from '../dto/movie';\nimport { addProtocol, getColor, parseISO8601Duration, parseIdFromUrl } from './global.helper';\n\n/**\n * Maps language-specific movie creator group labels.\n * @param language - The language code (e.g., 'en', 'cs')\n * @param key - The key of the creator group (e.g., 'directors', 'writers')\n * @returns The localized label for the creator group\n */\nexport const getLocalizedCreatorLabel = (\n language: string | undefined,\n key: 'directors' | 'writers' | 'cinematography' | 'music' | 'actors' | 'basedOn' | 'producers' | 'filmEditing' | 'costumeDesign' | 'productionDesign'\n): CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak => {\n const labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>> = {\n en: {\n directors: 'Directed by',\n writers: 'Screenplay',\n cinematography: 'Cinematography',\n music: 'Composer',\n actors: 'Cast',\n basedOn: 'Based on',\n producers: 'Produced by',\n filmEditing: 'Editing',\n costumeDesign: 'Costumes',\n productionDesign: 'Production design',\n casting: 'Casting',\n sound: 'Sound',\n makeup: 'Make-up'\n },\n cs: {\n directors: 'Režie',\n writers: 'Scénář',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrají',\n basedOn: 'Předloha',\n producers: 'Produkce',\n filmEditing: 'Střih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografie',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n },\n sk: {\n directors: 'Réžia',\n writers: 'Scenár',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrajú',\n basedOn: 'Predloha',\n producers: 'Produkcia',\n filmEditing: 'Strih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografia',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n }\n };\n\n const lang = language || 'cs'; // Default to Czech\n return (labels[lang] || labels['cs'])[key];\n};\n\nexport const getMovieId = (el: HTMLElement): number => {\n const url = el.querySelector('.tabs .tab-nav-list a').attributes.href;\n return parseIdFromUrl(url);\n};\n\nexport const getMovieTitle = (el: HTMLElement): string => {\n return el.querySelector('h1').innerText.split(`(`)[0].trim();\n};\n\nexport const getMovieGenres = (el: HTMLElement): CSFDGenres[] => {\n const genresRaw = el.querySelector('.genres').textContent;\n return genresRaw.split(' / ') as CSFDGenres[];\n};\n\nexport const getMovieOrigins = (el: HTMLElement): string[] => {\n const originsRaw = el.querySelector('.origin').textContent;\n const origins = originsRaw.split(',')[0];\n return origins.split(' / ');\n};\n\nexport const getMovieColorRating = (bodyClasses: string[]): CSFDColorRating => {\n return getColor(bodyClasses[1]);\n};\n\nexport const getMovieRating = (el: HTMLElement): number => {\n const ratingRaw = el.querySelector('.film-rating-average').textContent;\n const rating = ratingRaw?.replace(/%/g, '').trim();\n const ratingInt = parseInt(rating);\n\n if (Number.isInteger(ratingInt)) {\n return ratingInt;\n } else {\n return null;\n }\n};\n\nexport const getMovieRatingCount = (el: HTMLElement): number => {\n const ratingCountRaw = el.querySelector('.box-rating-container .counter')?.textContent;\n const ratingCount = +ratingCountRaw?.replace(/[(\\s)]/g, '');\n if (Number.isInteger(ratingCount)) {\n return ratingCount;\n } else {\n return null;\n }\n};\n\nexport const getMovieYear = (el: string): number => {\n try {\n const jsonLd = JSON.parse(el);\n return +jsonLd.dateCreated;\n } catch (error) {\n console.error('node-csfd-api: Error parsing JSON-LD', error);\n return null;\n }\n};\n\nexport const getMovieDuration = (jsonLdRaw: string, el: HTMLElement): number => {\n let duration = null;\n try {\n const jsonLd = JSON.parse(jsonLdRaw);\n duration = jsonLd.duration;\n return parseISO8601Duration(duration);\n } catch (error) {\n const origin = el.querySelector('.origin').innerText;\n const timeString = origin.split(',');\n if (timeString.length > 2) {\n // Get last time elelment\n const timeString2 = timeString.pop().trim();\n // Clean it\n const timeRaw = timeString2.split('(')[0].trim();\n // Split by minutes and hours\n const hoursMinsRaw = timeRaw.split('min')[0];\n const hoursMins = hoursMinsRaw.split('h');\n // Resolve hours + minutes format\n duration = hoursMins.length > 1 ? +hoursMins[0] * 60 + +hoursMins[1] : +hoursMins[0];\n return duration;\n } else {\n return null;\n }\n }\n};\n\nexport const getMovieTitlesOther = (el: HTMLElement): CSFDTitlesOther[] => {\n const namesNode = el.querySelectorAll('.film-names li');\n\n if (!namesNode.length) {\n return [];\n }\n\n const titlesOther = namesNode.map((el) => {\n const country = el.querySelector('img.flag').attributes.alt;\n const title = el.textContent.trim().split('\\n')[0];\n\n if (country && title) {\n return {\n country,\n title\n };\n } else {\n return null;\n }\n });\n\n return titlesOther.filter((x) => x);\n};\n\nexport const getMoviePoster = (el: HTMLElement | null): string => {\n const poster = el.querySelector('.film-posters img');\n // Resolve empty image\n if (poster) {\n if (poster.classNames?.includes('empty-image')) {\n return null;\n } else {\n // Full sized image (not thumb)\n const imageThumb = poster.attributes.src.split('?')[0];\n const image = imageThumb.replace(/\\/w140\\//, '/w1080/');\n return addProtocol(image);\n }\n } else {\n return null;\n }\n};\n\nexport const getMovieRandomPhoto = (el: HTMLElement | null): string => {\n const imageNode = el.querySelector('.gallery-item picture img');\n const image = imageNode?.attributes?.src;\n if (image) {\n return image.replace(/\\/w663\\//, '/w1326/');\n } else {\n return null;\n }\n};\n\nexport const getMovieTrivia = (el: HTMLElement | null): string[] => {\n const triviaNodes = el.querySelectorAll('.article-trivia ul li');\n if (triviaNodes?.length) {\n return triviaNodes.map((node) => node.textContent.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n } else {\n return null;\n }\n};\n\nexport const getMovieDescriptions = (el: HTMLElement): string[] => {\n return el\n .querySelectorAll('.body--plots .plot-full p, .body--plots .plots .plots-item p')\n .map((movie) => movie.textContent?.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n};\n\nconst parseMoviePeople = (el: HTMLElement): CSFDMovieCreator[] => {\n const people = el.querySelectorAll('a');\n return (\n people\n // Filter out \"more\" links\n .filter((x) => x.classNames.length === 0)\n .map((person) => {\n return {\n id: parseIdFromUrl(person.attributes.href),\n name: person.innerText.trim(),\n url: `https://www.csfd.cz${person.attributes.href}`\n };\n })\n );\n};\n\nexport const getMovieGroup = (el: HTMLElement, group: CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak): CSFDMovieCreator[] => {\n const creators = el.querySelectorAll('.creators h4');\n const element = creators.filter((elem) => elem.textContent.trim().includes(group))[0];\n if (element?.parentNode) {\n return parseMoviePeople(element.parentNode as HTMLElement);\n } else {\n return [];\n }\n};\n\nexport const getMovieType = (el: HTMLElement): string => {\n const type = el.querySelector('.film-header-name .type');\n return type?.innerText?.replace(/[{()}]/g, '') || 'film';\n};\n\nexport const getMovieVods = (el: HTMLElement | null): CSFDVod[] => {\n let vods: CSFDVod[] = [];\n if (el) {\n const buttons = el.querySelectorAll('.box-buttons .button');\n const buttonsVod = buttons.filter((x) => !x.classNames.includes('button-social'));\n vods = buttonsVod.map((btn) => {\n return {\n title: btn.textContent.trim() as CSFDVodService,\n url: btn.attributes.href\n };\n });\n }\n return vods.length ? vods : [];\n};\n\n// Get box content\nconst getBoxContent = (el: HTMLElement, box: string): HTMLElement => {\n const headers = el.querySelectorAll('section.box .box-header');\n return headers.find((header) => header.querySelector('h3').textContent.trim().includes(box))\n ?.parentNode;\n};\n\nexport const getMovieBoxMovies = (el: HTMLElement, boxName: CSFDBoxContent): CSFDMovieListItem[] => {\n const movieListItem: CSFDMovieListItem[] = [];\n const box = getBoxContent(el, boxName);\n const movieTitleNodes = box?.querySelectorAll('.article-header .film-title-name');\n if (movieTitleNodes?.length) {\n for (const item of movieTitleNodes) {\n movieListItem.push({\n id: parseIdFromUrl(item.attributes.href),\n title: item.textContent.trim(),\n url: `https://www.csfd.cz${item.attributes.href}`\n });\n }\n }\n return movieListItem;\n};\n\nexport const getMoviePremieres = (el: HTMLElement): CSFDPremiere[] => {\n const premiereNodes = el.querySelectorAll('.box-premieres li');\n const premiere: CSFDPremiere[] = [];\n for (const premiereNode of premiereNodes) {\n const title = premiereNode.querySelector('p + span').attributes.title;\n\n if (title) {\n const [date, ...company] = title?.split(' ');\n\n premiere.push({\n country: premiereNode.querySelector('.flag')?.attributes.title || null,\n format: premiereNode.querySelector('p').textContent.trim()?.split(' od')[0],\n date,\n company: company.join(' ')\n });\n }\n }\n return premiere;\n};\n\nexport const getMovieTags = (el: HTMLElement): string[] => {\n const tagsRaw = el.querySelectorAll('.box-content a[href*=\"/tag/\"]');\n return tagsRaw.map((tag) => tag.textContent);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"movie.helper.js","names":["labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>>","getColor","parseISO8601Duration","el","addProtocol","parseIdFromUrl","vods: CSFDVod[]","movieListItem: CSFDMovieListItem[]","premiere: CSFDPremiere[]"],"sources":["../../src/helpers/movie.helper.ts"],"sourcesContent":["import { HTMLElement } from 'node-html-parser';\nimport { CSFDColorRating } from '../dto/global';\nimport {\n CSFDBoxContent,\n CSFDCreatorGroups,\n CSFDCreatorGroupsEnglish,\n CSFDCreatorGroupsSlovak,\n CSFDGenres,\n CSFDMovieCreator,\n CSFDMovieListItem,\n CSFDPremiere,\n CSFDTitlesOther,\n CSFDVod,\n CSFDVodService\n} from '../dto/movie';\nimport { addProtocol, getColor, parseISO8601Duration, parseIdFromUrl } from './global.helper';\n\n/**\n * Maps language-specific movie creator group labels.\n * @param language - The language code (e.g., 'en', 'cs')\n * @param key - The key of the creator group (e.g., 'directors', 'writers')\n * @returns The localized label for the creator group\n */\nexport const getLocalizedCreatorLabel = (\n language: string | undefined,\n key: 'directors' | 'writers' | 'cinematography' | 'music' | 'actors' | 'basedOn' | 'producers' | 'filmEditing' | 'costumeDesign' | 'productionDesign' | 'casting' | 'sound' | 'makeup'\n): CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak => {\n const labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>> = {\n en: {\n directors: 'Directed by',\n writers: 'Screenplay',\n cinematography: 'Cinematography',\n music: 'Composer',\n actors: 'Cast',\n basedOn: 'Based on',\n producers: 'Produced by',\n filmEditing: 'Editing',\n costumeDesign: 'Costumes',\n productionDesign: 'Production design',\n casting: 'Casting',\n sound: 'Sound',\n makeup: 'Make-up'\n },\n cs: {\n directors: 'Režie',\n writers: 'Scénář',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrají',\n basedOn: 'Předloha',\n producers: 'Produkce',\n filmEditing: 'Střih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografie',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n },\n sk: {\n directors: 'Réžia',\n writers: 'Scenár',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrajú',\n basedOn: 'Predloha',\n producers: 'Produkcia',\n filmEditing: 'Strih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografia',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n }\n };\n\n const lang = language || 'cs'; // Default to Czech\n return (labels[lang] || labels['cs'])[key];\n};\n\nexport const getMovieId = (el: HTMLElement): number => {\n const url = el.querySelector('.tabs .tab-nav-list a').attributes.href;\n return parseIdFromUrl(url);\n};\n\nexport const getMovieTitle = (el: HTMLElement): string => {\n return el.querySelector('h1').innerText.split(`(`)[0].trim();\n};\n\nexport const getMovieGenres = (el: HTMLElement): CSFDGenres[] => {\n const genresRaw = el.querySelector('.genres').textContent;\n return genresRaw.split(' / ') as CSFDGenres[];\n};\n\nexport const getMovieOrigins = (el: HTMLElement): string[] => {\n const originsRaw = el.querySelector('.origin').textContent;\n const origins = originsRaw.split(',')[0];\n return origins.split(' / ');\n};\n\nexport const getMovieColorRating = (bodyClasses: string[]): CSFDColorRating => {\n return getColor(bodyClasses[1]);\n};\n\nexport const getMovieRating = (el: HTMLElement): number => {\n const ratingRaw = el.querySelector('.film-rating-average').textContent;\n const rating = ratingRaw?.replace(/%/g, '').trim();\n const ratingInt = parseInt(rating);\n\n if (Number.isInteger(ratingInt)) {\n return ratingInt;\n } else {\n return null;\n }\n};\n\nexport const getMovieRatingCount = (el: HTMLElement): number => {\n const ratingCountRaw = el.querySelector('.box-rating-container .counter')?.textContent;\n const ratingCount = +ratingCountRaw?.replace(/[(\\s)]/g, '');\n if (Number.isInteger(ratingCount)) {\n return ratingCount;\n } else {\n return null;\n }\n};\n\nexport const getMovieYear = (el: string): number => {\n try {\n const jsonLd = JSON.parse(el);\n return +jsonLd.dateCreated;\n } catch (error) {\n console.error('node-csfd-api: Error parsing JSON-LD', error);\n return null;\n }\n};\n\nexport const getMovieDuration = (jsonLdRaw: string, el: HTMLElement): number => {\n let duration = null;\n try {\n const jsonLd = JSON.parse(jsonLdRaw);\n duration = jsonLd.duration;\n return parseISO8601Duration(duration);\n } catch (error) {\n const origin = el.querySelector('.origin').innerText;\n const timeString = origin.split(',');\n if (timeString.length > 2) {\n // Get last time elelment\n const timeString2 = timeString.pop().trim();\n // Clean it\n const timeRaw = timeString2.split('(')[0].trim();\n // Split by minutes and hours\n const hoursMinsRaw = timeRaw.split('min')[0];\n const hoursMins = hoursMinsRaw.split('h');\n // Resolve hours + minutes format\n duration = hoursMins.length > 1 ? +hoursMins[0] * 60 + +hoursMins[1] : +hoursMins[0];\n return duration;\n } else {\n return null;\n }\n }\n};\n\nexport const getMovieTitlesOther = (el: HTMLElement): CSFDTitlesOther[] => {\n const namesNode = el.querySelectorAll('.film-names li');\n\n if (!namesNode.length) {\n return [];\n }\n\n const titlesOther = namesNode.map((el) => {\n const country = el.querySelector('img.flag').attributes.alt;\n const title = el.textContent.trim().split('\\n')[0];\n\n if (country && title) {\n return {\n country,\n title\n };\n } else {\n return null;\n }\n });\n\n return titlesOther.filter((x) => x);\n};\n\nexport const getMoviePoster = (el: HTMLElement | null): string => {\n const poster = el.querySelector('.film-posters img');\n // Resolve empty image\n if (poster) {\n if (poster.classNames?.includes('empty-image')) {\n return null;\n } else {\n // Full sized image (not thumb)\n const imageThumb = poster.attributes.src.split('?')[0];\n const image = imageThumb.replace(/\\/w140\\//, '/w1080/');\n return addProtocol(image);\n }\n } else {\n return null;\n }\n};\n\nexport const getMovieRandomPhoto = (el: HTMLElement | null): string => {\n const imageNode = el.querySelector('.gallery-item picture img');\n const image = imageNode?.attributes?.src;\n if (image) {\n return image.replace(/\\/w663\\//, '/w1326/');\n } else {\n return null;\n }\n};\n\nexport const getMovieTrivia = (el: HTMLElement | null): string[] => {\n const triviaNodes = el.querySelectorAll('.article-trivia ul li');\n if (triviaNodes?.length) {\n return triviaNodes.map((node) => node.textContent.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n } else {\n return null;\n }\n};\n\nexport const getMovieDescriptions = (el: HTMLElement): string[] => {\n return el\n .querySelectorAll('.body--plots .plot-full p, .body--plots .plots .plots-item p')\n .map((movie) => movie.textContent?.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n};\n\nconst parseMoviePeople = (el: HTMLElement): CSFDMovieCreator[] => {\n const people = el.querySelectorAll('a');\n return (\n people\n // Filter out \"more\" links\n .filter((x) => x.classNames.length === 0)\n .map((person) => {\n return {\n id: parseIdFromUrl(person.attributes.href),\n name: person.innerText.trim(),\n url: `https://www.csfd.cz${person.attributes.href}`\n };\n })\n );\n};\n\nexport const getMovieGroup = (el: HTMLElement, group: CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak): CSFDMovieCreator[] => {\n const creators = el.querySelectorAll('.creators h4');\n const element = creators.filter((elem) => elem.textContent.trim().includes(group))[0];\n if (element?.parentNode) {\n return parseMoviePeople(element.parentNode as HTMLElement);\n } else {\n return [];\n }\n};\n\nexport const getMovieType = (el: HTMLElement): string => {\n const type = el.querySelector('.film-header-name .type');\n return type?.innerText?.replace(/[{()}]/g, '') || 'film';\n};\n\nexport const getMovieVods = (el: HTMLElement | null): CSFDVod[] => {\n let vods: CSFDVod[] = [];\n if (el) {\n const buttons = el.querySelectorAll('.box-buttons .button');\n const buttonsVod = buttons.filter((x) => !x.classNames.includes('button-social'));\n vods = buttonsVod.map((btn) => {\n return {\n title: btn.textContent.trim() as CSFDVodService,\n url: btn.attributes.href\n };\n });\n }\n return vods.length ? vods : [];\n};\n\n// Get box content\nconst getBoxContent = (el: HTMLElement, box: string): HTMLElement => {\n const headers = el.querySelectorAll('section.box .box-header');\n return headers.find((header) => header.querySelector('h3').textContent.trim().includes(box))\n ?.parentNode;\n};\n\nexport const getMovieBoxMovies = (el: HTMLElement, boxName: CSFDBoxContent): CSFDMovieListItem[] => {\n const movieListItem: CSFDMovieListItem[] = [];\n const box = getBoxContent(el, boxName);\n const movieTitleNodes = box?.querySelectorAll('.article-header .film-title-name');\n if (movieTitleNodes?.length) {\n for (const item of movieTitleNodes) {\n movieListItem.push({\n id: parseIdFromUrl(item.attributes.href),\n title: item.textContent.trim(),\n url: `https://www.csfd.cz${item.attributes.href}`\n });\n }\n }\n return movieListItem;\n};\n\nexport const getMoviePremieres = (el: HTMLElement): CSFDPremiere[] => {\n const premiereNodes = el.querySelectorAll('.box-premieres li');\n const premiere: CSFDPremiere[] = [];\n for (const premiereNode of premiereNodes) {\n const title = premiereNode.querySelector('p + span').attributes.title;\n\n if (title) {\n const [date, ...company] = title?.split(' ');\n\n premiere.push({\n country: premiereNode.querySelector('.flag')?.attributes.title || null,\n format: premiereNode.querySelector('p').textContent.trim()?.split(' od')[0],\n date,\n company: company.join(' ')\n });\n }\n }\n return premiere;\n};\n\nexport const getMovieTags = (el: HTMLElement): string[] => {\n const tagsRaw = el.querySelectorAll('.box-content a[href*=\"/tag/\"]');\n return tagsRaw.map((tag) => tag.textContent);\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"movie.helper.mjs","names":["labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>>","el","vods: CSFDVod[]","movieListItem: CSFDMovieListItem[]","premiere: CSFDPremiere[]"],"sources":["../../src/helpers/movie.helper.ts"],"sourcesContent":["import { HTMLElement } from 'node-html-parser';\nimport { CSFDColorRating } from '../dto/global';\nimport {\n CSFDBoxContent,\n CSFDCreatorGroups,\n CSFDCreatorGroupsEnglish,\n CSFDCreatorGroupsSlovak,\n CSFDGenres,\n CSFDMovieCreator,\n CSFDMovieListItem,\n CSFDPremiere,\n CSFDTitlesOther,\n CSFDVod,\n CSFDVodService\n} from '../dto/movie';\nimport { addProtocol, getColor, parseISO8601Duration, parseIdFromUrl } from './global.helper';\n\n/**\n * Maps language-specific movie creator group labels.\n * @param language - The language code (e.g., 'en', 'cs')\n * @param key - The key of the creator group (e.g., 'directors', 'writers')\n * @returns The localized label for the creator group\n */\nexport const getLocalizedCreatorLabel = (\n language: string | undefined,\n key: 'directors' | 'writers' | 'cinematography' | 'music' | 'actors' | 'basedOn' | 'producers' | 'filmEditing' | 'costumeDesign' | 'productionDesign'\n): CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak => {\n const labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>> = {\n en: {\n directors: 'Directed by',\n writers: 'Screenplay',\n cinematography: 'Cinematography',\n music: 'Composer',\n actors: 'Cast',\n basedOn: 'Based on',\n producers: 'Produced by',\n filmEditing: 'Editing',\n costumeDesign: 'Costumes',\n productionDesign: 'Production design',\n casting: 'Casting',\n sound: 'Sound',\n makeup: 'Make-up'\n },\n cs: {\n directors: 'Režie',\n writers: 'Scénář',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrají',\n basedOn: 'Předloha',\n producers: 'Produkce',\n filmEditing: 'Střih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografie',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n },\n sk: {\n directors: 'Réžia',\n writers: 'Scenár',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrajú',\n basedOn: 'Predloha',\n producers: 'Produkcia',\n filmEditing: 'Strih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografia',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n }\n };\n\n const lang = language || 'cs'; // Default to Czech\n return (labels[lang] || labels['cs'])[key];\n};\n\nexport const getMovieId = (el: HTMLElement): number => {\n const url = el.querySelector('.tabs .tab-nav-list a').attributes.href;\n return parseIdFromUrl(url);\n};\n\nexport const getMovieTitle = (el: HTMLElement): string => {\n return el.querySelector('h1').innerText.split(`(`)[0].trim();\n};\n\nexport const getMovieGenres = (el: HTMLElement): CSFDGenres[] => {\n const genresRaw = el.querySelector('.genres').textContent;\n return genresRaw.split(' / ') as CSFDGenres[];\n};\n\nexport const getMovieOrigins = (el: HTMLElement): string[] => {\n const originsRaw = el.querySelector('.origin').textContent;\n const origins = originsRaw.split(',')[0];\n return origins.split(' / ');\n};\n\nexport const getMovieColorRating = (bodyClasses: string[]): CSFDColorRating => {\n return getColor(bodyClasses[1]);\n};\n\nexport const getMovieRating = (el: HTMLElement): number => {\n const ratingRaw = el.querySelector('.film-rating-average').textContent;\n const rating = ratingRaw?.replace(/%/g, '').trim();\n const ratingInt = parseInt(rating);\n\n if (Number.isInteger(ratingInt)) {\n return ratingInt;\n } else {\n return null;\n }\n};\n\nexport const getMovieRatingCount = (el: HTMLElement): number => {\n const ratingCountRaw = el.querySelector('.box-rating-container .counter')?.textContent;\n const ratingCount = +ratingCountRaw?.replace(/[(\\s)]/g, '');\n if (Number.isInteger(ratingCount)) {\n return ratingCount;\n } else {\n return null;\n }\n};\n\nexport const getMovieYear = (el: string): number => {\n try {\n const jsonLd = JSON.parse(el);\n return +jsonLd.dateCreated;\n } catch (error) {\n console.error('node-csfd-api: Error parsing JSON-LD', error);\n return null;\n }\n};\n\nexport const getMovieDuration = (jsonLdRaw: string, el: HTMLElement): number => {\n let duration = null;\n try {\n const jsonLd = JSON.parse(jsonLdRaw);\n duration = jsonLd.duration;\n return parseISO8601Duration(duration);\n } catch (error) {\n const origin = el.querySelector('.origin').innerText;\n const timeString = origin.split(',');\n if (timeString.length > 2) {\n // Get last time elelment\n const timeString2 = timeString.pop().trim();\n // Clean it\n const timeRaw = timeString2.split('(')[0].trim();\n // Split by minutes and hours\n const hoursMinsRaw = timeRaw.split('min')[0];\n const hoursMins = hoursMinsRaw.split('h');\n // Resolve hours + minutes format\n duration = hoursMins.length > 1 ? +hoursMins[0] * 60 + +hoursMins[1] : +hoursMins[0];\n return duration;\n } else {\n return null;\n }\n }\n};\n\nexport const getMovieTitlesOther = (el: HTMLElement): CSFDTitlesOther[] => {\n const namesNode = el.querySelectorAll('.film-names li');\n\n if (!namesNode.length) {\n return [];\n }\n\n const titlesOther = namesNode.map((el) => {\n const country = el.querySelector('img.flag').attributes.alt;\n const title = el.textContent.trim().split('\\n')[0];\n\n if (country && title) {\n return {\n country,\n title\n };\n } else {\n return null;\n }\n });\n\n return titlesOther.filter((x) => x);\n};\n\nexport const getMoviePoster = (el: HTMLElement | null): string => {\n const poster = el.querySelector('.film-posters img');\n // Resolve empty image\n if (poster) {\n if (poster.classNames?.includes('empty-image')) {\n return null;\n } else {\n // Full sized image (not thumb)\n const imageThumb = poster.attributes.src.split('?')[0];\n const image = imageThumb.replace(/\\/w140\\//, '/w1080/');\n return addProtocol(image);\n }\n } else {\n return null;\n }\n};\n\nexport const getMovieRandomPhoto = (el: HTMLElement | null): string => {\n const imageNode = el.querySelector('.gallery-item picture img');\n const image = imageNode?.attributes?.src;\n if (image) {\n return image.replace(/\\/w663\\//, '/w1326/');\n } else {\n return null;\n }\n};\n\nexport const getMovieTrivia = (el: HTMLElement | null): string[] => {\n const triviaNodes = el.querySelectorAll('.article-trivia ul li');\n if (triviaNodes?.length) {\n return triviaNodes.map((node) => node.textContent.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n } else {\n return null;\n }\n};\n\nexport const getMovieDescriptions = (el: HTMLElement): string[] => {\n return el\n .querySelectorAll('.body--plots .plot-full p, .body--plots .plots .plots-item p')\n .map((movie) => movie.textContent?.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n};\n\nconst parseMoviePeople = (el: HTMLElement): CSFDMovieCreator[] => {\n const people = el.querySelectorAll('a');\n return (\n people\n // Filter out \"more\" links\n .filter((x) => x.classNames.length === 0)\n .map((person) => {\n return {\n id: parseIdFromUrl(person.attributes.href),\n name: person.innerText.trim(),\n url: `https://www.csfd.cz${person.attributes.href}`\n };\n })\n );\n};\n\nexport const getMovieGroup = (el: HTMLElement, group: CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak): CSFDMovieCreator[] => {\n const creators = el.querySelectorAll('.creators h4');\n const element = creators.filter((elem) => elem.textContent.trim().includes(group))[0];\n if (element?.parentNode) {\n return parseMoviePeople(element.parentNode as HTMLElement);\n } else {\n return [];\n }\n};\n\nexport const getMovieType = (el: HTMLElement): string => {\n const type = el.querySelector('.film-header-name .type');\n return type?.innerText?.replace(/[{()}]/g, '') || 'film';\n};\n\nexport const getMovieVods = (el: HTMLElement | null): CSFDVod[] => {\n let vods: CSFDVod[] = [];\n if (el) {\n const buttons = el.querySelectorAll('.box-buttons .button');\n const buttonsVod = buttons.filter((x) => !x.classNames.includes('button-social'));\n vods = buttonsVod.map((btn) => {\n return {\n title: btn.textContent.trim() as CSFDVodService,\n url: btn.attributes.href\n };\n });\n }\n return vods.length ? vods : [];\n};\n\n// Get box content\nconst getBoxContent = (el: HTMLElement, box: string): HTMLElement => {\n const headers = el.querySelectorAll('section.box .box-header');\n return headers.find((header) => header.querySelector('h3').textContent.trim().includes(box))\n ?.parentNode;\n};\n\nexport const getMovieBoxMovies = (el: HTMLElement, boxName: CSFDBoxContent): CSFDMovieListItem[] => {\n const movieListItem: CSFDMovieListItem[] = [];\n const box = getBoxContent(el, boxName);\n const movieTitleNodes = box?.querySelectorAll('.article-header .film-title-name');\n if (movieTitleNodes?.length) {\n for (const item of movieTitleNodes) {\n movieListItem.push({\n id: parseIdFromUrl(item.attributes.href),\n title: item.textContent.trim(),\n url: `https://www.csfd.cz${item.attributes.href}`\n });\n }\n }\n return movieListItem;\n};\n\nexport const getMoviePremieres = (el: HTMLElement): CSFDPremiere[] => {\n const premiereNodes = el.querySelectorAll('.box-premieres li');\n const premiere: CSFDPremiere[] = [];\n for (const premiereNode of premiereNodes) {\n const title = premiereNode.querySelector('p + span').attributes.title;\n\n if (title) {\n const [date, ...company] = title?.split(' ');\n\n premiere.push({\n country: premiereNode.querySelector('.flag')?.attributes.title || null,\n format: premiereNode.querySelector('p').textContent.trim()?.split(' od')[0],\n date,\n company: company.join(' ')\n });\n }\n }\n return premiere;\n};\n\nexport const getMovieTags = (el: HTMLElement): string[] => {\n const tagsRaw = el.querySelectorAll('.box-content a[href*=\"/tag/\"]');\n return tagsRaw.map((tag) => tag.textContent);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"movie.helper.mjs","names":["labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>>","el","vods: CSFDVod[]","movieListItem: CSFDMovieListItem[]","premiere: CSFDPremiere[]"],"sources":["../../src/helpers/movie.helper.ts"],"sourcesContent":["import { HTMLElement } from 'node-html-parser';\nimport { CSFDColorRating } from '../dto/global';\nimport {\n CSFDBoxContent,\n CSFDCreatorGroups,\n CSFDCreatorGroupsEnglish,\n CSFDCreatorGroupsSlovak,\n CSFDGenres,\n CSFDMovieCreator,\n CSFDMovieListItem,\n CSFDPremiere,\n CSFDTitlesOther,\n CSFDVod,\n CSFDVodService\n} from '../dto/movie';\nimport { addProtocol, getColor, parseISO8601Duration, parseIdFromUrl } from './global.helper';\n\n/**\n * Maps language-specific movie creator group labels.\n * @param language - The language code (e.g., 'en', 'cs')\n * @param key - The key of the creator group (e.g., 'directors', 'writers')\n * @returns The localized label for the creator group\n */\nexport const getLocalizedCreatorLabel = (\n language: string | undefined,\n key: 'directors' | 'writers' | 'cinematography' | 'music' | 'actors' | 'basedOn' | 'producers' | 'filmEditing' | 'costumeDesign' | 'productionDesign' | 'casting' | 'sound' | 'makeup'\n): CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak => {\n const labels: Record<string, Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>> = {\n en: {\n directors: 'Directed by',\n writers: 'Screenplay',\n cinematography: 'Cinematography',\n music: 'Composer',\n actors: 'Cast',\n basedOn: 'Based on',\n producers: 'Produced by',\n filmEditing: 'Editing',\n costumeDesign: 'Costumes',\n productionDesign: 'Production design',\n casting: 'Casting',\n sound: 'Sound',\n makeup: 'Make-up'\n },\n cs: {\n directors: 'Režie',\n writers: 'Scénář',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrají',\n basedOn: 'Předloha',\n producers: 'Produkce',\n filmEditing: 'Střih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografie',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n },\n sk: {\n directors: 'Réžia',\n writers: 'Scenár',\n cinematography: 'Kamera',\n music: 'Hudba',\n actors: 'Hrajú',\n basedOn: 'Predloha',\n producers: 'Produkcia',\n filmEditing: 'Strih',\n costumeDesign: 'Kostýmy',\n productionDesign: 'Scénografia',\n casting: 'Casting',\n sound: 'Zvuk',\n makeup: 'Masky'\n }\n };\n\n const lang = language || 'cs'; // Default to Czech\n return (labels[lang] || labels['cs'])[key];\n};\n\nexport const getMovieId = (el: HTMLElement): number => {\n const url = el.querySelector('.tabs .tab-nav-list a').attributes.href;\n return parseIdFromUrl(url);\n};\n\nexport const getMovieTitle = (el: HTMLElement): string => {\n return el.querySelector('h1').innerText.split(`(`)[0].trim();\n};\n\nexport const getMovieGenres = (el: HTMLElement): CSFDGenres[] => {\n const genresRaw = el.querySelector('.genres').textContent;\n return genresRaw.split(' / ') as CSFDGenres[];\n};\n\nexport const getMovieOrigins = (el: HTMLElement): string[] => {\n const originsRaw = el.querySelector('.origin').textContent;\n const origins = originsRaw.split(',')[0];\n return origins.split(' / ');\n};\n\nexport const getMovieColorRating = (bodyClasses: string[]): CSFDColorRating => {\n return getColor(bodyClasses[1]);\n};\n\nexport const getMovieRating = (el: HTMLElement): number => {\n const ratingRaw = el.querySelector('.film-rating-average').textContent;\n const rating = ratingRaw?.replace(/%/g, '').trim();\n const ratingInt = parseInt(rating);\n\n if (Number.isInteger(ratingInt)) {\n return ratingInt;\n } else {\n return null;\n }\n};\n\nexport const getMovieRatingCount = (el: HTMLElement): number => {\n const ratingCountRaw = el.querySelector('.box-rating-container .counter')?.textContent;\n const ratingCount = +ratingCountRaw?.replace(/[(\\s)]/g, '');\n if (Number.isInteger(ratingCount)) {\n return ratingCount;\n } else {\n return null;\n }\n};\n\nexport const getMovieYear = (el: string): number => {\n try {\n const jsonLd = JSON.parse(el);\n return +jsonLd.dateCreated;\n } catch (error) {\n console.error('node-csfd-api: Error parsing JSON-LD', error);\n return null;\n }\n};\n\nexport const getMovieDuration = (jsonLdRaw: string, el: HTMLElement): number => {\n let duration = null;\n try {\n const jsonLd = JSON.parse(jsonLdRaw);\n duration = jsonLd.duration;\n return parseISO8601Duration(duration);\n } catch (error) {\n const origin = el.querySelector('.origin').innerText;\n const timeString = origin.split(',');\n if (timeString.length > 2) {\n // Get last time elelment\n const timeString2 = timeString.pop().trim();\n // Clean it\n const timeRaw = timeString2.split('(')[0].trim();\n // Split by minutes and hours\n const hoursMinsRaw = timeRaw.split('min')[0];\n const hoursMins = hoursMinsRaw.split('h');\n // Resolve hours + minutes format\n duration = hoursMins.length > 1 ? +hoursMins[0] * 60 + +hoursMins[1] : +hoursMins[0];\n return duration;\n } else {\n return null;\n }\n }\n};\n\nexport const getMovieTitlesOther = (el: HTMLElement): CSFDTitlesOther[] => {\n const namesNode = el.querySelectorAll('.film-names li');\n\n if (!namesNode.length) {\n return [];\n }\n\n const titlesOther = namesNode.map((el) => {\n const country = el.querySelector('img.flag').attributes.alt;\n const title = el.textContent.trim().split('\\n')[0];\n\n if (country && title) {\n return {\n country,\n title\n };\n } else {\n return null;\n }\n });\n\n return titlesOther.filter((x) => x);\n};\n\nexport const getMoviePoster = (el: HTMLElement | null): string => {\n const poster = el.querySelector('.film-posters img');\n // Resolve empty image\n if (poster) {\n if (poster.classNames?.includes('empty-image')) {\n return null;\n } else {\n // Full sized image (not thumb)\n const imageThumb = poster.attributes.src.split('?')[0];\n const image = imageThumb.replace(/\\/w140\\//, '/w1080/');\n return addProtocol(image);\n }\n } else {\n return null;\n }\n};\n\nexport const getMovieRandomPhoto = (el: HTMLElement | null): string => {\n const imageNode = el.querySelector('.gallery-item picture img');\n const image = imageNode?.attributes?.src;\n if (image) {\n return image.replace(/\\/w663\\//, '/w1326/');\n } else {\n return null;\n }\n};\n\nexport const getMovieTrivia = (el: HTMLElement | null): string[] => {\n const triviaNodes = el.querySelectorAll('.article-trivia ul li');\n if (triviaNodes?.length) {\n return triviaNodes.map((node) => node.textContent.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n } else {\n return null;\n }\n};\n\nexport const getMovieDescriptions = (el: HTMLElement): string[] => {\n return el\n .querySelectorAll('.body--plots .plot-full p, .body--plots .plots .plots-item p')\n .map((movie) => movie.textContent?.trim().replace(/(\\r\\n|\\n|\\r|\\t)/gm, ''));\n};\n\nconst parseMoviePeople = (el: HTMLElement): CSFDMovieCreator[] => {\n const people = el.querySelectorAll('a');\n return (\n people\n // Filter out \"more\" links\n .filter((x) => x.classNames.length === 0)\n .map((person) => {\n return {\n id: parseIdFromUrl(person.attributes.href),\n name: person.innerText.trim(),\n url: `https://www.csfd.cz${person.attributes.href}`\n };\n })\n );\n};\n\nexport const getMovieGroup = (el: HTMLElement, group: CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak): CSFDMovieCreator[] => {\n const creators = el.querySelectorAll('.creators h4');\n const element = creators.filter((elem) => elem.textContent.trim().includes(group))[0];\n if (element?.parentNode) {\n return parseMoviePeople(element.parentNode as HTMLElement);\n } else {\n return [];\n }\n};\n\nexport const getMovieType = (el: HTMLElement): string => {\n const type = el.querySelector('.film-header-name .type');\n return type?.innerText?.replace(/[{()}]/g, '') || 'film';\n};\n\nexport const getMovieVods = (el: HTMLElement | null): CSFDVod[] => {\n let vods: CSFDVod[] = [];\n if (el) {\n const buttons = el.querySelectorAll('.box-buttons .button');\n const buttonsVod = buttons.filter((x) => !x.classNames.includes('button-social'));\n vods = buttonsVod.map((btn) => {\n return {\n title: btn.textContent.trim() as CSFDVodService,\n url: btn.attributes.href\n };\n });\n }\n return vods.length ? vods : [];\n};\n\n// Get box content\nconst getBoxContent = (el: HTMLElement, box: string): HTMLElement => {\n const headers = el.querySelectorAll('section.box .box-header');\n return headers.find((header) => header.querySelector('h3').textContent.trim().includes(box))\n ?.parentNode;\n};\n\nexport const getMovieBoxMovies = (el: HTMLElement, boxName: CSFDBoxContent): CSFDMovieListItem[] => {\n const movieListItem: CSFDMovieListItem[] = [];\n const box = getBoxContent(el, boxName);\n const movieTitleNodes = box?.querySelectorAll('.article-header .film-title-name');\n if (movieTitleNodes?.length) {\n for (const item of movieTitleNodes) {\n movieListItem.push({\n id: parseIdFromUrl(item.attributes.href),\n title: item.textContent.trim(),\n url: `https://www.csfd.cz${item.attributes.href}`\n });\n }\n }\n return movieListItem;\n};\n\nexport const getMoviePremieres = (el: HTMLElement): CSFDPremiere[] => {\n const premiereNodes = el.querySelectorAll('.box-premieres li');\n const premiere: CSFDPremiere[] = [];\n for (const premiereNode of premiereNodes) {\n const title = premiereNode.querySelector('p + span').attributes.title;\n\n if (title) {\n const [date, ...company] = title?.split(' ');\n\n premiere.push({\n country: premiereNode.querySelector('.flag')?.attributes.title || null,\n format: premiereNode.querySelector('p').textContent.trim()?.split(' od')[0],\n date,\n company: company.join(' ')\n });\n }\n }\n return premiere;\n};\n\nexport const getMovieTags = (el: HTMLElement): string[] => {\n const tagsRaw = el.querySelectorAll('.box-content a[href*=\"/tag/\"]');\n return tagsRaw.map((tag) => tag.textContent);\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_global_helper = require('./global.helper.js');
|
|
3
2
|
let node_html_parser = require("node-html-parser");
|
|
4
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
5
3
|
|
|
6
4
|
//#region src/helpers/search-user.helper.ts
|
|
7
5
|
const getUser = (el) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-user.helper.js","names":["NodeType","addProtocol"],"sources":["../../src/helpers/search-user.helper.ts"],"sourcesContent":["import { HTMLElement, NodeType } from 'node-html-parser';\nimport { addProtocol } from './global.helper';\n\nexport const getUser = (el: HTMLElement): string => {\n return el.querySelector('.user-title-name').text;\n};\n\nexport const getUserRealName = (el: HTMLElement): string => {\n const p = el.querySelector('.article-content p');\n if (!p) return null;\n\n const textNodes = p.childNodes.filter(n => n.nodeType === NodeType.TEXT_NODE && n.rawText.trim() !== '');\n const name = textNodes.length ? textNodes[0].rawText.trim() : null;\n\n return name;\n};\n\nexport const getAvatar = (el: HTMLElement): string => {\n const image = el.querySelector('.article-img img').attributes.src;\n return addProtocol(image);\n};\n\nexport const getUserUrl = (el: HTMLElement): string => {\n return el.querySelector('.user-title-name').attributes.href;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"search-user.helper.js","names":["NodeType","addProtocol"],"sources":["../../src/helpers/search-user.helper.ts"],"sourcesContent":["import { HTMLElement, NodeType } from 'node-html-parser';\nimport { addProtocol } from './global.helper';\n\nexport const getUser = (el: HTMLElement): string => {\n return el.querySelector('.user-title-name').text;\n};\n\nexport const getUserRealName = (el: HTMLElement): string => {\n const p = el.querySelector('.article-content p');\n if (!p) return null;\n\n const textNodes = p.childNodes.filter(n => n.nodeType === NodeType.TEXT_NODE && n.rawText.trim() !== '');\n const name = textNodes.length ? textNodes[0].rawText.trim() : null;\n\n return name;\n};\n\nexport const getAvatar = (el: HTMLElement): string => {\n const image = el.querySelector('.article-img img').attributes.src;\n return addProtocol(image);\n};\n\nexport const getUserUrl = (el: HTMLElement): string => {\n return el.querySelector('.user-title-name').attributes.href;\n};\n"],"mappings":";;;;AAGA,MAAa,WAAW,OAA4B;AAClD,QAAO,GAAG,cAAc,mBAAmB,CAAC;;AAG9C,MAAa,mBAAmB,OAA4B;CAC1D,MAAM,IAAI,GAAG,cAAc,qBAAqB;AAChD,KAAI,CAAC,EAAG,QAAO;CAEf,MAAM,YAAY,EAAE,WAAW,QAAO,MAAK,EAAE,aAAaA,0BAAS,aAAa,EAAE,QAAQ,MAAM,KAAK,GAAG;AAGxG,QAFa,UAAU,SAAS,UAAU,GAAG,QAAQ,MAAM,GAAG;;AAKhE,MAAa,aAAa,OAA4B;CACpD,MAAM,QAAQ,GAAG,cAAc,mBAAmB,CAAC,WAAW;AAC9D,QAAOC,kCAAY,MAAM;;AAG3B,MAAa,cAAc,OAA4B;AACrD,QAAO,GAAG,cAAc,mBAAmB,CAAC,WAAW"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-csfd-api",
|
|
3
|
-
"version": "4.0.0-next.
|
|
3
|
+
"version": "4.0.0-next.1",
|
|
4
4
|
"description": "ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)",
|
|
5
5
|
"author": "BART! <bart@bartweb.cz>",
|
|
6
6
|
"publishConfig": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"types": "./index.d.ts",
|
|
42
42
|
"exports": {
|
|
43
43
|
".": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
44
|
+
"require": "./index.js",
|
|
45
|
+
"import": "./index.mjs"
|
|
46
46
|
},
|
|
47
47
|
"./package.json": "./package.json"
|
|
48
48
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_cinema_helper = require('../helpers/cinema.helper.js');
|
|
5
4
|
let node_html_parser = require("node-html-parser");
|
|
6
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
7
5
|
|
|
8
6
|
//#region src/services/cinema.service.ts
|
|
9
7
|
var CinemaScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cinema.service.js","names":["fetchPage","cinemasUrl","cinemas: CSFDCinema[]","parseCinema","cinema: CSFDCinema","getCinemaId","getCinemaUrl","getCinemaCoords","getGroupedFilmsByDate"],"sources":["../../src/services/cinema.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDCinema, CSFDCinemaPeriod } from '../dto/cinema';\nimport { fetchPage } from '../fetchers';\nimport { CSFDOptions } from '../types';\nimport { cinemasUrl } from '../vars';\nimport {\n getCinemaCoords,\n getCinemaId,\n getCinemaUrl,\n getGroupedFilmsByDate,\n parseCinema\n} from './../helpers/cinema.helper';\n\nexport class CinemaScraper {\n public async cinemas(\n district: number = 1,\n period: CSFDCinemaPeriod = 'today',\n options?: CSFDOptions\n ): Promise<CSFDCinema[]> {\n const url = cinemasUrl(district, period, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const cinemasHtml = parse(response);\n\n const contentNode = cinemasHtml.querySelectorAll('#snippet--cinemas section[id*=\"cinema-\"]');\n\n return this.buildCinemas(contentNode);\n }\n\n private buildCinemas(contentNode: HTMLElement[]): CSFDCinema[] {\n const cinemas: CSFDCinema[] = [];\n\n contentNode.forEach((x) => {\n const cinemaInfo = parseCinema(x);\n const cinema: CSFDCinema = {\n id: getCinemaId(x),\n name: cinemaInfo?.name,\n city: cinemaInfo?.city,\n url: getCinemaUrl(x),\n coords: getCinemaCoords(x),\n screenings: getGroupedFilmsByDate(x)\n };\n cinemas.push(cinema);\n });\n\n return cinemas;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"cinema.service.js","names":["fetchPage","cinemasUrl","cinemas: CSFDCinema[]","parseCinema","cinema: CSFDCinema","getCinemaId","getCinemaUrl","getCinemaCoords","getGroupedFilmsByDate"],"sources":["../../src/services/cinema.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDCinema, CSFDCinemaPeriod } from '../dto/cinema';\nimport { fetchPage } from '../fetchers';\nimport { CSFDOptions } from '../types';\nimport { cinemasUrl } from '../vars';\nimport {\n getCinemaCoords,\n getCinemaId,\n getCinemaUrl,\n getGroupedFilmsByDate,\n parseCinema\n} from './../helpers/cinema.helper';\n\nexport class CinemaScraper {\n public async cinemas(\n district: number = 1,\n period: CSFDCinemaPeriod = 'today',\n options?: CSFDOptions\n ): Promise<CSFDCinema[]> {\n const url = cinemasUrl(district, period, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const cinemasHtml = parse(response);\n\n const contentNode = cinemasHtml.querySelectorAll('#snippet--cinemas section[id*=\"cinema-\"]');\n\n return this.buildCinemas(contentNode);\n }\n\n private buildCinemas(contentNode: HTMLElement[]): CSFDCinema[] {\n const cinemas: CSFDCinema[] = [];\n\n contentNode.forEach((x) => {\n const cinemaInfo = parseCinema(x);\n const cinema: CSFDCinema = {\n id: getCinemaId(x),\n name: cinemaInfo?.name,\n city: cinemaInfo?.city,\n url: getCinemaUrl(x),\n coords: getCinemaCoords(x),\n screenings: getGroupedFilmsByDate(x)\n };\n cinemas.push(cinema);\n });\n\n return cinemas;\n }\n}\n"],"mappings":";;;;;;AAaA,IAAa,gBAAb,MAA2B;CACzB,MAAa,QACX,WAAmB,GACnB,SAA2B,SAC3B,SACuB;EAKvB,MAAM,0CAHW,MAAMA,wBADXC,wBAAW,UAAU,QAAQ,EAAE,UAAU,SAAS,UAAU,CAAC,EACnC,EAAE,GAAG,SAAS,SAAS,CAAC,CAC3B,CAEH,iBAAiB,6CAA2C;AAE5F,SAAO,KAAK,aAAa,YAAY;;CAGvC,AAAQ,aAAa,aAA0C;EAC7D,MAAMC,UAAwB,EAAE;AAEhC,cAAY,SAAS,MAAM;GACzB,MAAM,aAAaC,kCAAY,EAAE;GACjC,MAAMC,SAAqB;IACzB,IAAIC,kCAAY,EAAE;IAClB,MAAM,YAAY;IAClB,MAAM,YAAY;IAClB,KAAKC,mCAAa,EAAE;IACpB,QAAQC,sCAAgB,EAAE;IAC1B,YAAYC,4CAAsB,EAAE;IACrC;AACD,WAAQ,KAAK,OAAO;IACpB;AAEF,SAAO"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_creator_helper = require('../helpers/creator.helper.js');
|
|
5
4
|
let node_html_parser = require("node-html-parser");
|
|
6
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
7
5
|
|
|
8
6
|
//#region src/services/creator.service.ts
|
|
9
7
|
var CreatorScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"creator.service.js","names":["fetchPage","creatorUrl","getCreatorName","getCreatorBirthdayInfo","getCreatorPhoto","getCreatorBio","getCreatorFilms"],"sources":["../../src/services/creator.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDCreator } from '../dto/creator';\nimport { fetchPage } from '../fetchers';\nimport {\n getCreatorBio,\n getCreatorBirthdayInfo,\n getCreatorFilms,\n getCreatorName,\n getCreatorPhoto\n} from '../helpers/creator.helper';\nimport { CSFDOptions } from '../types';\nimport { creatorUrl } from '../vars';\n\nexport class CreatorScraper {\n public async creator(creatorId: number, options?: CSFDOptions): Promise<CSFDCreator> {\n const id = Number(creatorId);\n if (isNaN(id)) {\n throw new Error('node-csfd-api: creatorId must be a valid number');\n }\n const url = creatorUrl(id, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const creatorHtml = parse(response);\n\n const asideNode = creatorHtml.querySelector('.creator-about');\n const filmsNode = creatorHtml.querySelector('.creator-filmography');\n return this.buildCreator(+creatorId, asideNode, filmsNode);\n }\n\n private buildCreator(id: number, asideEl: HTMLElement, filmsNode: HTMLElement): CSFDCreator {\n return {\n id,\n name: getCreatorName(asideEl),\n birthday: getCreatorBirthdayInfo(asideEl)?.birthday,\n birthplace: getCreatorBirthdayInfo(asideEl)?.birthPlace,\n photo: getCreatorPhoto(asideEl),\n age: getCreatorBirthdayInfo(asideEl)?.age || null,\n bio: getCreatorBio(asideEl),\n films: getCreatorFilms(filmsNode)\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"creator.service.js","names":["fetchPage","creatorUrl","getCreatorName","getCreatorBirthdayInfo","getCreatorPhoto","getCreatorBio","getCreatorFilms"],"sources":["../../src/services/creator.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDCreator } from '../dto/creator';\nimport { fetchPage } from '../fetchers';\nimport {\n getCreatorBio,\n getCreatorBirthdayInfo,\n getCreatorFilms,\n getCreatorName,\n getCreatorPhoto\n} from '../helpers/creator.helper';\nimport { CSFDOptions } from '../types';\nimport { creatorUrl } from '../vars';\n\nexport class CreatorScraper {\n public async creator(creatorId: number, options?: CSFDOptions): Promise<CSFDCreator> {\n const id = Number(creatorId);\n if (isNaN(id)) {\n throw new Error('node-csfd-api: creatorId must be a valid number');\n }\n const url = creatorUrl(id, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const creatorHtml = parse(response);\n\n const asideNode = creatorHtml.querySelector('.creator-about');\n const filmsNode = creatorHtml.querySelector('.creator-filmography');\n return this.buildCreator(+creatorId, asideNode, filmsNode);\n }\n\n private buildCreator(id: number, asideEl: HTMLElement, filmsNode: HTMLElement): CSFDCreator {\n return {\n id,\n name: getCreatorName(asideEl),\n birthday: getCreatorBirthdayInfo(asideEl)?.birthday,\n birthplace: getCreatorBirthdayInfo(asideEl)?.birthPlace,\n photo: getCreatorPhoto(asideEl),\n age: getCreatorBirthdayInfo(asideEl)?.age || null,\n bio: getCreatorBio(asideEl),\n films: getCreatorFilms(filmsNode)\n };\n }\n}\n"],"mappings":";;;;;;AAaA,IAAa,iBAAb,MAA4B;CAC1B,MAAa,QAAQ,WAAmB,SAA6C;EACnF,MAAM,KAAK,OAAO,UAAU;AAC5B,MAAI,MAAM,GAAG,CACX,OAAM,IAAI,MAAM,kDAAkD;EAKpE,MAAM,0CAFW,MAAMA,wBADXC,wBAAW,IAAI,EAAE,UAAU,SAAS,UAAU,CAAC,EACrB,EAAE,GAAG,SAAS,SAAS,CAAC,CAE3B;EAEnC,MAAM,YAAY,YAAY,cAAc,iBAAiB;EAC7D,MAAM,YAAY,YAAY,cAAc,uBAAuB;AACnE,SAAO,KAAK,aAAa,CAAC,WAAW,WAAW,UAAU;;CAG5D,AAAQ,aAAa,IAAY,SAAsB,WAAqC;AAC1F,SAAO;GACL;GACA,MAAMC,sCAAe,QAAQ;GAC7B,UAAUC,8CAAuB,QAAQ,EAAE;GAC3C,YAAYA,8CAAuB,QAAQ,EAAE;GAC7C,OAAOC,uCAAgB,QAAQ;GAC/B,KAAKD,8CAAuB,QAAQ,EAAE,OAAO;GAC7C,KAAKE,qCAAc,QAAQ;GAC3B,OAAOC,uCAAgB,UAAU;GAClC"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_movie_helper = require('../helpers/movie.helper.js');
|
|
5
4
|
let node_html_parser = require("node-html-parser");
|
|
6
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
7
5
|
|
|
8
6
|
//#region src/services/movie.service.ts
|
|
9
7
|
var MovieScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"movie.service.js","names":["fetchPage","movieUrl","getMovieTitle","getMovieYear","getMovieDuration","getMovieDescriptions","getMovieGenres","getMovieType","getMovieOrigins","getMovieColorRating","getMovieRating","getMovieRatingCount","getMovieTitlesOther","getMoviePoster","getMovieRandomPhoto","getMovieTrivia","getMovieGroup","getLocalizedCreatorLabel","getMovieVods","getMovieTags","getMoviePremieres","getMovieBoxMovies"],"sources":["../../src/services/movie.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDFilmTypes } from '../dto/global';\nimport { CSFDMovie } from '../dto/movie';\nimport { fetchPage } from '../fetchers';\nimport {\n getLocalizedCreatorLabel,\n getMovieBoxMovies,\n getMovieColorRating,\n getMovieDescriptions,\n getMovieDuration,\n getMovieGenres,\n getMovieGroup,\n getMovieOrigins,\n getMoviePoster,\n getMoviePremieres,\n getMovieRandomPhoto,\n getMovieRating,\n getMovieRatingCount,\n getMovieTags,\n getMovieTitle,\n getMovieTitlesOther,\n getMovieTrivia,\n getMovieType,\n getMovieVods,\n getMovieYear\n} from '../helpers/movie.helper';\nimport { CSFDOptions } from '../types';\nimport { movieUrl } from '../vars';\n\nexport class MovieScraper {\n public async movie(movieId: number, options?: CSFDOptions): Promise<CSFDMovie> {\n const id = Number(movieId);\n if (isNaN(id)) {\n throw new Error('node-csfd-api: movieId must be a valid number');\n }\n const url = movieUrl(id, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const movieHtml = parse(response);\n\n const pageClasses = movieHtml.querySelector('.page-content').classNames.split(' ');\n const asideNode = movieHtml.querySelector('.aside-movie-profile');\n const movieNode = movieHtml.querySelector('.main-movie-profile');\n const jsonLd = movieHtml.querySelector('script[type=\"application/ld+json\"]').innerText;\n return this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd, options);\n }\n\n private buildMovie(\n movieId: number,\n el: HTMLElement,\n asideEl: HTMLElement,\n pageClasses: string[],\n jsonLd: string,\n options: CSFDOptions\n ): CSFDMovie {\n return {\n id: movieId,\n title: getMovieTitle(el),\n year: getMovieYear(jsonLd),\n duration: getMovieDuration(jsonLd, el),\n descriptions: getMovieDescriptions(el),\n genres: getMovieGenres(el),\n type: getMovieType(el) as CSFDFilmTypes,\n url: movieUrl(movieId, { language: options?.language }),\n origins: getMovieOrigins(el),\n colorRating: getMovieColorRating(pageClasses),\n rating: getMovieRating(asideEl),\n ratingCount: getMovieRatingCount(asideEl),\n titlesOther: getMovieTitlesOther(el),\n poster: getMoviePoster(el),\n photo: getMovieRandomPhoto(el),\n trivia: getMovieTrivia(el),\n creators: {\n directors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'directors')),\n writers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'writers')),\n cinematography: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'cinematography')),\n music: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'music')),\n actors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'actors')),\n basedOn: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'basedOn')),\n producers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'producers')),\n filmEditing: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'filmEditing')),\n costumeDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'costumeDesign')),\n productionDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'productionDesign'))\n },\n vod: getMovieVods(asideEl),\n tags: getMovieTags(asideEl),\n premieres: getMoviePremieres(asideEl),\n related: getMovieBoxMovies(asideEl, 'Související'),\n similar: getMovieBoxMovies(asideEl, 'Podobné')\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"movie.service.js","names":["fetchPage","movieUrl","getMovieTitle","getMovieYear","getMovieDuration","getMovieDescriptions","getMovieGenres","getMovieType","getMovieOrigins","getMovieColorRating","getMovieRating","getMovieRatingCount","getMovieTitlesOther","getMoviePoster","getMovieRandomPhoto","getMovieTrivia","getMovieGroup","getLocalizedCreatorLabel","getMovieVods","getMovieTags","getMoviePremieres","getMovieBoxMovies"],"sources":["../../src/services/movie.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDFilmTypes } from '../dto/global';\nimport { CSFDMovie } from '../dto/movie';\nimport { fetchPage } from '../fetchers';\nimport {\n getLocalizedCreatorLabel,\n getMovieBoxMovies,\n getMovieColorRating,\n getMovieDescriptions,\n getMovieDuration,\n getMovieGenres,\n getMovieGroup,\n getMovieOrigins,\n getMoviePoster,\n getMoviePremieres,\n getMovieRandomPhoto,\n getMovieRating,\n getMovieRatingCount,\n getMovieTags,\n getMovieTitle,\n getMovieTitlesOther,\n getMovieTrivia,\n getMovieType,\n getMovieVods,\n getMovieYear\n} from '../helpers/movie.helper';\nimport { CSFDOptions } from '../types';\nimport { movieUrl } from '../vars';\n\nexport class MovieScraper {\n public async movie(movieId: number, options?: CSFDOptions): Promise<CSFDMovie> {\n const id = Number(movieId);\n if (isNaN(id)) {\n throw new Error('node-csfd-api: movieId must be a valid number');\n }\n const url = movieUrl(id, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const movieHtml = parse(response);\n\n const pageClasses = movieHtml.querySelector('.page-content').classNames.split(' ');\n const asideNode = movieHtml.querySelector('.aside-movie-profile');\n const movieNode = movieHtml.querySelector('.main-movie-profile');\n const jsonLd = movieHtml.querySelector('script[type=\"application/ld+json\"]').innerText;\n return this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd, options);\n }\n\n private buildMovie(\n movieId: number,\n el: HTMLElement,\n asideEl: HTMLElement,\n pageClasses: string[],\n jsonLd: string,\n options: CSFDOptions\n ): CSFDMovie {\n return {\n id: movieId,\n title: getMovieTitle(el),\n year: getMovieYear(jsonLd),\n duration: getMovieDuration(jsonLd, el),\n descriptions: getMovieDescriptions(el),\n genres: getMovieGenres(el),\n type: getMovieType(el) as CSFDFilmTypes,\n url: movieUrl(movieId, { language: options?.language }),\n origins: getMovieOrigins(el),\n colorRating: getMovieColorRating(pageClasses),\n rating: getMovieRating(asideEl),\n ratingCount: getMovieRatingCount(asideEl),\n titlesOther: getMovieTitlesOther(el),\n poster: getMoviePoster(el),\n photo: getMovieRandomPhoto(el),\n trivia: getMovieTrivia(el),\n creators: {\n directors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'directors')),\n writers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'writers')),\n cinematography: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'cinematography')),\n music: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'music')),\n actors: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'actors')),\n basedOn: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'basedOn')),\n producers: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'producers')),\n filmEditing: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'filmEditing')),\n costumeDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'costumeDesign')),\n productionDesign: getMovieGroup(el, getLocalizedCreatorLabel(options?.language, 'productionDesign'))\n },\n vod: getMovieVods(asideEl),\n tags: getMovieTags(asideEl),\n premieres: getMoviePremieres(asideEl),\n related: getMovieBoxMovies(asideEl, 'Související'),\n similar: getMovieBoxMovies(asideEl, 'Podobné')\n };\n }\n}\n"],"mappings":";;;;;;AA6BA,IAAa,eAAb,MAA0B;CACxB,MAAa,MAAM,SAAiB,SAA2C;EAC7E,MAAM,KAAK,OAAO,QAAQ;AAC1B,MAAI,MAAM,GAAG,CACX,OAAM,IAAI,MAAM,gDAAgD;EAKlE,MAAM,wCAFW,MAAMA,wBADXC,sBAAS,IAAI,EAAE,UAAU,SAAS,UAAU,CAAC,EACnB,EAAE,GAAG,SAAS,SAAS,CAAC,CAE7B;EAEjC,MAAM,cAAc,UAAU,cAAc,gBAAgB,CAAC,WAAW,MAAM,IAAI;EAClF,MAAM,YAAY,UAAU,cAAc,uBAAuB;EACjE,MAAM,YAAY,UAAU,cAAc,sBAAsB;EAChE,MAAM,SAAS,UAAU,cAAc,uCAAqC,CAAC;AAC7E,SAAO,KAAK,WAAW,CAAC,SAAS,WAAW,WAAW,aAAa,QAAQ,QAAQ;;CAGtF,AAAQ,WACN,SACA,IACA,SACA,aACA,QACA,SACW;AACX,SAAO;GACL,IAAI;GACJ,OAAOC,mCAAc,GAAG;GACxB,MAAMC,kCAAa,OAAO;GAC1B,UAAUC,sCAAiB,QAAQ,GAAG;GACtC,cAAcC,0CAAqB,GAAG;GACtC,QAAQC,oCAAe,GAAG;GAC1B,MAAMC,kCAAa,GAAG;GACtB,KAAKN,sBAAS,SAAS,EAAE,UAAU,SAAS,UAAU,CAAC;GACvD,SAASO,qCAAgB,GAAG;GAC5B,aAAaC,yCAAoB,YAAY;GAC7C,QAAQC,oCAAe,QAAQ;GAC/B,aAAaC,yCAAoB,QAAQ;GACzC,aAAaC,yCAAoB,GAAG;GACpC,QAAQC,oCAAe,GAAG;GAC1B,OAAOC,yCAAoB,GAAG;GAC9B,QAAQC,oCAAe,GAAG;GAC1B,UAAU;IACR,WAAWC,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,YAAY,CAAC;IACtF,SAASD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,UAAU,CAAC;IAClF,gBAAgBD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,iBAAiB,CAAC;IAChG,OAAOD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,QAAQ,CAAC;IAC9E,QAAQD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,SAAS,CAAC;IAChF,SAASD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,UAAU,CAAC;IAClF,WAAWD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,YAAY,CAAC;IACtF,aAAaD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,cAAc,CAAC;IAC1F,eAAeD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,gBAAgB,CAAC;IAC9F,kBAAkBD,mCAAc,IAAIC,8CAAyB,SAAS,UAAU,mBAAmB,CAAC;IACrG;GACD,KAAKC,kCAAa,QAAQ;GAC1B,MAAMC,kCAAa,QAAQ;GAC3B,WAAWC,uCAAkB,QAAQ;GACrC,SAASC,uCAAkB,SAAS,cAAc;GAClD,SAASA,uCAAkB,SAAS,UAAU;GAC/C"}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_global_helper = require('../helpers/global.helper.js');
|
|
5
4
|
const require_search_user_helper = require('../helpers/search-user.helper.js');
|
|
6
5
|
const require_search_helper = require('../helpers/search.helper.js');
|
|
7
6
|
let node_html_parser = require("node-html-parser");
|
|
8
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
9
7
|
|
|
10
8
|
//#region src/services/search.service.ts
|
|
11
9
|
var SearchScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.service.js","names":["fetchPage","searchUrl","movies: CSFDSearchMovie[]","users: CSFDSearchUser[]","tvSeries: CSFDSearchMovie[]","getUrlByLanguage","getSearchUrl","movie: CSFDSearchMovie","parseIdFromUrl","getSearchTitle","getSearchYear","getSearchType","getSearchColorRating","getSearchPoster","getSearchOrigins","parseSearchPeople","getUserUrl","user: CSFDSearchUser","getUser","getUserRealName","getAvatar","user: CSFDSearchMovie"],"sources":["../../src/services/search.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDSearch, CSFDSearchMovie, CSFDSearchUser } from '../dto/search';\nimport { fetchPage } from '../fetchers';\nimport { parseIdFromUrl } from '../helpers/global.helper';\nimport { getAvatar, getUser, getUserRealName, getUserUrl } from '../helpers/search-user.helper';\nimport {\n getSearchColorRating,\n getSearchOrigins,\n getSearchPoster,\n getSearchTitle,\n getSearchType,\n getSearchUrl,\n getSearchYear,\n parseSearchPeople\n} from '../helpers/search.helper';\nimport { CSFDLanguage, CSFDOptions } from '../types';\nimport { getUrlByLanguage, searchUrl } from '../vars';\n\nexport class SearchScraper {\n public async search(text: string, options?: CSFDOptions): Promise<CSFDSearch> {\n const url = searchUrl(text, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const html = parse(response);\n const moviesNode = html.querySelectorAll('.main-movies article');\n const usersNode = html.querySelectorAll('.main-users article');\n const tvSeriesNode = html.querySelectorAll('.main-series article');\n\n return this.parseSearch(moviesNode, usersNode, tvSeriesNode, options?.language);\n }\n\n private parseSearch(\n moviesNode: HTMLElement[],\n usersNode: HTMLElement[],\n tvSeriesNode: HTMLElement[],\n language?: CSFDLanguage\n ) {\n const movies: CSFDSearchMovie[] = [];\n const users: CSFDSearchUser[] = [];\n const tvSeries: CSFDSearchMovie[] = [];\n const baseUrl = getUrlByLanguage(language);\n\n moviesNode.forEach((m) => {\n const url = getSearchUrl(m);\n\n const movie: CSFDSearchMovie = {\n id: parseIdFromUrl(url),\n title: getSearchTitle(m),\n year: getSearchYear(m),\n url: `${baseUrl}${url}`,\n type: getSearchType(m),\n colorRating: getSearchColorRating(m),\n poster: getSearchPoster(m),\n origins: getSearchOrigins(m),\n creators: {\n directors: parseSearchPeople(m, 'directors'),\n actors: parseSearchPeople(m, 'actors')\n }\n };\n movies.push(movie);\n });\n\n usersNode.forEach((m) => {\n const url = getUserUrl(m);\n\n const user: CSFDSearchUser = {\n id: parseIdFromUrl(url),\n user: getUser(m),\n userRealName: getUserRealName(m),\n avatar: getAvatar(m),\n url: `${baseUrl}${url}`\n };\n users.push(user);\n });\n\n tvSeriesNode.forEach((m) => {\n const url = getSearchUrl(m);\n\n const user: CSFDSearchMovie = {\n id: parseIdFromUrl(url),\n title: getSearchTitle(m),\n year: getSearchYear(m),\n url: `${baseUrl}${url}`,\n type: getSearchType(m),\n colorRating: getSearchColorRating(m),\n poster: getSearchPoster(m),\n origins: getSearchOrigins(m),\n creators: {\n directors: parseSearchPeople(m, 'directors'),\n actors: parseSearchPeople(m, 'actors')\n }\n };\n tvSeries.push(user);\n });\n\n const search: CSFDSearch = {\n movies: movies,\n users: users,\n tvSeries: tvSeries,\n creators: []\n };\n return search;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.service.js","names":["fetchPage","searchUrl","movies: CSFDSearchMovie[]","users: CSFDSearchUser[]","tvSeries: CSFDSearchMovie[]","getUrlByLanguage","getSearchUrl","movie: CSFDSearchMovie","parseIdFromUrl","getSearchTitle","getSearchYear","getSearchType","getSearchColorRating","getSearchPoster","getSearchOrigins","parseSearchPeople","getUserUrl","user: CSFDSearchUser","getUser","getUserRealName","getAvatar","user: CSFDSearchMovie"],"sources":["../../src/services/search.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDSearch, CSFDSearchMovie, CSFDSearchUser } from '../dto/search';\nimport { fetchPage } from '../fetchers';\nimport { parseIdFromUrl } from '../helpers/global.helper';\nimport { getAvatar, getUser, getUserRealName, getUserUrl } from '../helpers/search-user.helper';\nimport {\n getSearchColorRating,\n getSearchOrigins,\n getSearchPoster,\n getSearchTitle,\n getSearchType,\n getSearchUrl,\n getSearchYear,\n parseSearchPeople\n} from '../helpers/search.helper';\nimport { CSFDLanguage, CSFDOptions } from '../types';\nimport { getUrlByLanguage, searchUrl } from '../vars';\n\nexport class SearchScraper {\n public async search(text: string, options?: CSFDOptions): Promise<CSFDSearch> {\n const url = searchUrl(text, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const html = parse(response);\n const moviesNode = html.querySelectorAll('.main-movies article');\n const usersNode = html.querySelectorAll('.main-users article');\n const tvSeriesNode = html.querySelectorAll('.main-series article');\n\n return this.parseSearch(moviesNode, usersNode, tvSeriesNode, options?.language);\n }\n\n private parseSearch(\n moviesNode: HTMLElement[],\n usersNode: HTMLElement[],\n tvSeriesNode: HTMLElement[],\n language?: CSFDLanguage\n ) {\n const movies: CSFDSearchMovie[] = [];\n const users: CSFDSearchUser[] = [];\n const tvSeries: CSFDSearchMovie[] = [];\n const baseUrl = getUrlByLanguage(language);\n\n moviesNode.forEach((m) => {\n const url = getSearchUrl(m);\n\n const movie: CSFDSearchMovie = {\n id: parseIdFromUrl(url),\n title: getSearchTitle(m),\n year: getSearchYear(m),\n url: `${baseUrl}${url}`,\n type: getSearchType(m),\n colorRating: getSearchColorRating(m),\n poster: getSearchPoster(m),\n origins: getSearchOrigins(m),\n creators: {\n directors: parseSearchPeople(m, 'directors'),\n actors: parseSearchPeople(m, 'actors')\n }\n };\n movies.push(movie);\n });\n\n usersNode.forEach((m) => {\n const url = getUserUrl(m);\n\n const user: CSFDSearchUser = {\n id: parseIdFromUrl(url),\n user: getUser(m),\n userRealName: getUserRealName(m),\n avatar: getAvatar(m),\n url: `${baseUrl}${url}`\n };\n users.push(user);\n });\n\n tvSeriesNode.forEach((m) => {\n const url = getSearchUrl(m);\n\n const user: CSFDSearchMovie = {\n id: parseIdFromUrl(url),\n title: getSearchTitle(m),\n year: getSearchYear(m),\n url: `${baseUrl}${url}`,\n type: getSearchType(m),\n colorRating: getSearchColorRating(m),\n poster: getSearchPoster(m),\n origins: getSearchOrigins(m),\n creators: {\n directors: parseSearchPeople(m, 'directors'),\n actors: parseSearchPeople(m, 'actors')\n }\n };\n tvSeries.push(user);\n });\n\n const search: CSFDSearch = {\n movies: movies,\n users: users,\n tvSeries: tvSeries,\n creators: []\n };\n return search;\n }\n}\n"],"mappings":";;;;;;;;AAkBA,IAAa,gBAAb,MAA2B;CACzB,MAAa,OAAO,MAAc,SAA4C;EAI5E,MAAM,mCAFW,MAAMA,wBADXC,uBAAU,MAAM,EAAE,UAAU,SAAS,UAAU,CAAC,EACtB,EAAE,GAAG,SAAS,SAAS,CAAC,CAElC;EAC5B,MAAM,aAAa,KAAK,iBAAiB,uBAAuB;EAChE,MAAM,YAAY,KAAK,iBAAiB,sBAAsB;EAC9D,MAAM,eAAe,KAAK,iBAAiB,uBAAuB;AAElE,SAAO,KAAK,YAAY,YAAY,WAAW,cAAc,SAAS,SAAS;;CAGjF,AAAQ,YACN,YACA,WACA,cACA,UACA;EACA,MAAMC,SAA4B,EAAE;EACpC,MAAMC,QAA0B,EAAE;EAClC,MAAMC,WAA8B,EAAE;EACtC,MAAM,UAAUC,8BAAiB,SAAS;AAE1C,aAAW,SAAS,MAAM;GACxB,MAAM,MAAMC,mCAAa,EAAE;GAE3B,MAAMC,QAAyB;IAC7B,IAAIC,qCAAe,IAAI;IACvB,OAAOC,qCAAe,EAAE;IACxB,MAAMC,oCAAc,EAAE;IACtB,KAAK,GAAG,UAAU;IAClB,MAAMC,oCAAc,EAAE;IACtB,aAAaC,2CAAqB,EAAE;IACpC,QAAQC,sCAAgB,EAAE;IAC1B,SAASC,uCAAiB,EAAE;IAC5B,UAAU;KACR,WAAWC,wCAAkB,GAAG,YAAY;KAC5C,QAAQA,wCAAkB,GAAG,SAAS;KACvC;IACF;AACD,UAAO,KAAK,MAAM;IAClB;AAEF,YAAU,SAAS,MAAM;GACvB,MAAM,MAAMC,sCAAW,EAAE;GAEzB,MAAMC,OAAuB;IAC3B,IAAIT,qCAAe,IAAI;IACvB,MAAMU,mCAAQ,EAAE;IAChB,cAAcC,2CAAgB,EAAE;IAChC,QAAQC,qCAAU,EAAE;IACpB,KAAK,GAAG,UAAU;IACnB;AACD,SAAM,KAAK,KAAK;IAChB;AAEF,eAAa,SAAS,MAAM;GAC1B,MAAM,MAAMd,mCAAa,EAAE;GAE3B,MAAMe,OAAwB;IAC5B,IAAIb,qCAAe,IAAI;IACvB,OAAOC,qCAAe,EAAE;IACxB,MAAMC,oCAAc,EAAE;IACtB,KAAK,GAAG,UAAU;IAClB,MAAMC,oCAAc,EAAE;IACtB,aAAaC,2CAAqB,EAAE;IACpC,QAAQC,sCAAgB,EAAE;IAC1B,SAASC,uCAAiB,EAAE;IAC5B,UAAU;KACR,WAAWC,wCAAkB,GAAG,YAAY;KAC5C,QAAQA,wCAAkB,GAAG,SAAS;KACvC;IACF;AACD,YAAS,KAAK,KAAK;IACnB;AAQF,SAN2B;GACjB;GACD;GACG;GACV,UAAU,EAAE;GACb"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_global_helper = require('../helpers/global.helper.js');
|
|
5
4
|
const require_user_ratings_helper = require('../helpers/user-ratings.helper.js');
|
|
6
5
|
let node_html_parser = require("node-html-parser");
|
|
7
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
8
6
|
|
|
9
7
|
//#region src/services/user-ratings.service.ts
|
|
10
8
|
var UserRatingsScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-ratings.service.js","names":["allMovies: CSFDUserRatings[]","userRatingsUrl","fetchPage","movies","sleep","films: CSFDUserRatings[]","getUserRatingType","getUserRatingId","getUserRatingTitle","getUserRatingYear","getUserRatingUrl","getUserRatingColorRating","getUserRatingDate","getUserRating"],"sources":["../../src/services/user-ratings.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDColorRating, CSFDStars } from '../dto/global';\nimport { CSFDUserRatingConfig, CSFDUserRatings } from '../dto/user-ratings';\nimport { fetchPage } from '../fetchers';\nimport { sleep } from '../helpers/global.helper';\nimport {\n getUserRating,\n getUserRatingColorRating,\n getUserRatingDate,\n getUserRatingId,\n getUserRatingTitle,\n getUserRatingType,\n getUserRatingUrl,\n getUserRatingYear\n} from '../helpers/user-ratings.helper';\nimport { CSFDOptions } from '../types';\nimport { userRatingsUrl } from '../vars';\n\nexport class UserRatingsScraper {\n public async userRatings(\n user: string | number,\n config?: CSFDUserRatingConfig,\n options?: CSFDOptions\n ): Promise<CSFDUserRatings[]> {\n let allMovies: CSFDUserRatings[] = [];\n const pageToFetch = config?.page || 1;\n const url = userRatingsUrl(user, pageToFetch > 1 ? pageToFetch : undefined, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const items = parse(response);\n const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');\n\n // Get number of pages\n const pagesNode = items.querySelector('.pagination');\n const pages = +pagesNode?.childNodes[pagesNode.childNodes.length - 4].rawText || 1;\n\n allMovies = this.getPage(config, movies);\n\n if (config?.allPages) {\n console.log('User', user, url);\n console.log('Fetching all pages', pages);\n for (let i = 2; i <= pages; i++) {\n console.log('Fetching page', i, 'out of', pages, '...');\n const url = userRatingsUrl(user, i, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const items = parse(response);\n const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');\n allMovies = [...allMovies, ...this.getPage(config, movies)];\n\n // Sleep\n if (config.allPagesDelay) {\n await sleep(config.allPagesDelay);\n }\n }\n return allMovies;\n }\n\n return allMovies;\n }\n\n private getPage(config: CSFDUserRatingConfig, movies: HTMLElement[]) {\n const films: CSFDUserRatings[] = [];\n if (config) {\n if (config.includesOnly?.length && config.excludes?.length) {\n console.warn(\n `node-csfd-api:\n You can not use both parameters 'includesOnly' and 'excludes'.\n Parameter 'includesOnly' will be used now:`,\n config.includesOnly\n );\n }\n }\n\n for (const el of movies) {\n const type = getUserRatingType(el);\n\n // Filtering includesOnly\n if (config?.includesOnly?.length) {\n if (config.includesOnly.some((include) => type === include)) {\n films.push(this.buildUserRatings(el));\n }\n // Filter excludes\n } else if (config?.excludes?.length) {\n if (!config.excludes.some((exclude) => type === exclude)) {\n films.push(this.buildUserRatings(el));\n }\n } else {\n // Without filtering\n films.push(this.buildUserRatings(el));\n }\n }\n return films;\n }\n\n private buildUserRatings(el: HTMLElement): CSFDUserRatings {\n return {\n id: getUserRatingId(el),\n title: getUserRatingTitle(el),\n year: getUserRatingYear(el),\n type: getUserRatingType(el),\n url: getUserRatingUrl(el),\n colorRating: getUserRatingColorRating(el) as CSFDColorRating,\n userDate: getUserRatingDate(el),\n userRating: getUserRating(el) as CSFDStars\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-ratings.service.js","names":["allMovies: CSFDUserRatings[]","userRatingsUrl","fetchPage","movies","sleep","films: CSFDUserRatings[]","getUserRatingType","getUserRatingId","getUserRatingTitle","getUserRatingYear","getUserRatingUrl","getUserRatingColorRating","getUserRatingDate","getUserRating"],"sources":["../../src/services/user-ratings.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDColorRating, CSFDStars } from '../dto/global';\nimport { CSFDUserRatingConfig, CSFDUserRatings } from '../dto/user-ratings';\nimport { fetchPage } from '../fetchers';\nimport { sleep } from '../helpers/global.helper';\nimport {\n getUserRating,\n getUserRatingColorRating,\n getUserRatingDate,\n getUserRatingId,\n getUserRatingTitle,\n getUserRatingType,\n getUserRatingUrl,\n getUserRatingYear\n} from '../helpers/user-ratings.helper';\nimport { CSFDOptions } from '../types';\nimport { userRatingsUrl } from '../vars';\n\nexport class UserRatingsScraper {\n public async userRatings(\n user: string | number,\n config?: CSFDUserRatingConfig,\n options?: CSFDOptions\n ): Promise<CSFDUserRatings[]> {\n let allMovies: CSFDUserRatings[] = [];\n const pageToFetch = config?.page || 1;\n const url = userRatingsUrl(user, pageToFetch > 1 ? pageToFetch : undefined, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const items = parse(response);\n const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');\n\n // Get number of pages\n const pagesNode = items.querySelector('.pagination');\n const pages = +pagesNode?.childNodes[pagesNode.childNodes.length - 4].rawText || 1;\n\n allMovies = this.getPage(config, movies);\n\n if (config?.allPages) {\n console.log('User', user, url);\n console.log('Fetching all pages', pages);\n for (let i = 2; i <= pages; i++) {\n console.log('Fetching page', i, 'out of', pages, '...');\n const url = userRatingsUrl(user, i, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const items = parse(response);\n const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');\n allMovies = [...allMovies, ...this.getPage(config, movies)];\n\n // Sleep\n if (config.allPagesDelay) {\n await sleep(config.allPagesDelay);\n }\n }\n return allMovies;\n }\n\n return allMovies;\n }\n\n private getPage(config: CSFDUserRatingConfig, movies: HTMLElement[]) {\n const films: CSFDUserRatings[] = [];\n if (config) {\n if (config.includesOnly?.length && config.excludes?.length) {\n console.warn(\n `node-csfd-api:\n You can not use both parameters 'includesOnly' and 'excludes'.\n Parameter 'includesOnly' will be used now:`,\n config.includesOnly\n );\n }\n }\n\n for (const el of movies) {\n const type = getUserRatingType(el);\n\n // Filtering includesOnly\n if (config?.includesOnly?.length) {\n if (config.includesOnly.some((include) => type === include)) {\n films.push(this.buildUserRatings(el));\n }\n // Filter excludes\n } else if (config?.excludes?.length) {\n if (!config.excludes.some((exclude) => type === exclude)) {\n films.push(this.buildUserRatings(el));\n }\n } else {\n // Without filtering\n films.push(this.buildUserRatings(el));\n }\n }\n return films;\n }\n\n private buildUserRatings(el: HTMLElement): CSFDUserRatings {\n return {\n id: getUserRatingId(el),\n title: getUserRatingTitle(el),\n year: getUserRatingYear(el),\n type: getUserRatingType(el),\n url: getUserRatingUrl(el),\n colorRating: getUserRatingColorRating(el) as CSFDColorRating,\n userDate: getUserRatingDate(el),\n userRating: getUserRating(el) as CSFDStars\n };\n }\n}\n"],"mappings":";;;;;;;AAkBA,IAAa,qBAAb,MAAgC;CAC9B,MAAa,YACX,MACA,QACA,SAC4B;EAC5B,IAAIA,YAA+B,EAAE;EACrC,MAAM,cAAc,QAAQ,QAAQ;EACpC,MAAM,MAAMC,4BAAe,MAAM,cAAc,IAAI,cAAc,QAAW,EAAE,UAAU,SAAS,UAAU,CAAC;EAE5G,MAAM,oCADW,MAAMC,wBAAU,KAAK,EAAE,GAAG,SAAS,SAAS,CAAC,CACjC;EAC7B,MAAM,SAAS,MAAM,iBAAiB,6CAA6C;EAGnF,MAAM,YAAY,MAAM,cAAc,cAAc;EACpD,MAAM,QAAQ,CAAC,WAAW,WAAW,UAAU,WAAW,SAAS,GAAG,WAAW;AAEjF,cAAY,KAAK,QAAQ,QAAQ,OAAO;AAExC,MAAI,QAAQ,UAAU;AACpB,WAAQ,IAAI,QAAQ,MAAM,IAAI;AAC9B,WAAQ,IAAI,sBAAsB,MAAM;AACxC,QAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAAK;AAC/B,YAAQ,IAAI,iBAAiB,GAAG,UAAU,OAAO,MAAM;IAKvD,MAAMC,uCAHW,MAAMD,wBADXD,4BAAe,MAAM,GAAG,EAAE,UAAU,SAAS,UAAU,CAAC,EAC9B,EAAE,GAAG,SAAS,SAAS,CAAC,CAEjC,CACR,iBAAiB,6CAA6C;AACnF,gBAAY,CAAC,GAAG,WAAW,GAAG,KAAK,QAAQ,QAAQE,SAAO,CAAC;AAG3D,QAAI,OAAO,cACT,OAAMC,4BAAM,OAAO,cAAc;;AAGrC,UAAO;;AAGT,SAAO;;CAGT,AAAQ,QAAQ,QAA8B,QAAuB;EACnE,MAAMC,QAA2B,EAAE;AACnC,MAAI,QACF;OAAI,OAAO,cAAc,UAAU,OAAO,UAAU,OAClD,SAAQ,KACN;;qDAGA,OAAO,aACR;;AAIL,OAAK,MAAM,MAAM,QAAQ;GACvB,MAAM,OAAOC,8CAAkB,GAAG;AAGlC,OAAI,QAAQ,cAAc,QACxB;QAAI,OAAO,aAAa,MAAM,YAAY,SAAS,QAAQ,CACzD,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;cAG9B,QAAQ,UAAU,QAC3B;QAAI,CAAC,OAAO,SAAS,MAAM,YAAY,SAAS,QAAQ,CACtD,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;SAIvC,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;;AAGzC,SAAO;;CAGT,AAAQ,iBAAiB,IAAkC;AACzD,SAAO;GACL,IAAIC,4CAAgB,GAAG;GACvB,OAAOC,+CAAmB,GAAG;GAC7B,MAAMC,8CAAkB,GAAG;GAC3B,MAAMH,8CAAkB,GAAG;GAC3B,KAAKI,6CAAiB,GAAG;GACzB,aAAaC,qDAAyB,GAAG;GACzC,UAAUC,8CAAkB,GAAG;GAC/B,YAAYC,0CAAc,GAAG;GAC9B"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
1
|
const require_index = require('../fetchers/index.js');
|
|
3
2
|
const require_vars = require('../vars.js');
|
|
4
3
|
const require_global_helper = require('../helpers/global.helper.js');
|
|
5
4
|
const require_user_reviews_helper = require('../helpers/user-reviews.helper.js');
|
|
6
5
|
let node_html_parser = require("node-html-parser");
|
|
7
|
-
node_html_parser = require_rolldown_runtime.__toESM(node_html_parser);
|
|
8
6
|
|
|
9
7
|
//#region src/services/user-reviews.service.ts
|
|
10
8
|
var UserReviewsScraper = class {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-reviews.service.js","names":["allReviews: CSFDUserReviews[]","userReviewsUrl","fetchPage","reviews","sleep","films: CSFDUserReviews[]","getUserReviewType","getUserReviewId","getUserReviewTitle","getUserReviewYear","getUserReviewUrl","getUserReviewColorRating","getUserReviewDate","getUserReviewRating","getUserReviewText","getUserReviewPoster"],"sources":["../../src/services/user-reviews.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDColorRating, CSFDStars } from '../dto/global';\nimport { CSFDUserReviews, CSFDUserReviewsConfig } from '../dto/user-reviews';\nimport { fetchPage } from '../fetchers';\nimport { sleep } from '../helpers/global.helper';\nimport {\n getUserReviewColorRating,\n getUserReviewDate,\n getUserReviewId,\n getUserReviewPoster,\n getUserReviewRating,\n getUserReviewText,\n getUserReviewTitle,\n getUserReviewType,\n getUserReviewUrl,\n getUserReviewYear\n} from '../helpers/user-reviews.helper';\nimport { CSFDOptions } from '../types';\nimport { userReviewsUrl } from '../vars';\n\nexport class UserReviewsScraper {\n public async userReviews(\n user: string | number,\n config?: CSFDUserReviewsConfig,\n options?: CSFDOptions\n ): Promise<CSFDUserReviews[]> {\n let allReviews: CSFDUserReviews[] = [];\n const pageToFetch = config?.page || 1;\n const url = userReviewsUrl(user, pageToFetch > 1 ? pageToFetch : undefined, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const items = parse(response);\n const reviews = items.querySelectorAll('.user-reviews .article');\n\n // Get number of pages\n const pagesNode = items.querySelector('.pagination');\n const pages = +pagesNode?.childNodes[pagesNode.childNodes.length - 4].rawText || 1;\n\n allReviews = this.getPage(config, reviews);\n\n if (config?.allPages) {\n console.log('User', user, url);\n console.log('Fetching all pages', pages);\n for (let i = 2; i <= pages; i++) {\n console.log('Fetching page', i, 'out of', pages, '...');\n const url = userReviewsUrl(user, i, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const items = parse(response);\n const reviews = items.querySelectorAll('.user-reviews .article');\n allReviews = [...allReviews, ...this.getPage(config, reviews)];\n\n // Sleep\n if (config.allPagesDelay) {\n await sleep(config.allPagesDelay);\n }\n }\n return allReviews;\n }\n\n return allReviews;\n }\n\n private getPage(config: CSFDUserReviewsConfig, reviews: HTMLElement[]) {\n const films: CSFDUserReviews[] = [];\n if (config) {\n if (config.includesOnly?.length && config.excludes?.length) {\n console.warn(\n `node-csfd-api:\n You can not use both parameters 'includesOnly' and 'excludes'.\n Parameter 'includesOnly' will be used now:`,\n config.includesOnly\n );\n }\n }\n\n for (const el of reviews) {\n const type = getUserReviewType(el);\n\n // Filtering includesOnly\n if (config?.includesOnly?.length) {\n if (config.includesOnly.some((include) => type === include)) {\n films.push(this.buildUserReviews(el));\n }\n // Filter excludes\n } else if (config?.excludes?.length) {\n if (!config.excludes.some((exclude) => type === exclude)) {\n films.push(this.buildUserReviews(el));\n }\n } else {\n // Without filtering\n films.push(this.buildUserReviews(el));\n }\n }\n return films;\n }\n\n private buildUserReviews(el: HTMLElement): CSFDUserReviews {\n return {\n id: getUserReviewId(el),\n title: getUserReviewTitle(el),\n year: getUserReviewYear(el),\n type: getUserReviewType(el),\n url: getUserReviewUrl(el),\n colorRating: getUserReviewColorRating(el) as CSFDColorRating,\n userDate: getUserReviewDate(el),\n userRating: getUserReviewRating(el) as CSFDStars,\n text: getUserReviewText(el),\n poster: getUserReviewPoster(el)\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-reviews.service.js","names":["allReviews: CSFDUserReviews[]","userReviewsUrl","fetchPage","reviews","sleep","films: CSFDUserReviews[]","getUserReviewType","getUserReviewId","getUserReviewTitle","getUserReviewYear","getUserReviewUrl","getUserReviewColorRating","getUserReviewDate","getUserReviewRating","getUserReviewText","getUserReviewPoster"],"sources":["../../src/services/user-reviews.service.ts"],"sourcesContent":["import { HTMLElement, parse } from 'node-html-parser';\nimport { CSFDColorRating, CSFDStars } from '../dto/global';\nimport { CSFDUserReviews, CSFDUserReviewsConfig } from '../dto/user-reviews';\nimport { fetchPage } from '../fetchers';\nimport { sleep } from '../helpers/global.helper';\nimport {\n getUserReviewColorRating,\n getUserReviewDate,\n getUserReviewId,\n getUserReviewPoster,\n getUserReviewRating,\n getUserReviewText,\n getUserReviewTitle,\n getUserReviewType,\n getUserReviewUrl,\n getUserReviewYear\n} from '../helpers/user-reviews.helper';\nimport { CSFDOptions } from '../types';\nimport { userReviewsUrl } from '../vars';\n\nexport class UserReviewsScraper {\n public async userReviews(\n user: string | number,\n config?: CSFDUserReviewsConfig,\n options?: CSFDOptions\n ): Promise<CSFDUserReviews[]> {\n let allReviews: CSFDUserReviews[] = [];\n const pageToFetch = config?.page || 1;\n const url = userReviewsUrl(user, pageToFetch > 1 ? pageToFetch : undefined, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n const items = parse(response);\n const reviews = items.querySelectorAll('.user-reviews .article');\n\n // Get number of pages\n const pagesNode = items.querySelector('.pagination');\n const pages = +pagesNode?.childNodes[pagesNode.childNodes.length - 4].rawText || 1;\n\n allReviews = this.getPage(config, reviews);\n\n if (config?.allPages) {\n console.log('User', user, url);\n console.log('Fetching all pages', pages);\n for (let i = 2; i <= pages; i++) {\n console.log('Fetching page', i, 'out of', pages, '...');\n const url = userReviewsUrl(user, i, { language: options?.language });\n const response = await fetchPage(url, { ...options?.request });\n\n const items = parse(response);\n const reviews = items.querySelectorAll('.user-reviews .article');\n allReviews = [...allReviews, ...this.getPage(config, reviews)];\n\n // Sleep\n if (config.allPagesDelay) {\n await sleep(config.allPagesDelay);\n }\n }\n return allReviews;\n }\n\n return allReviews;\n }\n\n private getPage(config: CSFDUserReviewsConfig, reviews: HTMLElement[]) {\n const films: CSFDUserReviews[] = [];\n if (config) {\n if (config.includesOnly?.length && config.excludes?.length) {\n console.warn(\n `node-csfd-api:\n You can not use both parameters 'includesOnly' and 'excludes'.\n Parameter 'includesOnly' will be used now:`,\n config.includesOnly\n );\n }\n }\n\n for (const el of reviews) {\n const type = getUserReviewType(el);\n\n // Filtering includesOnly\n if (config?.includesOnly?.length) {\n if (config.includesOnly.some((include) => type === include)) {\n films.push(this.buildUserReviews(el));\n }\n // Filter excludes\n } else if (config?.excludes?.length) {\n if (!config.excludes.some((exclude) => type === exclude)) {\n films.push(this.buildUserReviews(el));\n }\n } else {\n // Without filtering\n films.push(this.buildUserReviews(el));\n }\n }\n return films;\n }\n\n private buildUserReviews(el: HTMLElement): CSFDUserReviews {\n return {\n id: getUserReviewId(el),\n title: getUserReviewTitle(el),\n year: getUserReviewYear(el),\n type: getUserReviewType(el),\n url: getUserReviewUrl(el),\n colorRating: getUserReviewColorRating(el) as CSFDColorRating,\n userDate: getUserReviewDate(el),\n userRating: getUserReviewRating(el) as CSFDStars,\n text: getUserReviewText(el),\n poster: getUserReviewPoster(el)\n };\n }\n}\n"],"mappings":";;;;;;;AAoBA,IAAa,qBAAb,MAAgC;CAC9B,MAAa,YACX,MACA,QACA,SAC4B;EAC5B,IAAIA,aAAgC,EAAE;EACtC,MAAM,cAAc,QAAQ,QAAQ;EACpC,MAAM,MAAMC,4BAAe,MAAM,cAAc,IAAI,cAAc,QAAW,EAAE,UAAU,SAAS,UAAU,CAAC;EAE5G,MAAM,oCADW,MAAMC,wBAAU,KAAK,EAAE,GAAG,SAAS,SAAS,CAAC,CACjC;EAC7B,MAAM,UAAU,MAAM,iBAAiB,yBAAyB;EAGhE,MAAM,YAAY,MAAM,cAAc,cAAc;EACpD,MAAM,QAAQ,CAAC,WAAW,WAAW,UAAU,WAAW,SAAS,GAAG,WAAW;AAEjF,eAAa,KAAK,QAAQ,QAAQ,QAAQ;AAE1C,MAAI,QAAQ,UAAU;AACpB,WAAQ,IAAI,QAAQ,MAAM,IAAI;AAC9B,WAAQ,IAAI,sBAAsB,MAAM;AACxC,QAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAAK;AAC/B,YAAQ,IAAI,iBAAiB,GAAG,UAAU,OAAO,MAAM;IAKvD,MAAMC,wCAHW,MAAMD,wBADXD,4BAAe,MAAM,GAAG,EAAE,UAAU,SAAS,UAAU,CAAC,EAC9B,EAAE,GAAG,SAAS,SAAS,CAAC,CAEjC,CACP,iBAAiB,yBAAyB;AAChE,iBAAa,CAAC,GAAG,YAAY,GAAG,KAAK,QAAQ,QAAQE,UAAQ,CAAC;AAG9D,QAAI,OAAO,cACT,OAAMC,4BAAM,OAAO,cAAc;;AAGrC,UAAO;;AAGT,SAAO;;CAGT,AAAQ,QAAQ,QAA+B,SAAwB;EACrE,MAAMC,QAA2B,EAAE;AACnC,MAAI,QACF;OAAI,OAAO,cAAc,UAAU,OAAO,UAAU,OAClD,SAAQ,KACN;;qDAGA,OAAO,aACR;;AAIL,OAAK,MAAM,MAAM,SAAS;GACxB,MAAM,OAAOC,8CAAkB,GAAG;AAGlC,OAAI,QAAQ,cAAc,QACxB;QAAI,OAAO,aAAa,MAAM,YAAY,SAAS,QAAQ,CACzD,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;cAG9B,QAAQ,UAAU,QAC3B;QAAI,CAAC,OAAO,SAAS,MAAM,YAAY,SAAS,QAAQ,CACtD,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;SAIvC,OAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;;AAGzC,SAAO;;CAGT,AAAQ,iBAAiB,IAAkC;AACzD,SAAO;GACL,IAAIC,4CAAgB,GAAG;GACvB,OAAOC,+CAAmB,GAAG;GAC7B,MAAMC,8CAAkB,GAAG;GAC3B,MAAMH,8CAAkB,GAAG;GAC3B,KAAKI,6CAAiB,GAAG;GACzB,aAAaC,qDAAyB,GAAG;GACzC,UAAUC,8CAAkB,GAAG;GAC/B,YAAYC,gDAAoB,GAAG;GACnC,MAAMC,8CAAkB,GAAG;GAC3B,QAAQC,gDAAoB,GAAG;GAChC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
|
|
25
|
-
exports.__toESM = __toESM;
|