Merge pull request #2231 from GenericMale/fix-magentatv.at

Fix magentatv.at
This commit is contained in:
Aleksandr Statciuk 2023-11-17 18:05:23 +03:00 committed by GitHub
commit a50649775f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 126 additions and 92 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
{"imageVersion":"1cjcfg","eventId":"crid:~~2F~~2Fgn.tv~~2F2236391~~2FEP019388320252,imi:af4af994f29354e64878101c0612b17999d0c1a3","channelId":"13TH_STREET_HD","title":"Law & Order: Special Victims Unit","startTime":1667087700,"endTime":1667094000,"mergedId":"184536|de","minimumAge":"16","replayTvMinAge":16,"seriesId":"crid:~~2F~~2Fgn.tv~~2F7896816~~2FSH019388320000","parentSeriesId":"crid:~~2F~~2Fbds.tv~~2F14625541","episodeName":"Mutterinstinkt","seasonNumber":6,"episodeNumber":1,"shortDescription":"Patty Branson wird von einem Jungen in einem Park angegriffen und von diesem verfolgt. Der Junge wurde von Michelle Osborne engagiert, die vorgibt, die leibliche Mutter des Mädchens zu sein. Doch ist dies tatsächlich die Wahrheit?","longDescription":"Patty Branson wird von einem Jungen in einem Park angegriffen und von diesem verfolgt. Der Junge wurde von Michelle Osborne engagiert, die vorgibt, die leibliche Mutter des Mädchens zu sein. Doch ist dies tatsächlich die Wahrheit?","actors":["Christopher Meloni","Mariska Hargitay","Richard Belzer","Dann Florek","Ice-T","BD Wong","Diane Neal","Tamara Tunie","Abigail Breslin","Lea Thompson"],"directors":["Arthur W. Forney"],"producers":["Dick Wolf","Ted Kotcheff","Neal Baer"],"audioLanguages":[{"lang":"de"}],"productionDate":"2004","countryOfOrigin":"US","genres":["Drama-Serie","Krimi Drama","Action","Thriller"],"seriesPremiereAirings":true} {"id":"gn.tv-24101298-EP048489190016","name":"So Help Me Todd","episodes_count":null,"seasons_count":0,"poster_image_url":"https://tv-at-prod.yo-digital.com/prod/images/1422/800/p24101298_e_h8_ae.jpg","is_live":true,"show_type":"TVShow","release_year":2023,"end_year":null,"ratings":"12","is_adult":false,"trailer":[],"details":{"description":"Ava ist 17 und eine geniale Hackerin. Jetzt steht die Teenagerin vor Gericht, weil sie sich illegal Zugang zum Verteidigungsministerium verschafft hat. Todd soll das IT-Genie überwachen.","metadata":[{"name":"Genres","value":"Kriminaldrama","type":"GENRES"}]},"locale":"","last_updated":"1699163343000","seasons":[],"roles":[{"role_name":"Schauspieler","person_id":"74131","person_name":"Marcia Gay Harden","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/74131_v9_bb.jpg"},{"role_name":"Schauspieler","person_id":"517088","person_name":"Skylar Astin","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/517088_v9_bc.jpg"},{"role_name":"Schauspieler","person_id":"1210251","person_name":"Madeline Wise","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/1210251_v9_aa.jpg"},{"role_name":"Schauspieler","person_id":"703443","person_name":"Tristen J. Winger","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/703443_v9_aa.jpg"},{"role_name":"Schauspieler","person_id":"1200248","person_name":"Inga Schlingmann","image_url":null},{"role_name":"Schauspieler","person_id":"230208","person_name":"Rosa Evangelina Arredondo","image_url":null},{"role_name":"Schauspieler","person_id":"37735","person_name":"Laila Robins","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/37735_v9_bc.jpg"},{"role_name":"Produzent","person_id":"290831","person_name":"Scott Prendergast","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/290831_v9_aa.jpg"},{"role_name":"Produzent","person_id":"195655","person_name":"Liz Kruger","image_url":null},{"role_name":"Produzent","person_id":"491285","person_name":"Elizabeth Klaviter","image_url":null},{"role_name":"Produzent","person_id":"287585","person_name":"Dr. Phil McGraw","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/287585_v9_bb.jpg"},{"role_name":"Produzent","person_id":"299674","person_name":"Jay McGraw","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/299674_v9_bb.jpg"},{"role_name":"Produzent","person_id":"497742","person_name":"Julia Eisenman","image_url":null},{"role_name":"Produzent","person_id":"1117587","person_name":"Amy York Rubin","image_url":null},{"role_name":"Drehbuchautor","person_id":"1242913","person_name":"Steven Paul Martinez","image_url":null},{"role_name":"Regisseur","person_id":"530202","person_name":"Jay Karas","image_url":"https://tv-at-prod.yo-digital.com/prod/images/cast/548/728/530202_v9_ba.jpg"}],"cache_ttl":null,"data_source":"CTS"}

View file

@ -1,44 +1,38 @@
const axios = require('axios') const axios = require('axios')
const crypto = require('crypto')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const API_STATIC_ENDPOINT = 'https://static.spark.magentatv.at/deu/web/epg-service-lite/at' const API_ENDPOINT = 'https://tv-at-prod.yo-digital.com/at-bifrost'
const API_PROD_ENDPOINT = 'https://prod.spark.magentatv.at/deu/web/linear-service/v2'
const headers = {
'Device-Id': crypto.randomUUID(),
'app_key': 'CTnKA63ruKM0JM1doxAXwwyQLLmQiEiy',
'app_version': '02.0.830',
'X-User-Agent': 'web|web|Firefox-120|02.0.830|1',
'x-request-tracking-id': crypto.randomUUID()
}
module.exports = { module.exports = {
site: 'magentatv.at', site: 'magentatv.at',
days: 2, days: 2,
request: { request: {
headers,
cache: { cache: {
ttl: 60 * 60 * 1000 // 1 hour ttl: 60 * 60 * 1000 // 1 hour
} }
}, },
url: function ({ date }) { url: function ({ channel, date }) {
return `${API_STATIC_ENDPOINT}/de/events/segments/${date.format('YYYYMMDDHHmmss')}` return `${API_ENDPOINT}/epg/channel/schedules/v2?station_ids=${channel.site_id}&date=${date.format('YYYY-MM-DD')}&hour_offset=${date.format('H')}&hour_range=3&natco_code=at`
}, },
async parser({ content, channel, date }) { async parser({ content, channel, date }) {
let programs = [] let programs = []
let items = parseItems(content, channel) if (!content) return programs
let items = parseItems(JSON.parse(content), channel)
if (!items.length) return programs if (!items.length) return programs
const promises = [
axios.get( const promises = [3, 6, 9, 12, 15, 18, 21].map(i =>
`${API_STATIC_ENDPOINT}/de/events/segments/${date.add(6, 'h').format('YYYYMMDDHHmmss')}`, axios.get(`${API_ENDPOINT}/epg/channel/schedules/v2?station_ids=${channel.site_id}&date=${date.format('YYYY-MM-DD')}&hour_offset=${i}&hour_range=3&natco_code=at`, {headers}))
{
responseType: 'arraybuffer'
}
),
axios.get(
`${API_STATIC_ENDPOINT}/de/events/segments/${date.add(12, 'h').format('YYYYMMDDHHmmss')}`,
{
responseType: 'arraybuffer'
}
),
axios.get(
`${API_STATIC_ENDPOINT}/de/events/segments/${date.add(18, 'h').format('YYYYMMDDHHmmss')}`,
{
responseType: 'arraybuffer'
}
)
]
await Promise.allSettled(promises) await Promise.allSettled(promises)
.then(results => { .then(results => {
@ -55,16 +49,16 @@ module.exports = {
for (let item of items) { for (let item of items) {
const detail = await loadProgramDetails(item) const detail = await loadProgramDetails(item)
programs.push({ programs.push({
title: item.title, title: item.description,
sub_title: detail.episodeName, description: parseDescription(detail),
description: detail.longDescription, date: parseDate(item),
date: detail.productionDate, category: parseCategory(item),
category: detail.genres, icon: detail.poster_image_url,
actors: detail.actors, actors: parseRoles(detail, 'Schauspieler'),
directors: detail.directors, directors: parseRoles(detail, 'Regisseur'),
producers: detail.producers, producers: parseRoles(detail, 'Produzent'),
season: parseSeason(detail), season: parseSeason(item),
episode: parseEpisode(detail), episode: parseEpisode(item),
start: parseStart(item), start: parseStart(item),
stop: parseStop(item) stop: parseStop(item)
}) })
@ -74,57 +68,74 @@ module.exports = {
}, },
async channels() { async channels() {
const data = await axios const data = await axios
.get(`${API_PROD_ENDPOINT}/channels?cityId=65535&language=de&productClass=Orion-DASH`) .get(`${API_ENDPOINT}/epg/channel?natco_code=at`, {headers})
.then(r => r.data) .then(r => r.data)
.catch(console.log) .catch(console.log)
return data.channels.map(item => { return data.channels.map(item => {
return { return {
lang: 'de', lang: 'de',
site_id: item.id, site_id: item.station_id,
name: item.name name: item.title
} }
}) })
} }
} }
async function loadProgramDetails(item) { async function loadProgramDetails(item) {
if (!item.id) return {} if (!item.program_id) return {}
const url = `${API_PROD_ENDPOINT}/replayEvent/${item.id}?returnLinearContent=true` const url = `${API_ENDPOINT}/details/series/${item.program_id}?natco_code=at`
const data = await axios const data = await axios
.get(url) .get(url, {headers})
.then(r => r.data) .then(r => r.data)
.catch(console.log) .catch(console.log)
return data || {} return data || {}
} }
function parseDate(item) {
return item && item.release_year ? item.release_year.toString() : null
}
function parseStart(item) { function parseStart(item) {
return dayjs.unix(item.startTime) return dayjs(item.start_time)
} }
function parseStop(item) { function parseStop(item) {
return dayjs.unix(item.endTime) return dayjs(item.end_time)
} }
function parseItems(content, channel) { function parseItems(data, channel) {
if (!content) return [] if (!data || !data.channels) return []
const data = JSON.parse(content) const channelData = data.channels[channel.site_id]
if (!data || !Array.isArray(data.entries)) return []
const channelData = data.entries.find(e => e.channelId === channel.site_id)
if (!channelData) return [] if (!channelData) return []
return channelData
return Array.isArray(channelData.events) ? channelData.events : []
} }
function parseSeason(detail) { function parseCategory(item) {
if (!detail.seasonNumber) return null if (!item.genres) return null
if (String(detail.seasonNumber).length > 2) return null return item.genres.map(genre => genre.id)
return detail.seasonNumber
} }
function parseEpisode(detail) { function parseSeason(item) {
if (!detail.episodeNumber) return null if(item.season_display_number === 'Folgen') return null
if (String(detail.episodeNumber).length > 3) return null return item.season_number
return detail.episodeNumber }
function parseEpisode(item) {
if(item.episode_number) return parseInt(item.episode_number)
if(item.season_display_number === 'Folgen') return item.season_number
return null
}
function parseDescription(item) {
if (!item.details) return null
return item.details.description
}
function parseRoles(item, role_name) {
if (!item.roles) return null
return item.roles
.filter(role => role.role_name === role_name)
.map(role => role.person_name)
} }

View file

@ -11,41 +11,56 @@ const customParseFormat = require('dayjs/plugin/customParseFormat')
dayjs.extend(customParseFormat) dayjs.extend(customParseFormat)
dayjs.extend(utc) dayjs.extend(utc)
const API_STATIC_ENDPOINT = 'https://static.spark.magentatv.at/deu/web/epg-service-lite/at' const API_ENDPOINT = 'https://tv-at-prod.yo-digital.com/at-bifrost'
const API_PROD_ENDPOINT = 'https://prod.spark.magentatv.at/deu/web/linear-service/v2'
jest.mock('axios') jest.mock('axios')
const date = dayjs.utc('2022-10-30', 'YYYY-MM-DD').startOf('d') const date = dayjs.utc('2022-10-30', 'YYYY-MM-DD').startOf('d')
const channel = { const channel = {
site_id: '13TH_STREET_HD', site_id: '206969383991',
xmltv_id: '13thStreet.de', xmltv_id: '13thStreet.de',
lang: 'de' lang: 'de'
} }
it('can generate valid url', () => { it('can generate valid url', () => {
expect(url({ date })).toBe(`${API_STATIC_ENDPOINT}/de/events/segments/20221030000000`) expect(url({ date, channel })).toBe(`${API_ENDPOINT}/epg/channel/schedules/v2?station_ids=206969383991&date=2022-10-30&hour_offset=0&hour_range=3&natco_code=at`)
}) })
it('can parse response', async () => { it('can parse response', async () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content_0000.json')) const content = fs.readFileSync(path.resolve(__dirname, '__data__/content_0000.json'))
axios.get.mockImplementation(url => { axios.get.mockImplementation(url => {
if (url === `${API_STATIC_ENDPOINT}/de/events/segments/20221030060000`) { if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=0&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_0300.json'))
})
} else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=3&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({ return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_0600.json')) data: fs.readFileSync(path.resolve(__dirname, '__data__/content_0600.json'))
}) })
} else if (url === `${API_STATIC_ENDPOINT}/de/events/segments/20221030120000`) { } else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=6&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_0900.json'))
})
} else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=9&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({ return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_1200.json')) data: fs.readFileSync(path.resolve(__dirname, '__data__/content_1200.json'))
}) })
} else if (url === `${API_STATIC_ENDPOINT}/de/events/segments/20221030180000`) { } else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=12&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_1500.json'))
})
} else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=15&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({ return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_1800.json')) data: fs.readFileSync(path.resolve(__dirname, '__data__/content_1800.json'))
}) })
} else if (url === `${API_ENDPOINT}/epg/channel/schedules/v2?date=2023-11-15&hour_offset=18&hour_range=3&station_ids=206969383991&natco_code=at`) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/content_2100.json'))
})
} else if ( } else if (
url === url ===
`${API_PROD_ENDPOINT}/replayEvent/crid:~~2F~~2Fgn.tv~~2F2236391~~2FEP019388320252,imi:af4af994f29354e64878101c0612b17999d0c1a3?returnLinearContent=true` `${API_ENDPOINT}/details/series/gn.tv-24101298-EP048489190016?natco_code=at`
) { ) {
return Promise.resolve({ return Promise.resolve({
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/program.json'))) data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/program.json')))
@ -63,30 +78,34 @@ it('can parse response', async () => {
}) })
expect(results[0]).toMatchObject({ expect(results[0]).toMatchObject({
start: '2022-10-29T23:55:00.000Z', start: '2023-11-14T23:20:00.000Z',
stop: '2022-10-30T01:40:00.000Z', stop: '2023-11-15T00:05:00.000Z',
title: 'Law & Order: Special Victims Unit', title: 'So Help Me Todd',
sub_title: 'Mutterinstinkt',
description: description:
'Patty Branson wird von einem Jungen in einem Park angegriffen und von diesem verfolgt. Der Junge wurde von Michelle Osborne engagiert, die vorgibt, die leibliche Mutter des Mädchens zu sein. Doch ist dies tatsächlich die Wahrheit?', 'Ava ist 17 und eine geniale Hackerin. Jetzt steht die Teenagerin vor Gericht, weil sie sich illegal Zugang zum Verteidigungsministerium verschafft hat. Todd soll das IT-Genie überwachen.',
date: '2004', date: '2023',
category: ['Drama-Serie', 'Krimi Drama', 'Action', 'Thriller'], category: ['Kriminaldrama'],
actors: [ actors: [
'Christopher Meloni', 'Marcia Gay Harden',
'Mariska Hargitay', 'Skylar Astin',
'Richard Belzer', 'Madeline Wise',
'Dann Florek', 'Tristen J. Winger',
'Ice-T', 'Inga Schlingmann',
'BD Wong', 'Rosa Evangelina Arredondo',
'Diane Neal', 'Laila Robins'
'Tamara Tunie',
'Abigail Breslin',
'Lea Thompson'
], ],
directors: ['Arthur W. Forney'], directors: ['Jay Karas'],
producers: ['Dick Wolf', 'Ted Kotcheff', 'Neal Baer'], producers: [
season: 6, 'Scott Prendergast',
episode: 1 'Liz Kruger',
'Elizabeth Klaviter',
'Dr. Phil McGraw',
'Jay McGraw',
'Julia Eisenman',
'Amy York Rubin'
],
season: 1,
episode: 15
}) })
}) })