From 1d8423d61adc886daaab3852b23098bae3a76a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Candela?= Date: Mon, 19 Jan 2026 20:28:54 +0100 Subject: [PATCH 1/4] Fixed movistarplus.es returning 400 errors --- .../movistarplus.es/movistarplus.es.config.js | 141 ++++++++++++------ 1 file changed, 94 insertions(+), 47 deletions(-) diff --git a/sites/movistarplus.es/movistarplus.es.config.js b/sites/movistarplus.es/movistarplus.es.config.js index c58b51901d..00930b959a 100644 --- a/sites/movistarplus.es/movistarplus.es.config.js +++ b/sites/movistarplus.es/movistarplus.es.config.js @@ -1,6 +1,11 @@ const axios = require('axios') const cheerio = require('cheerio') const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const timezone = require('dayjs/plugin/timezone') + +dayjs.extend(utc) +dayjs.extend(timezone) module.exports = { site: 'movistarplus.es', @@ -8,35 +13,87 @@ module.exports = { url({ channel, date }) { return `https://www.movistarplus.es/programacion-tv/${channel.site_id}/${date.format('YYYY-MM-DD')}` }, - async parser({ content }) { + request: { + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language': 'es-ES,es;q=0.9,en;q=0.8', + Referer: 'https://www.movistarplus.es/programacion-tv' + }, + maxRedirects: 5 + }, + async parser({ content, date }) { let programs = [] - let items = parseItems(content) - if (!items.length) return programs - const $ = cheerio.load(content) - const programElements = $('div[id^="ele-"]').get() - for (let i = 0; i < items.length; i++) { - const el = items[i] - let description = null + const programDivs = $('div[id^="ele-"]').toArray() + + for (let i = 0; i < programDivs.length; i++) { + const el = $(programDivs[i]) + + const title = el.find('li.title').text().trim() + if (!title) continue + + const timeText = el.find('li.time').text().trim() + if (!timeText) continue + + const [hours, minutes] = timeText.split(':').map(h => parseInt(h, 10)) - if (programElements[i]) { - const programDiv = $(programElements[i]) - const programLink = programDiv.find('a').attr('href') - - if (programLink) { - const idMatch = programLink.match(/id=(\d+)/) - if (idMatch && idMatch[1]) { - description = await getProgramDescription(programLink).catch(() => null) + // Parse time in Spain timezone (Europe/Madrid) + let startDate = dayjs.tz( + `${date.format('YYYY-MM-DD')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`, + 'YYYY-MM-DD HH:mm', + 'Europe/Madrid' + ) + + // If the time is in early morning (before 5 AM), it's the next day + if (hours < 5) { + startDate = startDate.add(1, 'day') + } + + // Calculate end time from next program's start time + let endDate + if (i < programDivs.length - 1) { + const nextEl = $(programDivs[i + 1]) + const nextTimeText = nextEl.find('li.time').text().trim() + if (nextTimeText) { + const [nextHours, nextMinutes] = nextTimeText.split(':').map(h => parseInt(h, 10)) + endDate = dayjs.tz( + `${date.format('YYYY-MM-DD')} ${nextHours.toString().padStart(2, '0')}:${nextMinutes.toString().padStart(2, '0')}`, + 'YYYY-MM-DD HH:mm', + 'Europe/Madrid' + ) + + // If the next time is in early morning (before 5 AM), it's the next day + if (nextHours < 5) { + endDate = endDate.add(1, 'day') + } + + // If end time is still before or same as start time, add another day + if (endDate.isBefore(startDate) || endDate.isSame(startDate)) { + endDate = endDate.add(1, 'day') } } } + // If no end time, use start of next day + if (!endDate) { + endDate = startDate.add(1, 'day').startOf('day') + } + + const programLink = el.find('a').attr('href') + let description = null + + if (programLink) { + description = await getProgramDescription(programLink).catch(() => null) + } + programs.push({ - title: el.item.name, - description: description, - start: dayjs(el.item.startDate), - stop: dayjs(el.item.endDate) + title, + description, + start: startDate, + stop: endDate }) } @@ -44,7 +101,13 @@ module.exports = { }, async channels() { const html = await axios - .get('https://www.movistarplus.es/programacion-tv') + .get('https://www.movistarplus.es/programacion-tv', { + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' + } + }) .then(r => r.data) .catch(console.log) @@ -65,33 +128,17 @@ module.exports = { } } -function parseItems(content) { - try { - const $ = cheerio.load(content) - let scheme = $('script:contains("@type": "ItemList")').html() - scheme = JSON.parse(scheme) - if (!scheme || !Array.isArray(scheme.itemListElement)) return [] - - return scheme.itemListElement - } catch { - return [] - } -} - async function getProgramDescription(programUrl) { - try { - const response = await axios.get(programUrl, { - headers: { - 'Referer': 'https://www.movistarplus.es/programacion-tv/' - } - }) + const response = await axios.get(programUrl, { + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + Referer: 'https://www.movistarplus.es/programacion-tv/' + } + }) - const $ = cheerio.load(response.data) - const description = $('.show-content .text p').first().text().trim() || null + const $ = cheerio.load(response.data) + const description = $('.show-content .text p').first().text().trim() || null - return description - } catch (error) { - console.error(`Error fetching description from ${programUrl}:`, error.message) - return null - } + return description } From f0b037d7061f4f9de6f72454afa2ac42e36825ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Candela?= <44000469+Alvarocandela@users.noreply.github.com> Date: Tue, 27 Jan 2026 13:22:43 +0100 Subject: [PATCH 2/4] Change Git repo Updated the Git repository URL in the Dockerfile --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 74555a834a..609f0c9fdc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM node:22-alpine -ARG GIT_REPO=https://github.com/iptv-org/epg.git +ARG GIT_REPO=https://github.com/alvarocandela/epg.git ARG GIT_BRANCH=master ARG WORKDIR=/epg ENV CRON_SCHEDULE="0 0 * * *" @@ -19,4 +19,5 @@ RUN apk del git curl \ COPY pm2.config.js $WORKDIR WORKDIR $WORKDIR EXPOSE 3000 -CMD [ "pm2-runtime", "pm2.config.js" ] \ No newline at end of file + +CMD [ "pm2-runtime", "pm2.config.js" ] From 894eefa8e012d3f92418baa91d4e4bfdb96b4e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Candela?= <44000469+Alvarocandela@users.noreply.github.com> Date: Tue, 27 Jan 2026 14:28:18 +0100 Subject: [PATCH 3/4] Update Dockerfile to use local copy --- Dockerfile | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 609f0c9fdc..31e0e6bbe9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,20 @@ FROM node:22-alpine -ARG GIT_REPO=https://github.com/alvarocandela/epg.git -ARG GIT_BRANCH=master + ARG WORKDIR=/epg ENV CRON_SCHEDULE="0 0 * * *" ENV RUN_AT_STARTUP=true + RUN apk update \ && apk upgrade --available \ - && apk add curl git tzdata bash \ + && apk add tzdata bash \ && npm install -g npm@latest \ && npm install pm2 -g \ - && mkdir $(echo "${WORKDIR}") -p \ - && cd $WORKDIR \ - && git clone --depth 1 -b $(echo "${GIT_BRANCH} ${GIT_REPO}") . \ - && npm install \ - && mkdir /public -RUN apk del git curl \ - && rm -rf /var/cache/apk/* -COPY pm2.config.js $WORKDIR + && mkdir $(echo "${WORKDIR}") -p WORKDIR $WORKDIR +COPY package*.json ./ +RUN npm install +COPY . . +RUN mkdir -p /public EXPOSE 3000 CMD [ "pm2-runtime", "pm2.config.js" ] From aa91e146047b1a9bbc33d9594899a351447fa0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Candela?= Date: Tue, 27 Jan 2026 14:46:57 +0100 Subject: [PATCH 4/4] Revert "Change Git repo" This reverts commit f0b037d7061f4f9de6f72454afa2ac42e36825ef. --- Dockerfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 31e0e6bbe9..fa922c5c15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,10 @@ FROM node:22-alpine +<<<<<<< HEAD +======= +ARG GIT_REPO=https://github.com/iptv-org/epg.git +ARG GIT_BRANCH=master +>>>>>>> parent of f0b037d7 (Change Git repo) ARG WORKDIR=/epg ENV CRON_SCHEDULE="0 0 * * *" ENV RUN_AT_STARTUP=true @@ -16,5 +21,4 @@ RUN npm install COPY . . RUN mkdir -p /public EXPOSE 3000 - -CMD [ "pm2-runtime", "pm2.config.js" ] +CMD [ "pm2-runtime", "pm2.config.js" ] \ No newline at end of file