Skip to content

Commit dc86203

Browse files
Merge pull request #2907 from corrreia/more-data-meo.pt
More data meo.pt
2 parents 539613a + 0969125 commit dc86203

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
lines changed

sites/meo.pt/meo.pt.config.js

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,50 @@ module.exports = {
2020
}
2121
}
2222
},
23-
parser({ content }) {
23+
async parser({ content }) {
24+
const axios = require('axios')
2425
let programs = []
2526
const items = parseItems(content)
26-
items.forEach(item => {
27+
if (!items.length) return programs
28+
29+
// simple per-run in-memory cache
30+
const detailsCache = new Map()
31+
32+
for (const item of items) {
2733
const start = parseStart(item)
2834
let stop = parseStop(item)
2935
if (stop < start) {
3036
stop = stop.plus({ days: 1 })
3137
}
32-
programs.push({
33-
title: item.name,
38+
39+
let description = ''
40+
let image = ''
41+
42+
const programID = item.uniqueId || null
43+
if (programID) {
44+
let details = detailsCache.get(programID)
45+
if (!details) {
46+
details = await fetchProgramDetails(programID, axios).catch(() => null)
47+
if (details) detailsCache.set(programID, details)
48+
}
49+
if (details) {
50+
description = details.description || description
51+
image = details.image || image
52+
}
53+
}
54+
55+
const prog = {
56+
title: item.name || 'Sem título',
3457
start,
3558
stop
36-
})
37-
})
59+
}
60+
if (description) prog.description = description
61+
if (image) {
62+
prog.icon = { src: image }
63+
prog.image = image
64+
}
65+
programs.push(prog)
66+
}
3867

3968
return programs
4069
},
@@ -43,12 +72,15 @@ module.exports = {
4372
const data = await axios
4473
.post('https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getGridAnon', null, {
4574
headers: {
46-
Origin: 'https://www.meo.pt'
75+
Origin: 'https://www.meo.pt',
76+
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; en-US Trident/4.0)'
4777
}
4878
})
4979
.then(r => r.data)
5080
.catch(console.log)
5181

82+
// channel logo at data.d.channels.logo
83+
5284
return data.d.channels
5385
.map(item => {
5486
return {
@@ -80,3 +112,42 @@ function parseItems(content) {
80112

81113
return Array.isArray(programs) ? programs : []
82114
}
115+
116+
async function fetchProgramDetails(programID, axiosInstance) {
117+
try {
118+
const response = await axiosInstance.post(
119+
'https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramDetails',
120+
{
121+
service: 'programdetail',
122+
programID: String(programID),
123+
accountID: ''
124+
},
125+
{
126+
headers: {
127+
Origin: 'https://www.meo.pt',
128+
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; en-US Trident/4.0)'
129+
},
130+
timeout: 10000
131+
}
132+
)
133+
134+
const data = response.data
135+
// Response structure has program data directly in data.d
136+
const program = data?.d
137+
if (!program || typeof program !== 'object') return null
138+
139+
// Build image URL using MEO's image handler
140+
let image = null
141+
if (program.progName && program.channelSigla) {
142+
const encodedTitle = encodeURIComponent(program.progName)
143+
image = `https://proxycache.online.meo.pt/eemstb/ImageHandler.ashx?evTitle=${encodedTitle}&chCallLetter=${program.channelSigla}&profile=16_9&width=600`
144+
}
145+
146+
const description = program.description || null
147+
148+
return { description, image }
149+
} catch {
150+
// Silent fail returning null so parser continues
151+
return null
152+
}
153+
}

sites/meo.pt/meo.pt.test.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ const customParseFormat = require('dayjs/plugin/customParseFormat')
77
dayjs.extend(customParseFormat)
88
dayjs.extend(utc)
99

10+
const axios = require('axios')
11+
12+
jest.mock('axios')
13+
1014
const date = dayjs.utc('2022-12-02', 'YYYY-MM-DD').startOf('d')
1115
const channel = {
1216
site_id: 'RTPM',
@@ -39,9 +43,13 @@ it('can generate valid request method', () => {
3943
})
4044
})
4145

42-
it('can parse response', () => {
46+
it('can parse response', async () => {
4347
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
44-
let results = parser({ content }).map(p => {
48+
49+
axios.post.mockResolvedValue({ data: {} })
50+
51+
let results = await parser({ content })
52+
results = results.map(p => {
4553
p.start = p.start.toJSON()
4654
p.stop = p.stop.toJSON()
4755
return p
@@ -54,7 +62,7 @@ it('can parse response', () => {
5462
})
5563
})
5664

57-
it('can handle empty guide', () => {
58-
const result = parser({ content: '', channel, date })
65+
it('can handle empty guide', async () => {
66+
const result = await parser({ content: '', channel, date })
5967
expect(result).toMatchObject([])
6068
})

0 commit comments

Comments
 (0)