mirror of
https://github.com/iptv-org/epg
synced 2026-05-05 17:07:03 -04:00
Update dsmart.com.tr guide.
Test: ```sh npm test --- dsmart.com.tr > test > run-script-os dsmart.com.tr > test:win32 > SET "TZ=Pacific/Nauru" && npx jest --runInBand dsmart.com.tr PASS sites/dsmart.com.tr/dsmart.com.tr.test.js √ can generate valid url (6 ms) √ can parse response (14 ms) √ can handle empty guide (2 ms) Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total Snapshots: 0 total Time: 0.828 s, estimated 1 s Ran all test suites matching /dsmart.com.tr/i. ``` Grab: ```sh npm run grab --- --site=dsmart.com.tr > grab > npx tsx scripts/commands/epg/grab.ts --site=dsmart.com.tr starting... config: output: guide.xml maxConnections: 1 gzip: false site: dsmart.com.tr loading channels... found 104 channel(s) run #1: [1/208] dsmart.com.tr (tr) - 5d25dbe5cfef0b5761a051db - Jan 13, 2025 (38 programs) [2/208] dsmart.com.tr (tr) - 5d25dbe5cfef0b5761a051db - Jan 14, 2025 (36 programs) ... [207/208] dsmart.com.tr (tr) - 58d29bb0eefad3db9c6062b4 - Jan 14, 2025 (35 programs) [208/208] dsmart.com.tr (tr) - 58d29bb0eefad3db9c6062b4 - Jan 13, 2025 (41 programs) saving to "guide.xml"... done in 00h 00m 12s ``` Signed-off-by: Toha <tohenk@yahoo.com>
This commit is contained in:
@@ -1,104 +1,130 @@
|
||||
const axios = require('axios')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
const duration = require('dayjs/plugin/duration')
|
||||
const doFetch = require('@ntlab/sfetch')
|
||||
const debug = require('debug')('site:dsmart.com.tr')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(duration)
|
||||
|
||||
const API_ENDPOINT = 'https://www.dsmart.com.tr/api/v1/public/epg/schedules'
|
||||
doFetch.setDebugger(debug)
|
||||
|
||||
const channelsWithSchedule = true
|
||||
const pageLimit = 10
|
||||
const caches = {}
|
||||
|
||||
module.exports = {
|
||||
site: 'dsmart.com.tr',
|
||||
days: 2,
|
||||
url({ date, channel }) {
|
||||
const [page] = channel.site_id.split('#')
|
||||
|
||||
return `${API_ENDPOINT}?page=${page}&limit=1&day=${date.format('YYYY-MM-DD')}`
|
||||
request: {
|
||||
cache: {
|
||||
ttl: 24 * 60 * 60 * 1000 // 1 day
|
||||
}
|
||||
},
|
||||
parser: function ({ content, channel }) {
|
||||
let programs = []
|
||||
const items = parseItems(content, channel)
|
||||
items.forEach(item => {
|
||||
const prev = programs[programs.length - 1]
|
||||
let start
|
||||
if (prev) {
|
||||
start = parseStart(item, prev.stop)
|
||||
} else {
|
||||
start = parseStart(item, dayjs.utc(item.day))
|
||||
url({ date, page = 1 }) {
|
||||
return `https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=${
|
||||
page
|
||||
}&limit=${
|
||||
pageLimit
|
||||
}&day=${
|
||||
date.format('YYYY-MM-DD')
|
||||
}`
|
||||
},
|
||||
async parser({ content, channel, date, useCache = true }) {
|
||||
const programs = []
|
||||
if (content) {
|
||||
if (typeof content === 'string') {
|
||||
content = JSON.parse(content)
|
||||
}
|
||||
let duration = parseDuration(item)
|
||||
let stop = start.add(duration, 's')
|
||||
|
||||
programs.push({
|
||||
title: item.program_name,
|
||||
category: parseCategory(item),
|
||||
description: item.description.trim(),
|
||||
start,
|
||||
stop
|
||||
})
|
||||
})
|
||||
if (useCache) {
|
||||
const cacheKey = date.format('YYYYMMDD')
|
||||
// cache whole channels for the day
|
||||
if (caches[cacheKey] === undefined) {
|
||||
if (content?.data?.total) {
|
||||
const queues = []
|
||||
const pages = Math.ceil(content.data.total / pageLimit)
|
||||
for (let page = 2; page <= pages; page++) {
|
||||
queues.push(module.exports.url({ date, page }))
|
||||
}
|
||||
await doFetch(queues, (url, res) => {
|
||||
if (Array.isArray(res?.data?.channels)) {
|
||||
content.data.channels.push(...res.data.channels)
|
||||
}
|
||||
})
|
||||
caches[cacheKey] = content
|
||||
}
|
||||
} else {
|
||||
content = caches[cacheKey]
|
||||
}
|
||||
}
|
||||
if (Array.isArray(content?.data?.channels)) {
|
||||
content.data.channels
|
||||
.filter(i => i._id === channel.site_id)
|
||||
.forEach(i => {
|
||||
if (i.schedule.length) {
|
||||
let dayStart, ofs
|
||||
programs.push(...i.schedule
|
||||
.map(p => {
|
||||
const baseDate = dayjs.utc(p.day)
|
||||
const startDate = dayjs.utc(p.start_date)
|
||||
// calculate base offset if needed
|
||||
if (!dayStart) {
|
||||
dayStart = startDate
|
||||
ofs = dayjs.duration(dayjs.utc(`${p.day.substr(0, 11)}${p.start_date.substr(11)}`).diff(baseDate))
|
||||
.asSeconds()
|
||||
}
|
||||
const delta = dayjs.duration(startDate.diff(dayStart)).asSeconds()
|
||||
// ignore days in duration
|
||||
const [h, m, s] = (p.duration.includes(',') ? p.duration.split(',')[1].trim() : p.duration)
|
||||
.split(':').map(Number)
|
||||
const duration = (h * 3600) + (m * 60) + s
|
||||
const start = baseDate.add(ofs + delta, 's')
|
||||
const stop = start.add(duration, 's')
|
||||
return {
|
||||
title: p.program_name,
|
||||
description: p.description,
|
||||
category: p.genre && p.genre.includes('/') ?
|
||||
p.genre.split('/').map(g => `${g.substr(0, 1).toUpperCase()}${g.substr(1)}`) : null,
|
||||
start,
|
||||
stop
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return programs
|
||||
},
|
||||
async channels() {
|
||||
const perPage = 1
|
||||
const totalChannels = 210
|
||||
const pages = Math.ceil(totalChannels / perPage)
|
||||
|
||||
const channels = []
|
||||
for (let i in Array(pages).fill(0)) {
|
||||
const page = parseInt(i) + 1
|
||||
const url = `${API_ENDPOINT}?page=${page}&limit=${perPage}&day=${dayjs().format(
|
||||
'YYYY-MM-DD'
|
||||
)}`
|
||||
let offset = i * perPage
|
||||
await axios
|
||||
.get(url)
|
||||
.then(r => r.data)
|
||||
.then(data => {
|
||||
offset++
|
||||
if (data && data.data && Array.isArray(data.data.channels)) {
|
||||
data.data.channels.forEach((item, j) => {
|
||||
const index = offset + j
|
||||
channels.push({
|
||||
lang: 'tr',
|
||||
name: item.channel_name,
|
||||
site_id: index + '#' + item._id
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err.message)
|
||||
})
|
||||
}
|
||||
const f = page => this.url({ date: dayjs(), page })
|
||||
let pages, page = 1
|
||||
const queues = [f(page)]
|
||||
await doFetch(queues, (url, res) => {
|
||||
if (!pages && res.data.total) {
|
||||
pages = Math.ceil(res.data.total / pageLimit)
|
||||
while (page <= pages) {
|
||||
queues.push(f(++page))
|
||||
}
|
||||
}
|
||||
if (Array.isArray(res?.data?.channels)) {
|
||||
channels.push(...res.data.channels
|
||||
.filter(i => (channelsWithSchedule && i.schedule.length) || !channelsWithSchedule)
|
||||
.map(i => {
|
||||
return {
|
||||
lang: 'tr',
|
||||
name: i.channel_name,
|
||||
site_id: i._id
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return channels
|
||||
}
|
||||
}
|
||||
|
||||
function parseCategory(item) {
|
||||
return item.genre !== '0' ? item.genre : null
|
||||
}
|
||||
|
||||
function parseStart(item, date) {
|
||||
const time = dayjs.utc(item.start_date)
|
||||
|
||||
return dayjs.utc(`${date.format('YYYY-MM-DD')} ${time.format('HH:mm:ss')}`, 'YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
function parseDuration(item) {
|
||||
const [, H, mm, ss] = item.duration.match(/(\d+):(\d+):(\d+)$/)
|
||||
|
||||
return parseInt(H) * 3600 + parseInt(mm) * 60 + parseInt(ss)
|
||||
}
|
||||
|
||||
function parseItems(content, channel) {
|
||||
const [, channelId] = channel.site_id.split('#')
|
||||
const data = JSON.parse(content)
|
||||
if (!data || !data.data || !Array.isArray(data.data.channels)) return null
|
||||
const channelData = data.data.channels.find(i => i._id == channelId)
|
||||
|
||||
return channelData && Array.isArray(channelData.schedule) ? channelData.schedule : []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user