node-csfd-api 3.0.0-next.2 → 3.0.0-next.21
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 +103 -45
- package/fetchers/fetch.polyfill.d.ts +1 -0
- package/fetchers/fetch.polyfill.js +9 -0
- package/{cjs/fetchers → fetchers}/index.js +5 -14
- package/helpers/cinema.helper.d.ts +19 -0
- package/helpers/cinema.helper.js +105 -0
- package/{cjs/helpers → helpers}/creator.helper.js +12 -11
- package/{types/helpers → helpers}/global.helper.d.ts +10 -0
- package/{cjs/helpers → helpers}/global.helper.js +9 -5
- package/{cjs/helpers → helpers}/movie.helper.js +9 -4
- package/{types/helpers → helpers}/search.helper.d.ts +1 -1
- package/{cjs/helpers → helpers}/search.helper.js +5 -3
- package/{cjs/helpers → helpers}/user-ratings.helper.js +2 -1
- package/{types/index.d.ts → index.d.ts} +5 -1
- package/index.js +39 -0
- package/interfaces/cinema.interface.d.ts +23 -0
- package/interfaces/user-ratings.interface.js +2 -0
- package/package.json +21 -14
- package/services/cinema.service.d.ts +6 -0
- package/services/cinema.service.js +34 -0
- package/services/creator.service.js +32 -0
- package/{cjs/services → services}/movie.service.js +10 -21
- package/{cjs/services → services}/search.service.js +29 -20
- package/{cjs/services → services}/user-ratings.service.js +25 -36
- package/{types/vars.d.ts → vars.d.ts} +2 -0
- package/{cjs/vars.js → vars.js} +5 -1
- package/cjs/index.js +0 -50
- package/cjs/services/creator.service.js +0 -43
- package/esm/fetchers/index.js +0 -32
- package/esm/helpers/creator.helper.js +0 -73
- package/esm/helpers/global.helper.js +0 -56
- package/esm/helpers/movie.helper.js +0 -223
- package/esm/helpers/search-user.helper.js +0 -15
- package/esm/helpers/search.helper.js +0 -49
- package/esm/helpers/user-ratings.helper.js +0 -47
- package/esm/index.js +0 -46
- package/esm/interfaces/creator.interface.js +0 -1
- package/esm/interfaces/global.js +0 -1
- package/esm/interfaces/movie.interface.js +0 -1
- package/esm/interfaces/search.interface.js +0 -1
- package/esm/interfaces/user-ratings.interface.js +0 -1
- package/esm/services/creator.service.js +0 -39
- package/esm/services/movie.service.js +0 -65
- package/esm/services/search.service.js +0 -67
- package/esm/services/user-ratings.service.js +0 -91
- package/esm/vars.js +0 -4
- package/types/index.ts +0 -22
- /package/{types/fetchers → fetchers}/index.d.ts +0 -0
- /package/{types/helpers → helpers}/creator.helper.d.ts +0 -0
- /package/{types/helpers → helpers}/movie.helper.d.ts +0 -0
- /package/{types/helpers → helpers}/search-user.helper.d.ts +0 -0
- /package/{cjs/helpers → helpers}/search-user.helper.js +0 -0
- /package/{types/helpers → helpers}/user-ratings.helper.d.ts +0 -0
- /package/{cjs/interfaces/creator.interface.js → interfaces/cinema.interface.js} +0 -0
- /package/{types/interfaces → interfaces}/creator.interface.d.ts +0 -0
- /package/{cjs/interfaces/global.js → interfaces/creator.interface.js} +0 -0
- /package/{types/interfaces → interfaces}/global.d.ts +0 -0
- /package/{cjs/interfaces/movie.interface.js → interfaces/global.js} +0 -0
- /package/{types/interfaces → interfaces}/movie.interface.d.ts +0 -0
- /package/{cjs/interfaces/search.interface.js → interfaces/movie.interface.js} +0 -0
- /package/{types/interfaces → interfaces}/search.interface.d.ts +0 -0
- /package/{cjs/interfaces/user-ratings.interface.js → interfaces/search.interface.js} +0 -0
- /package/{types/interfaces → interfaces}/user-ratings.interface.d.ts +0 -0
- /package/{types/services → services}/creator.service.d.ts +0 -0
- /package/{types/services → services}/movie.service.d.ts +0 -0
- /package/{types/services → services}/search.service.d.ts +0 -0
- /package/{types/services → services}/user-ratings.service.d.ts +0 -0
package/README.md
CHANGED
|
@@ -3,29 +3,31 @@
|
|
|
3
3
|
[](https://github.com/bartholomej/node-csfd-api/actions)
|
|
4
4
|
[](https://codecov.io/gh/bartholomej/node-csfd-api)
|
|
5
5
|
|
|
6
|
-
# CSFD API
|
|
6
|
+
# CSFD API 🎥 2025
|
|
7
7
|
|
|
8
8
|
> JavaScript NPM library for scraping **Czech Movie Database (csfd.cz)**
|
|
9
9
|
>
|
|
10
|
-
> - Browser + Node.js (SSR)
|
|
11
10
|
> - JavaScript / TypeScript
|
|
11
|
+
> - Browser + Node.js (SSR)
|
|
12
12
|
> - Tested (~100% Code coverage)
|
|
13
|
-
> - ✅ Ready for new ČSFD
|
|
13
|
+
> - ✅ Ready for new ČSFD 2025!
|
|
14
14
|
> - You can use in:
|
|
15
|
+
> - Docker – [_How to do it?_](#-docker)
|
|
15
16
|
> - Firebase function
|
|
16
17
|
> - AWS λ (lambda function)
|
|
18
|
+
> - CloudFlare Worker
|
|
17
19
|
> - Chrome extension
|
|
18
20
|
> - React native app
|
|
19
|
-
> -
|
|
21
|
+
> - Browsers (Pay attention to CORS)
|
|
20
22
|
|
|
21
|
-
## Install
|
|
23
|
+
## 🗜️ Install
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
|
-
npm install node-csfd-api
|
|
26
|
+
npm install node-csfd-api
|
|
25
27
|
# yarn add node-csfd-api
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
## Usage and examples
|
|
30
|
+
## 🛠️ Usage and examples
|
|
29
31
|
|
|
30
32
|
- [Movies and TV Series](#Movie)
|
|
31
33
|
- [User Ratings](#User-Ratings)
|
|
@@ -34,7 +36,7 @@ npm install node-csfd-api --save
|
|
|
34
36
|
|
|
35
37
|
### Movie
|
|
36
38
|
|
|
37
|
-
Get info about [this movie](https://www.csfd.cz/film/535121-na-spatne-strane/komentare/) _(id: 535121)_
|
|
39
|
+
> Get info about [this movie](https://www.csfd.cz/film/535121-na-spatne-strane/komentare/) _(id: 535121)_
|
|
38
40
|
|
|
39
41
|
```javascript
|
|
40
42
|
import { csfd } from 'node-csfd-api';
|
|
@@ -42,8 +44,9 @@ import { csfd } from 'node-csfd-api';
|
|
|
42
44
|
csfd.movie(535121).then((movie) => console.log(movie));
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
<details>
|
|
48
|
+
<summary>Click here to see full result example</summary>
|
|
49
|
+
|
|
47
50
|
```javascript
|
|
48
51
|
{
|
|
49
52
|
id: 535121,
|
|
@@ -135,10 +138,11 @@ csfd.movie(535121).then((movie) => console.log(movie));
|
|
|
135
138
|
]
|
|
136
139
|
}
|
|
137
140
|
```
|
|
141
|
+
</details>
|
|
138
142
|
|
|
139
143
|
### Search
|
|
140
144
|
|
|
141
|
-
> Search movies and
|
|
145
|
+
> Search movies, users and TV series
|
|
142
146
|
|
|
143
147
|
```javascript
|
|
144
148
|
import { csfd } from 'node-csfd-api';
|
|
@@ -146,10 +150,11 @@ import { csfd } from 'node-csfd-api';
|
|
|
146
150
|
csfd.search('bart').then((search) => console.log(search));
|
|
147
151
|
```
|
|
148
152
|
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
<details>
|
|
154
|
+
<summary>Click here to see full result example</summary>
|
|
155
|
+
|
|
151
156
|
```javascript
|
|
152
|
-
|
|
157
|
+
[
|
|
153
158
|
{
|
|
154
159
|
id: 19653,
|
|
155
160
|
title: 'Black Bart',
|
|
@@ -173,6 +178,19 @@ movies: [
|
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
],
|
|
181
|
+
tvSeries: [
|
|
182
|
+
{
|
|
183
|
+
id: 71924,
|
|
184
|
+
title: 'Království',
|
|
185
|
+
year: 1994,
|
|
186
|
+
url: 'https://www.csfd.cz/film/71924-kralovstvi/',
|
|
187
|
+
type: 'seriál',
|
|
188
|
+
colorRating: 'good',
|
|
189
|
+
poster: 'https://image.pmgstatic.com/cache/resized/w60h85/files/images/film/posters/166/708/166708064_2da697.jpg',
|
|
190
|
+
origins: ['Dánsko'],
|
|
191
|
+
creators: []
|
|
192
|
+
}
|
|
193
|
+
],
|
|
176
194
|
users: [
|
|
177
195
|
{
|
|
178
196
|
id: 912,
|
|
@@ -184,9 +202,11 @@ users: [
|
|
|
184
202
|
]
|
|
185
203
|
```
|
|
186
204
|
|
|
205
|
+
</details>
|
|
206
|
+
|
|
187
207
|
### Creators
|
|
188
208
|
|
|
189
|
-
>
|
|
209
|
+
> Get creator info + filmography
|
|
190
210
|
|
|
191
211
|
```javascript
|
|
192
212
|
import { csfd } from 'node-csfd-api';
|
|
@@ -194,7 +214,8 @@ import { csfd } from 'node-csfd-api';
|
|
|
194
214
|
csfd.creator(2120).then((creator) => console.log(creator));
|
|
195
215
|
```
|
|
196
216
|
|
|
197
|
-
|
|
217
|
+
<details>
|
|
218
|
+
<summary>Click here to see full result example</summary>
|
|
198
219
|
|
|
199
220
|
```javascript
|
|
200
221
|
{
|
|
@@ -271,6 +292,8 @@ csfd.creator(2120).then((creator) => console.log(creator));
|
|
|
271
292
|
}
|
|
272
293
|
```
|
|
273
294
|
|
|
295
|
+
</details>
|
|
296
|
+
|
|
274
297
|
### User Ratings
|
|
275
298
|
|
|
276
299
|
#### Last ratings (last page)
|
|
@@ -300,7 +323,8 @@ csfd
|
|
|
300
323
|
.then((ratings) => console.log(ratings));
|
|
301
324
|
```
|
|
302
325
|
|
|
303
|
-
|
|
326
|
+
<details>
|
|
327
|
+
<summary>Click here to see full result example</summary>
|
|
304
328
|
|
|
305
329
|
```javascript
|
|
306
330
|
[
|
|
@@ -325,7 +349,9 @@ csfd
|
|
|
325
349
|
];
|
|
326
350
|
```
|
|
327
351
|
|
|
328
|
-
|
|
352
|
+
</details>
|
|
353
|
+
|
|
354
|
+
#### Options for user ratings
|
|
329
355
|
|
|
330
356
|
| Option | Type | Default | Description |
|
|
331
357
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------ |
|
|
@@ -334,15 +360,62 @@ csfd
|
|
|
334
360
|
| **allPages** | boolean | false | Get all pages |
|
|
335
361
|
| **allPagesDelay** | number | 0 | Delay on each page request. In milliseconds |
|
|
336
362
|
|
|
337
|
-
_Note: You can not use both parameters
|
|
363
|
+
_Note: You can not use both parameters `includesOnly` and `excludes`. Parameter `includesOnly` has a priority._
|
|
364
|
+
|
|
365
|
+
## 📦 Docker
|
|
366
|
+
|
|
367
|
+
You can use this library in Docker.
|
|
338
368
|
|
|
339
|
-
|
|
369
|
+
We have [prepared a Docker image](https://hub.docker.com/r/bartholomej/node-csfd-api) for you.
|
|
340
370
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
371
|
+
### Prebuilt image
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
docker pull bartholomej/node-csfd-api
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Build & run your own image
|
|
378
|
+
|
|
379
|
+
> Build image
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
docker build -t node-csfd-api .
|
|
383
|
+
```
|
|
344
384
|
|
|
345
|
-
|
|
385
|
+
> Run image on port 3000
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
docker run -p 3000:3000 node-csfd-api
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
> Open http://localhost:3000
|
|
392
|
+
|
|
393
|
+
### API endpoints
|
|
394
|
+
|
|
395
|
+
> Some examples
|
|
396
|
+
|
|
397
|
+
- `/movie/535121`
|
|
398
|
+
- `/search/quentin+tarantino`
|
|
399
|
+
- `/creator/2120`
|
|
400
|
+
- `/user-ratings/912-bart`
|
|
401
|
+
|
|
402
|
+
## 🧑💻 Used by
|
|
403
|
+
|
|
404
|
+
### Web extensions
|
|
405
|
+
|
|
406
|
+
- [Netflix: chrome extension](https://chrome.google.com/webstore/detail/netflix-csfd/eomgekccbddnlpmehgdjmlphndjgnlni) ([code](https://github.com/bartholomej/netflix-csfd-ext))
|
|
407
|
+
- [Dafilms: chrome extension](https://chrome.google.com/webstore/detail/dafilms/hgcgneddmgflnbmhkjnefiobjgobbmdm) ([code](https://github.com/bartholomej/dafilms-ext))
|
|
408
|
+
- [Kviff.tv: chrome extension](https://chrome.google.com/webstore/detail/kvifftv-%20-csfd/ihpngekoejodiligajlppbeedofhnmfm) ([code](https://github.com/bartholomej/kviff-ext))
|
|
409
|
+
|
|
410
|
+
### Web applications
|
|
411
|
+
|
|
412
|
+
- [bartweb.cz](https://bartweb.cz) – **Last seen** section (**Firebase function**)
|
|
413
|
+
|
|
414
|
+
### Mobile applications
|
|
415
|
+
|
|
416
|
+
- [KinoKlub](https://play.google.com/store/apps/details?id=com.aquasoup) – Mobile application for AeroFilms (React Native: Android + iOS application)
|
|
417
|
+
|
|
418
|
+
## 🔮 Roadmap
|
|
346
419
|
|
|
347
420
|
### Scraping more pages
|
|
348
421
|
|
|
@@ -381,8 +454,8 @@ _Note: You can not use both parameters 'includesOnly' and 'excludes'. Parameter
|
|
|
381
454
|
- [ ] Search
|
|
382
455
|
- [x] Movies
|
|
383
456
|
- [x] Users
|
|
457
|
+
- [x] TV Series
|
|
384
458
|
- [ ] Creators
|
|
385
|
-
- [ ] TV Series
|
|
386
459
|
- [x] Creators
|
|
387
460
|
- [x] Bio
|
|
388
461
|
- [x] Movies (TODO categories)
|
|
@@ -390,7 +463,7 @@ _Note: You can not use both parameters 'includesOnly' and 'excludes'. Parameter
|
|
|
390
463
|
- [x] Last ratings
|
|
391
464
|
- [x] All pages
|
|
392
465
|
|
|
393
|
-
## Development
|
|
466
|
+
## 🛠️ Development
|
|
394
467
|
|
|
395
468
|
### Developing and debugging library
|
|
396
469
|
|
|
@@ -406,22 +479,7 @@ You can find and modify it in [`./demo.ts`](https://github.com/bartholomej/node-
|
|
|
406
479
|
yarn demo
|
|
407
480
|
```
|
|
408
481
|
|
|
409
|
-
##
|
|
410
|
-
|
|
411
|
-
### Publish Stable
|
|
412
|
-
|
|
413
|
-
```shell
|
|
414
|
-
yarn release:patch
|
|
415
|
-
# yarn release:minor
|
|
416
|
-
# yarn release:major
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Publish next channel
|
|
420
|
-
|
|
421
|
-
1. Bump version `-beta.0` in `package.json`
|
|
422
|
-
2. `yarn release:beta`
|
|
423
|
-
|
|
424
|
-
## Contribution
|
|
482
|
+
## 🤝 Contribution
|
|
425
483
|
|
|
426
484
|
I welcome you to customize this according to your needs ;)
|
|
427
485
|
|
|
@@ -433,7 +491,7 @@ Give a ⭐️ if this project helped you!
|
|
|
433
491
|
|
|
434
492
|
Or if you are brave enough consider [making a donation](https://github.com/sponsors/bartholomej) for some 🍺 or 🍵 ;)
|
|
435
493
|
|
|
436
|
-
## Privacy Policy
|
|
494
|
+
## 🕵️♀️ Privacy Policy
|
|
437
495
|
|
|
438
496
|
I DO NOT STORE ANY DATA. PERIOD.
|
|
439
497
|
|
|
@@ -441,9 +499,9 @@ I physically can't. I have nowhere to store it. I don't even have a server datab
|
|
|
441
499
|
|
|
442
500
|
That's why, with node-csfd-api, what happens on your device stays on your device till disappear.
|
|
443
501
|
|
|
444
|
-
## License
|
|
502
|
+
## 📝 License
|
|
445
503
|
|
|
446
|
-
Copyright ©
|
|
504
|
+
Copyright © 2020 – 2025 [Lukas Bartak](http://bartweb.cz)
|
|
447
505
|
|
|
448
506
|
Proudly powered by nature 🗻, wind 💨, tea 🍵 and beer 🍺 ;)
|
|
449
507
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fetchSafe: typeof fetch;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchSafe = void 0;
|
|
4
|
+
// Check if `fetch` is available in global scope (nodejs 18+) or in window (browser). If not, use cross-fetch polyfill.
|
|
5
|
+
const cross_fetch_1 = require("cross-fetch");
|
|
6
|
+
exports.fetchSafe = (typeof fetch === 'function' && fetch) || // ServiceWorker fetch (Cloud Functions + Chrome extension)
|
|
7
|
+
(typeof global === 'object' && global.fetch) || // Node.js 18+ fetch
|
|
8
|
+
(typeof window !== 'undefined' && window.fetch) || // Browser fetch
|
|
9
|
+
cross_fetch_1.fetch; // Polyfill fetch
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import fetch from 'cross-fetch';
|
|
3
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
3
|
exports.fetchPage = void 0;
|
|
4
|
+
const fetch_polyfill_1 = require("./fetch.polyfill");
|
|
14
5
|
const USER_AGENTS = [
|
|
15
6
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
|
|
16
7
|
'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',
|
|
@@ -20,17 +11,17 @@ const USER_AGENTS = [
|
|
|
20
11
|
const headers = {
|
|
21
12
|
'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)]
|
|
22
13
|
};
|
|
23
|
-
const fetchPage = (url) =>
|
|
14
|
+
const fetchPage = async (url) => {
|
|
24
15
|
try {
|
|
25
|
-
const response =
|
|
16
|
+
const response = await (0, fetch_polyfill_1.fetchSafe)(url, { headers });
|
|
26
17
|
if (response.status >= 400 && response.status < 600) {
|
|
27
18
|
throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);
|
|
28
19
|
}
|
|
29
|
-
return
|
|
20
|
+
return await response.text();
|
|
30
21
|
}
|
|
31
22
|
catch (e) {
|
|
32
23
|
console.error(e);
|
|
33
24
|
return 'Error';
|
|
34
25
|
}
|
|
35
|
-
}
|
|
26
|
+
};
|
|
36
27
|
exports.fetchPage = fetchPage;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CSFDCinemaGroupedFilmsByDate, CSFDCinemaMeta, CSFDCinemaMovie } from 'interfaces/cinema.interface';
|
|
2
|
+
import { HTMLElement } from 'node-html-parser';
|
|
3
|
+
import { CSFDColorRating } from '../interfaces/global';
|
|
4
|
+
export declare const getColorRating: (el: HTMLElement) => CSFDColorRating;
|
|
5
|
+
export declare const getCinemaId: (el: HTMLElement | null) => number;
|
|
6
|
+
export declare const getId: (url: string) => number;
|
|
7
|
+
export declare const getName: (el: HTMLElement | null) => string;
|
|
8
|
+
export declare const getCoords: (el: HTMLElement | null) => {
|
|
9
|
+
lat: number;
|
|
10
|
+
lng: number;
|
|
11
|
+
};
|
|
12
|
+
export declare const getCinemaUrl: (el: HTMLElement | null) => string;
|
|
13
|
+
export declare const parseCinema: (el: HTMLElement | null) => {
|
|
14
|
+
city: string;
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const getGroupedFilmsByDate: (el: HTMLElement | null) => CSFDCinemaGroupedFilmsByDate[];
|
|
18
|
+
export declare const getFilms: (date: string, el: HTMLElement | null) => CSFDCinemaMovie[];
|
|
19
|
+
export declare const parseMeta: (meta: string[]) => CSFDCinemaMeta[];
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMeta = exports.getFilms = exports.getGroupedFilmsByDate = exports.parseCinema = exports.getCinemaUrl = exports.getCoords = exports.getName = exports.getId = exports.getCinemaId = exports.getColorRating = void 0;
|
|
4
|
+
const global_helper_1 = require("./global.helper");
|
|
5
|
+
const getColorRating = (el) => {
|
|
6
|
+
return (0, global_helper_1.parseColor)(el === null || el === void 0 ? void 0 : el.classNames.split(' ').pop());
|
|
7
|
+
};
|
|
8
|
+
exports.getColorRating = getColorRating;
|
|
9
|
+
const getCinemaId = (el) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const id = (_a = el === null || el === void 0 ? void 0 : el.id) === null || _a === void 0 ? void 0 : _a.split('-')[1];
|
|
12
|
+
return +id;
|
|
13
|
+
};
|
|
14
|
+
exports.getCinemaId = getCinemaId;
|
|
15
|
+
const getId = (url) => {
|
|
16
|
+
if (url) {
|
|
17
|
+
return (0, global_helper_1.parseIdFromUrl)(url);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
};
|
|
21
|
+
exports.getId = getId;
|
|
22
|
+
const getName = (el) => {
|
|
23
|
+
return el.querySelector('h1').innerText.trim();
|
|
24
|
+
};
|
|
25
|
+
exports.getName = getName;
|
|
26
|
+
const getCoords = (el) => {
|
|
27
|
+
const linkMapsEl = el.querySelector('a[href*="q="]');
|
|
28
|
+
if (!linkMapsEl)
|
|
29
|
+
return null;
|
|
30
|
+
const linkMaps = linkMapsEl.getAttribute('href');
|
|
31
|
+
const [_, latLng] = linkMaps.split('q=');
|
|
32
|
+
const coords = latLng.split(',');
|
|
33
|
+
if (coords.length !== 2)
|
|
34
|
+
return null;
|
|
35
|
+
const lat = Number(coords[0]);
|
|
36
|
+
const lng = Number(coords[1]);
|
|
37
|
+
if (Number.isFinite(lat) && Number.isFinite(lng)) {
|
|
38
|
+
return { lat, lng };
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
};
|
|
42
|
+
exports.getCoords = getCoords;
|
|
43
|
+
const getCinemaUrl = (el) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
return (_b = (_a = el.querySelector('a[title="Přejít na webovou stránku kina"]')) === null || _a === void 0 ? void 0 : _a.attributes.href) !== null && _b !== void 0 ? _b : '';
|
|
46
|
+
};
|
|
47
|
+
exports.getCinemaUrl = getCinemaUrl;
|
|
48
|
+
const parseCinema = (el) => {
|
|
49
|
+
const title = el.querySelector('.box-header h2').innerText.trim();
|
|
50
|
+
const [city, name] = title.split(' - ');
|
|
51
|
+
return { city, name };
|
|
52
|
+
};
|
|
53
|
+
exports.parseCinema = parseCinema;
|
|
54
|
+
const getGroupedFilmsByDate = (el) => {
|
|
55
|
+
const divs = el.querySelectorAll(':scope > div');
|
|
56
|
+
const getDatesAndFilms = divs
|
|
57
|
+
.map((_, index) => index)
|
|
58
|
+
.filter((index) => index % 2 === 0)
|
|
59
|
+
.map((index) => {
|
|
60
|
+
var _a, _b, _c;
|
|
61
|
+
const [date, films] = divs.slice(index, index + 2);
|
|
62
|
+
const dateText = (_c = (_b = (_a = date === null || date === void 0 ? void 0 : date.firstChild) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : "";
|
|
63
|
+
return { date: dateText, films: (0, exports.getFilms)('', films) };
|
|
64
|
+
});
|
|
65
|
+
return getDatesAndFilms;
|
|
66
|
+
};
|
|
67
|
+
exports.getGroupedFilmsByDate = getGroupedFilmsByDate;
|
|
68
|
+
const getFilms = (date, el) => {
|
|
69
|
+
const filmNodes = el.querySelectorAll('.cinema-table tr');
|
|
70
|
+
const films = filmNodes.map((filmNode) => {
|
|
71
|
+
var _a, _b, _c, _d;
|
|
72
|
+
const url = (_a = filmNode.querySelector('td.name h3 a')) === null || _a === void 0 ? void 0 : _a.attributes.href;
|
|
73
|
+
const id = (0, exports.getId)(url);
|
|
74
|
+
const title = (_b = filmNode.querySelector('.name h3')) === null || _b === void 0 ? void 0 : _b.text.trim();
|
|
75
|
+
const colorRating = (0, exports.getColorRating)(filmNode.querySelector('.name .icon'));
|
|
76
|
+
const showTimes = (_c = filmNode.querySelectorAll('.td-time')) === null || _c === void 0 ? void 0 : _c.map((x) => x.textContent.trim());
|
|
77
|
+
const meta = (_d = filmNode.querySelectorAll('.td-title span')) === null || _d === void 0 ? void 0 : _d.map((x) => x.text.trim());
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
title,
|
|
81
|
+
url,
|
|
82
|
+
colorRating,
|
|
83
|
+
showTimes,
|
|
84
|
+
meta: (0, exports.parseMeta)(meta)
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
return films;
|
|
88
|
+
};
|
|
89
|
+
exports.getFilms = getFilms;
|
|
90
|
+
const parseMeta = (meta) => {
|
|
91
|
+
const metaConvert = [];
|
|
92
|
+
for (const element of meta) {
|
|
93
|
+
if (element === 'T') {
|
|
94
|
+
metaConvert.push('subtitles');
|
|
95
|
+
}
|
|
96
|
+
else if (element === 'D') {
|
|
97
|
+
metaConvert.push('dubbing');
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
metaConvert.push(element);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return metaConvert;
|
|
104
|
+
};
|
|
105
|
+
exports.parseMeta = parseMeta;
|
|
@@ -18,24 +18,25 @@ const getName = (el) => {
|
|
|
18
18
|
};
|
|
19
19
|
exports.getName = getName;
|
|
20
20
|
const getBirthdayInfo = (el) => {
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
var _a, _b;
|
|
22
|
+
const infoBlock = el.querySelector('h1 + p');
|
|
23
|
+
const text = infoBlock === null || infoBlock === void 0 ? void 0 : infoBlock.innerHTML.trim();
|
|
24
|
+
const birthPlaceRow = (_a = infoBlock === null || infoBlock === void 0 ? void 0 : infoBlock.querySelector('.info-place')) === null || _a === void 0 ? void 0 : _a.innerHTML.trim();
|
|
25
|
+
const ageRow = (_b = infoBlock === null || infoBlock === void 0 ? void 0 : infoBlock.querySelector('.info')) === null || _b === void 0 ? void 0 : _b.innerHTML.trim();
|
|
26
|
+
let birthday = '';
|
|
27
|
+
if (text) {
|
|
28
|
+
const parts = text.split('\n');
|
|
27
29
|
const birthdayRow = parts.find((x) => x.includes('nar.'));
|
|
28
|
-
const ageRow = parts.find((x) => x.includes('let)'));
|
|
29
|
-
const birthPlaceRow = parts.find((x) => x.includes('<br>')); // Ugly but there is no other way to detect
|
|
30
30
|
birthday = birthdayRow ? (0, exports.parseBirthday)(birthdayRow) : '';
|
|
31
|
-
age = ageRow ? +(0, exports.parseAge)(ageRow) : null;
|
|
32
|
-
birthPlace = birthPlaceRow ? (0, exports.parseBirthPlace)(birthPlaceRow) : '';
|
|
33
31
|
}
|
|
32
|
+
const age = ageRow ? +(0, exports.parseAge)(ageRow) : null;
|
|
33
|
+
const birthPlace = birthPlaceRow ? (0, exports.parseBirthPlace)(birthPlaceRow) : '';
|
|
34
34
|
return { birthday, age, birthPlace };
|
|
35
35
|
};
|
|
36
36
|
exports.getBirthdayInfo = getBirthdayInfo;
|
|
37
37
|
const getBio = (el) => {
|
|
38
|
-
|
|
38
|
+
var _a;
|
|
39
|
+
return ((_a = el.querySelector('.article-content p')) === null || _a === void 0 ? void 0 : _a.text.trim().split('\n')[0].trim()) || null;
|
|
39
40
|
};
|
|
40
41
|
exports.getBio = getBio;
|
|
41
42
|
const getPhoto = (el) => {
|
|
@@ -4,4 +4,14 @@ export declare const parseIdFromUrl: (url: string) => number;
|
|
|
4
4
|
export declare const getColor: (cls: string) => CSFDColorRating;
|
|
5
5
|
export declare const parseColor: (quality: Colors) => CSFDColorRating;
|
|
6
6
|
export declare const addProtocol: (url: string) => string;
|
|
7
|
+
export declare const getDuration: (matches: any[]) => {
|
|
8
|
+
sign: string;
|
|
9
|
+
years: any;
|
|
10
|
+
months: any;
|
|
11
|
+
weeks: any;
|
|
12
|
+
days: any;
|
|
13
|
+
hours: any;
|
|
14
|
+
minutes: any;
|
|
15
|
+
seconds: any;
|
|
16
|
+
};
|
|
7
17
|
export declare const parseISO8601Duration: (iso: string) => number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseISO8601Duration = exports.addProtocol = exports.parseColor = exports.getColor = exports.parseIdFromUrl = void 0;
|
|
3
|
+
exports.parseISO8601Duration = exports.getDuration = exports.addProtocol = exports.parseColor = exports.getColor = exports.parseIdFromUrl = void 0;
|
|
4
4
|
const parseIdFromUrl = (url) => {
|
|
5
5
|
if (url) {
|
|
6
6
|
const idSlug = url === null || url === void 0 ? void 0 : url.split('/')[2];
|
|
@@ -46,10 +46,8 @@ const addProtocol = (url) => {
|
|
|
46
46
|
return url.startsWith('//') ? 'https:' + url : url;
|
|
47
47
|
};
|
|
48
48
|
exports.addProtocol = addProtocol;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const matches = iso.match(iso8601DurationRegex);
|
|
52
|
-
const duration = {
|
|
49
|
+
const getDuration = (matches) => {
|
|
50
|
+
return {
|
|
53
51
|
sign: matches[1] === undefined ? '+' : '-',
|
|
54
52
|
years: matches[2] === undefined ? 0 : matches[2],
|
|
55
53
|
months: matches[3] === undefined ? 0 : matches[3],
|
|
@@ -59,6 +57,12 @@ const parseISO8601Duration = (iso) => {
|
|
|
59
57
|
minutes: matches[7] === undefined ? 0 : matches[7],
|
|
60
58
|
seconds: matches[8] === undefined ? 0 : matches[8]
|
|
61
59
|
};
|
|
60
|
+
};
|
|
61
|
+
exports.getDuration = getDuration;
|
|
62
|
+
const parseISO8601Duration = (iso) => {
|
|
63
|
+
const iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
|
|
64
|
+
const matches = iso.match(iso8601DurationRegex);
|
|
65
|
+
const duration = (0, exports.getDuration)(matches);
|
|
62
66
|
return +duration.minutes;
|
|
63
67
|
};
|
|
64
68
|
exports.parseISO8601Duration = parseISO8601Duration;
|
|
@@ -28,9 +28,10 @@ const getColorRating = (bodyClasses) => {
|
|
|
28
28
|
exports.getColorRating = getColorRating;
|
|
29
29
|
const getRating = (el) => {
|
|
30
30
|
const ratingRaw = el.querySelector('.film-rating-average').textContent;
|
|
31
|
-
const rating =
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const rating = ratingRaw === null || ratingRaw === void 0 ? void 0 : ratingRaw.replace(/%/g, '').trim();
|
|
32
|
+
const ratingInt = parseInt(rating);
|
|
33
|
+
if (Number.isInteger(ratingInt)) {
|
|
34
|
+
return ratingInt;
|
|
34
35
|
}
|
|
35
36
|
else {
|
|
36
37
|
return null;
|
|
@@ -90,7 +91,10 @@ const getDuration = (jsonLdRaw, el) => {
|
|
|
90
91
|
exports.getDuration = getDuration;
|
|
91
92
|
const getTitlesOther = (el) => {
|
|
92
93
|
const namesNode = el.querySelectorAll('.film-names li');
|
|
93
|
-
|
|
94
|
+
if (!namesNode.length) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
const titlesOther = namesNode.map((el) => {
|
|
94
98
|
const country = el.querySelector('img.flag').attributes.alt;
|
|
95
99
|
const title = el.textContent.trim().split('\n')[0];
|
|
96
100
|
if (country && title) {
|
|
@@ -103,6 +107,7 @@ const getTitlesOther = (el) => {
|
|
|
103
107
|
return null;
|
|
104
108
|
}
|
|
105
109
|
});
|
|
110
|
+
return titlesOther.filter((x) => x);
|
|
106
111
|
};
|
|
107
112
|
exports.getTitlesOther = getTitlesOther;
|
|
108
113
|
const getPoster = (el) => {
|
|
@@ -8,4 +8,4 @@ export declare const getUrl: (el: HTMLElement) => string;
|
|
|
8
8
|
export declare const getColorRating: (el: HTMLElement) => CSFDColorRating;
|
|
9
9
|
export declare const getPoster: (el: HTMLElement) => string;
|
|
10
10
|
export declare const getOrigins: (el: HTMLElement) => string[];
|
|
11
|
-
export declare const parsePeople: (el: HTMLElement, type:
|
|
11
|
+
export declare const parsePeople: (el: HTMLElement, type: "directors" | "actors") => CSFDCreator[];
|
|
@@ -30,9 +30,11 @@ const getPoster = (el) => {
|
|
|
30
30
|
};
|
|
31
31
|
exports.getPoster = getPoster;
|
|
32
32
|
const getOrigins = (el) => {
|
|
33
|
-
var _a;
|
|
34
|
-
const originsRaw = el.querySelector('.article-content p .info').text;
|
|
35
|
-
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const originsRaw = (_a = el.querySelector('.article-content p .info')) === null || _a === void 0 ? void 0 : _a.text;
|
|
35
|
+
if (!originsRaw)
|
|
36
|
+
return [];
|
|
37
|
+
const originsAll = (_b = originsRaw === null || originsRaw === void 0 ? void 0 : originsRaw.split(', ')) === null || _b === void 0 ? void 0 : _b[0];
|
|
36
38
|
return originsAll === null || originsAll === void 0 ? void 0 : originsAll.split('/').map((country) => country.trim());
|
|
37
39
|
};
|
|
38
40
|
exports.getOrigins = getOrigins;
|
|
@@ -23,7 +23,8 @@ const getTitle = (el) => {
|
|
|
23
23
|
};
|
|
24
24
|
exports.getTitle = getTitle;
|
|
25
25
|
const getYear = (el) => {
|
|
26
|
-
|
|
26
|
+
var _a;
|
|
27
|
+
return +((_a = el.querySelectorAll('td.name .film-title-info .info')[0]) === null || _a === void 0 ? void 0 : _a.text.slice(1, -1)) || null;
|
|
27
28
|
};
|
|
28
29
|
exports.getYear = getYear;
|
|
29
30
|
const getColorRating = (el) => {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { CSFDCinema, CSFDCinemaPeriod } from 'interfaces/cinema.interface';
|
|
1
2
|
import { CSFDCreator } from './interfaces/creator.interface';
|
|
2
3
|
import { CSFDMovie } from './interfaces/movie.interface';
|
|
3
4
|
import { CSFDSearch } from './interfaces/search.interface';
|
|
4
5
|
import { CSFDUserRatingConfig, CSFDUserRatings } from './interfaces/user-ratings.interface';
|
|
6
|
+
import { CinemaScraper } from './services/cinema.service';
|
|
5
7
|
import { CreatorScraper } from './services/creator.service';
|
|
6
8
|
import { MovieScraper } from './services/movie.service';
|
|
7
9
|
import { SearchScraper } from './services/search.service';
|
|
@@ -11,10 +13,12 @@ export declare class Csfd {
|
|
|
11
13
|
private movieService;
|
|
12
14
|
private creatorService;
|
|
13
15
|
private searchService;
|
|
14
|
-
|
|
16
|
+
private cinemaService;
|
|
17
|
+
constructor(userRatingsService: UserRatingsScraper, movieService: MovieScraper, creatorService: CreatorScraper, searchService: SearchScraper, cinemaService: CinemaScraper);
|
|
15
18
|
userRatings(user: string | number, config?: CSFDUserRatingConfig): Promise<CSFDUserRatings[]>;
|
|
16
19
|
movie(movie: number): Promise<CSFDMovie>;
|
|
17
20
|
creator(creator: number): Promise<CSFDCreator>;
|
|
18
21
|
search(text: string): Promise<CSFDSearch>;
|
|
22
|
+
cinema(district: number, period: CSFDCinemaPeriod): Promise<CSFDCinema[]>;
|
|
19
23
|
}
|
|
20
24
|
export declare const csfd: Csfd;
|