Skip to content

Commit 1d8423d

Browse files
committed
Fixed movistarplus.es returning 400 errors
1 parent 71792ab commit 1d8423d

File tree

1 file changed

+94
-47
lines changed

1 file changed

+94
-47
lines changed
Lines changed: 94 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,113 @@
11
const axios = require('axios')
22
const cheerio = require('cheerio')
33
const dayjs = require('dayjs')
4+
const utc = require('dayjs/plugin/utc')
5+
const timezone = require('dayjs/plugin/timezone')
6+
7+
dayjs.extend(utc)
8+
dayjs.extend(timezone)
49

510
module.exports = {
611
site: 'movistarplus.es',
712
days: 2,
813
url({ channel, date }) {
914
return `https://www.movistarplus.es/programacion-tv/${channel.site_id}/${date.format('YYYY-MM-DD')}`
1015
},
11-
async parser({ content }) {
16+
request: {
17+
headers: {
18+
'User-Agent':
19+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
20+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
21+
'Accept-Language': 'es-ES,es;q=0.9,en;q=0.8',
22+
Referer: 'https://www.movistarplus.es/programacion-tv'
23+
},
24+
maxRedirects: 5
25+
},
26+
async parser({ content, date }) {
1227
let programs = []
13-
let items = parseItems(content)
14-
if (!items.length) return programs
15-
1628
const $ = cheerio.load(content)
17-
const programElements = $('div[id^="ele-"]').get()
1829

19-
for (let i = 0; i < items.length; i++) {
20-
const el = items[i]
21-
let description = null
30+
const programDivs = $('div[id^="ele-"]').toArray()
31+
32+
for (let i = 0; i < programDivs.length; i++) {
33+
const el = $(programDivs[i])
34+
35+
const title = el.find('li.title').text().trim()
36+
if (!title) continue
37+
38+
const timeText = el.find('li.time').text().trim()
39+
if (!timeText) continue
40+
41+
const [hours, minutes] = timeText.split(':').map(h => parseInt(h, 10))
2242

23-
if (programElements[i]) {
24-
const programDiv = $(programElements[i])
25-
const programLink = programDiv.find('a').attr('href')
26-
27-
if (programLink) {
28-
const idMatch = programLink.match(/id=(\d+)/)
29-
if (idMatch && idMatch[1]) {
30-
description = await getProgramDescription(programLink).catch(() => null)
43+
// Parse time in Spain timezone (Europe/Madrid)
44+
let startDate = dayjs.tz(
45+
`${date.format('YYYY-MM-DD')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`,
46+
'YYYY-MM-DD HH:mm',
47+
'Europe/Madrid'
48+
)
49+
50+
// If the time is in early morning (before 5 AM), it's the next day
51+
if (hours < 5) {
52+
startDate = startDate.add(1, 'day')
53+
}
54+
55+
// Calculate end time from next program's start time
56+
let endDate
57+
if (i < programDivs.length - 1) {
58+
const nextEl = $(programDivs[i + 1])
59+
const nextTimeText = nextEl.find('li.time').text().trim()
60+
if (nextTimeText) {
61+
const [nextHours, nextMinutes] = nextTimeText.split(':').map(h => parseInt(h, 10))
62+
endDate = dayjs.tz(
63+
`${date.format('YYYY-MM-DD')} ${nextHours.toString().padStart(2, '0')}:${nextMinutes.toString().padStart(2, '0')}`,
64+
'YYYY-MM-DD HH:mm',
65+
'Europe/Madrid'
66+
)
67+
68+
// If the next time is in early morning (before 5 AM), it's the next day
69+
if (nextHours < 5) {
70+
endDate = endDate.add(1, 'day')
71+
}
72+
73+
// If end time is still before or same as start time, add another day
74+
if (endDate.isBefore(startDate) || endDate.isSame(startDate)) {
75+
endDate = endDate.add(1, 'day')
3176
}
3277
}
3378
}
3479

80+
// If no end time, use start of next day
81+
if (!endDate) {
82+
endDate = startDate.add(1, 'day').startOf('day')
83+
}
84+
85+
const programLink = el.find('a').attr('href')
86+
let description = null
87+
88+
if (programLink) {
89+
description = await getProgramDescription(programLink).catch(() => null)
90+
}
91+
3592
programs.push({
36-
title: el.item.name,
37-
description: description,
38-
start: dayjs(el.item.startDate),
39-
stop: dayjs(el.item.endDate)
93+
title,
94+
description,
95+
start: startDate,
96+
stop: endDate
4097
})
4198
}
4299

43100
return programs
44101
},
45102
async channels() {
46103
const html = await axios
47-
.get('https://www.movistarplus.es/programacion-tv')
104+
.get('https://www.movistarplus.es/programacion-tv', {
105+
headers: {
106+
'User-Agent':
107+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
108+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
109+
}
110+
})
48111
.then(r => r.data)
49112
.catch(console.log)
50113

@@ -65,33 +128,17 @@ module.exports = {
65128
}
66129
}
67130

68-
function parseItems(content) {
69-
try {
70-
const $ = cheerio.load(content)
71-
let scheme = $('script:contains("@type": "ItemList")').html()
72-
scheme = JSON.parse(scheme)
73-
if (!scheme || !Array.isArray(scheme.itemListElement)) return []
74-
75-
return scheme.itemListElement
76-
} catch {
77-
return []
78-
}
79-
}
80-
81131
async function getProgramDescription(programUrl) {
82-
try {
83-
const response = await axios.get(programUrl, {
84-
headers: {
85-
'Referer': 'https://www.movistarplus.es/programacion-tv/'
86-
}
87-
})
132+
const response = await axios.get(programUrl, {
133+
headers: {
134+
'User-Agent':
135+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
136+
Referer: 'https://www.movistarplus.es/programacion-tv/'
137+
}
138+
})
88139

89-
const $ = cheerio.load(response.data)
90-
const description = $('.show-content .text p').first().text().trim() || null
140+
const $ = cheerio.load(response.data)
141+
const description = $('.show-content .text p').first().text().trim() || null
91142

92-
return description
93-
} catch (error) {
94-
console.error(`Error fetching description from ${programUrl}:`, error.message)
95-
return null
96-
}
143+
return description
97144
}

0 commit comments

Comments
 (0)