diff --git a/sites/vodafone.pt/readme.md b/sites/vodafone.pt/readme.md index b5f697ae..a015f0b1 100644 --- a/sites/vodafone.pt/readme.md +++ b/sites/vodafone.pt/readme.md @@ -3,17 +3,17 @@ ### Download the guide ```sh -npm run grab --- --site=meo.pt +npm run grab --- --site=vodafone.pt ``` ### Update channel list ```sh -npm run channels:parse --- --config=./sites/meo.pt/meo.pt.config.js --output=./sites/meo.pt/meo.pt.channels.xml +npm run channels:parse --- --config=./sites/vodafone.pt/vodafone.pt.config.js --output=./sites/vodafone.pt/vodafone.pt.channels.xml ``` ### Test ```sh -npm test --- meo.pt +npm test --- vodafone.pt ``` diff --git a/sites/vodafone.pt/vodafone.pt.channels.xml b/sites/vodafone.pt/vodafone.pt.channels.xml index 8b137891..240210bc 100644 --- a/sites/vodafone.pt/vodafone.pt.channels.xml +++ b/sites/vodafone.pt/vodafone.pt.channels.xml @@ -1 +1,163 @@ - + + + RTP1 + RTP2 + SIC + TVI + SIC Noticias + RTP3 + CNN Portugal + CMTV + News Now + Globo + Canal 11 + V+ TVI + Porto Canal + SIC Caras + SIC Radical + SIC Mulher + RTP Memória + SportTV+ + SportTV1 + SportTV2 + SportTV3 + SportTV4 + SportTV5 + SportTV6 + SportTV7 + Eurosport 1 + Eurosport 2 + A Bola TV + BTV + Sporting TV + DAZN 1 + DAZN 2 + DAZN 3 + DAZN 4 + DAZN 5 + DAZN 6 + W-Sport + Fight Network + FightBox + Nautical + Channel + Fuel TV + SportTV NBA + Disney Channel + Disney Jr. + Panda Kids + Cartoon Network + Canal Panda + BabyTV + SIC K + CARTOONITO + Nickelodeon + Super RTL + Biggs + Dizi + SIC Novelas + Canal + Hollywood + CineMundo + STAR Movies + STAR Channel + AXN + STAR Life + STAR Crime + STAR Comedy + AXN White + AXN Movies + SyFy + AMC + Eurochannel PT + Canal Q + MTV + MTV 00s + MCM Top + MCM Pop + CMusicTV + Mezzo + Afro Music + Trace Urban + Trace Toca + Mezzo Live + 24Kitchen + Casa e Cozinha + Food Network + Discovery + Channel + National + Geographic + Nat + Geo Wild + História + Odisseia + DocuBox + AMC Crime + Investigation + Discovery + Record Europa + AMC Break + TLC + E! + Travel Channel + Fashion + HGTV + M6 + Fast & Fun Box + GINX ESports TV + Luxe.tv + InSight TV + My Zen TV + GameToon + ARTV + Record News + CNN + Euronews + PT + Euronews + Bloomberg + SkyNews + BBC World News + CNBC + AlJazeera + Rai News + 24h + DW + France 24 + Français + France 24 + English + TCV News + Phoenix + RTP Madeira + RTP Açores + Localvisão TV + RTP África + TPA + Canal 180 + Galicia + + TVE + TV5Monde + Rai 1 + Vox + RTL + Pro TV + International + KBS World + Arirang + NHK World + + Cubavisión + Freedom + Canção Nova + uniFÉ + Kuriakos TV + BenficaTV Multicam 1 + BenficaTV Multicam 2 + BenficaTV Multicam 3 + BenficaTV Multicam 4 + Conta Lá + \ No newline at end of file diff --git a/sites/vodafone.pt/vodafone.pt.config.js b/sites/vodafone.pt/vodafone.pt.config.js index 8b137891..560bac56 100644 --- a/sites/vodafone.pt/vodafone.pt.config.js +++ b/sites/vodafone.pt/vodafone.pt.config.js @@ -1 +1,103 @@ +const { DateTime } = require('luxon') +const fs = require('fs') +const path = require('path') +module.exports = { + site: 'vodafone.pt', + url: 'https://cdn.pt.vtv.vodafone.com/epg/', + days: 7, + periods: [ + '06-12', '12-18', '18-00', '00-06', + ], + + request: { + method: 'GET', + headers: { + Origin: 'https://www.vodafone.pt', + Referer: 'https://www.vodafone.pt/', + 'User-Agent': 'Mozilla/5.0 (compatible; tv_grab_pt_vodafone)', + Accept: 'application/json, text/javascript, */*; q=0.01', + 'Accept-Language': 'pt-PT,pt;q=0.9,en;q=0.8' + }, + path: ({ channel, date, period }) => { + const raw = String(period || '') + let p = raw.trim() + const hasJsonSuffix = /\.json$/i.test(p) + p = p.replace(/\s+/g, '') + p = p.replace(/:/g, '-') + p = p.replace(/_/g, '-') + p = p.replace(/h$/i, '') + p = p.replace(/Z$/i, '') + p = p.replace(/(^|-)0+([0-9])/g, (m, a, b) => (a || '') + b) + p = p.replace(/[^0-9\-\.]/g, '') + if (hasJsonSuffix && !/\.json$/i.test(p)) p = p + '.json' + const year = date.toFormat('yyyy') + const month = date.toFormat('MM') + const day = date.toFormat('dd') + return `${channel}/${year}/${month}/${day}/${p}` + } + }, + + parser({ content }) { + if (!content) return [] + let programs = [] + let data + try { + data = JSON.parse(content) + } catch (err) { + return [] + } + const items = data?.result?.objects || [] + items.forEach(item => { + if (!item.startDate || !item.endDate) return + let start = DateTime.fromSeconds(item.startDate, { zone: 'UTC' }).toUTC() + let stop = DateTime.fromSeconds(item.endDate, { zone: 'UTC' }).toUTC() + if (stop < start) { + stop = stop.plus({ days: 1 }) + } + const prog = { + title: item.name || 'Sem título', + start, + stop + } + if (item.description) prog.description = item.description + if (item.metas?.year?.value) prog.year = item.metas.year.value + if (item.tags?.genre?.objects) { + prog.category = item.tags.genre.objects.map(g => g.value) + } + programs.push(prog) + }) + return programs + }, + + async channels() { + const channelListPath = path.join(__dirname, 'channel.list') + let content + try { + content = fs.readFileSync(channelListPath, 'utf8') + } catch (err) { + return [] + } + const lines = content.split(/\r?\n/) + const channels = lines + .map(l => { + const line = l.replace(/^#.*$/, '').trim() + if (!line) return null + let parts = line.split('\t') + if (parts.length === 1) parts = line.split('|') + if (parts.length === 1) parts = line.split(/\s+/) + if (!parts[0]) return null + const id = parts[0].trim() + let name = parts[1] ? parts[1].replace(/"/g, '').trim() : id + const icon = parts[2] ? parts[2].trim() : undefined + return { + lang: 'pt', + site_id: id, + name, + icon + } + }) + .filter(Boolean) + return channels + } +}