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 crypto = require('crypto')
const dayjs = require('dayjs')
const API_STATIC_ENDPOINT = 'https://static.spark.magentatv.at/deu/web/epg-service-lite/at'
const API_PROD_ENDPOINT = 'https://prod.spark.magentatv.at/deu/web/linear-service/v2'
const API_ENDPOINT = 'https://tv-at-prod.yo-digital.com/at-bifrost'
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 = {
site: 'magentatv.at',
days: 2,
request: {
headers,
cache: {
ttl: 60 * 60 * 1000 // 1 hour
}
},
url: function ({ date }) {
return `${API_STATIC_ENDPOINT}/de/events/segments/${date.format('YYYYMMDDHHmmss')}`
url: function ({ channel, date }) {
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 }) {
let programs = []
let items = parseItems(content, channel)
if (!content) return programs
let items = parseItems(JSON.parse(content), channel)
if (!items.length) return programs
const promises = [
axios.get(
`${API_STATIC_ENDPOINT}/de/events/segments/${date.add(6, 'h').format('YYYYMMDDHHmmss')}`,
{
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'
}
)
]
const promises = [3, 6, 9, 12, 15, 18, 21].map(i =>
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}))
await Promise.allSettled(promises)
.then(results => {
@ -55,16 +49,16 @@ module.exports = {
for (let item of items) {
const detail = await loadProgramDetails(item)
programs.push({
title: item.title,
sub_title: detail.episodeName,
description: detail.longDescription,
date: detail.productionDate,
category: detail.genres,
actors: detail.actors,
directors: detail.directors,
producers: detail.producers,
season: parseSeason(detail),
episode: parseEpisode(detail),
title: item.description,
description: parseDescription(detail),
date: parseDate(item),
category: parseCategory(item),
icon: detail.poster_image_url,
actors: parseRoles(detail, 'Schauspieler'),
directors: parseRoles(detail, 'Regisseur'),
producers: parseRoles(detail, 'Produzent'),
season: parseSeason(item),
episode: parseEpisode(item),
start: parseStart(item),
stop: parseStop(item)
})
@ -74,57 +68,74 @@ module.exports = {
},
async channels() {
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)
.catch(console.log)
return data.channels.map(item => {
return {
lang: 'de',
site_id: item.id,
name: item.name
site_id: item.station_id,
name: item.title
}
})
}
}
async function loadProgramDetails(item) {
if (!item.id) return {}
const url = `${API_PROD_ENDPOINT}/replayEvent/${item.id}?returnLinearContent=true`
if (!item.program_id) return {}
const url = `${API_ENDPOINT}/details/series/${item.program_id}?natco_code=at`
const data = await axios
.get(url)
.get(url, {headers})
.then(r => r.data)
.catch(console.log)
return data || {}
}
function parseDate(item) {
return item && item.release_year ? item.release_year.toString() : null
}
function parseStart(item) {
return dayjs.unix(item.startTime)
return dayjs(item.start_time)
}
function parseStop(item) {
return dayjs.unix(item.endTime)
return dayjs(item.end_time)
}
function parseItems(content, channel) {
if (!content) return []
const data = JSON.parse(content)
if (!data || !Array.isArray(data.entries)) return []
const channelData = data.entries.find(e => e.channelId === channel.site_id)
function parseItems(data, channel) {
if (!data || !data.channels) return []
const channelData = data.channels[channel.site_id]
if (!channelData) return []
return Array.isArray(channelData.events) ? channelData.events : []
return channelData
}
function parseSeason(detail) {
if (!detail.seasonNumber) return null
if (String(detail.seasonNumber).length > 2) return null
return detail.seasonNumber
function parseCategory(item) {
if (!item.genres) return null
return item.genres.map(genre => genre.id)
}
function parseEpisode(detail) {
if (!detail.episodeNumber) return null
if (String(detail.episodeNumber).length > 3) return null
return detail.episodeNumber
function parseSeason(item) {
if(item.season_display_number === 'Folgen') return null
return item.season_number
}
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(utc)
const API_STATIC_ENDPOINT = 'https://static.spark.magentatv.at/deu/web/epg-service-lite/at'
const API_PROD_ENDPOINT = 'https://prod.spark.magentatv.at/deu/web/linear-service/v2'
const API_ENDPOINT = 'https://tv-at-prod.yo-digital.com/at-bifrost'
jest.mock('axios')
const date = dayjs.utc('2022-10-30', 'YYYY-MM-DD').startOf('d')
const channel = {
site_id: '13TH_STREET_HD',
site_id: '206969383991',
xmltv_id: '13thStreet.de',
lang: 'de'
}
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 () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content_0000.json'))
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({
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({
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({
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 (
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({
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/program.json')))
@ -63,30 +78,34 @@ it('can parse response', async () => {
})
expect(results[0]).toMatchObject({
start: '2022-10-29T23:55:00.000Z',
stop: '2022-10-30T01:40:00.000Z',
title: 'Law & Order: Special Victims Unit',
sub_title: 'Mutterinstinkt',
start: '2023-11-14T23:20:00.000Z',
stop: '2023-11-15T00:05:00.000Z',
title: 'So Help Me Todd',
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?',
date: '2004',
category: ['Drama-Serie', 'Krimi Drama', 'Action', 'Thriller'],
'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: '2023',
category: ['Kriminaldrama'],
actors: [
'Christopher Meloni',
'Mariska Hargitay',
'Richard Belzer',
'Dann Florek',
'Ice-T',
'BD Wong',
'Diane Neal',
'Tamara Tunie',
'Abigail Breslin',
'Lea Thompson'
'Marcia Gay Harden',
'Skylar Astin',
'Madeline Wise',
'Tristen J. Winger',
'Inga Schlingmann',
'Rosa Evangelina Arredondo',
'Laila Robins'
],
directors: ['Arthur W. Forney'],
producers: ['Dick Wolf', 'Ted Kotcheff', 'Neal Baer'],
season: 6,
episode: 1
directors: ['Jay Karas'],
producers: [
'Scott Prendergast',
'Liz Kruger',
'Elizabeth Klaviter',
'Dr. Phil McGraw',
'Jay McGraw',
'Julia Eisenman',
'Amy York Rubin'
],
season: 1,
episode: 15
})
})