Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 94 additions & 47 deletions sites/movistarplus.es/movistarplus.es.config.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,113 @@
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',
days: 2,
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
})
}

return programs
},
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)

Expand All @@ -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
}