Merge pull request #2991 from CyberPoison/master

Fix `meo.pt` and `nostv.pt` grabbers
This commit is contained in:
Ismaël Moret authored and GitHub committed 2026-02-14 13:58:28 +01:00
commit 4a057e4573
6 files changed
+192 -149

No files matched your search

+26 -1
View File
@@ -1 +1,26 @@
{"d":{"__type":"Ptsi.Isites.GridTv.CanaisService.GridTV","ExtensionData":{},"services":[],"channels":[{"__type":"Ptsi.Isites.GridTv.CanaisService.Channels","ExtensionData":{},"id":100,"name":"RTP MEMÓRIA","sigla":"RTPM","friendlyUrlName":"RTP_Memoria","url":"https://meogo.meo.pt/direto?canalUrl=RTP_Memoria","meogo":true,"logo":"https://www.meo.pt/PublishingImages/canais/rtp-memoria.png","isAdult":false,"categories":[{"ExtensionData":{},"id":4,"name":"Entretenimento"}],"types":[{"ExtensionData":{},"id":0,"name":"Gravações Automáticas"},{"ExtensionData":{},"id":1,"name":"Restart TV"}],"programs":[{"ExtensionData":{},"date":"1-12-2022","timeIni":"23:35","timeEnd":"00:17","number":15992358,"uniqueId":"27621378","name":"Walker, O Ranger Do Texas T6 - Ep. 14","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"103787"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"00:17","timeEnd":"01:07","number":17690651,"uniqueId":"27621379","name":"O Barco Do Amor T7 - Ep. 21","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"117870"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"01:07","timeEnd":"01:57","number":17690652,"uniqueId":"27621380","name":"Um Anjo Na Terra T3 - Ep. 22","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"117869"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"01:57","timeEnd":"02:39","number":15992358,"uniqueId":"27621381","name":"Walker, O Ranger Do Texas T6 - Ep. 14","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"103787"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"02:39","timeEnd":"03:42","number":17690659,"uniqueId":"27621382","name":"5 Para A Meia-Noite T7 - Ep. 29","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"118268"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"03:42","timeEnd":"04:33","number":13223378,"uniqueId":"27621383","name":"O Conde D´Abranhos - Ep. 9","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"1367"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"04:33","timeEnd":"05:02","number":17690660,"uniqueId":"27621384","name":"Quebra-Cabeças T4 - Ep. 60","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"91370"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"05:02","timeEnd":"05:19","number":17690661,"uniqueId":"27621385","name":"As Aventuras De Eva - Ep. 9","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"118559"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"05:19","timeEnd":"06:02","number":13338966,"uniqueId":"27621386","name":"Bem-Vindos A Beirais T4 - Ep. 36","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"80897"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"06:02","timeEnd":"06:29","number":12414718,"uniqueId":"27621387","name":"Horizontes Da Memória T6 - Ep. 19","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"74413"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"06:29","timeEnd":"06:56","number":13492284,"uniqueId":"27621388","name":"SMS - Ser Mais Sabedor T1 - Ep. 49","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-0000-0000-000000000000","recordingProgramID":"00000000-0000-0000-0000-000000000000","seriesID":"81681"},{"ExtensionData":{},"date":"2-12-2022","timeIni":"06:56","timeEnd":"07:00","number":17733452,"uniqueId":"27621389","name":"A Música Portuguesa A Gostar Dela Própria T1 - Ep. 103","synopse":null,"imageM":null,"imageL":null,"imageXL":null,"recordType":0,"recordingDefinitionID":"00000000-0000-000Line truncated
{
"Status": "OK",
"StatusCode": 200,
"Result": [
{
"CallLetter": "RTP1",
"EndDate": "2026-01-23T00:04:00",
"Id": 42314383,
"IsAdultContent": false,
"ProgramId": 22604754,
"StartDate": "2026-01-22T23:40:00",
"Synopsis": "'Barman' é uma série de comédia dramática sobre um jovem comediante que começa a trabalhar como Barman porque precisa de arranjar dinheiro depressa, pelo caminho é obrigado a lidar com a vida noturna e conciliar duas realidades diferentes.",
"Title": "Barman - Ep. 4"
},
{
"CallLetter": "RTP1",
"EndDate": "2026-01-23T00:30:00",
"Id": 42314384,
"IsAdultContent": false,
"ProgramId": 22604763,
"StartDate": "2026-01-23T00:04:00",
"Synopsis": "'Barman' é uma série de comédia dramática sobre um jovem comediante que começa a trabalhar como Barman porque precisa de arranjar dinheiro depressa, pelo caminho é obrigado a lidar com a vida noturna e conciliar duas realidades diferentes.",
"Title": "Barman - Ep. 5"
}
]
}
+53 -102
View File
@@ -3,65 +3,55 @@ const { DateTime } = require('luxon')
module.exports = {
site: 'meo.pt',
days: 2,
url: 'https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramsFromChannels',
url: function ({ channel, date }) {
return `https://meogouser.apps.meo.pt/Services/GridTv/GridTv.svc/GetLiveChannelProgramsByDate?callLetter=${channel.site_id}&date=${date.format('YYYY-MM-DD')}&userAgent=IPTV_OFR_GTV`
},
request: {
method: 'POST',
method: 'GET',
headers: {
Origin: 'https://www.meo.pt',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; en-US Trident/4.0)'
},
data: function ({ channel, date }) {
return {
service: 'channelsguide',
channels: [channel.site_id],
dateStart: date.format('YYYY-MM-DDT00:00:00-00:00'),
dateEnd: date.add(1, 'd').format('YYYY-MM-DDT00:00:00-00:00'),
accountID: ''
}
'accept': '*/*',
'accept-language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,cs;q=0.5',
'cache-control': 'no-cache',
'origin': 'https://www.meo.pt',
'pragma': 'no-cache',
'priority': 'u=1, i',
'referer': 'https://www.meo.pt/',
'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144"',
'sec-ch-ua-mobile': '?1',
'sec-ch-ua-platform': '"Android"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36'
}
},
async parser({ content }) {
const axios = require('axios')
async parser({ content, channel }) {
let programs = []
const items = parseItems(content)
if (!items.length) return programs
// simple per-run in-memory cache
const detailsCache = new Map()
for (const item of items) {
const start = parseStart(item)
let stop = parseStop(item)
if (stop < start) {
stop = stop.plus({ days: 1 })
}
let description = ''
let image = ''
const programID = item.uniqueId || null
if (programID) {
let details = detailsCache.get(programID)
if (!details) {
details = await fetchProgramDetails(programID, axios).catch(() => null)
if (details) detailsCache.set(programID, details)
}
if (details) {
description = details.description || description
image = details.image || image
}
}
const start = DateTime.fromISO(item.StartDate, { zone: 'Europe/Lisbon' }).toUTC()
const stop = DateTime.fromISO(item.EndDate, { zone: 'Europe/Lisbon' }).toUTC()
const prog = {
title: item.name || 'Sem título',
title: item.Title || 'Sem título',
start,
stop
}
if (description) prog.description = description
if (image) {
if (item.Synopsis) {
prog.description = item.Synopsis
}
// Construct image URL using the same logic as before if possible
if (item.Title && channel.site_id) {
const encodedTitle = encodeURIComponent(item.Title)
const image = `https://proxycache.online.meo.pt/eemstb/ImageHandler.ashx?evTitle=${encodedTitle}&chCallLetter=${channel.site_id}&profile=16_9&width=600`
prog.icon = { src: image }
prog.image = image
}
programs.push(prog)
}
@@ -70,84 +60,45 @@ module.exports = {
async channels() {
const axios = require('axios')
const data = await axios
.post('https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getGridAnon', null, {
.get('https://meogouser.apps.meo.pt/Services/GridTv/GridTv.svc/GetContentsForChannels?userAgent=IPTV_OFR_GTV', {
headers: {
Origin: 'https://www.meo.pt',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; en-US Trident/4.0)'
'accept': '*/*',
'accept-language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,cs;q=0.5',
'cache-control': 'no-cache',
'origin': 'https://www.meo.pt',
'pragma': 'no-cache',
'priority': 'u=1, i',
'referer': 'https://www.meo.pt/',
'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144"',
'sec-ch-ua-mobile': '?1',
'sec-ch-ua-platform': '"Android"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36'
}
})
.then(r => r.data)
.catch(console.log)
// channel logo at data.d.channels.logo
return data.d.channels
return data.Result
.map(item => {
return {
lang: 'pt',
site_id: item.sigla,
name: item.name
site_id: item.CallLetter,
name: item.Title
}
})
.filter(channel => channel.site_id)
}
}
function parseStart(item) {
return DateTime.fromFormat(`${item.date} ${item.timeIni}`, 'd-M-yyyy HH:mm', {
zone: 'Europe/Lisbon'
}).toUTC()
}
function parseStop(item) {
return DateTime.fromFormat(`${item.date} ${item.timeEnd}`, 'd-M-yyyy HH:mm', {
zone: 'Europe/Lisbon'
}).toUTC()
}
function parseItems(content) {
if (!content) return []
const data = JSON.parse(content)
const programs = data?.d?.channels?.[0]?.programs
return Array.isArray(programs) ? programs : []
}
async function fetchProgramDetails(programID, axiosInstance) {
try {
const response = await axiosInstance.post(
'https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramDetails',
{
service: 'programdetail',
programID: String(programID),
accountID: ''
},
{
headers: {
Origin: 'https://www.meo.pt',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; en-US Trident/4.0)'
},
timeout: 10000
}
)
const data = response.data
// Response structure has program data directly in data.d
const program = data?.d
if (!program || typeof program !== 'object') return null
// Build image URL using MEO's image handler
let image = null
if (program.progName && program.channelSigla) {
const encodedTitle = encodeURIComponent(program.progName)
image = `https://proxycache.online.meo.pt/eemstb/ImageHandler.ashx?evTitle=${encodedTitle}&chCallLetter=${program.channelSigla}&profile=16_9&width=600`
}
const description = program.description || null
return { description, image }
const data = typeof content === 'string' ? JSON.parse(content) : content
return Array.isArray(data.Result) ? data.Result : []
} catch {
// Silent fail returning null so parser continues
return null
return []
}
}
+15 -20
View File
@@ -18,37 +18,28 @@ const channel = {
}
it('can generate valid url', () => {
expect(url).toBe(
'https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramsFromChannels'
expect(url({ channel, date })).toBe(
'https://meogouser.apps.meo.pt/Services/GridTv/GridTv.svc/GetLiveChannelProgramsByDate?callLetter=RTPM&date=2022-12-02&userAgent=IPTV_OFR_GTV'
)
})
it('can generate valid request method', () => {
expect(request.method).toBe('POST')
expect(request.method).toBe('GET')
})
it('can generate valid request headers', () => {
expect(request.headers).toMatchObject({
Origin: 'https://www.meo.pt'
})
})
it('can generate valid request method', () => {
expect(request.data({ channel, date })).toMatchObject({
service: 'channelsguide',
channels: ['RTPM'],
dateStart: '2022-12-02T00:00:00-00:00',
dateEnd: '2022-12-03T00:00:00-00:00',
accountID: ''
'origin': 'https://www.meo.pt',
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36'
})
})
it('can parse response', async () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf-8')
axios.post.mockResolvedValue({ data: {} })
axios.get.mockResolvedValue({ data: {} })
let results = await parser({ content })
let results = await parser({ content, channel })
results = results.map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
@@ -56,9 +47,13 @@ it('can parse response', async () => {
})
expect(results[0]).toMatchObject({
start: '2022-12-01T23:35:00.000Z',
stop: '2022-12-02T00:17:00.000Z',
title: 'Walker, O Ranger Do Texas T6 - Ep. 14'
start: '2026-01-22T23:40:00.000Z',
stop: '2026-01-23T00:04:00.000Z',
title: 'Barman - Ep. 4',
description: "'Barman' é uma série de comédia dramática sobre um jovem comediante que começa a trabalhar como Barman porque precisa de arranjar dinheiro depressa, pelo caminho é obrigado a lidar com a vida noturna e conciliar duas realidades diferentes.",
icon: {
src: 'https://proxycache.online.meo.pt/eemstb/ImageHandler.ashx?evTitle=Barman%20-%20Ep.%204&chCallLetter=RTPM&profile=16_9&width=600'
}
})
})
+67 -1
View File
@@ -1 +1,67 @@
[{"CoreId":"2023121151009543","AssetId":"EPGE2023121151009543","ContentId":"epg@2023121151009543","ProgramId":"3011502","AggregatorId":"2967456","DateFullEventId":"2023121151009543","GridItemsLink":"/v2/browse/epg@2023121151009543/grid/items","PlayListTrayItemLink":"/v1/contents/epg@2023121151009543/PlayListTray/items","UtcDateTimeStart":"2023-12-11T16:30:00Z","UtcDateTimeEnd":"2023-12-11T17:00:00Z","Type":4,"IsAdult":false,"AiringChannel":{"IsOnline":true,"IsTimeWarpable":true,"IsRestartable":true,"ServiceId":"510","ChannelId":"510","AssetId":"EPGC510","Name":"S+ HD","RatingDisplay":"M3","DvbLocator":"dvb://36.4C.835","Rating":20,"Position":129,"QualityVersion":2,"Images":[{"ImageId":"SAUDEMAIS.png","Url":"http://vip.repositories.local.internal/Repositories.EPG/OttChannelIcons/SAUDEMAIS.png","Type":16}]},"Metadata":{"Title":"Village Vets","SubTitle":"","RatingDisplay":"NC","GenreDisplay":"Reality TV","SeriesId":"142241","Description":"A história de dois melhores amigos veterinários e o seu extraordinário trabalho na Austrália.","ReleaseYear":"2014","Rating":0,"Season":1,"Episode":12,"Duration":30,"ProgramId":3011502,"AggregatorId":2967456,"IsNPVR":true,"IsStartOver":true},"Images":[{"ImageId":"8329ed1aec5d4c0faa2056972256ff9f","Url":"http://vip.pam.local.internal/PAM.Images/Store/8329ed1aec5d4c0faa2056972256ff9f","Type":1}]},{"CoreId":"2023121151009544","AssetId":"EPGE2023121151009544","ContentId":"epg@2023121151009544","ProgramId":"3161537","AggregatorId":"2165665","DateFullEventId":"2023121151009544","GridItemsLink":"/v2/browse/epg@2023121151009544/grid/items","PlayListTrayItemLink":"/v1/contents/epg@2023121151009544/PlayListTray/items","UtcDateTimeStart":"2023-12-11T17:00:00Z","UtcDateTimeEnd":"2023-12-11T18:00:00Z","Type":4,"IsAdult":false,"AiringChannel":{"IsOnline":true,"IsTimeWarpable":true,"IsRestartable":true,"ServiceId":"510","ChannelId":"510","AssetId":"EPGC510","Name":"S+ HD","RatingDisplay":"M3","DvbLocator":"dvb://36.4C.835","Rating":20,"Position":129,"QualityVersion":2,"Images":[{"ImageId":"SAUDEMAIS.png","Url":"http://vip.repositories.local.internal/Repositories.EPG/OttChannelIcons/SAUDEMAIS.png","Type":16}]},"Metadata":{"Title":"Histórias Clínicas","SubTitle":"Associações","RatingDisplay":"M12","GenreDisplay":"Saúde","SeriesId":"102905","Description":"Processo de Decisão Clínica.","ReleaseYear":"2018","Rating":80,"Season":7,"Episode":13,"Duration":60,"ProgramId":3161537,"AggregatorId":2165665,"IsNPVR":true,"IsStartOver":true},"Images":[{"ImageId":"818dba4817a7464f9e8433620270b01d","Url":"http://vip.pam.local.internal/PAM.Images/Store/818dba4817a7464f9e8433620270b01d","Type":1}]},{"CoreId":"2023121151009545","AssetId":"EPGE2023121151009545","ContentId":"epg@2023121151009545","ProgramId":"3357379","AggregatorId":"2182966","DateFullEventId":"2023121151009545","GridItemsLink":"/v2/browse/epg@2023121151009545/grid/items","PlayListTrayItemLink":"/v1/contents/epg@2023121151009545/PlayListTray/items","UtcDateTimeStart":"2023-12-11T18:00:00Z","UtcDateTimeEnd":"2023-12-11T19:00:00Z","Type":4,"IsAdult":false,"AiringChannel":{"IsOnline":true,"IsTimeWarpable":true,"IsRestartable":true,"ServiceId":"510","ChannelId":"510","AssetId":"EPGC510","Name":"S+ HD","RatingDisplay":"M3","DvbLocator":"dvb://36.4C.835","Rating":20,"Position":129,"QualityVersion":2,"Images":[{"ImageId":"SAUDEMAIS.png","Url":"http://vip.repositories.local.internal/Repositories.EPG/OttChannelIcons/SAUDEMAIS.png","Type":16}]},"Metadata":{"Title":"Corpo Clínico","SubTitle":"","RatingDisplay":"Todos","GenreDisplay":"Saúde","SeriesId":"103390","Description":"Farmacovigilância.","ReleaseYear":"2018","Rating":1,"Season":12,"Episode":5,"Duration":60,"ProgramId":3357379,"AggregatorId":2182966,"IsNPVR":true,"IsStartOver":true},"Images":[{"ImageId":"a060ca5930444d3a864ad20615e7df33","Url":"http://vip.pam.local.internal/PAM.Images/Store/a060ca5930444d3a864ad20615e7df33","Type":1}]},{"CoreId":"2023121151009546","AssetId":"EPGE2023121151009546","ContentId":"epg@2023121151009546","ProgramId":"3364579","AggregatorId":"3161534","DateFullEventId":"2023121151009546","GridItemsLink":"/v2/browse/epg@2023121151009546/grid/items","PlayListTrayItemLink":"/v1/contents/epg@2023121151009546/PlayListTray/items","UtcDateTimeStart":"2023-12-11T19:00:00Z","UtcDateTimeEnd":"2023-12-11T20:00:00Z","Type":4,"IsAdult":false,"AiringChannel":{"IsOnline":true,"IsTimeWarpable":true,"IsRestartable":true,"ServiceId":"510","ChannelId":"510","AssetId":"EPGC510","Name":"S+ HD","RatingDisplay":"M3","DvbLocator":"dvb://36.4C.835","Rating":20,"Position":129,"QualityVersion":2,"Images":[{"ImageId":"SAUDEMAIS.png","Url":"http://vip.repositories.local.internal/Repositories.EPG/OttChannelIcons/SAUDEMAIS.png","Type":16}]},"Metadata":{"Title":"Caixa de Pandora","SubTitle":"","RatingDisplay":"M12","GenreDisplay":"Talk-Show","SeriesId":"152921","Description":"Programa de 45 minutos, em estúdio, que reúne 4 mulheres de diversas idades e backgrounds que conversam todas as seLine truncated
[
{
"CoreId": "2026012313905035",
"AssetId": "EPGE2026012313905035",
"ContentId": "epg@2026012313905035",
"ProgramId": "3805166",
"AggregatorId": "2649043",
"DateFullEventId": "2026012313905035",
"GridItemsLink": "/v2/browse/epg@2026012313905035/grid/items",
"PlayListTrayItemLink": "/v1/contents/epg@2026012313905035/PlayListTray/items",
"DetailNodeItemNavLink": "/nodeitems/epg@2026012313905035/detail?context=schedule",
"UtcDateTimeStart": "2026-01-23T22:39:00Z",
"UtcDateTimeEnd": "2026-01-24T00:23:00Z",
"Type": 4,
"IsAdult": false,
"AiringChannel": {
"IsOnline": true,
"IsTimeWarpable": true,
"IsRestartable": true,
"ServiceId": "139",
"ChannelId": "5",
"AssetId": "EPGC139",
"Name": "RTP 1 HD",
"RatingDisplay": "M3",
"DvbLocator": "dvb://36.4E.1E79",
"Rating": 20,
"Position": 1,
"QualityVersion": 2,
"Images": [
{
"ImageId": "RTPHD.png",
"Type": 16,
"Url": "http://vip.repositories.local.internal/Repositories.EPG/OttChannelIcons/RTPHD.png"
}
]
},
"Metadata": {
"Title": "Em Casa d'Amália",
"SubTitle": "",
"RatingDisplay": "M6",
"GenreDisplay": "Talk-Show",
"SeriesId": "124075",
"Description": "Que mais poderíamos pedir para o regresso deste programa, do que receber um dos poetas de Amália? Manuel Alegre, autor do icónico \"Trova do Vento que Passa\", estará connosco. A este raro momento, juntam-se também ilustres convidados: Paulo de Carvalho e o seu filho Agir, Rita Guerra e André Amaro...",
"ReleaseYear": "2025",
"Rating": 60,
"Season": 9,
"Episode": 15,
"Duration": 104,
"ProgramId": 3805166,
"AggregatorId": 2649043,
"IsNPVR": true,
"IsStartOver": true
},
"Images": [
{
"ImageId": "901d96a8f1534749b076212c296d821e",
"Type": 1,
"Url": "http://vip.pam.local.internal/PAM.Images/Store/901d96a8f1534749b076212c296d821e"
},
{
"ImageId": "4de2fbd7177c4e7c8cc9faf703b119b5",
"Type": 38,
"Url": "http://vip.pam.local.internal/PAM.Images/Store/4de2fbd7177c4e7c8cc9faf703b119b5"
}
]
}
]
+23 -14
View File
@@ -5,24 +5,33 @@ const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const headers = {
'X-Apikey': 'xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI',
'X-Core-Appversion': '2.20.0.3',
'X-Core-Contentratinglimit': '0',
'X-Core-Deviceid': '',
'X-Core-Devicetype': 'web',
Origin: 'https://nostv.pt',
'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': 'application/json, text/plain, */*',
'accept-language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,cs;q=0.5',
'cache-control': 'no-cache',
'origin': 'https://nostv.pt',
'pragma': 'no-cache',
'priority': 'u=1, i',
'referer': 'https://nostv.pt/',
'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144"',
'sec-ch-ua-mobile': '?1',
'sec-ch-ua-platform': '"Android"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site',
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36',
'x-apikey': 'xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI',
'x-core-appversion': '2.20.2.2',
'x-core-contentratinglimit': '0',
'x-core-deviceid': '',
'x-core-devicetype': 'web',
'x-core-timezoneoffset': '3600000'
}
module.exports = {
site: 'nostv.pt',
days: 2,
url({ channel, date }) {
return `https://api.clg.nos.pt/nostv/ott/schedule/range/contents/guest?channels=${channel.site_id
}&minDate=${date.format('YYYY-MM-DD')}T00:00:00Z&maxDate=${date.format(
'YYYY-MM-DD'
)}T23:59:59Z&isDateInclusive=true&client_id=${headers['X-Apikey']}`
return `https://api.clg.nos.pt/nostv/ott/schedule/range/contents/guest?channels=${channel.site_id}&minDate=${date.format('YYYY-MM-DD')}T00:00:00Z&maxDate=${date.format('YYYY-MM-DD')}T23:59:59Z&isDateInclusive=true&client_id=${headers['x-apikey']}`
},
request: { headers },
parser({ content }) {
@@ -31,7 +40,7 @@ module.exports = {
const items = Array.isArray(content) ? content : JSON.parse(content)
items.forEach(item => {
const image = item.Images
? `https://mage.stream.nos.pt/mage/v1/Images?sourceUri=${item.Images[0].Url}&profile=ott_1_452x340&client_id=${headers['X-Apikey']}`
? `https://mage.stream.nos.pt/mage/v1/Images?sourceUri=${item.Images[0].Url}&profile=ott_1_452x340&client_id=${headers['x-apikey']}`
: null
programs.push({
title: item.Metadata?.Title,
@@ -54,7 +63,7 @@ module.exports = {
async channels() {
const result = await axios
.get(
`https://api.clg.nos.pt/nostv/ott/channels/guest?client_id=${headers['X-Apikey']}`,
`https://api.clg.nos.pt/nostv/ott/channels/guest?client_id=${headers['x-apikey']}`,
{ headers }
)
.then(r => r.data)
+8 -11
View File
@@ -28,20 +28,17 @@ it('can parse response', () => {
return p
})
const image = 'https://mage.stream.nos.pt/mage/v1/Images?sourceUri=http://vip.pam.local.internal/PAM.Images/Store/8329ed1aec5d4c0faa2056972256ff9f&profile=ott_1_452x340&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
expect(results[0]).toMatchObject({
start: '2023-12-11T16:30:00.000Z',
stop: '2023-12-11T17:00:00.000Z',
title: 'Village Vets',
description:
'A história de dois melhores amigos veterinários e o seu extraordinário trabalho na Austrália.',
season: 1,
episode: 12,
start: '2026-01-23T22:39:00.000Z',
stop: '2026-01-24T00:23:00.000Z',
title: 'Em Casa d\'Amália',
description: 'Que mais poderíamos pedir para o regresso deste programa, do que receber um dos poetas de Amália? Manuel Alegre, autor do icónico "Trova do Vento que Passa", estará connosco. A este raro momento, juntam-se também ilustres convidados: Paulo de Carvalho e o seu filho Agir, Rita Guerra e André Amaro...',
season: 9,
episode: 15,
icon: {
src: image
src: 'https://mage.stream.nos.pt/mage/v1/Images?sourceUri=http://vip.pam.local.internal/PAM.Images/Store/901d96a8f1534749b076212c296d821e&profile=ott_1_452x340&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
},
image
image: 'https://mage.stream.nos.pt/mage/v1/Images?sourceUri=http://vip.pam.local.internal/PAM.Images/Store/901d96a8f1534749b076212c296d821e&profile=ott_1_452x340&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
})
})