node-csfd-api 2.13.1 → 2.14.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/helpers/cinema.helper.d.ts +18 -0
- package/helpers/cinema.helper.js +105 -0
- package/index.d.ts +5 -1
- package/index.js +8 -2
- package/interfaces/cinema.interface.d.ts +23 -0
- package/interfaces/cinema.interface.js +2 -0
- package/package.json +1 -1
- package/services/cinema.service.d.ts +6 -0
- package/services/cinema.service.js +34 -0
- package/services/creator.service.js +5 -1
- package/services/movie.service.js +5 -1
- package/services/search.service.js +3 -3
- package/vars.d.ts +2 -0
- package/vars.js +5 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HTMLElement } from 'node-html-parser';
|
|
2
|
+
import { CSFDColorRating } from '../interfaces/global';
|
|
3
|
+
import { CSFDCinemaGroupedFilmsByDate, CSFDCinemaMeta, CSFDCinemaMovie } from './../interfaces/cinema.interface';
|
|
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 | null;
|
|
7
|
+
export declare const getCoords: (el: HTMLElement | null) => {
|
|
8
|
+
lat: number;
|
|
9
|
+
lng: number;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare const getCinemaUrl: (el: HTMLElement | null) => string;
|
|
12
|
+
export declare const parseCinema: (el: HTMLElement | null) => {
|
|
13
|
+
city: string;
|
|
14
|
+
name: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const getGroupedFilmsByDate: (el: HTMLElement | null) => CSFDCinemaGroupedFilmsByDate[];
|
|
17
|
+
export declare const getFilms: (date: string, el: HTMLElement | null) => CSFDCinemaMovie[];
|
|
18
|
+
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.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 getCoords = (el) => {
|
|
23
|
+
if (!el)
|
|
24
|
+
return null;
|
|
25
|
+
const linkMapsEl = el.querySelector('a[href*="q="]');
|
|
26
|
+
if (!linkMapsEl)
|
|
27
|
+
return null;
|
|
28
|
+
const linkMaps = linkMapsEl.getAttribute('href');
|
|
29
|
+
const [_, latLng] = linkMaps.split('q=');
|
|
30
|
+
const coords = latLng.split(',');
|
|
31
|
+
if (coords.length !== 2)
|
|
32
|
+
return null;
|
|
33
|
+
const lat = Number(coords[0]);
|
|
34
|
+
const lng = Number(coords[1]);
|
|
35
|
+
if (Number.isFinite(lat) && Number.isFinite(lng)) {
|
|
36
|
+
return { lat, lng };
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
exports.getCoords = getCoords;
|
|
41
|
+
const getCinemaUrl = (el) => {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
if (!el)
|
|
44
|
+
return '';
|
|
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 : null;
|
|
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;
|
package/index.d.ts
CHANGED
|
@@ -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 | string, period: CSFDCinemaPeriod): Promise<CSFDCinema[]>;
|
|
19
23
|
}
|
|
20
24
|
export declare const csfd: Csfd;
|
package/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.csfd = exports.Csfd = void 0;
|
|
4
|
+
const cinema_service_1 = require("./services/cinema.service");
|
|
4
5
|
const creator_service_1 = require("./services/creator.service");
|
|
5
6
|
const movie_service_1 = require("./services/movie.service");
|
|
6
7
|
const search_service_1 = require("./services/search.service");
|
|
7
8
|
const user_ratings_service_1 = require("./services/user-ratings.service");
|
|
8
9
|
class Csfd {
|
|
9
|
-
constructor(userRatingsService, movieService, creatorService, searchService) {
|
|
10
|
+
constructor(userRatingsService, movieService, creatorService, searchService, cinemaService) {
|
|
10
11
|
this.userRatingsService = userRatingsService;
|
|
11
12
|
this.movieService = movieService;
|
|
12
13
|
this.creatorService = creatorService;
|
|
13
14
|
this.searchService = searchService;
|
|
15
|
+
this.cinemaService = cinemaService;
|
|
14
16
|
}
|
|
15
17
|
async userRatings(user, config) {
|
|
16
18
|
return this.userRatingsService.userRatings(user, config);
|
|
@@ -24,10 +26,14 @@ class Csfd {
|
|
|
24
26
|
async search(text) {
|
|
25
27
|
return this.searchService.search(text);
|
|
26
28
|
}
|
|
29
|
+
async cinema(district, period) {
|
|
30
|
+
return this.cinemaService.cinemas(+district, period);
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
exports.Csfd = Csfd;
|
|
29
34
|
const movieScraper = new movie_service_1.MovieScraper();
|
|
30
35
|
const userRatingsScraper = new user_ratings_service_1.UserRatingsScraper();
|
|
36
|
+
const cinemaScraper = new cinema_service_1.CinemaScraper();
|
|
31
37
|
const creatorScraper = new creator_service_1.CreatorScraper();
|
|
32
38
|
const searchScraper = new search_service_1.SearchScraper();
|
|
33
|
-
exports.csfd = new Csfd(userRatingsScraper, movieScraper, creatorScraper, searchScraper);
|
|
39
|
+
exports.csfd = new Csfd(userRatingsScraper, movieScraper, creatorScraper, searchScraper, cinemaScraper);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CSFDMovieListItem } from './movie.interface';
|
|
2
|
+
export interface CSFDCinema {
|
|
3
|
+
id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
city: string;
|
|
6
|
+
url: string;
|
|
7
|
+
coords: {
|
|
8
|
+
lat: number;
|
|
9
|
+
lng: number;
|
|
10
|
+
};
|
|
11
|
+
region?: string;
|
|
12
|
+
screenings: CSFDCinemaGroupedFilmsByDate[];
|
|
13
|
+
}
|
|
14
|
+
export interface CSFDCinemaGroupedFilmsByDate {
|
|
15
|
+
date: string;
|
|
16
|
+
films: CSFDCinemaMovie[];
|
|
17
|
+
}
|
|
18
|
+
export interface CSFDCinemaMovie extends CSFDMovieListItem {
|
|
19
|
+
meta: CSFDCinemaMeta[];
|
|
20
|
+
showTimes: string[];
|
|
21
|
+
}
|
|
22
|
+
export type CSFDCinemaMeta = 'dubbing' | '3D' | 'subtitles' | string;
|
|
23
|
+
export type CSFDCinemaPeriod = 'today' | 'weekend' | 'week' | 'tomorrow' | 'month';
|
package/package.json
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CinemaScraper = void 0;
|
|
4
|
+
const node_html_parser_1 = require("node-html-parser");
|
|
5
|
+
const fetchers_1 = require("../fetchers");
|
|
6
|
+
const vars_1 = require("../vars");
|
|
7
|
+
const cinema_helper_1 = require("./../helpers/cinema.helper");
|
|
8
|
+
class CinemaScraper {
|
|
9
|
+
async cinemas(district = 1, period = 'today') {
|
|
10
|
+
const url = (0, vars_1.cinemasUrl)(district, period);
|
|
11
|
+
const response = await (0, fetchers_1.fetchPage)(url);
|
|
12
|
+
const cinemasHtml = (0, node_html_parser_1.parse)(response);
|
|
13
|
+
const contentNode = cinemasHtml.querySelectorAll('#snippet--cinemas section.box');
|
|
14
|
+
this.buildCinemas(contentNode);
|
|
15
|
+
return this.cinema;
|
|
16
|
+
}
|
|
17
|
+
buildCinemas(contentNode) {
|
|
18
|
+
const cinemas = [];
|
|
19
|
+
contentNode.forEach((x) => {
|
|
20
|
+
const cinemaInfo = (0, cinema_helper_1.parseCinema)(x);
|
|
21
|
+
const cinema = {
|
|
22
|
+
id: (0, cinema_helper_1.getCinemaId)(x),
|
|
23
|
+
name: cinemaInfo === null || cinemaInfo === void 0 ? void 0 : cinemaInfo.name,
|
|
24
|
+
city: cinemaInfo === null || cinemaInfo === void 0 ? void 0 : cinemaInfo.city,
|
|
25
|
+
url: (0, cinema_helper_1.getCinemaUrl)(x),
|
|
26
|
+
coords: (0, cinema_helper_1.getCoords)(x),
|
|
27
|
+
screenings: (0, cinema_helper_1.getGroupedFilmsByDate)(x)
|
|
28
|
+
};
|
|
29
|
+
cinemas.push(cinema);
|
|
30
|
+
});
|
|
31
|
+
this.cinema = cinemas;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.CinemaScraper = CinemaScraper;
|
|
@@ -7,7 +7,11 @@ const creator_helper_1 = require("../helpers/creator.helper");
|
|
|
7
7
|
const vars_1 = require("../vars");
|
|
8
8
|
class CreatorScraper {
|
|
9
9
|
async creator(creatorId) {
|
|
10
|
-
const
|
|
10
|
+
const id = Number(creatorId);
|
|
11
|
+
if (isNaN(id)) {
|
|
12
|
+
throw new Error('node-csfd-api: creatorId must be a valid number');
|
|
13
|
+
}
|
|
14
|
+
const url = (0, vars_1.creatorUrl)(id);
|
|
11
15
|
const response = await (0, fetchers_1.fetchPage)(url);
|
|
12
16
|
const creatorHtml = (0, node_html_parser_1.parse)(response);
|
|
13
17
|
const asideNode = creatorHtml.querySelector('.creator-about');
|
|
@@ -7,7 +7,11 @@ const movie_helper_1 = require("../helpers/movie.helper");
|
|
|
7
7
|
const vars_1 = require("../vars");
|
|
8
8
|
class MovieScraper {
|
|
9
9
|
async movie(movieId) {
|
|
10
|
-
const
|
|
10
|
+
const id = Number(movieId);
|
|
11
|
+
if (isNaN(id)) {
|
|
12
|
+
throw new Error('node-csfd-api: movieId must be a valid number');
|
|
13
|
+
}
|
|
14
|
+
const url = (0, vars_1.movieUrl)(id);
|
|
11
15
|
const response = await (0, fetchers_1.fetchPage)(url);
|
|
12
16
|
const movieHtml = (0, node_html_parser_1.parse)(response);
|
|
13
17
|
const pageClasses = movieHtml.querySelector('.page-content').classNames.split(' ');
|
|
@@ -21,7 +21,7 @@ class SearchScraper {
|
|
|
21
21
|
const movies = [];
|
|
22
22
|
const users = [];
|
|
23
23
|
const tvSeries = [];
|
|
24
|
-
moviesNode.
|
|
24
|
+
moviesNode.forEach((m) => {
|
|
25
25
|
const url = (0, search_helper_1.getUrl)(m);
|
|
26
26
|
const movie = {
|
|
27
27
|
id: (0, global_helper_1.parseIdFromUrl)(url),
|
|
@@ -39,7 +39,7 @@ class SearchScraper {
|
|
|
39
39
|
};
|
|
40
40
|
movies.push(movie);
|
|
41
41
|
});
|
|
42
|
-
usersNode.
|
|
42
|
+
usersNode.forEach((m) => {
|
|
43
43
|
const url = (0, search_user_helper_1.getUserUrl)(m);
|
|
44
44
|
const user = {
|
|
45
45
|
id: (0, global_helper_1.parseIdFromUrl)(url),
|
|
@@ -50,7 +50,7 @@ class SearchScraper {
|
|
|
50
50
|
};
|
|
51
51
|
users.push(user);
|
|
52
52
|
});
|
|
53
|
-
tvSeriesNode.
|
|
53
|
+
tvSeriesNode.forEach((m) => {
|
|
54
54
|
const url = (0, search_helper_1.getUrl)(m);
|
|
55
55
|
const user = {
|
|
56
56
|
id: (0, global_helper_1.parseIdFromUrl)(url),
|
package/vars.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CSFDCinemaPeriod } from './interfaces/cinema.interface';
|
|
1
2
|
export declare const userRatingsUrl: (user: string | number, page?: number) => string;
|
|
2
3
|
export declare const movieUrl: (movie: number) => string;
|
|
3
4
|
export declare const creatorUrl: (creator: number | string) => string;
|
|
5
|
+
export declare const cinemasUrl: (district: number | string, period: CSFDCinemaPeriod) => string;
|
|
4
6
|
export declare const searchUrl: (text: string) => string;
|
package/vars.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.searchUrl = exports.creatorUrl = exports.movieUrl = exports.userRatingsUrl = void 0;
|
|
3
|
+
exports.searchUrl = exports.cinemasUrl = exports.creatorUrl = exports.movieUrl = exports.userRatingsUrl = void 0;
|
|
4
4
|
const userRatingsUrl = (user, page) => `https://www.csfd.cz/uzivatel/${encodeURIComponent(user)}/hodnoceni/${page ? '?page=' + page : ''}`;
|
|
5
5
|
exports.userRatingsUrl = userRatingsUrl;
|
|
6
6
|
const movieUrl = (movie) => `https://www.csfd.cz/film/${encodeURIComponent(movie)}/prehled/`;
|
|
7
7
|
exports.movieUrl = movieUrl;
|
|
8
8
|
const creatorUrl = (creator) => `https://www.csfd.cz/tvurce/${encodeURIComponent(creator)}`;
|
|
9
9
|
exports.creatorUrl = creatorUrl;
|
|
10
|
+
const cinemasUrl = (district, period) => {
|
|
11
|
+
return `https://www.csfd.cz/kino/?period=${period}&district=${district}`;
|
|
12
|
+
};
|
|
13
|
+
exports.cinemasUrl = cinemasUrl;
|
|
10
14
|
const searchUrl = (text) => `https://www.csfd.cz/hledat/?q=${encodeURIComponent(text)}`;
|
|
11
15
|
exports.searchUrl = searchUrl;
|