epg-grabber 0.26.0 → 0.27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/utils.js +147 -3
- package/tests/index.test.js +0 -7
- package/tests/utils.test.js +120 -6
package/package.json
CHANGED
package/src/utils.js
CHANGED
|
@@ -149,8 +149,10 @@ utils.escapeString = function (string, defaultValue = '') {
|
|
|
149
149
|
.trim()
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
utils.convertToXMLTV = function ({ channels, programs }) {
|
|
153
|
-
let output = `<?xml version="1.0" encoding="UTF-8" ?><tv
|
|
152
|
+
utils.convertToXMLTV = function ({ channels, programs, date = dayjs.utc() }) {
|
|
153
|
+
let output = `<?xml version="1.0" encoding="UTF-8" ?><tv date="${dayjs(date).format(
|
|
154
|
+
'YYYYMMDD'
|
|
155
|
+
)}">\r\n`
|
|
154
156
|
for (let channel of channels) {
|
|
155
157
|
const id = utils.escapeString(channel['xmltv_id'])
|
|
156
158
|
const displayName = utils.escapeString(channel.name)
|
|
@@ -178,11 +180,30 @@ utils.convertToXMLTV = function ({ channels, programs }) {
|
|
|
178
180
|
const lang = program.lang || 'en'
|
|
179
181
|
const xmltv_ns = createXMLTVNS(program.season, program.episode)
|
|
180
182
|
const onscreen = createOnScreen(program.season, program.episode)
|
|
183
|
+
const date = program.date || ''
|
|
184
|
+
const credits = createCredits({
|
|
185
|
+
director: program.director,
|
|
186
|
+
actor: program.actor,
|
|
187
|
+
writer: program.writer,
|
|
188
|
+
adapter: program.adapter,
|
|
189
|
+
producer: program.producer,
|
|
190
|
+
composer: program.composer,
|
|
191
|
+
editor: program.editor,
|
|
192
|
+
presenter: program.presenter,
|
|
193
|
+
commentator: program.commentator,
|
|
194
|
+
guest: program.guest
|
|
195
|
+
})
|
|
181
196
|
const icon = utils.escapeString(program.icon)
|
|
197
|
+
const sub_title = utils.escapeString(program.sub_title)
|
|
198
|
+
const url = program.url ? createURL(program.url, channel) : ''
|
|
182
199
|
|
|
183
200
|
if (start && stop && title) {
|
|
184
201
|
output += `<programme start="${start}" stop="${stop}" channel="${channel}"><title lang="${lang}">${title}</title>`
|
|
185
202
|
|
|
203
|
+
if (sub_title) {
|
|
204
|
+
output += `<sub-title>${sub_title}</sub-title>`
|
|
205
|
+
}
|
|
206
|
+
|
|
186
207
|
if (description) {
|
|
187
208
|
output += `<desc lang="${lang}">${description}</desc>`
|
|
188
209
|
}
|
|
@@ -195,6 +216,10 @@ utils.convertToXMLTV = function ({ channels, programs }) {
|
|
|
195
216
|
})
|
|
196
217
|
}
|
|
197
218
|
|
|
219
|
+
if (url) {
|
|
220
|
+
output += url
|
|
221
|
+
}
|
|
222
|
+
|
|
198
223
|
if (xmltv_ns) {
|
|
199
224
|
output += `<episode-num system="xmltv_ns">${xmltv_ns}</episode-num>`
|
|
200
225
|
}
|
|
@@ -202,11 +227,18 @@ utils.convertToXMLTV = function ({ channels, programs }) {
|
|
|
202
227
|
if (onscreen) {
|
|
203
228
|
output += `<episode-num system="onscreen">${onscreen}</episode-num>`
|
|
204
229
|
}
|
|
230
|
+
if (date) {
|
|
231
|
+
output += `<date>${date}</date>`
|
|
232
|
+
}
|
|
205
233
|
|
|
206
234
|
if (icon) {
|
|
207
235
|
output += `<icon src="${icon}"/>`
|
|
208
236
|
}
|
|
209
237
|
|
|
238
|
+
if (credits) {
|
|
239
|
+
output += `<credits>${credits}</credits>`
|
|
240
|
+
}
|
|
241
|
+
|
|
210
242
|
output += '</programme>\r\n'
|
|
211
243
|
}
|
|
212
244
|
}
|
|
@@ -230,6 +262,105 @@ utils.convertToXMLTV = function ({ channels, programs }) {
|
|
|
230
262
|
return `S${s}E${e}`
|
|
231
263
|
}
|
|
232
264
|
|
|
265
|
+
function createURL(urlObj, channel = '') {
|
|
266
|
+
const urls = Array.isArray(urlObj) ? urlObj : [urlObj]
|
|
267
|
+
let output = ''
|
|
268
|
+
for (let url of urls) {
|
|
269
|
+
if (typeof url === 'string' || url instanceof String) {
|
|
270
|
+
url = { value: url }
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
let attr = url.system ? ` system="${url.system}"` : ''
|
|
274
|
+
if (url.value.includes('http')) {
|
|
275
|
+
output += `<url${attr}>${url.value}</url>`
|
|
276
|
+
} else if (channel) {
|
|
277
|
+
let chan = channels.find(c => c.xmltv_id.localeCompare(channel) === 0)
|
|
278
|
+
if (chan && chan.site) {
|
|
279
|
+
output += `<url${attr}>https://${chan.site}${url.value}</url>`
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return output
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function createImage(imgObj, channel = '') {
|
|
288
|
+
const imgs = Array.isArray(imgObj) ? imgObj : [imgObj]
|
|
289
|
+
let output = ''
|
|
290
|
+
for (let img of imgs) {
|
|
291
|
+
if (typeof img === 'string' || img instanceof String) {
|
|
292
|
+
img = { value: img }
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const imageTypes = ['poster', 'backdrop', 'still', 'person', 'character']
|
|
296
|
+
const imageSizes = ['1', '2', '3']
|
|
297
|
+
const imageOrients = ['P', 'L']
|
|
298
|
+
|
|
299
|
+
let attr = ''
|
|
300
|
+
|
|
301
|
+
if (img.type && imageTypes.some(el => img.type.includes(el))) {
|
|
302
|
+
attr += ` type="${img.type}"`
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (img.size && imageSizes.some(el => img.size.includes(el))) {
|
|
306
|
+
attr += ` size="${img.size}"`
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (img.orient && imageOrients.some(el => img.orient.includes(el))) {
|
|
310
|
+
attr += ` orient="${img.orient}"`
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (img.system) {
|
|
314
|
+
attr += ` system="${img.system}"`
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (img.value.includes('http')) {
|
|
318
|
+
output += `<image${attr}>${img.value}</image>`
|
|
319
|
+
} else if (channel) {
|
|
320
|
+
let chan = channels.find(c => c.xmltv_id.localeCompare(channel) === 0)
|
|
321
|
+
if (chan && chan.site) {
|
|
322
|
+
output += `<image${attr}>https://${chan.site}${img.value}</image>`
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return output
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function createCredits(obj) {
|
|
331
|
+
let cast = Object.entries(obj)
|
|
332
|
+
.filter(x => x[1])
|
|
333
|
+
.map(([name, value]) => ({ name, value }))
|
|
334
|
+
|
|
335
|
+
let output = ''
|
|
336
|
+
for (let type of cast) {
|
|
337
|
+
const r = Array.isArray(type.value) ? type.value : [type.value]
|
|
338
|
+
for (let person of r) {
|
|
339
|
+
if (typeof person === 'string' || person instanceof String) {
|
|
340
|
+
person = { value: person }
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
let attr = ''
|
|
344
|
+
if (type.name.localeCompare('actor') === 0 && type.value.role) {
|
|
345
|
+
attr += ` role="${type.value.role}"`
|
|
346
|
+
}
|
|
347
|
+
if (type.name.localeCompare('actor') === 0 && type.value.guest) {
|
|
348
|
+
attr += ` guest="${type.value.guest}"`
|
|
349
|
+
}
|
|
350
|
+
output += `<${type.name}${attr}>${person.value}`
|
|
351
|
+
|
|
352
|
+
if (person.url) {
|
|
353
|
+
output += createURL(person.url)
|
|
354
|
+
}
|
|
355
|
+
if (person.image) {
|
|
356
|
+
output += createImage(person.image)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
output += `</${type.name}>`
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return output
|
|
363
|
+
}
|
|
233
364
|
return output
|
|
234
365
|
}
|
|
235
366
|
|
|
@@ -348,11 +479,24 @@ utils.parsePrograms = async function (data, config) {
|
|
|
348
479
|
category: program.category || null,
|
|
349
480
|
season: program.season || null,
|
|
350
481
|
episode: program.episode || null,
|
|
482
|
+
sub_title: program.sub_title || null,
|
|
483
|
+
url: program.url || null,
|
|
351
484
|
icon: program.icon || null,
|
|
352
485
|
channel: channel.xmltv_id,
|
|
353
486
|
lang: program.lang || channel.lang || config.lang || 'en',
|
|
354
487
|
start: program.start ? dayjs(program.start).unix() : null,
|
|
355
|
-
stop: program.stop ? dayjs(program.stop).unix() : null
|
|
488
|
+
stop: program.stop ? dayjs(program.stop).unix() : null,
|
|
489
|
+
date: program.date || null,
|
|
490
|
+
director: program.director || null,
|
|
491
|
+
actor: program.actor || null,
|
|
492
|
+
writer: program.writer || null,
|
|
493
|
+
adapter: program.adapter || null,
|
|
494
|
+
producer: program.producer || null,
|
|
495
|
+
composer: program.composer || null,
|
|
496
|
+
editor: program.editor || null,
|
|
497
|
+
presenter: program.presenter || null,
|
|
498
|
+
commentator: program.commentator || null,
|
|
499
|
+
guest: program.guest || null
|
|
356
500
|
}
|
|
357
501
|
})
|
|
358
502
|
}
|
package/tests/index.test.js
CHANGED
|
@@ -58,14 +58,7 @@ it('can grab single channel programs', done => {
|
|
|
58
58
|
grabber
|
|
59
59
|
.grab(channel, '2022-01-01', (data, err) => {
|
|
60
60
|
if (err) {
|
|
61
|
-
console.log(` Error: ${err.message}`)
|
|
62
61
|
done()
|
|
63
|
-
} else {
|
|
64
|
-
console.log(
|
|
65
|
-
` ${data.channel.site} - ${data.channel.xmltv_id} - ${data.date.format(
|
|
66
|
-
'MMM D, YYYY'
|
|
67
|
-
)} (${data.programs.length} programs)`
|
|
68
|
-
)
|
|
69
62
|
}
|
|
70
63
|
})
|
|
71
64
|
.then(programs => {
|
package/tests/utils.test.js
CHANGED
|
@@ -4,6 +4,8 @@ import axios from 'axios'
|
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import fs from 'fs'
|
|
6
6
|
|
|
7
|
+
jest.useFakeTimers('modern').setSystemTime(new Date('2022-05-05'))
|
|
8
|
+
|
|
7
9
|
it('can load valid config.js', () => {
|
|
8
10
|
const config = utils.loadConfig(require(path.resolve('./tests/input/example.com.config.js')))
|
|
9
11
|
expect(config).toMatchObject({
|
|
@@ -56,7 +58,9 @@ it('can convert object to xmltv string', () => {
|
|
|
56
58
|
const programs = [
|
|
57
59
|
{
|
|
58
60
|
title: 'Program 1',
|
|
61
|
+
sub_title: 'Sub-title & 1',
|
|
59
62
|
description: 'Description for Program 1',
|
|
63
|
+
url: 'http://example.com/title.html',
|
|
60
64
|
start: 1616133600,
|
|
61
65
|
stop: 1616135400,
|
|
62
66
|
category: 'Test',
|
|
@@ -64,12 +68,19 @@ it('can convert object to xmltv string', () => {
|
|
|
64
68
|
episode: 239,
|
|
65
69
|
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
|
|
66
70
|
channel: '1TV.com',
|
|
67
|
-
lang: 'it'
|
|
71
|
+
lang: 'it',
|
|
72
|
+
date: '20220505',
|
|
73
|
+
director: {
|
|
74
|
+
value: 'Director 1',
|
|
75
|
+
url: { value: 'http://example.com/director1.html', system: 'TestSystem' }
|
|
76
|
+
},
|
|
77
|
+
actor: ['Actor 1', 'Actor 2'],
|
|
78
|
+
writer: 'Writer 1'
|
|
68
79
|
}
|
|
69
80
|
]
|
|
70
81
|
const output = utils.convertToXMLTV({ channels, programs })
|
|
71
82
|
expect(output).toBe(
|
|
72
|
-
'<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"
|
|
83
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><sub-title>Sub-title & 1</sub-title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><url>http://example.com/title.html</url><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><date>20220505</date><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url></director><actor>Actor 1</actor><actor>Actor 2</actor><writer>Writer 1</writer></credits></programme>\r\n</tv>'
|
|
73
84
|
)
|
|
74
85
|
})
|
|
75
86
|
|
|
@@ -91,7 +102,7 @@ it('can convert object to xmltv string without season number', () => {
|
|
|
91
102
|
]
|
|
92
103
|
const output = utils.convertToXMLTV({ channels, programs })
|
|
93
104
|
expect(output).toBe(
|
|
94
|
-
'<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><episode-num system="xmltv_ns">0.238.0/1</episode-num><episode-num system="onscreen">S01E239</episode-num><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
105
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><episode-num system="xmltv_ns">0.238.0/1</episode-num><episode-num system="onscreen">S01E239</episode-num><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
95
106
|
)
|
|
96
107
|
})
|
|
97
108
|
|
|
@@ -113,7 +124,7 @@ it('can convert object to xmltv string without episode number', () => {
|
|
|
113
124
|
]
|
|
114
125
|
const output = utils.convertToXMLTV({ channels, programs })
|
|
115
126
|
expect(output).toBe(
|
|
116
|
-
'<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
127
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
117
128
|
)
|
|
118
129
|
})
|
|
119
130
|
|
|
@@ -140,7 +151,7 @@ it('can convert object to xmltv string without categories', () => {
|
|
|
140
151
|
const config = { site: 'example.com' }
|
|
141
152
|
const output = utils.convertToXMLTV({ config, channels, programs })
|
|
142
153
|
expect(output).toBe(
|
|
143
|
-
'<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title></programme>\r\n</tv>'
|
|
154
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title></programme>\r\n</tv>'
|
|
144
155
|
)
|
|
145
156
|
})
|
|
146
157
|
|
|
@@ -161,7 +172,110 @@ it('can convert object to xmltv string with multiple categories', () => {
|
|
|
161
172
|
]
|
|
162
173
|
const output = utils.convertToXMLTV({ channels, programs })
|
|
163
174
|
expect(output).toBe(
|
|
164
|
-
'<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test1</category><category lang="it">Test2</category><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
175
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test1</category><category lang="it">Test2</category><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('can convert object to xmltv string with multiple urls', () => {
|
|
180
|
+
const file = fs.readFileSync('./tests/input/example.com.channels.xml', { encoding: 'utf-8' })
|
|
181
|
+
const { channels } = utils.parseChannels(file)
|
|
182
|
+
const programs = [
|
|
183
|
+
{
|
|
184
|
+
title: 'Program 1',
|
|
185
|
+
description: 'Description for Program 1',
|
|
186
|
+
start: 1616133600,
|
|
187
|
+
stop: 1616135400,
|
|
188
|
+
category: ['Test1', 'Test2'],
|
|
189
|
+
url: [
|
|
190
|
+
'https://example.com/noattr.html',
|
|
191
|
+
{ value: 'https://example.com/attr.html', system: 'TestSystem' }
|
|
192
|
+
],
|
|
193
|
+
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
|
|
194
|
+
channel: '1TV.com',
|
|
195
|
+
lang: 'it'
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
const output = utils.convertToXMLTV({ channels, programs })
|
|
199
|
+
expect(output).toBe(
|
|
200
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test1</category><category lang="it">Test2</category><url>https://example.com/noattr.html</url><url system="TestSystem">https://example.com/attr.html</url><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/></programme>\r\n</tv>'
|
|
201
|
+
)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('can convert object to xmltv string with multiple images', () => {
|
|
205
|
+
const file = fs.readFileSync('./tests/input/example.com.channels.xml', { encoding: 'utf-8' })
|
|
206
|
+
const { channels } = utils.parseChannels(file)
|
|
207
|
+
const programs = [
|
|
208
|
+
{
|
|
209
|
+
title: 'Program 1',
|
|
210
|
+
description: 'Description for Program 1',
|
|
211
|
+
start: 1616133600,
|
|
212
|
+
stop: 1616135400,
|
|
213
|
+
category: ['Test1', 'Test2'],
|
|
214
|
+
url: [
|
|
215
|
+
'https://example.com/noattr.html',
|
|
216
|
+
{ value: 'https://example.com/attr.html', system: 'TestSystem' }
|
|
217
|
+
],
|
|
218
|
+
actor: {
|
|
219
|
+
value: 'Actor 1',
|
|
220
|
+
image: [
|
|
221
|
+
'https://example.com/image1.jpg',
|
|
222
|
+
{
|
|
223
|
+
value: 'https://example.com/image2.jpg',
|
|
224
|
+
type: 'person',
|
|
225
|
+
size: '2',
|
|
226
|
+
system: 'TestSystem',
|
|
227
|
+
orient: 'P'
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
},
|
|
231
|
+
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
|
|
232
|
+
channel: '1TV.com',
|
|
233
|
+
lang: 'it'
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
const output = utils.convertToXMLTV({ channels, programs })
|
|
237
|
+
expect(output).toBe(
|
|
238
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test1</category><category lang="it">Test2</category><url>https://example.com/noattr.html</url><url system="TestSystem">https://example.com/attr.html</url><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/><credits><actor>Actor 1<image>https://example.com/image1.jpg</image><image type="person" size="2" orient="P" system="TestSystem">https://example.com/image2.jpg</image></actor></credits></programme>\r\n</tv>'
|
|
239
|
+
)
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('can convert object to xmltv string with multiple credits member', () => {
|
|
243
|
+
const file = fs.readFileSync('./tests/input/example.com.channels.xml', { encoding: 'utf-8' })
|
|
244
|
+
const { channels } = utils.parseChannels(file)
|
|
245
|
+
const programs = [
|
|
246
|
+
{
|
|
247
|
+
title: 'Program 1',
|
|
248
|
+
sub_title: 'Sub-title 1',
|
|
249
|
+
description: 'Description for Program 1',
|
|
250
|
+
url: 'http://example.com/title.html',
|
|
251
|
+
start: 1616133600,
|
|
252
|
+
stop: 1616135400,
|
|
253
|
+
category: 'Test',
|
|
254
|
+
season: 9,
|
|
255
|
+
episode: 239,
|
|
256
|
+
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
|
|
257
|
+
channel: '1TV.com',
|
|
258
|
+
lang: 'it',
|
|
259
|
+
date: '20220505',
|
|
260
|
+
director: {
|
|
261
|
+
value: 'Director 1',
|
|
262
|
+
url: { value: 'http://example.com/director1.html', system: 'TestSystem' }
|
|
263
|
+
},
|
|
264
|
+
actor: {
|
|
265
|
+
value: 'Actor 1',
|
|
266
|
+
role: 'Manny',
|
|
267
|
+
guest: 'yes',
|
|
268
|
+
url: { value: 'http://example.com/actor1.html', system: 'TestSystem' }
|
|
269
|
+
},
|
|
270
|
+
writer: [
|
|
271
|
+
{ value: 'Writer 1', url: { value: 'http://example.com/w1.html', system: 'TestSystem' } },
|
|
272
|
+
{ value: 'Writer 2', url: { value: 'http://example.com/w2.html', system: 'TestSystem' } }
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
const output = utils.convertToXMLTV({ channels, programs })
|
|
277
|
+
expect(output).toBe(
|
|
278
|
+
'<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><sub-title>Sub-title 1</sub-title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><url>http://example.com/title.html</url><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><date>20220505</date><icon src="https://example.com/images/Program1.png?x=шеллы&sid=777"/><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url></director><actor role="Manny" guest="yes">Actor 1<url system="TestSystem">http://example.com/actor1.html</url></actor><writer>Writer 1<url system="TestSystem">http://example.com/w1.html</url></writer><writer>Writer 2<url system="TestSystem">http://example.com/w2.html</url></writer></credits></programme>\r\n</tv>'
|
|
165
279
|
)
|
|
166
280
|
})
|
|
167
281
|
|