fix tvprofil.com

This commit is contained in:
whitesnakeftw
2025-07-30 03:13:16 +02:00
parent 03f86d5ed8
commit b1592c7f7b
4 changed files with 725 additions and 925 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -12,22 +12,28 @@ module.exports = {
}, },
request: { request: {
headers: { headers: {
'x-requested-with': 'XMLHttpRequest' 'x-requested-with': 'XMLHttpRequest',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
'referer': 'https://tvprofil.com/tvprogram/',
'accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01'
} }
}, },
parser: function ({ content }) { parser: function ({ content }) {
let programs = [] let programs = []
const items = parseItems(content) const items = parseItems(content)
items.forEach(item => { items.forEach(item => {
const $item = cheerio.load(item) const $ = cheerio.load(item)
const title = parseTitle($item) $('div.row').each((_, el) => {
const category = parseCategory($item) const $item = $(el)
const start = parseStart($item) const title = parseTitle($item)
const duration = parseDuration($item) const category = parseCategory($item)
const stop = start.add(duration, 's') const start = parseStart($item)
const image = parseImage($item) const duration = parseDuration($item)
const stop = start.add(duration, 's')
const icon = parseImage($item)
programs.push({ title, category, start, stop, image }) programs.push({ title, category, start, stop, icon })
})
}) })
return programs return programs
@@ -102,64 +108,73 @@ module.exports = {
} }
function parseImage($item) { function parseImage($item) {
return $item(':root').data('image') return $item.attr('data-image') || null
} }
function parseDuration($item) { function parseDuration($item) {
return $item(':root').data('len') return parseInt($item.attr('data-len'))
} }
function parseStart($item) { function parseStart($item) {
const timestamp = $item(':root').data('ts') const timestamp = parseInt($item.attr('data-ts'))
return dayjs.unix(timestamp) return dayjs.unix(timestamp)
} }
function parseCategory($item) { function parseCategory($item) {
return $item('.col:nth-child(2) > small').text() || null return $item.find('.col:nth-child(2) > small').text() || null
} }
function parseTitle($item) { function parseTitle($item) {
let title = $item('.col:nth-child(2) > a').text() let title = $item.find('.col:nth-child(2) > a').text()
title += $item('.col:nth-child(2)').clone().children().remove().end().text() title += $item.find('.col:nth-child(2)').clone().children().remove().end().text()
return title.replace('®', '').trim().replace(/,$/, '') return title.replace('®', '').trim().replace(/,$/, '')
} }
function parseItems(content) { function parseItems(content) {
let data = (content.match(/cb\((.*)\)/) || [null, null])[1] let data = (content.match(/^[^(]+\(([\s\S]*)\)$/) || [null, null])[1]
if (!data) return [] if (!data) return []
let json = JSON.parse(data) let json = JSON.parse(data)
if (!json || !json.data || !json.data.program) return [] if (!json || !json.data || !json.data.program) return []
const $ = cheerio.load(json.data.program) return [json.data.program]
return $('.row').toArray()
} }
function buildQuery(site_id, date) { function buildQuery(site_id, date) {
const query = { const query = {
datum: date.format('YYYY-MM-DD'), datum: date.format('YYYY-MM-DD'),
kanal: site_id, kanal: site_id
callback: 'cb' // callback: 'cb' // possibly still working
} }
let c = 4 let c = 4
const a = query.datum + query.kanal + c let a = query.datum + query.kanal + c
const ua = query.kanal + query.datum let ua = query.kanal + query.datum
let i = a.length, if (
b = 2 typeof ua === 'undefined' ||
ua === null ||
ua === '' ||
ua === 0 ||
ua === '0' ||
ua !== ua
) {
ua = 'none'
}
for (let j = 0; j < ua.length; j++) c += ua.charCodeAt(j) for (let j = 0; j < ua.length; j++) c += ua.charCodeAt(j)
let i = a.length
let b = 2
while (i--) { while (i--) {
b += (a.charCodeAt(i) + c * 2) * i b += (a.charCodeAt(i) + c * 2) * i
} }
b = b.toString() b = b.toString()
const key = 'b' + b.charCodeAt(b.length - 1) const lastCharCode = b.charCodeAt(b.length - 1)
const key = 'b' + lastCharCode
query['callback'] = `tvprogramit${lastCharCode}`
query[key] = b query[key] = b
return new URLSearchParams(query).toString() return new URLSearchParams(query).toString()
} }

View File

@@ -7,7 +7,7 @@ const customParseFormat = require('dayjs/plugin/customParseFormat')
dayjs.extend(customParseFormat) dayjs.extend(customParseFormat)
dayjs.extend(utc) dayjs.extend(utc)
const date = dayjs.utc('2025-01-19', 'YYYY-MM-DD').startOf('d') const date = dayjs.utc('2025-07-29', 'YYYY-MM-DD').startOf('d')
const channel = { const channel = {
site_id: 'bg/tv-programa#24kitchen-bg', site_id: 'bg/tv-programa#24kitchen-bg',
xmltv_id: '24KitchenBulgaria.bg' xmltv_id: '24KitchenBulgaria.bg'
@@ -15,13 +15,14 @@ const channel = {
it('can generate valid url', () => { it('can generate valid url', () => {
expect(url({ channel, date })).toBe( expect(url({ channel, date })).toBe(
'https://tvprofil.com/bg/tv-programa/program/?datum=2025-01-19&kanal=24kitchen-bg&callback=cb&b52=824084' 'https://tvprofil.com/bg/tv-programa/program/?datum=2025-07-29&kanal=24kitchen-bg&callback=tvprogramit48&b48=827670'
) )
}) })
it('can generate valid request headers', () => { it('can generate valid request headers', () => {
expect(request.headers).toMatchObject({ expect(request.headers).toMatchObject({
'x-requested-with': 'XMLHttpRequest' 'x-requested-with': 'XMLHttpRequest',
'referer': 'https://tvprofil.com/tvprogram/',
}) })
}) })
@@ -34,9 +35,9 @@ it('can parse response', () => {
}) })
expect(results[0]).toMatchObject({ expect(results[0]).toMatchObject({
title: 'Мексиканска кухня с Пати 10, еп. 9', title: 'Save with Jamie 1, ep. 2',
start: '2023-01-12T04:00:00.000Z', start: '2025-07-29T05:00:00.000Z',
stop: '2023-01-12T04:30:00.000Z' stop: '2025-07-29T06:00:00.000Z'
}) })
}) })