mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-10 09:00:07 -04:00
Merge pull request #2231 from GenericMale/fix-magentatv.at
Fix magentatv.at
This commit is contained in:
commit
a50649775f
11 changed files with 126 additions and 92 deletions
File diff suppressed because one or more lines are too long
1
sites/magentatv.at/__data__/content_0300.json
Normal file
1
sites/magentatv.at/__data__/content_0300.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
sites/magentatv.at/__data__/content_0900.json
Normal file
1
sites/magentatv.at/__data__/content_0900.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
sites/magentatv.at/__data__/content_1500.json
Normal file
1
sites/magentatv.at/__data__/content_1500.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
sites/magentatv.at/__data__/content_2100.json
Normal file
1
sites/magentatv.at/__data__/content_2100.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -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"}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue