mirror of
https://github.com/iptv-org/epg
synced 2026-06-30 12:17:11 -04:00
Properly generate TV schedule URL when redirected.
On www.tvpassport.com when schedule redirected to new URL, the requested date stripped from new URL so the fetched schedules only valid for current date. If URL was redirected, simply use the new URL with requested date appended. Signed-off-by: Toha <tohenk@yahoo.com>
This commit is contained in:
@@ -11,29 +11,24 @@ dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
const headers = {}
|
||||
|
||||
module.exports = {
|
||||
site: 'tvpassport.com',
|
||||
days: 3,
|
||||
url({ channel, date }) {
|
||||
return `https://www.tvpassport.com/tv-listings/stations/${channel.site_id}/${date.format(
|
||||
'YYYY-MM-DD'
|
||||
)}`
|
||||
async url({ channel, date }) {
|
||||
return await getSiteUrl(channel, date.format('YYYY-MM-DD'))
|
||||
},
|
||||
async request() {
|
||||
return {
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
Cookie: await getCookie()
|
||||
}
|
||||
}
|
||||
request: {
|
||||
timeout: 30000,
|
||||
headers
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
let programs = []
|
||||
const currentTimezone = parseCurrentTimezone(content)
|
||||
const items = parseItems(content)
|
||||
for (let item of items) {
|
||||
const $item = cheerio.load(item)
|
||||
const start = parseStart($item, currentTimezone)
|
||||
parser({ content }) {
|
||||
const programs = []
|
||||
const [$, tz, items] = parseItems(content)
|
||||
for (const item of items) {
|
||||
const $item = $(item)
|
||||
const start = parseStart($item, tz)
|
||||
const duration = parseDuration($item)
|
||||
const stop = start.add(duration, 'm')
|
||||
let title = parseTitle($item)
|
||||
@@ -85,7 +80,7 @@ module.exports = {
|
||||
await doFetch(queue, async (url, res) => {
|
||||
if (!res) return
|
||||
|
||||
const [, site_id] = url.match(/\/tv-listings\/stations\/(.*)$/)
|
||||
const site_id = getSiteId(url)
|
||||
|
||||
console.log(`[${i}/${total}]`, url)
|
||||
|
||||
@@ -109,63 +104,88 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
async function getCookie() {
|
||||
const res = await axios.get('https://www.tvpassport.com/tv-listings')
|
||||
const setCookie = res.headers['set-cookie']
|
||||
if (!setCookie || setCookie.length === 0) return ''
|
||||
const cookies = setCookie.map(cookie => cookie.split(';')[0])
|
||||
return cookies.join('; ')
|
||||
async function getSiteUrl(channel, date) {
|
||||
const f = () =>
|
||||
`https://www.tvpassport.com/tv-listings/stations/${channel.site_id}/${date}`
|
||||
let url = f()
|
||||
const res = await axios.head(url, { headers })
|
||||
.then(res => saveCookies(res))
|
||||
.then(res => res?.request?.res?.responseUrl)
|
||||
.catch(console.error)
|
||||
if (res && res !== url) {
|
||||
channel.site_id = getSiteId(res)
|
||||
url = f()
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
function getSiteId(url) {
|
||||
const [, site_id] = url.match(/\/tv-listings\/stations\/(.*)$/)
|
||||
|
||||
return site_id
|
||||
}
|
||||
|
||||
function saveCookies(res) {
|
||||
if (res.headers && Array.isArray(res.headers['set-cookie'])) {
|
||||
const cookies = []
|
||||
cookies.push(...res.headers['set-cookie']
|
||||
.map(cookie => cookie.split(';')[0].trim()))
|
||||
headers.Cookie = cookies.length ? cookies.join('; ') : null
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
function parseDescription($item) {
|
||||
return $item('*').data('description')
|
||||
return $item.data('description')
|
||||
}
|
||||
|
||||
function parseImage($item) {
|
||||
const showpicture = $item('*').data('showpicture')
|
||||
const showpicture = $item.data('showpicture')
|
||||
const url = new URL(showpicture, 'https://cdn.tvpassport.com/image/show/960x540/')
|
||||
|
||||
return url.href
|
||||
}
|
||||
|
||||
function parseTitle($item) {
|
||||
return $item('*').data('showname').toString()
|
||||
return $item.data('showname').toString()
|
||||
}
|
||||
|
||||
function parseSubTitle($item) {
|
||||
return $item('*').data('episodetitle')?.toString() || null
|
||||
return $item.data('episodetitle')?.toString() || null
|
||||
}
|
||||
|
||||
function parseYear($item) {
|
||||
return $item('*').data('year')?.toString() || null
|
||||
return $item.data('year')?.toString() || null
|
||||
}
|
||||
|
||||
function parseCategory($item) {
|
||||
const showtype = $item('*').data('showtype')
|
||||
const showtype = $item.data('showtype')
|
||||
|
||||
return showtype ? showtype.split(', ') : []
|
||||
}
|
||||
|
||||
function parseActors($item) {
|
||||
const cast = $item('*').data('cast')
|
||||
const cast = $item.data('cast')
|
||||
|
||||
return cast ? cast.split(', ') : []
|
||||
}
|
||||
|
||||
function parseDirector($item) {
|
||||
const director = $item('*').data('director')
|
||||
const director = $item.data('director')
|
||||
|
||||
return director ? director.split(', ') : []
|
||||
}
|
||||
|
||||
function parseGuest($item) {
|
||||
const guest = $item('*').data('guest')
|
||||
const guest = $item.data('guest')
|
||||
|
||||
return guest ? guest.split(', ') : []
|
||||
}
|
||||
|
||||
function parseRating($item) {
|
||||
const rating = $item('*').data('rating')
|
||||
const rating = $item.data('rating')
|
||||
|
||||
return rating
|
||||
? {
|
||||
@@ -176,28 +196,24 @@ function parseRating($item) {
|
||||
}
|
||||
|
||||
function parseStart($item, currentTimezone) {
|
||||
const time = $item('*').data('st')
|
||||
const time = $item.data('st')
|
||||
|
||||
return dayjs.tz(time, 'YYYY-MM-DD HH:mm:ss', currentTimezone)
|
||||
}
|
||||
|
||||
function parseDuration($item) {
|
||||
const duration = $item('*').data('duration')
|
||||
const duration = $item.data('duration')
|
||||
|
||||
return parseInt(duration)
|
||||
}
|
||||
|
||||
function parseItems(content) {
|
||||
if (!content) return []
|
||||
if (!content) return [null, null, []]
|
||||
const $ = cheerio.load(content)
|
||||
|
||||
return $('.station-listings .list-group-item').toArray()
|
||||
return [
|
||||
$,
|
||||
$('#timezone_selector').val() || 'America/New_York',
|
||||
$('.station-listings .list-group-item').toArray()
|
||||
]
|
||||
}
|
||||
|
||||
function parseCurrentTimezone(content) {
|
||||
if (!content) return 'America/New_York'
|
||||
const $ = cheerio.load(content)
|
||||
|
||||
return $('#timezone_selector').val()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
const { parser, url } = require('./tvpassport.com.config.js')
|
||||
const axios = require('axios')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
|
||||
jest.mock('axios')
|
||||
|
||||
const date = dayjs.utc('2022-10-04', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = {
|
||||
site_id: 'youtoo-america-network/5463',
|
||||
xmltv_id: 'YTATV.us'
|
||||
}
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe(
|
||||
axios.head.mockImplementation(() => {
|
||||
return Promise.resolve({})
|
||||
})
|
||||
|
||||
it('can generate valid url', async () => {
|
||||
expect(await url({ channel, date })).toBe(
|
||||
'https://www.tvpassport.com/tv-listings/stations/youtoo-america-network/5463/2022-10-04'
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user