Replace LF endings with CRLF

This commit is contained in:
freearhey
2025-07-31 22:29:01 +03:00
parent 17e3b4ddda
commit 29aa427923
379 changed files with 29332 additions and 29332 deletions

View File

@@ -1,130 +1,130 @@
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)
doFetch.setDebugger(debug)
const channelsWithSchedule = true
const pageLimit = 10
const caches = {}
module.exports = {
site: 'dsmart.com.tr',
days: 2,
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 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)
}
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 channels = []
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
}
}
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)
doFetch.setDebugger(debug)
const channelsWithSchedule = true
const pageLimit = 10
const caches = {}
module.exports = {
site: 'dsmart.com.tr',
days: 2,
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 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)
}
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 channels = []
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
}
}

View File

@@ -1,82 +1,82 @@
const { parser, url } = require('./dsmart.com.tr.config.js')
const axios = require('axios')
const dayjs = require('dayjs')
const fs = require('fs')
const path = require('path')
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('2025-01-13', 'YYYY-MM-DD').startOf('d')
const channel = {
site_id: '5fe07f5dcfef0b1593275822',
xmltv_id: 'Sinema1001.tr'
}
axios.get.mockImplementation(url => {
const result = {}
const urls = {
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13':
'content1.json',
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=2&limit=10&day=2025-01-13':
'content2.json',
}
if (urls[url] !== undefined) {
result.data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
if (!urls[url].startsWith('content1')) {
result.data = JSON.parse(result.data)
}
}
return Promise.resolve(result)
})
it('can generate valid url', () => {
expect(url({ date })).toBe(
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13'
)
})
it('can parse response', async () => {
const content = fs.readFileSync(path.join(__dirname, '__data__', 'content1.json')).toString()
const results = (await parser({ content, channel, date })).map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
})
expect(results.length).toBe(11)
expect(results[0]).toMatchObject({
start: '2025-01-12T21:30:00.000Z',
stop: '2025-01-12T23:30:00.000Z',
title: 'Taksi Şoförü',
description:
'Vietnam savaşının izlerinin etkisindeki bir asker ve New York sokakları. Travis Bickle, geceleri taksi şoförlüğü yaptığı New Yorkta bir yandan da gündelik yaşama ayak uydurmaya çalışır. Çürümeye yüz tutmuş bir topluma karşı tutulan bir ayna niteliğindeki film, yönetmen Martin Scorsesenin kariyerinin en önemli filmlerinden biri olarak kabul görür.',
category: ['Sinema', 'Genel']
})
expect(results[10]).toMatchObject({
start: '2025-01-13T19:00:00.000Z',
stop: '2025-01-13T21:00:00.000Z',
title: 'Senin Adın',
description:
'Dağların sardığı bir bölgede yaşayan Mitsuha, hayatından çok da memnun olmayan liseli bir kızdır. Babası vali olarak çalışmakta ve seçim kampanyaları ile uğraşmaktadır. Evde kendisi, kardeşi ve büyükannesi dışında kimse yoktur. Kırsal kesimdeki yaşamı onu bunaltmaktadır ve esas isteği Tokyo\'nun muhteşem şehir hayatının bir parçası olmaktır. Diğer tarafta ise Taki vardır.',
category: ['Sinema', 'Genel']
})
})
it('can handle empty guide', async () => {
const results = await parser({
channel,
date,
content: fs.readFileSync(path.join(__dirname, '__data__', 'no_content.json')).toString(),
useCache: false
})
expect(results).toMatchObject([])
})
const { parser, url } = require('./dsmart.com.tr.config.js')
const axios = require('axios')
const dayjs = require('dayjs')
const fs = require('fs')
const path = require('path')
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('2025-01-13', 'YYYY-MM-DD').startOf('d')
const channel = {
site_id: '5fe07f5dcfef0b1593275822',
xmltv_id: 'Sinema1001.tr'
}
axios.get.mockImplementation(url => {
const result = {}
const urls = {
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13':
'content1.json',
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=2&limit=10&day=2025-01-13':
'content2.json',
}
if (urls[url] !== undefined) {
result.data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
if (!urls[url].startsWith('content1')) {
result.data = JSON.parse(result.data)
}
}
return Promise.resolve(result)
})
it('can generate valid url', () => {
expect(url({ date })).toBe(
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13'
)
})
it('can parse response', async () => {
const content = fs.readFileSync(path.join(__dirname, '__data__', 'content1.json')).toString()
const results = (await parser({ content, channel, date })).map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
})
expect(results.length).toBe(11)
expect(results[0]).toMatchObject({
start: '2025-01-12T21:30:00.000Z',
stop: '2025-01-12T23:30:00.000Z',
title: 'Taksi Şoförü',
description:
'Vietnam savaşının izlerinin etkisindeki bir asker ve New York sokakları. Travis Bickle, geceleri taksi şoförlüğü yaptığı New Yorkta bir yandan da gündelik yaşama ayak uydurmaya çalışır. Çürümeye yüz tutmuş bir topluma karşı tutulan bir ayna niteliğindeki film, yönetmen Martin Scorsesenin kariyerinin en önemli filmlerinden biri olarak kabul görür.',
category: ['Sinema', 'Genel']
})
expect(results[10]).toMatchObject({
start: '2025-01-13T19:00:00.000Z',
stop: '2025-01-13T21:00:00.000Z',
title: 'Senin Adın',
description:
'Dağların sardığı bir bölgede yaşayan Mitsuha, hayatından çok da memnun olmayan liseli bir kızdır. Babası vali olarak çalışmakta ve seçim kampanyaları ile uğraşmaktadır. Evde kendisi, kardeşi ve büyükannesi dışında kimse yoktur. Kırsal kesimdeki yaşamı onu bunaltmaktadır ve esas isteği Tokyo\'nun muhteşem şehir hayatının bir parçası olmaktır. Diğer tarafta ise Taki vardır.',
category: ['Sinema', 'Genel']
})
})
it('can handle empty guide', async () => {
const results = await parser({
channel,
date,
content: fs.readFileSync(path.join(__dirname, '__data__', 'no_content.json')).toString(),
useCache: false
})
expect(results).toMatchObject([])
})