node-csfd-api
Version:
ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)
1 lines • 23.3 kB
Source Map (JSON)
{"version":3,"file":"movie.helper.cjs","names":["getColor","parseISO8601Duration","addProtocol","parseIdFromUrl","parseLastIdFromUrl","parseFilmType","parseDate"],"sources":["../../src/helpers/movie.helper.ts"],"sourcesContent":["import { HTMLElement } from 'node-html-parser';\nimport type { CSFDColorRating, CSFDFilmTypes } from '../dto/global';\nimport type {\n CSFDBoxContent,\n CSFDCreatorGroups,\n CSFDCreatorGroupsEnglish,\n CSFDCreatorGroupsSlovak,\n CSFDCreators,\n CSFDGenres,\n CSFDMovieCreator,\n CSFDMovieListItem,\n CSFDParent,\n CSFDPremiere,\n CSFDSeriesChild,\n CSFDTitlesOther,\n CSFDVod,\n CSFDVodService,\n MovieJsonLd\n} from '../dto/movie';\nimport type { CSFDOptions } from '../types';\nimport {\n addProtocol,\n getColor,\n parseDate,\n parseFilmType,\n parseISO8601Duration,\n parseIdFromUrl,\n parseLastIdFromUrl\n} from './global.helper';\n\n// Performance Optimization: Extract regex literal from loop map callbacks\n// This avoids redundant recompilation per iteration.\nconst CLEAN_TEXT_REGEX = /(\\r\\n|\\n|\\r|\\t)/gm;\n\nconst CREATOR_LABELS: Record<\n string,\n Record<string, CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak>\n> = {\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/**\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 */\nconst CREATOR_KEYS = [\n 'directors',\n 'writers',\n 'cinematography',\n 'music',\n 'actors',\n 'basedOn',\n 'producers',\n 'filmEditing',\n 'costumeDesign',\n 'productionDesign',\n 'sound'\n] as const;\n\n// ⚡ Bolt Performance Optimization:\n// Precomputed reverse map for O(1) creator group lookups instead of dynamic mapping and O(N) string includes checking inside a loop.\nconst REVERSE_CREATOR_LABELS = (() => {\n const map = new Map<string, (typeof CREATOR_KEYS)[number]>();\n for (const lang of Object.values(CREATOR_LABELS)) {\n for (const key of CREATOR_KEYS) {\n if (lang[key]) {\n map.set(lang[key] as string, key);\n }\n }\n }\n return map;\n})();\n\nexport const getLocalizedCreatorLabel = (\n language: string | undefined,\n key:\n | 'directors'\n | 'writers'\n | 'cinematography'\n | 'music'\n | 'actors'\n | 'basedOn'\n | 'producers'\n | 'filmEditing'\n | 'costumeDesign'\n | 'productionDesign'\n | 'casting'\n | 'sound'\n | 'makeup'\n): CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak => {\n const lang = language || 'cs'; // Default to Czech\n return (CREATOR_LABELS[lang] || CREATOR_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 getSeriesAndSeasonTitle = (\n el: HTMLElement\n): { seriesName: string | null; seasonName: string | null } => {\n const titleElement = el.querySelector('h1');\n if (!titleElement) {\n return { seriesName: null, seasonName: null };\n }\n\n const fullText = titleElement.innerText.trim();\n\n // Check if there's a series part indicated by ' - '\n if (fullText.includes(' - ')) {\n const [seriesName, seasonName] = fullText.split(' - ').map((part) => part.trim());\n return { seriesName, seasonName };\n }\n\n // If no series part found, return just the name\n return { seriesName: fullText, seasonName: null };\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 genresNode = el.querySelector('.genres');\n if (!genresNode) return [];\n return genresNode.childNodes\n .map((n) => n.textContent.trim())\n .filter((x) => x.length > 0) as CSFDGenres[];\n};\n\nexport const getMovieOrigins = (el: HTMLElement): string[] => {\n const originNode = el.querySelector('.origin');\n if (!originNode) return [];\n const text = originNode.childNodes[0]?.text || '';\n return text\n .split('/')\n .map((x) => x.trim())\n .filter((x) => x);\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('.ratings-list .counter')?.textContent;\n if (!ratingCountRaw) return null;\n const countString = ratingCountRaw.replace(/[^\\d]/g, '');\n const ratingCount = parseInt(countString, 10);\n if (Number.isInteger(ratingCount)) {\n return ratingCount;\n } else {\n return null;\n }\n};\n\nexport const getMovieYear = (jsonLd: MovieJsonLd | null): number => {\n if (jsonLd && jsonLd.dateCreated) {\n return +jsonLd.dateCreated;\n }\n return null;\n};\n\nexport const getMovieDuration = (jsonLd: MovieJsonLd | null, el: HTMLElement): number => {\n if (jsonLd && jsonLd.duration) {\n try {\n return parseISO8601Duration(jsonLd.duration);\n } catch (e) {\n // ignore\n }\n }\n\n try {\n const originText = el.querySelector('.origin')?.textContent;\n if (originText) {\n const match = originText.match(/(?:(\\d+)\\s*h)?\\s*(\\d+)\\s*min/);\n if (match) {\n const hours = parseInt(match[1] || '0', 10);\n const minutes = parseInt(match[2] || '0', 10);\n return hours * 60 + minutes;\n }\n }\n } catch (error) {\n return null;\n }\n return null;\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(CLEAN_TEXT_REGEX, ''));\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(CLEAN_TEXT_REGEX, ''));\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\n// export 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 getMovieCreators = (el: HTMLElement, options?: CSFDOptions): CSFDCreators => {\n const creators: CSFDCreators = {\n directors: [],\n writers: [],\n cinematography: [],\n music: [],\n actors: [],\n basedOn: [],\n producers: [],\n filmEditing: [],\n costumeDesign: [],\n productionDesign: [],\n sound: []\n };\n\n const groups = el.querySelectorAll('.creators h4');\n\n for (const group of groups) {\n let text = group.textContent.trim();\n if (text.endsWith(':')) {\n text = text.slice(0, -1);\n }\n const key = REVERSE_CREATOR_LABELS.get(text);\n if (key) {\n if (group.parentNode) {\n creators[key] = parseMoviePeople(group.parentNode as HTMLElement);\n }\n }\n }\n\n return creators;\n};\n\nexport const getSeasonsOrEpisodes = (el: HTMLElement): CSFDSeriesChild[] | null => {\n const childrenList = el.querySelector('.film-episodes-list');\n if (!childrenList) return null;\n\n const childrenNodes = childrenList.querySelectorAll('.film-title-inline');\n if (!childrenNodes?.length) return [];\n\n return childrenNodes.map((season) => {\n const nameContainer = season.querySelector('.film-title-name');\n const infoContainer = season.querySelector('.info');\n\n const href = nameContainer?.getAttribute('href');\n const url = href ? (href.startsWith('/') ? `https://www.csfd.cz${href}` : href) : null;\n\n return {\n id: parseLastIdFromUrl(href || ''),\n title: nameContainer?.textContent?.trim() || null,\n url,\n info: infoContainer?.textContent?.replace(/[{()}]/g, '').trim() || null\n };\n });\n};\n\nexport const getEpisodeCode = (el: HTMLElement): string | null => {\n const filmHeaderName = el.querySelector('.film-header-name h1');\n if (!filmHeaderName) return null;\n\n const text = filmHeaderName.textContent?.trim() || '';\n const match = text.match(/\\(([^)]+)\\)/);\n const code = match ? match[1] : null;\n\n return code;\n};\n\nexport const detectSeasonOrEpisodeListType = (el: HTMLElement) => {\n const episodesList = el.querySelector('.film-episodes-list');\n if (!episodesList) return null;\n\n const section = episodesList.closest('.updated-box') || episodesList.closest('section') || el;\n const headerText = section.querySelector('.updated-box-header h3')?.textContent?.trim() ?? '';\n\n if (headerText.includes('Série')) return 'seasons';\n if (headerText.includes('Epizody')) return 'episodes';\n return null;\n};\n\nexport const getSeasonOrEpisodeParent = (el: HTMLElement): CSFDParent | null => {\n let parents = el.querySelectorAll('.film-series-content h2 a');\n if (parents.length === 0) parents = el.querySelectorAll('.film-header-name h1 a');\n if (parents.length === 0) return null;\n\n const [parentSeries, parentSeason] = parents;\n\n const seriesId = parseIdFromUrl(parentSeries?.getAttribute('href'));\n const seasonId = parseLastIdFromUrl(parentSeason?.getAttribute('href') || '');\n const seriesTitle = parentSeries?.textContent?.trim() || null;\n const seasonTitle = parentSeason?.textContent?.trim() || null;\n\n const series = seriesId && seriesTitle ? { id: seriesId, title: seriesTitle } : null;\n const season = seasonId && seasonTitle ? { id: seasonId, title: seasonTitle } : null;\n\n if (!series && !season) return null;\n\n return { series, season };\n};\n\nexport const getMovieGroup = (\n el: HTMLElement,\n group: CSFDCreatorGroups | CSFDCreatorGroupsEnglish | CSFDCreatorGroupsSlovak\n): CSFDMovieCreator[] => {\n const creators = el.querySelectorAll('.creators h4');\n const element = creators.find((elem) => elem.textContent.trim().includes(group as string));\n if (element?.parentNode) {\n return parseMoviePeople(element.parentNode as HTMLElement);\n } else {\n return [];\n }\n};\n\nexport const getMovieType = (el: HTMLElement): CSFDFilmTypes => {\n const type = el.querySelector('.film-header-name .type');\n const text =\n type?.innerText\n ?.replace(/[{()}]/g, '')\n .split('\\n')[0]\n .trim() || 'film';\n return parseFilmType(text);\n};\n\nexport const getMovieVods = (el: HTMLElement | null): CSFDVod[] => {\n let vods: CSFDVod[] = [];\n if (el) {\n const buttonsVod = el.querySelectorAll('.box-film-vod .vod-badge-link');\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 .updated-box-header');\n return headers.find(\n (header) =>\n header.querySelector('h3')?.textContent.trim() === box ||\n header.querySelector('h2')?.textContent.trim() === box\n )?.parentNode;\n};\n\nexport const getMovieBoxMovies = (\n el: HTMLElement,\n boxName: CSFDBoxContent\n): 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 [dateRaw, ...company] = title?.split(' ');\n const date = parseDate(dateRaw);\n\n if (date) {\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 }\n return premiere;\n};\n\nexport const getMovieTags = (el: HTMLElement): string[] => {\n const tagsNodes = el.querySelectorAll('.updated-box-content-tags a');\n return tagsNodes.map((tag) => tag.textContent.trim());\n};\n"],"mappings":"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"}