11const axios = require ( 'axios' )
22const cheerio = require ( 'cheerio' )
33const 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
510module . 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 ( / i d = ( \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-
81131async 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