Files
epg/sites/toonamiaftermath.com/toonamiaftermath.com.config.js
T
2026-07-08 07:59:37 +07:00

150 lines
4.3 KiB
JavaScript

const fs = require('fs')
const path = require('path')
const https = require('https')
const axios = require('axios')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const API_ENDPOINT = 'https://api.toonamiaftermath.com'
// Let's Encrypt YR1 and YR2 will be expired on Sep 2 23:59:59 2028 GMT
const certfile = path.join(__dirname, '__data__', 'certificate.pem')
const httpsAgent = new https.Agent({ ca: fs.readFileSync(certfile) })
const caches = {}
module.exports = {
site: 'toonamiaftermath.com',
days: 3,
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 day
},
httpsAgent
},
async url({ channel, date }) {
return await getUrl(channel, date)
},
async parser({ channel, date, content }) {
const programs = []
const delay = parseInt(channel.site_id.split('+')[1]) || 0
const cdate = date.startOf('d')
const items = parseItems(content)
// fetch other playlist URLs if exist
if (items.length && Array.isArray(date.urls)) {
for (const url of date.urls) {
if (caches[url] !== undefined) {
items.push(...caches[url])
} else {
const result = await axios.get(url, { httpsAgent })
.then(res => res.data)
.catch(console.error)
const newItems = parseItems(result)
caches[url] = newItems
items.push(...newItems)
}
}
}
items.forEach(item => {
const start = getDate(item.startDate, delay)
const stop = getDate(item.endDate, delay)
if (isDate(start, cdate) || isDate(stop, cdate, true)) {
programs.push({
title: item.name,
description: item.info?.fullname,
sub_title: item.info?.episode,
image: item.info?.image,
start,
stop
})
}
})
return programs
},
async channels() {
const channels = []
const result = await axios.get('https://www.toonamiaftermath.com/bundle.js')
.then(res => res.data)
.catch(err => console.error(err.toString()))
const matches = result.match(/channels:(\[.*?\]),siteConfigs:/)
if (matches[1]) {
const vm = require('vm')
const items = vm.runInNewContext(`const o=${matches[1]}; o`)
if (Array.isArray(items)) {
channels.push(...items
.filter(item => item.scheduleName)
.map(item => ({
lang: 'en',
site_id: `${item.scheduleName}${item.streamDelay ? '+' + item.streamDelay : ''}`,
name: item.name
}))
)
}
}
return channels
}
}
async function getUrl(channel, date) {
const scheduleName = channel.site_id.split('+')[0]
const url = new URL(`${API_ENDPOINT}/playlists?scheduleName=${
scheduleName
}&startDate=${
date.startOf('d').toJSON()
}&thisWeek=true&weekStartDay=monday`)
const playlists = await axios.get(url.toString(), { httpsAgent })
.then(res => res.data)
.catch(err => console.error(err.toString()))
const urls = []
if (Array.isArray(playlists)) {
const dt = date.startOf('d')
playlists
.filter(p => isDate(getDate(p.startDate), dt) || isDate(getDate(p.endDate), dt, true))
.forEach(p => {
urls.push(`${API_ENDPOINT}/playlist?id=${p._id}&addInfo=true`)
})
}
if (!urls.length) {
throw new Error(`Unable to get schedule URL for ${scheduleName}!`)
}
const playlistUrl = urls.shift()
if (urls.length) {
// pass next playlist URLs in date object
date.urls = urls
}
return playlistUrl
}
function getDate(dt, delay = 0) {
return dayjs.utc(dt).add(delay, 'm')
}
function isDate(dt, ref, end) {
return dt.isSame(ref, 'd') && (end ? dt > ref : true)
}
function parseItems(content) {
if (!content) return []
if (typeof content === 'string' || Buffer.isBuffer(content)) {
content = JSON.parse(content)
}
if (!content || !content.playlist) return []
return content.playlist.blocks.reduce((acc, curr) => {
// short media type has no title, use block title instead
curr.mediaList.forEach(media => {
if (media.name === undefined) {
media.name = curr.name
}
})
return acc.concat(curr.mediaList)
}, [])
}