diff --git a/sites/distro.tv/distro.tv.config.js b/sites/distro.tv/distro.tv.config.js index e08e0c26..2df68113 100644 --- a/sites/distro.tv/distro.tv.config.js +++ b/sites/distro.tv/distro.tv.config.js @@ -1,71 +1,71 @@ -const axios = require('axios') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const customParseFormat = require('dayjs/plugin/customParseFormat') - -const HEADERS = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0', - 'Referer': 'https://distro.tv/', - 'Origin': 'https://distro.tv' -} - -dayjs.extend(utc) -dayjs.extend(customParseFormat) - -module.exports = { - site: 'distro.tv', - days: 2, - request: { - headers: HEADERS - }, - url({ channel }) { - const days = module.exports.days || 2 - const hours = days * 24 - return `https://tv.jsrdn.com/epg/query.php?range=now,${hours}h&id=${channel.site_id},` - }, - parser({ content, channel }) { - if (!content || !channel) return [] - let programs = [] - try { - const data = JSON.parse(content) - if (!data.epg || !data.epg[channel.site_id] || !Array.isArray(data.epg[channel.site_id].slots)) { - return [] - } - programs = data.epg[channel.site_id].slots.map(program => ({ - title: program.title, - description: program.description || null, - icon: program.img_thumbh || null, - start: dayjs.utc(program.start, 'YYYY-MM-DD HH:mm:ss'), - stop: dayjs.utc(program.end, 'YYYY-MM-DD HH:mm:ss') - })) - } catch { - return [] - } - - return programs.filter(p => p.title && p.start.isValid() && p.stop.isValid()) - }, - async channels() { - const { data } = await axios.get('https://tv.jsrdn.com/tv_v5/getfeed.php?type=live', { - headers: HEADERS - }) - - const channels = [] - if (data && data.shows) { - Object.values(data.shows).forEach(show => { - const episode = show.seasons?.[0]?.episodes?.[0] - if (episode && episode.id) { - channels.push({ - lang: 'en', - // lang: show.language || 'en', - site_id: episode.id.toString(), - name: show.title, - // logo: show.img_logo, - // url: episode.content?.url || null - }) - } - }) - } - - return channels - } +const axios = require('axios') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const customParseFormat = require('dayjs/plugin/customParseFormat') + +const HEADERS = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0', + 'Referer': 'https://distro.tv/', + 'Origin': 'https://distro.tv' +} + +dayjs.extend(utc) +dayjs.extend(customParseFormat) + +module.exports = { + site: 'distro.tv', + days: 2, + request: { + headers: HEADERS + }, + url({ channel }) { + const days = module.exports.days || 2 + const hours = days * 24 + return `https://tv.jsrdn.com/epg/query.php?range=now,${hours}h&id=${channel.site_id},` + }, + parser({ content, channel }) { + if (!content || !channel) return [] + let programs = [] + try { + const data = JSON.parse(content) + if (!data.epg || !data.epg[channel.site_id] || !Array.isArray(data.epg[channel.site_id].slots)) { + return [] + } + programs = data.epg[channel.site_id].slots.map(program => ({ + title: program.title, + description: program.description || null, + icon: program.img_thumbh || null, + start: dayjs.utc(program.start, 'YYYY-MM-DD HH:mm:ss'), + stop: dayjs.utc(program.end, 'YYYY-MM-DD HH:mm:ss') + })) + } catch { + return [] + } + + return programs.filter(p => p.title && p.start.isValid() && p.stop.isValid()) + }, + async channels() { + const { data } = await axios.get('https://tv.jsrdn.com/tv_v5/getfeed.php?type=live', { + headers: HEADERS + }) + + const channels = [] + if (data && data.shows) { + Object.values(data.shows).forEach(show => { + const episode = show.seasons?.[0]?.episodes?.[0] + if (episode && episode.id) { + channels.push({ + lang: 'en', + // lang: show.language || 'en', + site_id: episode.id.toString(), + name: show.title, + // logo: show.img_logo, + // url: episode.content?.url || null + }) + } + }) + } + + return channels + } } \ No newline at end of file diff --git a/sites/distro.tv/distro.tv.test.js b/sites/distro.tv/distro.tv.test.js index 82dc7435..d8f7a018 100644 --- a/sites/distro.tv/distro.tv.test.js +++ b/sites/distro.tv/distro.tv.test.js @@ -1,70 +1,70 @@ -const fs = require('fs') -const path = require('path') -const { parser, url, channels } = require('./distro.tv.config.js') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const customParseFormat = require('dayjs/plugin/customParseFormat') -dayjs.extend(customParseFormat) -dayjs.extend(utc) - -const axios = require('axios') -jest.mock('axios') - -const date = dayjs.utc('2026-02-10', 'YYYY-MM-DD').startOf('d') -const channel = { - site_id: '45143' -} - -it('can generate valid url', () => { - expect(url({ channel, date })).toBe( - 'https://tv.jsrdn.com/epg/query.php?range=now,48h&id=45143,' - ) -}) - -it('can parse response', () => { - const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8') - const results = parser({ content, channel }) - - expect(results[0]).toMatchObject({ - title: 'News', - description: 'The leading news stories of the moment.', - start: dayjs.utc('2026-02-10 10:17:05'), - stop: dayjs.utc('2026-02-10 10:30:00') - }) - expect(results[1]).toMatchObject({ - title: 'Euronews Now', - description: 'Breaking News. In depth analysis on the biggest stories making headlines in Europe and across the world.', - start: dayjs.utc('2026-02-10 10:30:00'), - stop: dayjs.utc('2026-02-10 10:46:00') - }) -}) - -it('can handle empty guide', () => { - const results = parser({ - content: '{"epg":{"45143":{"title":"Euronews","slots":[]}}}', - channel - }) - expect(results).toMatchObject([]) -}) - -it('can fetch channels', async () => { - axios.get.mockResolvedValue({ - data: { - shows: { - 414: { - title: 'Titanic TV', - language: 'en', - img_logo: 'logo.png', - seasons: [{ episodes: [{ id: 10953 }] }] - } - } - } - }) - - const result = await channels() - expect(result[0]).toMatchObject({ - lang: 'en', - site_id: '10953', - name: 'Titanic TV' - }) +const fs = require('fs') +const path = require('path') +const { parser, url, channels } = require('./distro.tv.config.js') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const customParseFormat = require('dayjs/plugin/customParseFormat') +dayjs.extend(customParseFormat) +dayjs.extend(utc) + +const axios = require('axios') +jest.mock('axios') + +const date = dayjs.utc('2026-02-10', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: '45143' +} + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe( + 'https://tv.jsrdn.com/epg/query.php?range=now,48h&id=45143,' + ) +}) + +it('can parse response', () => { + const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8') + const results = parser({ content, channel }) + + expect(results[0]).toMatchObject({ + title: 'News', + description: 'The leading news stories of the moment.', + start: dayjs.utc('2026-02-10 10:17:05'), + stop: dayjs.utc('2026-02-10 10:30:00') + }) + expect(results[1]).toMatchObject({ + title: 'Euronews Now', + description: 'Breaking News. In depth analysis on the biggest stories making headlines in Europe and across the world.', + start: dayjs.utc('2026-02-10 10:30:00'), + stop: dayjs.utc('2026-02-10 10:46:00') + }) +}) + +it('can handle empty guide', () => { + const results = parser({ + content: '{"epg":{"45143":{"title":"Euronews","slots":[]}}}', + channel + }) + expect(results).toMatchObject([]) +}) + +it('can fetch channels', async () => { + axios.get.mockResolvedValue({ + data: { + shows: { + 414: { + title: 'Titanic TV', + language: 'en', + img_logo: 'logo.png', + seasons: [{ episodes: [{ id: 10953 }] }] + } + } + } + }) + + const result = await channels() + expect(result[0]).toMatchObject({ + lang: 'en', + site_id: '10953', + name: 'Titanic TV' + }) }) \ No newline at end of file