node-csfd-api-racintom 1.0.0 → 1.2.0

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.
Files changed (104) hide show
  1. package/fetchers/fetch.polyfill.d.ts +1 -0
  2. package/fetchers/fetch.polyfill.js +9 -0
  3. package/fetchers/index.d.ts +1 -0
  4. package/fetchers/index.js +27 -0
  5. package/helpers/creator.helper.d.ts +17 -0
  6. package/helpers/creator.helper.js +87 -0
  7. package/helpers/global.helper.d.ts +17 -0
  8. package/helpers/global.helper.js +68 -0
  9. package/helpers/movie.helper.d.ts +26 -0
  10. package/helpers/movie.helper.js +270 -0
  11. package/helpers/search-user.helper.d.ts +5 -0
  12. package/helpers/search-user.helper.js +22 -0
  13. package/helpers/search.helper.d.ts +11 -0
  14. package/helpers/search.helper.js +62 -0
  15. package/helpers/user-ratings.helper.d.ts +13 -0
  16. package/helpers/user-ratings.helper.js +61 -0
  17. package/index.d.ts +20 -0
  18. package/index.js +33 -0
  19. package/interfaces/creator.interface.d.ts +12 -0
  20. package/interfaces/creator.interface.js +2 -0
  21. package/interfaces/global.d.ts +22 -0
  22. package/interfaces/global.js +2 -0
  23. package/interfaces/movie.interface.d.ts +73 -0
  24. package/interfaces/movie.interface.js +2 -0
  25. package/interfaces/search.interface.d.ts +27 -0
  26. package/interfaces/search.interface.js +2 -0
  27. package/interfaces/user-ratings.interface.d.ts +18 -0
  28. package/interfaces/user-ratings.interface.js +2 -0
  29. package/package.json +62 -86
  30. package/services/creator.service.d.ts +6 -0
  31. package/services/creator.service.js +32 -0
  32. package/services/movie.service.d.ts +6 -0
  33. package/services/movie.service.js +59 -0
  34. package/services/search.service.d.ts +5 -0
  35. package/services/search.service.js +80 -0
  36. package/services/user-ratings.service.d.ts +7 -0
  37. package/services/user-ratings.service.js +84 -0
  38. package/vars.d.ts +4 -0
  39. package/vars.js +11 -0
  40. package/.editorconfig +0 -13
  41. package/.eslintrc.json +0 -33
  42. package/.gitattributes +0 -2
  43. package/.github/FUNDING.yml +0 -8
  44. package/.github/pull_request_template.md +0 -19
  45. package/.github/workflows/main.yml +0 -40
  46. package/.github/workflows/publish.yml +0 -73
  47. package/.github/workflows/test.yml +0 -43
  48. package/.husky/pre-commit +0 -1
  49. package/.idea/codeStyles/Project.xml +0 -72
  50. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  51. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  52. package/.idea/misc.xml +0 -6
  53. package/.idea/modules.xml +0 -8
  54. package/.idea/node-csfd-api.iml +0 -9
  55. package/.idea/prettier.xml +0 -6
  56. package/.idea/vcs.xml +0 -7
  57. package/.nvmrc +0 -1
  58. package/.prettierignore +0 -8
  59. package/.prettierrc +0 -10
  60. package/.vscode/settings.json +0 -16
  61. package/Dockerfile +0 -19
  62. package/demo.ts +0 -35
  63. package/eslint.config.mjs +0 -55
  64. package/server.ts +0 -66
  65. package/src/fetchers/fetch.polyfill.ts +0 -7
  66. package/src/fetchers/index.ts +0 -25
  67. package/src/helpers/creator.helper.ts +0 -95
  68. package/src/helpers/global.helper.ts +0 -70
  69. package/src/helpers/movie.helper.ts +0 -276
  70. package/src/helpers/search-user.helper.ts +0 -19
  71. package/src/helpers/search.helper.ts +0 -66
  72. package/src/helpers/user-ratings.helper.ts +0 -62
  73. package/src/index.ts +0 -42
  74. package/src/interfaces/creator.interface.ts +0 -14
  75. package/src/interfaces/global.ts +0 -36
  76. package/src/interfaces/movie.interface.ts +0 -157
  77. package/src/interfaces/search.interface.ts +0 -32
  78. package/src/interfaces/user-ratings.interface.ts +0 -21
  79. package/src/services/creator.service.ts +0 -34
  80. package/src/services/movie.service.ts +0 -89
  81. package/src/services/search.service.ts +0 -101
  82. package/src/services/user-ratings.service.ts +0 -106
  83. package/src/vars.ts +0 -13
  84. package/tests/creator.test.ts +0 -182
  85. package/tests/fetchers.test.ts +0 -109
  86. package/tests/global.test.ts +0 -35
  87. package/tests/helpers.test.ts +0 -59
  88. package/tests/mocks/creator-actor.html.ts +0 -2244
  89. package/tests/mocks/creator-composer-empty.html.ts +0 -683
  90. package/tests/mocks/creator-director.html.ts +0 -3407
  91. package/tests/mocks/movie1.html.ts +0 -1430
  92. package/tests/mocks/movie2.html.ts +0 -740
  93. package/tests/mocks/movie3.html.ts +0 -1843
  94. package/tests/mocks/movie4.html.ts +0 -1568
  95. package/tests/mocks/search.html.ts +0 -838
  96. package/tests/mocks/series1.html.ts +0 -1540
  97. package/tests/mocks/userRatings.html.ts +0 -1354
  98. package/tests/movie.test.ts +0 -606
  99. package/tests/search.test.ts +0 -379
  100. package/tests/services.test.ts +0 -106
  101. package/tests/user-ratings.test.ts +0 -142
  102. package/tests/vars.test.ts +0 -34
  103. package/tsconfig.json +0 -23
  104. package/vitest.config.mts +0 -10
@@ -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
@@ -0,0 +1 @@
1
+ export declare const fetchPage: (url: string) => Promise<string>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchPage = void 0;
4
+ const fetch_polyfill_1 = require("./fetch.polyfill");
5
+ const USER_AGENTS = [
6
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
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',
8
+ 'Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36',
9
+ 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36'
10
+ ];
11
+ const headers = {
12
+ 'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)]
13
+ };
14
+ const fetchPage = async (url) => {
15
+ try {
16
+ const response = await (0, fetch_polyfill_1.fetchSafe)(url, { headers });
17
+ if (response.status >= 400 && response.status < 600) {
18
+ throw new Error(`node-csfd-api: Bad response ${response.status} for url: ${url}`);
19
+ }
20
+ return await response.text();
21
+ }
22
+ catch (e) {
23
+ console.error(e);
24
+ return 'Error';
25
+ }
26
+ };
27
+ exports.fetchPage = fetchPage;
@@ -0,0 +1,17 @@
1
+ import { HTMLElement } from 'node-html-parser';
2
+ import { CSFDCreatorScreening } from '../interfaces/creator.interface';
3
+ import { CSFDColorRating } from '../interfaces/global';
4
+ export declare const getColorRating: (el: HTMLElement) => CSFDColorRating;
5
+ export declare const getId: (url: string) => number;
6
+ export declare const getName: (el: HTMLElement | null) => string;
7
+ export declare const getBirthdayInfo: (el: HTMLElement | null) => {
8
+ birthday: string;
9
+ age: number;
10
+ birthPlace: string;
11
+ };
12
+ export declare const getBio: (el: HTMLElement | null) => string;
13
+ export declare const getPhoto: (el: HTMLElement | null) => string;
14
+ export declare const parseBirthday: (text: string) => any;
15
+ export declare const parseAge: (text: string) => any;
16
+ export declare const parseBirthPlace: (text: string) => any;
17
+ export declare const getFilms: (el: HTMLElement | null) => CSFDCreatorScreening[];
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFilms = exports.parseBirthPlace = exports.parseAge = exports.parseBirthday = exports.getPhoto = exports.getBio = exports.getBirthdayInfo = exports.getName = exports.getId = 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 getId = (url) => {
10
+ if (url) {
11
+ return (0, global_helper_1.parseIdFromUrl)(url);
12
+ }
13
+ return null;
14
+ };
15
+ exports.getId = getId;
16
+ const getName = (el) => {
17
+ return el.querySelector('h1').innerText.trim();
18
+ };
19
+ exports.getName = getName;
20
+ const getBirthdayInfo = (el) => {
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');
29
+ const birthdayRow = parts.find((x) => x.includes('nar.'));
30
+ birthday = birthdayRow ? (0, exports.parseBirthday)(birthdayRow) : '';
31
+ }
32
+ const age = ageRow ? +(0, exports.parseAge)(ageRow) : null;
33
+ const birthPlace = birthPlaceRow ? (0, exports.parseBirthPlace)(birthPlaceRow) : '';
34
+ return { birthday, age, birthPlace };
35
+ };
36
+ exports.getBirthdayInfo = getBirthdayInfo;
37
+ const getBio = (el) => {
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;
40
+ };
41
+ exports.getBio = getBio;
42
+ const getPhoto = (el) => {
43
+ const image = el.querySelector('img').attributes.src;
44
+ return (0, global_helper_1.addProtocol)(image);
45
+ };
46
+ exports.getPhoto = getPhoto;
47
+ const parseBirthday = (text) => {
48
+ return text.replace(/nar./g, '').trim();
49
+ };
50
+ exports.parseBirthday = parseBirthday;
51
+ const parseAge = (text) => {
52
+ return text.trim().replace(/\(/g, '').replace(/let\)/g, '').trim();
53
+ };
54
+ exports.parseAge = parseAge;
55
+ const parseBirthPlace = (text) => {
56
+ return text.trim().replace(/<br>/g, '').trim();
57
+ };
58
+ exports.parseBirthPlace = parseBirthPlace;
59
+ const getFilms = (el) => {
60
+ var _a;
61
+ const filmNodes = (_a = el.querySelectorAll('.box')[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll('table tr');
62
+ let yearCache;
63
+ const films = filmNodes.map((filmNode) => {
64
+ var _a, _b, _c;
65
+ const id = (0, exports.getId)((_a = filmNode.querySelector('td.name .film-title-name')) === null || _a === void 0 ? void 0 : _a.attributes.href);
66
+ const title = (_b = filmNode.querySelector('.name')) === null || _b === void 0 ? void 0 : _b.text.trim();
67
+ const year = +((_c = filmNode.querySelector('.year')) === null || _c === void 0 ? void 0 : _c.text.trim());
68
+ const colorRating = (0, exports.getColorRating)(filmNode.querySelector('.name .icon'));
69
+ // Cache year from previous film because there is a gap between movies with same year
70
+ if (year) {
71
+ yearCache = +year;
72
+ }
73
+ if (id && title) {
74
+ return {
75
+ id,
76
+ title,
77
+ year: year || yearCache,
78
+ colorRating
79
+ };
80
+ }
81
+ return {};
82
+ });
83
+ // Remove empty objects
84
+ const filmsUnique = films.filter((value) => Object.keys(value).length !== 0);
85
+ return filmsUnique;
86
+ };
87
+ exports.getFilms = getFilms;
@@ -0,0 +1,17 @@
1
+ import { CSFDColorRating } from '../interfaces/global';
2
+ import { Colors } from '../interfaces/user-ratings.interface';
3
+ export declare const parseIdFromUrl: (url: string) => number;
4
+ export declare const getColor: (cls: string) => CSFDColorRating;
5
+ export declare const parseColor: (quality: Colors) => CSFDColorRating;
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
+ };
17
+ export declare const parseISO8601Duration: (iso: string) => number;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseISO8601Duration = exports.getDuration = exports.addProtocol = exports.parseColor = exports.getColor = exports.parseIdFromUrl = void 0;
4
+ const parseIdFromUrl = (url) => {
5
+ if (url) {
6
+ const idSlug = url === null || url === void 0 ? void 0 : url.split('/')[2];
7
+ const id = idSlug === null || idSlug === void 0 ? void 0 : idSlug.split('-')[0];
8
+ return +id || null;
9
+ }
10
+ else {
11
+ return null;
12
+ }
13
+ };
14
+ exports.parseIdFromUrl = parseIdFromUrl;
15
+ const getColor = (cls) => {
16
+ switch (cls) {
17
+ case 'page-lightgrey':
18
+ return 'unknown';
19
+ case 'page-red':
20
+ return 'good';
21
+ case 'page-blue':
22
+ return 'average';
23
+ case 'page-grey':
24
+ return 'bad';
25
+ default:
26
+ return 'unknown';
27
+ }
28
+ };
29
+ exports.getColor = getColor;
30
+ const parseColor = (quality) => {
31
+ switch (quality) {
32
+ case 'lightgrey':
33
+ return 'unknown';
34
+ case 'red':
35
+ return 'good';
36
+ case 'blue':
37
+ return 'average';
38
+ case 'grey':
39
+ return 'bad';
40
+ default:
41
+ return 'unknown';
42
+ }
43
+ };
44
+ exports.parseColor = parseColor;
45
+ const addProtocol = (url) => {
46
+ return url.startsWith('//') ? 'https:' + url : url;
47
+ };
48
+ exports.addProtocol = addProtocol;
49
+ const getDuration = (matches) => {
50
+ return {
51
+ sign: matches[1] === undefined ? '+' : '-',
52
+ years: matches[2] === undefined ? 0 : matches[2],
53
+ months: matches[3] === undefined ? 0 : matches[3],
54
+ weeks: matches[4] === undefined ? 0 : matches[4],
55
+ days: matches[5] === undefined ? 0 : matches[5],
56
+ hours: matches[6] === undefined ? 0 : matches[6],
57
+ minutes: matches[7] === undefined ? 0 : matches[7],
58
+ seconds: matches[8] === undefined ? 0 : matches[8]
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);
66
+ return +duration.minutes;
67
+ };
68
+ exports.parseISO8601Duration = parseISO8601Duration;
@@ -0,0 +1,26 @@
1
+ import { HTMLElement } from 'node-html-parser';
2
+ import { CSFDColorRating } from '../interfaces/global';
3
+ import { CSFDBoxContent, CSFDCreator, CSFDCreatorGroups, CSFDGenres, CSFDMovieListItem, CSFDPremiere, CSFDSeasons, CSFDTitlesOther, CSFDVod } from '../interfaces/movie.interface';
4
+ export declare const getId: (el: HTMLElement) => number;
5
+ export declare const getTitle: (el: HTMLElement) => string;
6
+ export declare const getGenres: (el: HTMLElement) => CSFDGenres[];
7
+ export declare const getOrigins: (el: HTMLElement) => string[];
8
+ export declare const getColorRating: (bodyClasses: string[]) => CSFDColorRating;
9
+ export declare const getRating: (el: HTMLElement) => number;
10
+ export declare const getRatingCount: (el: HTMLElement) => number;
11
+ export declare const getYear: (el: string) => number;
12
+ export declare const getDuration: (jsonLdRaw: string, el: HTMLElement) => number;
13
+ export declare const getTitlesOther: (el: HTMLElement) => CSFDTitlesOther[];
14
+ export declare const getPoster: (el: HTMLElement | null) => string;
15
+ export declare const getRandomPhoto: (el: HTMLElement | null) => string;
16
+ export declare const getTrivia: (el: HTMLElement | null) => string[];
17
+ export declare const getDescriptions: (el: HTMLElement) => string[];
18
+ export declare const parsePeople: (el: HTMLElement) => CSFDCreator[];
19
+ export declare const getGroup: (el: HTMLElement, group: CSFDCreatorGroups) => CSFDCreator[];
20
+ export declare const getType: (el: HTMLElement) => string;
21
+ export declare const getVods: (el: HTMLElement | null) => CSFDVod[];
22
+ export declare const getBoxContent: (el: HTMLElement, box: string) => HTMLElement;
23
+ export declare const getBoxMovies: (el: HTMLElement, boxName: CSFDBoxContent) => CSFDMovieListItem[];
24
+ export declare const getPremieres: (el: HTMLElement) => CSFDPremiere[];
25
+ export declare const getTags: (el: HTMLElement) => string[];
26
+ export declare const getSeasonsInfo: (el: HTMLElement) => CSFDSeasons;
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSeasonsInfo = exports.getTags = exports.getPremieres = exports.getBoxMovies = exports.getBoxContent = exports.getVods = exports.getType = exports.getGroup = exports.parsePeople = exports.getDescriptions = exports.getTrivia = exports.getRandomPhoto = exports.getPoster = exports.getTitlesOther = exports.getDuration = exports.getYear = exports.getRatingCount = exports.getRating = exports.getColorRating = exports.getOrigins = exports.getGenres = exports.getTitle = exports.getId = void 0;
4
+ const global_helper_1 = require("./global.helper");
5
+ const getId = (el) => {
6
+ const url = el.querySelector('.tabs .tab-nav-list a').attributes.href;
7
+ return (0, global_helper_1.parseIdFromUrl)(url);
8
+ };
9
+ exports.getId = getId;
10
+ const getTitle = (el) => {
11
+ return el.querySelector('h1').innerText.split(`(`)[0].trim();
12
+ };
13
+ exports.getTitle = getTitle;
14
+ const getGenres = (el) => {
15
+ const genresRaw = el.querySelector('.genres').textContent;
16
+ return genresRaw.split(' / ');
17
+ };
18
+ exports.getGenres = getGenres;
19
+ const getOrigins = (el) => {
20
+ const originsRaw = el.querySelector('.origin').textContent;
21
+ const origins = originsRaw.split(',')[0];
22
+ return origins.split(' / ');
23
+ };
24
+ exports.getOrigins = getOrigins;
25
+ const getColorRating = (bodyClasses) => {
26
+ return (0, global_helper_1.getColor)(bodyClasses[1]);
27
+ };
28
+ exports.getColorRating = getColorRating;
29
+ const getRating = (el) => {
30
+ const ratingRaw = el.querySelector('.film-rating-average').textContent;
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;
35
+ }
36
+ else {
37
+ return null;
38
+ }
39
+ };
40
+ exports.getRating = getRating;
41
+ const getRatingCount = (el) => {
42
+ var _a;
43
+ const ratingCountRaw = (_a = el.querySelector('.box-rating-container .counter')) === null || _a === void 0 ? void 0 : _a.textContent;
44
+ const ratingCount = +(ratingCountRaw === null || ratingCountRaw === void 0 ? void 0 : ratingCountRaw.replace(/[(\s)]/g, ''));
45
+ if (Number.isInteger(ratingCount)) {
46
+ return ratingCount;
47
+ }
48
+ else {
49
+ return null;
50
+ }
51
+ };
52
+ exports.getRatingCount = getRatingCount;
53
+ const getYear = (el) => {
54
+ try {
55
+ const jsonLd = JSON.parse(el);
56
+ return +jsonLd.dateCreated;
57
+ }
58
+ catch (error) {
59
+ console.error('node-csfd-api: Error parsing JSON-LD', error);
60
+ return null;
61
+ }
62
+ };
63
+ exports.getYear = getYear;
64
+ const getDuration = (jsonLdRaw, el) => {
65
+ let duration = null;
66
+ try {
67
+ const jsonLd = JSON.parse(jsonLdRaw);
68
+ duration = jsonLd.duration;
69
+ return (0, global_helper_1.parseISO8601Duration)(duration);
70
+ }
71
+ catch (error) {
72
+ const origin = el.querySelector('.origin').innerText;
73
+ const timeString = origin.split(',');
74
+ if (timeString.length > 2) {
75
+ // Get last time elelment
76
+ const timeString2 = timeString.pop().trim();
77
+ // Clean it
78
+ const timeRaw = timeString2.split('(')[0].trim();
79
+ // Split by minutes and hours
80
+ const hoursMinsRaw = timeRaw.split('min')[0];
81
+ const hoursMins = hoursMinsRaw.split('h');
82
+ // Resolve hours + minutes format
83
+ duration = hoursMins.length > 1 ? +hoursMins[0] * 60 + +hoursMins[1] : +hoursMins[0];
84
+ return duration;
85
+ }
86
+ else {
87
+ return null;
88
+ }
89
+ }
90
+ };
91
+ exports.getDuration = getDuration;
92
+ const getTitlesOther = (el) => {
93
+ const namesNode = el.querySelectorAll('.film-names li');
94
+ if (!namesNode.length) {
95
+ return [];
96
+ }
97
+ const titlesOther = namesNode.map((el) => {
98
+ const country = el.querySelector('img.flag').attributes.alt;
99
+ const title = el.textContent.trim().split('\n')[0];
100
+ if (country && title) {
101
+ return {
102
+ country,
103
+ title
104
+ };
105
+ }
106
+ else {
107
+ return null;
108
+ }
109
+ });
110
+ return titlesOther.filter((x) => x);
111
+ };
112
+ exports.getTitlesOther = getTitlesOther;
113
+ const getPoster = (el) => {
114
+ var _a;
115
+ const poster = el.querySelector('.film-posters img');
116
+ // Resolve empty image
117
+ if (poster) {
118
+ if ((_a = poster.classNames) === null || _a === void 0 ? void 0 : _a.includes('empty-image')) {
119
+ return null;
120
+ }
121
+ else {
122
+ // Full sized image (not thumb)
123
+ const imageThumb = poster.attributes.src.split('?')[0];
124
+ const image = imageThumb.replace(/\/w140\//, '/w1080/');
125
+ return (0, global_helper_1.addProtocol)(image);
126
+ }
127
+ }
128
+ else {
129
+ return null;
130
+ }
131
+ };
132
+ exports.getPoster = getPoster;
133
+ const getRandomPhoto = (el) => {
134
+ var _a;
135
+ const imageNode = el.querySelector('.gallery-item picture img');
136
+ const image = (_a = imageNode === null || imageNode === void 0 ? void 0 : imageNode.attributes) === null || _a === void 0 ? void 0 : _a.src;
137
+ if (image) {
138
+ return image.replace(/\/w663\//, '/w1326/');
139
+ }
140
+ else {
141
+ return null;
142
+ }
143
+ };
144
+ exports.getRandomPhoto = getRandomPhoto;
145
+ const getTrivia = (el) => {
146
+ const triviaNodes = el.querySelectorAll('.article-trivia ul li');
147
+ if (triviaNodes === null || triviaNodes === void 0 ? void 0 : triviaNodes.length) {
148
+ return triviaNodes.map((node) => node.textContent.trim().replace(/(\r\n|\n|\r|\t)/gm, ''));
149
+ }
150
+ else {
151
+ return null;
152
+ }
153
+ };
154
+ exports.getTrivia = getTrivia;
155
+ const getDescriptions = (el) => {
156
+ return el
157
+ .querySelectorAll('.body--plots .plot-full p, .body--plots .plots .plots-item p')
158
+ .map((movie) => { var _a; return (_a = movie.textContent) === null || _a === void 0 ? void 0 : _a.trim().replace(/(\r\n|\n|\r|\t)/gm, ''); });
159
+ };
160
+ exports.getDescriptions = getDescriptions;
161
+ const parsePeople = (el) => {
162
+ const people = el.querySelectorAll('a');
163
+ return (people
164
+ // Filter out "more" links
165
+ .filter((x) => x.classNames.length === 0)
166
+ .map((person) => {
167
+ return {
168
+ id: (0, global_helper_1.parseIdFromUrl)(person.attributes.href),
169
+ name: person.innerText.trim(),
170
+ url: `https://www.csfd.cz${person.attributes.href}`
171
+ };
172
+ }));
173
+ };
174
+ exports.parsePeople = parsePeople;
175
+ const getGroup = (el, group) => {
176
+ const creators = el.querySelectorAll('.creators h4');
177
+ const element = creators.filter((elem) => elem.textContent.trim().includes(group))[0];
178
+ if (element === null || element === void 0 ? void 0 : element.parentNode) {
179
+ return (0, exports.parsePeople)(element.parentNode);
180
+ }
181
+ else {
182
+ return [];
183
+ }
184
+ };
185
+ exports.getGroup = getGroup;
186
+ const getType = (el) => {
187
+ var _a;
188
+ const type = el.querySelector('.film-header-name .type');
189
+ return ((_a = type === null || type === void 0 ? void 0 : type.innerText) === null || _a === void 0 ? void 0 : _a.replace(/[{()}]/g, '')) || 'film';
190
+ };
191
+ exports.getType = getType;
192
+ const getVods = (el) => {
193
+ let vods = [];
194
+ if (el) {
195
+ const buttons = el.querySelectorAll('.box-buttons .button');
196
+ const buttonsVod = buttons.filter((x) => !x.classNames.includes('button-social'));
197
+ vods = buttonsVod.map((btn) => {
198
+ return {
199
+ title: btn.textContent.trim(),
200
+ url: btn.attributes.href
201
+ };
202
+ });
203
+ }
204
+ return vods.length ? vods : [];
205
+ };
206
+ exports.getVods = getVods;
207
+ // Get box content
208
+ const getBoxContent = (el, box) => {
209
+ var _a;
210
+ const headers = el.querySelectorAll('section.box .box-header');
211
+ return (_a = headers.find((header) => header.querySelector('h3').textContent.trim().includes(box))) === null || _a === void 0 ? void 0 : _a.parentNode;
212
+ };
213
+ exports.getBoxContent = getBoxContent;
214
+ const getBoxMovies = (el, boxName) => {
215
+ const movieListItem = [];
216
+ const box = (0, exports.getBoxContent)(el, boxName);
217
+ const movieTitleNodes = box === null || box === void 0 ? void 0 : box.querySelectorAll('.article-header .film-title-name');
218
+ if (movieTitleNodes === null || movieTitleNodes === void 0 ? void 0 : movieTitleNodes.length) {
219
+ for (const item of movieTitleNodes) {
220
+ movieListItem.push({
221
+ id: (0, global_helper_1.parseIdFromUrl)(item.attributes.href),
222
+ title: item.textContent.trim(),
223
+ url: `https://www.csfd.cz${item.attributes.href}`
224
+ });
225
+ }
226
+ }
227
+ return movieListItem;
228
+ };
229
+ exports.getBoxMovies = getBoxMovies;
230
+ const getPremieres = (el) => {
231
+ var _a, _b;
232
+ const premiereNodes = el.querySelectorAll('.box-premieres li');
233
+ const premiere = [];
234
+ for (const premiereNode of premiereNodes) {
235
+ const title = premiereNode.querySelector('p + span').attributes.title;
236
+ if (title) {
237
+ const [date, ...company] = title === null || title === void 0 ? void 0 : title.split(' ');
238
+ premiere.push({
239
+ country: ((_a = premiereNode.querySelector('.flag')) === null || _a === void 0 ? void 0 : _a.attributes.title) || null,
240
+ format: (_b = premiereNode.querySelector('p').textContent.trim()) === null || _b === void 0 ? void 0 : _b.split(' od')[0],
241
+ date,
242
+ company: company.join(' ')
243
+ });
244
+ }
245
+ }
246
+ return premiere;
247
+ };
248
+ exports.getPremieres = getPremieres;
249
+ const getTags = (el) => {
250
+ const tagsRaw = el.querySelectorAll('.box-content a[href*="/podrobne-vyhledavani/?tag="]');
251
+ return tagsRaw.map((tag) => tag.textContent);
252
+ };
253
+ exports.getTags = getTags;
254
+ const getSeasonsInfo = (el) => {
255
+ const seasonsList = el.querySelector('.film-episodes-list');
256
+ if (seasonsList === null) {
257
+ return null;
258
+ }
259
+ const seasons = seasonsList.querySelectorAll('.film-title');
260
+ return seasons.map(season => {
261
+ const nameContainer = season.querySelector('.film-title-name');
262
+ const infoContainer = season.querySelector('.film-title-info');
263
+ return {
264
+ linkToDetail: nameContainer.getAttribute('href'),
265
+ name: nameContainer.textContent,
266
+ additionalInfo: infoContainer.textContent
267
+ };
268
+ });
269
+ };
270
+ exports.getSeasonsInfo = getSeasonsInfo;
@@ -0,0 +1,5 @@
1
+ import { HTMLElement } from 'node-html-parser';
2
+ export declare const getUser: (el: HTMLElement) => string;
3
+ export declare const getUserRealName: (el: HTMLElement) => string;
4
+ export declare const getAvatar: (el: HTMLElement) => string;
5
+ export declare const getUserUrl: (el: HTMLElement) => string;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getUserUrl = exports.getAvatar = exports.getUserRealName = exports.getUser = void 0;
4
+ const global_helper_1 = require("./global.helper");
5
+ const getUser = (el) => {
6
+ return el.querySelector('.user-title-name').text;
7
+ };
8
+ exports.getUser = getUser;
9
+ const getUserRealName = (el) => {
10
+ var _a;
11
+ return ((_a = el.querySelector('.user-real-name')) === null || _a === void 0 ? void 0 : _a.text.trim()) || null;
12
+ };
13
+ exports.getUserRealName = getUserRealName;
14
+ const getAvatar = (el) => {
15
+ const image = el.querySelector('.article-img img').attributes.src;
16
+ return (0, global_helper_1.addProtocol)(image);
17
+ };
18
+ exports.getAvatar = getAvatar;
19
+ const getUserUrl = (el) => {
20
+ return el.querySelector('.user-title-name').attributes.href;
21
+ };
22
+ exports.getUserUrl = getUserUrl;
@@ -0,0 +1,11 @@
1
+ import { HTMLElement } from 'node-html-parser';
2
+ import { CSFDColorRating, CSFDFilmTypes } from '../interfaces/global';
3
+ import { CSFDCreator } from '../interfaces/movie.interface';
4
+ export declare const getType: (el: HTMLElement) => CSFDFilmTypes;
5
+ export declare const getTitle: (el: HTMLElement) => string;
6
+ export declare const getYear: (el: HTMLElement) => number;
7
+ export declare const getUrl: (el: HTMLElement) => string;
8
+ export declare const getColorRating: (el: HTMLElement) => CSFDColorRating;
9
+ export declare const getPoster: (el: HTMLElement) => string;
10
+ export declare const getOrigins: (el: HTMLElement) => string[];
11
+ export declare const parsePeople: (el: HTMLElement, type: "directors" | "actors") => CSFDCreator[];
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePeople = exports.getOrigins = exports.getPoster = exports.getColorRating = exports.getUrl = exports.getYear = exports.getTitle = exports.getType = void 0;
4
+ const global_helper_1 = require("./global.helper");
5
+ const getType = (el) => {
6
+ const type = el.querySelectorAll('.film-title-info .info')[1];
7
+ return ((type === null || type === void 0 ? void 0 : type.innerText.replace(/[{()}]/g, '')) || 'film');
8
+ };
9
+ exports.getType = getType;
10
+ const getTitle = (el) => {
11
+ return el.querySelector('.film-title-name').text;
12
+ };
13
+ exports.getTitle = getTitle;
14
+ const getYear = (el) => {
15
+ var _a;
16
+ return +((_a = el.querySelectorAll('.film-title-info .info')[0]) === null || _a === void 0 ? void 0 : _a.innerText.replace(/[{()}]/g, ''));
17
+ };
18
+ exports.getYear = getYear;
19
+ const getUrl = (el) => {
20
+ return el.querySelector('.film-title-name').attributes.href;
21
+ };
22
+ exports.getUrl = getUrl;
23
+ const getColorRating = (el) => {
24
+ return (0, global_helper_1.parseColor)(el.querySelector('.article-header i.icon').classNames.split(' ').pop());
25
+ };
26
+ exports.getColorRating = getColorRating;
27
+ const getPoster = (el) => {
28
+ const image = el.querySelector('img').attributes.src;
29
+ return (0, global_helper_1.addProtocol)(image);
30
+ };
31
+ exports.getPoster = getPoster;
32
+ const getOrigins = (el) => {
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];
38
+ return originsAll === null || originsAll === void 0 ? void 0 : originsAll.split('/').map((country) => country.trim());
39
+ };
40
+ exports.getOrigins = getOrigins;
41
+ const parsePeople = (el, type) => {
42
+ let who;
43
+ if (type === 'directors')
44
+ who = 'Režie:';
45
+ if (type === 'actors')
46
+ who = 'Hrají:';
47
+ const peopleNode = Array.from(el && el.querySelectorAll('.article-content p')).find((el) => el.textContent.includes(who));
48
+ if (peopleNode) {
49
+ const people = Array.from(peopleNode.querySelectorAll('a'));
50
+ return people.map((person) => {
51
+ return {
52
+ id: (0, global_helper_1.parseIdFromUrl)(person.attributes.href),
53
+ name: person.innerText.trim(),
54
+ url: `https://www.csfd.cz${person.attributes.href}`
55
+ };
56
+ });
57
+ }
58
+ else {
59
+ return [];
60
+ }
61
+ };
62
+ exports.parsePeople = parsePeople;
@@ -0,0 +1,13 @@
1
+ import { HTMLElement } from 'node-html-parser';
2
+ import { CSFDColorRating, CSFDFilmTypes, CSFDStars } from '../interfaces/global';
3
+ import { Colors } from '../interfaces/user-ratings.interface';
4
+ export declare const getId: (el: HTMLElement) => number;
5
+ export declare const getUserRating: (el: HTMLElement) => CSFDStars;
6
+ export declare const getType: (el: HTMLElement) => CSFDFilmTypes;
7
+ export declare const getTitle: (el: HTMLElement) => string;
8
+ export declare const getYear: (el: HTMLElement) => number;
9
+ export declare const getColorRating: (el: HTMLElement) => CSFDColorRating;
10
+ export declare const getDate: (el: HTMLElement) => string;
11
+ export declare const getUrl: (el: HTMLElement) => string;
12
+ export declare const parseColor: (quality: Colors) => CSFDColorRating;
13
+ export declare const sleep: (ms: number) => Promise<unknown>;