@ygracs/xepg-lib-js 0.0.15

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.
@@ -0,0 +1,1024 @@
1
+ // [v0.1.050-20221206]
2
+
3
+ // === module init block ===
4
+
5
+ const fs = require('fs');
6
+ const fse = require('fs').promises;
7
+ const xmlParser = require('@ygracs/xml-js6');
8
+
9
+ const {
10
+ valueToIndex,
11
+ readAsString, readAsNumberEx,
12
+ isNotEmptyString,
13
+ isArray, isObject, isPlainObject,
14
+ } = require('@ygracs/bsfoc-lib-js');
15
+
16
+ const {
17
+ convValueToTZString, convTZStringToValue,
18
+ } = require('@ygracs/dtf-lib-js');
19
+
20
+ const {
21
+ chkDTSysID, getDTSysName,
22
+ convStringToDTValue, convDTValueToString,
23
+ } = require('./dts-helper.js');
24
+
25
+ const xObj = require('@ygracs/xobj-lib-js');
26
+
27
+ const TXmlContentParseOptions = xObj.TXmlContentParseOptions;
28
+ const insertXObjElement = xObj.insertXObjElement;
29
+ const getXObjElement = xObj.getXObjElement;
30
+
31
+ const XEPG_ROOT_ETAG_NAME = 'epgdoc';
32
+ const XEPG_DEF_NS_NAME = 'tvp';
33
+ const XEPG_DEF_NS_PATH = 'urn:e-doc:epg-doc:xepg';
34
+ const XEPG_HEADER_ETAG_NAME = `${XEPG_DEF_NS_NAME}:info`;
35
+ const XEPG_BODY_ETAG_NAME = `${XEPG_DEF_NS_NAME}:list`;
36
+ const XEPG_SCHED_ETAG_NAME = `${XEPG_DEF_NS_NAME}:item`;
37
+ const XEPG_PRVINFO_ETAG_NAME = `${XEPG_DEF_NS_NAME}:provider`;
38
+ const XEPG_DTSINFO_ETAG_NAME = `${XEPG_DEF_NS_NAME}:dtstype`;
39
+ const XEPG_DOCDTO_ETAG_NAME = `${XEPG_DEF_NS_NAME}:time`;
40
+ const XEPG_DOCDTE_ETAG_NAME = `${XEPG_DEF_NS_NAME}:expire`;
41
+ const XEPG_DOCTZ_ETAG_NAME = `${XEPG_DEF_NS_NAME}:timezone`;
42
+ const XEPG_DOCSCH_ETAG_NAME = `${XEPG_DEF_NS_NAME}:schema`;
43
+ const XEPG_DOCTYP_ETAG_NAME = `${XEPG_DEF_NS_NAME}:doctype`;
44
+ const XEPG_CHNID_ETAG_NAME = `${XEPG_DEF_NS_NAME}:chnid`;
45
+ const XEPG_CHNNAME_ETAG_NAME = `${XEPG_DEF_NS_NAME}:chname`;
46
+ const XEPG_CHNGID_ETAG_NAME = `${XEPG_DEF_NS_NAME}:chngid`;
47
+ const XEPG_CHNURL_ETAG_NAME = `${XEPG_DEF_NS_NAME}:srcurl`;
48
+ const XEPG_SCHEDTIME_ETAG_NAME = `${XEPG_DEF_NS_NAME}:time`;
49
+ const XEPG_SCHEDTITL_ETAG_NAME = `${XEPG_DEF_NS_NAME}:title`;
50
+ const XEPG_SCHEDCAT_ETAG_NAME = `${XEPG_DEF_NS_NAME}:cat`;
51
+ const XEPG_SCHEDPMARK_ETAG_NAME = `${XEPG_DEF_NS_NAME}:pcmark`;
52
+ const XEPG_SCHEDDESC_ETAG_NAME = `${XEPG_DEF_NS_NAME}:desc`;
53
+ const XEPG_XML_DOC_VERSION = '1.0';
54
+ const XEPG_DEF_ENCODING_VALUE = 'UTF-8';
55
+ const XEPG_DEF_DOCUMENT_TYPE = 'xepg';
56
+ const XEPG_DEF_DOCUMENT_SCHEMA = '0.2';
57
+ const XEPG_DEF_PROVIDER_NAME = 'xepg-lib-js';
58
+ const XEPG_DEF_PROVIDER_VER = '0.0.15';
59
+ const defXEpgDocOptions = {
60
+ xmlns_xepg_pref: XEPG_DEF_NS_NAME,
61
+ xmlns_xepg_path: XEPG_DEF_NS_PATH,
62
+ rootElementTagName: XEPG_ROOT_ETAG_NAME,
63
+ docHeaderTagName: XEPG_HEADER_ETAG_NAME,
64
+ docBodyTagName: XEPG_BODY_ETAG_NAME,
65
+ docBodyElementTagName: XEPG_SCHED_ETAG_NAME,
66
+ docProviderElementTagName: XEPG_PRVINFO_ETAG_NAME,
67
+ defProviderParam: {
68
+ name: XEPG_DEF_PROVIDER_NAME,
69
+ version: XEPG_DEF_PROVIDER_VER,
70
+ doctype: XEPG_DEF_DOCUMENT_TYPE,
71
+ schema: XEPG_DEF_DOCUMENT_SCHEMA,
72
+ xml: XEPG_XML_DOC_VERSION,
73
+ encoding: XEPG_DEF_ENCODING_VALUE,
74
+ },
75
+ };
76
+
77
+ const defParseOptions = new TXmlContentParseOptions();
78
+ //console.log('CHECK: defParseOptions => '+JSON.stringify(defParseOptions, null, 2));
79
+
80
+ // === module extra block (helper functions) ===
81
+
82
+ // === xObj-function wrappers (start) ===
83
+
84
+ function readXObjParam(obj){
85
+ return xObj.readXObjParam(obj, defParseOptions.settings.textKey);
86
+ };
87
+
88
+ function writeXObjParam(obj, value){
89
+ return xObj.writeXObjParam(obj, value, defParseOptions.settings.textKey);
90
+ };
91
+
92
+ function writeXObjAttr(obj, name, value) {
93
+ return xObj.writeXObjAttr(
94
+ obj, name, value, defParseOptions.settings.attributesKey
95
+ );
96
+ };
97
+
98
+ // === xObj-function wrappers (end) ===
99
+
100
+ function _getXmlChildElementParam(obj, elem){
101
+ const child = obj ? getXObjElement(obj, elem) : null;
102
+ return child ? readXObjParam(child) : '';
103
+ };
104
+
105
+ function writeXEpgDocDeclSection(obj, opt){
106
+ let xml_ver = XEPG_XML_DOC_VERSION;
107
+ let doc_def_enc = XEPG_DEF_ENCODING_VALUE;
108
+ let key_name = defParseOptions.settings.declarationKey;
109
+ if (isPlainObject(opt)) {
110
+ xml_ver = readAsString(opt.version, xml_ver);
111
+ doc_def_enc = readAsString(opt.encoding, doc_def_enc);
112
+ };
113
+ if (isPlainObject(obj) && isNotEmptyString(key_name)) {
114
+ obj[key_name] = {};
115
+ writeXObjAttr(obj[key_name], 'version', xml_ver);
116
+ writeXObjAttr(obj[key_name], 'encoding', doc_def_enc);
117
+ };
118
+ };
119
+
120
+ // === module main block (function definitions) ===
121
+
122
+ // === module main block (class definitions) ===
123
+
124
+ class TXEpgSchedulesList {
125
+ #_content = null;
126
+ #_options = null;
127
+ #_dts_src = null;
128
+ #_tz_src = null;
129
+
130
+ constructor(obj, opt) {
131
+ const _content = isArray(obj) ? obj : [];
132
+ const _options = isPlainObject(opt) ? opt : {};
133
+ let { dts_src, tz_src } = _options;
134
+ if (!isPlainObject(dts_src)) dts_src = null;
135
+ if (!isPlainObject(tz_src)) tz_src = null;
136
+ // save content source
137
+ this.#_content = _content;
138
+ // save options
139
+ this.#_options = _options;
140
+ // save refs to a time source priveders
141
+ this.#_dts_src = dts_src;
142
+ this.#_tz_src = tz_src;
143
+ }
144
+
145
+ #_getItem = function(value){
146
+ if (this.chkScheduleIndex(value)) {
147
+ return this.#_content[Number(value)];
148
+ };
149
+ };
150
+
151
+ get schedQty(){
152
+ return this.#_content.length;
153
+ }
154
+
155
+ // will deprecate
156
+ //get SchedulesQty(){ return this.#_content.length; }
157
+
158
+ get dtstype(){
159
+ let result = valueToIndex(
160
+ _getXmlChildElementParam(this.#_dts_src, 'value')
161
+ );
162
+ return chkDTSysID(result) ? result : -1;
163
+ }
164
+
165
+ get curDocTZ(){
166
+ return (
167
+ this.#_tz_src
168
+ ? convTZStringToValue(readXObjParam(this.#_tz_src).trim())
169
+ : 0
170
+ );
171
+ }
172
+
173
+ hasNoSchedules(){
174
+ return this.schedQty === 0;
175
+ }
176
+
177
+ hasSchedules(){
178
+ return this.schedQty > 0;
179
+ }
180
+
181
+ chkScheduleIndex(value){
182
+ const index = valueToIndex(value);
183
+ return index !== -1 && index < this.schedQty;
184
+ }
185
+
186
+ getScheduleInfo(index){
187
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => was called...');
188
+ const curObj = this.#_getItem(index);
189
+ let tmpObj = {};
190
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+']');
191
+ //console.log('TXEpgSchedulesList => getScheduleInfo('+index+') => '+JSON.stringify(curObj, null, 2));
192
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+'] - [time]');
193
+ tmpObj.time = convStringToDTValue(
194
+ _getXmlChildElementParam(curObj, XEPG_SCHEDTIME_ETAG_NAME).trim(),
195
+ this.dtstype, this.curDocTZ
196
+ );
197
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+'] - [title]');
198
+ tmpObj.title = _getXmlChildElementParam(curObj, XEPG_SCHEDTITL_ETAG_NAME).trim();
199
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+'] - [category]');
200
+ tmpObj.cat = _getXmlChildElementParam(curObj, XEPG_SCHEDCAT_ETAG_NAME).trim();
201
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+'] - [pcmark]');
202
+ tmpObj.pcmark = readAsNumberEx(
203
+ _getXmlChildElementParam(curObj, XEPG_SCHEDPMARK_ETAG_NAME), 0
204
+ );
205
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => index:['+index+'] - [description]');
206
+ tmpObj.descr = _getXmlChildElementParam(curObj, XEPG_SCHEDDESC_ETAG_NAME);
207
+ //console.log('TXEpgSchedulesList => getScheduleInfo('+index+') => '+JSON.stringify(curObj, null, 2));
208
+ //console.log('TXEpgSchedulesList => getScheduleInfo('+index+') => '+JSON.stringify(tmpObj, null, 2));
209
+ // TODO: wrap tmpObj into container object
210
+ //console.log('TXEpgSchedulesList => getScheduleInfo() => was left...');
211
+ return tmpObj;
212
+ }
213
+
214
+ getAllSchedulesInfo(){
215
+ let result = [];
216
+ for (let i = 0; i < this.schedQty; i++) {
217
+ let item = this.getScheduleInfo(i);
218
+ if (isPlainObject(item)) result.push(item);
219
+ };
220
+ return result;
221
+ }
222
+
223
+ asJSON(){
224
+ return JSON.stringify(this.#_content, null, 2);
225
+ }
226
+
227
+ };
228
+
229
+ class TXEpgProviderContainer {
230
+ #_content = null;
231
+ #_options = null;
232
+
233
+ constructor(obj, opt) {
234
+ // load content
235
+ const _content = isPlainObject(obj) ? obj : {};
236
+ // load options
237
+ const _options = isPlainObject(opt) ? opt : {};
238
+ let {
239
+ parseOptions,
240
+ } = _options;
241
+ if (!(parseOptions instanceof TXmlContentParseOptions)) {
242
+ parseOptions = new TXmlContentParseOptions(parseOptions);
243
+ _options.parseOptions = parseOptions;
244
+ };
245
+ // save content source
246
+ this.#_content = _content;
247
+ // save options
248
+ this.#_options = _options;
249
+ // init instance
250
+ this.#_init();
251
+ }
252
+
253
+ #_init(){
254
+ //const _options = this.#_options;
255
+ //const { rootETagNS } = _options;
256
+ //let { docSchemaETagName, docTypeETagName } = _options;
257
+ //docSchemaETagName = `${rootETagNS}:schema`;
258
+ //docSchemaETagName = XEPG_DOCSCH_ETAG_NAME;
259
+ //docTypeETagName = `${rootETagNS}:doctype`;
260
+ //docTypeETagName = XEPG_DOCTYP_ETAG_NAME;
261
+ //_options.docSchemaETagName = docSchemaETagName;
262
+ //_options.docTypeETagName = docTypeETagName;
263
+ }
264
+
265
+ get name(){
266
+ return _getXmlChildElementParam(this.#_content, 'name').trim();
267
+ }
268
+
269
+ set name(value){
270
+ this.setName(value);
271
+ }
272
+
273
+ get version(){
274
+ return _getXmlChildElementParam(this.#_content, 'version').trim();
275
+ }
276
+
277
+ set version(value){
278
+ if (this.name !== '') {
279
+ const _value = typeof value === 'string' ? value.trim() : '';
280
+ const item = insertXObjElement(this.#_content, 'version', true);
281
+ if (item) writeXObjParam(item, _value);
282
+ };
283
+ }
284
+
285
+ get schema(){
286
+ return _getXmlChildElementParam(this.#_content, XEPG_DOCSCH_ETAG_NAME).trim();
287
+ }
288
+
289
+ set schema(value){
290
+ const _value = typeof value === 'string' ? value.trim() : '';
291
+ const item = insertXObjElement(this.#_content, XEPG_DOCSCH_ETAG_NAME, true);
292
+ if (item) writeXObjParam(item, _value);
293
+ }
294
+
295
+ get doctype(){
296
+ return _getXmlChildElementParam(this.#_content, XEPG_DOCTYP_ETAG_NAME).trim();
297
+ }
298
+
299
+ set doctype(value){
300
+ const _value = typeof value === 'string' ? value.trim() : '';
301
+ const item = insertXObjElement(this.#_content, XEPG_DOCTYP_ETAG_NAME, true);
302
+ if (item) writeXObjParam(item, _value);
303
+ }
304
+
305
+ setName(value){
306
+ let isSUCCEED = false;
307
+ let item = insertXObjElement(this.#_content, 'name', true);
308
+ if (item) {
309
+ const name = typeof value === 'string' ? value.trim() : '';
310
+ isSUCCEED = writeXObjParam(item, name);
311
+ };
312
+ return isSUCCEED;
313
+ }
314
+
315
+ getInfo(){
316
+ return {
317
+ name: this.name,
318
+ version: this.version,
319
+ schema: this.schema,
320
+ doctype: this.doctype,
321
+ };
322
+ }
323
+
324
+ setInfo(obj){
325
+ if (!isObject(obj)) return;
326
+ let name = '';
327
+ let version = '';
328
+ let schema = '';
329
+ let doctype = '';
330
+ if (isArray(obj)) {
331
+ [ name, version, schema, doctype ] = obj;
332
+ } else {
333
+ if (typeof obj.name === 'string') {
334
+ ({ name, version, schema, doctype } = obj);
335
+ } else {
336
+ name = _getXmlChildElementParam(obj, 'name');
337
+ version = _getXmlChildElementParam(obj, 'version');
338
+ schema = _getXmlChildElementParam(obj, XEPG_DOCSCH_ETAG_NAME);
339
+ doctype = _getXmlChildElementParam(obj, XEPG_DOCTYP_ETAG_NAME);
340
+ };
341
+ };
342
+ name = typeof name === 'string' ? name.trim() : '';
343
+ version = typeof version === 'string' ? version.trim() : '';
344
+ schema = typeof schema === 'string' ? schema.trim() : '';
345
+ doctype = typeof doctype === 'string' ? doctype.trim() : '';
346
+ if (name === '') version = '';
347
+ this.setName(name);
348
+ this.version = version;
349
+ this.schema = schema;
350
+ this.doctype = doctype;
351
+ }
352
+
353
+ init(opt){
354
+ let prov_opt = { ...defXEpgDocOptions.defProviderParam };
355
+ let name = '';
356
+ let version = '';
357
+ let schema = '';
358
+ let doctype = '';
359
+ const _options = isObject(opt) ? opt : {};
360
+ if (isArray(_options)) {
361
+ [ name, version, schema, doctype ] = _options;
362
+ } else {
363
+ ({ name, version, schema, doctype } = _options);
364
+ };
365
+ name = readAsString(name, prov_opt.name, true);
366
+ version = readAsString(version, prov_opt.version, true);
367
+ doctype = readAsString(doctype, prov_opt.doctype, true);
368
+ schema = readAsString(schema, prov_opt.schema, true);
369
+ this.name = name;
370
+ this.version = version;
371
+ this.schema = schema;
372
+ this.doctype = doctype;
373
+ }
374
+
375
+ };
376
+
377
+ class TXepgDTSProvider {
378
+ #_content = null;
379
+ #_options = null;
380
+
381
+ constructor(obj, opt) {
382
+ // load content
383
+ const _content = isPlainObject(obj) ? obj : {};
384
+ // load options
385
+ let _options = isPlainObject(opt) ? opt : {};
386
+ let {
387
+ parseOptions,
388
+ } = _options;
389
+ if (!(parseOptions instanceof TXmlContentParseOptions)) {
390
+ parseOptions = new TXmlContentParseOptions(parseOptions);
391
+ _options.parseOptions = parseOptions;
392
+ };
393
+ // save content source
394
+ this.#_content = _content;
395
+ // save options
396
+ this.#_options = _options;
397
+ // init instance
398
+ this.#_init();
399
+ }
400
+
401
+ #_init(){
402
+ insertXObjElement(this.#_content, XEPG_DTSINFO_ETAG_NAME);
403
+ }
404
+
405
+ get dtstype(){
406
+ const item = getXObjElement(this.#_content, XEPG_DTSINFO_ETAG_NAME);
407
+ let result = -1;
408
+ if (isPlainObject(item)) {
409
+ result = valueToIndex(_getXmlChildElementParam(item, 'value'));
410
+ if (!chkDTSysID(result)) result = -1;
411
+ };
412
+ return result;
413
+ }
414
+
415
+ set dtstype(value){
416
+ if (chkDTSysID(value)) {
417
+ const item = getXObjElement(this.#_content, XEPG_DTSINFO_ETAG_NAME);
418
+ if (item) {
419
+ let name = getDTSysName(value);
420
+ let curItem = insertXObjElement(item, 'value', true);
421
+ if (curItem) writeXObjParam(curItem, valueToIndex(value));
422
+ curItem = insertXObjElement(item, 'name', true);
423
+ if (curItem) writeXObjParam(curItem, name);
424
+ };
425
+ };
426
+ }
427
+
428
+ get curDocTZ(){
429
+ return convTZStringToValue(
430
+ _getXmlChildElementParam(this.#_content, XEPG_DOCTZ_ETAG_NAME)
431
+ );
432
+ }
433
+
434
+ set curDocTZ(value){
435
+ let item = insertXObjElement(this.#_content, XEPG_DOCTZ_ETAG_NAME, true);
436
+ if (item) writeXObjParam(item, convValueToTZString(value));
437
+ }
438
+
439
+ };
440
+
441
+ class TXEpgHeaderContainer {
442
+ #_content = null;
443
+ #_options = null;
444
+ #_dtsProv = null;
445
+
446
+ constructor(obj, opt) {
447
+ // load content
448
+ const _content = isPlainObject(obj) ? obj : {};
449
+ // load options
450
+ let _options = isPlainObject(opt) ? opt : {};
451
+ let {
452
+ parseOptions,
453
+ } = _options;
454
+ if (!(parseOptions instanceof TXmlContentParseOptions)) {
455
+ parseOptions = new TXmlContentParseOptions(parseOptions);
456
+ _options.parseOptions = parseOptions;
457
+ };
458
+ // save content source
459
+ this.#_content = _content;
460
+ // save options
461
+ this.#_options = _options;
462
+ // init DTS-provider
463
+ this.#_dtsProv = new TXepgDTSProvider(this.#_content, _options);
464
+ }
465
+
466
+ get dts(){
467
+ return this.#_dtsProv;
468
+ }
469
+
470
+ get dtstype(){
471
+ return this.#_dtsProv.dtstype;
472
+ }
473
+
474
+ set dtstype(value){
475
+ this.#_dtsProv.dtstype = value;
476
+ }
477
+
478
+ get curDocTZ(){
479
+ return this.#_dtsProv.curDocTZ;
480
+ }
481
+
482
+ set curDocTZ(value){
483
+ this.#_dtsProv.curDocTZ = value;
484
+ }
485
+
486
+ #_getProv(){
487
+ const docProv = getXObjElement(this.#_content, XEPG_PRVINFO_ETAG_NAME);
488
+ return isPlainObject(docProv) ? docProv : null;
489
+ }
490
+
491
+ #_initProv(){
492
+ const _content = this.#_content;
493
+ let docProv = getXObjElement(_content, XEPG_PRVINFO_ETAG_NAME);
494
+ if (!docProv) {
495
+ docProv = insertXObjElement(_content, XEPG_PRVINFO_ETAG_NAME);
496
+ };
497
+ return isPlainObject(docProv) ? docProv : null;
498
+ }
499
+
500
+ get Provider(){
501
+ const docProv = this.#_getProv();
502
+ return (
503
+ docProv
504
+ ? new TXEpgProviderContainer(docProv, this.#_options)
505
+ : null
506
+ );
507
+ }
508
+
509
+ getDocumentDT(){
510
+ let dt_str = _getXmlChildElementParam(this.#_content, XEPG_DOCDTO_ETAG_NAME).trim();
511
+ return (
512
+ dt_str !== ''
513
+ ? convStringToDTValue(dt_str, this.dtstype, this.curDocTZ)
514
+ : 0
515
+ );
516
+ }
517
+
518
+ setDocumentDT(){
519
+ let dt_val = Date.now();
520
+ let dt_str = convDTValueToString(dt_val, this.dtstype, this.curDocTZ);
521
+ let item = insertXObjElement(this.#_content, XEPG_DOCDTO_ETAG_NAME, true);
522
+ if (item) writeXObjParam(item, dt_str);
523
+ }
524
+
525
+ getDocumentEDT(){
526
+ let dt_str = _getXmlChildElementParam(this.#_content, XEPG_DOCDTE_ETAG_NAME).trim();
527
+ return (
528
+ dt_str !== ''
529
+ ? convStringToDTValue(dt_str, this.dtstype, this.curDocTZ)
530
+ : 0
531
+ );
532
+ }
533
+
534
+ setDocumentEDT(value){
535
+ // TODO: check if value is a DateTime-string
536
+ let dt_str = convDTValueToString(value, this.dtstype, this.curDocTZ);
537
+ let item = insertXObjElement(this.#_content, XEPG_DOCDTE_ETAG_NAME, true);
538
+ if (item) writeXObjParam(item, dt_str);
539
+ }
540
+
541
+ getChannelInfo(){
542
+ const _content = this.#_content;
543
+ let item = {
544
+ chnid: _getXmlChildElementParam(_content, XEPG_CHNID_ETAG_NAME).trim(),
545
+ chname: _getXmlChildElementParam(_content, XEPG_CHNNAME_ETAG_NAME).trim(),
546
+ chngid: _getXmlChildElementParam(_content, XEPG_CHNGID_ETAG_NAME).trim(),
547
+ srcurl: _getXmlChildElementParam(_content, XEPG_CHNURL_ETAG_NAME).trim(),
548
+ };
549
+ return item;
550
+ }
551
+
552
+ setChannelInfo(obj){
553
+ let chnid = '';
554
+ let chname = '';
555
+ let chngid = '';
556
+ let srcurl = '';
557
+ if (isArray(obj)) {
558
+ [ chnid, chname, chngid, srcurl ] = obj;
559
+ } else if (isObject(obj)) {
560
+ ({ chnid } = obj);
561
+ if (typeof chnid === 'string') {
562
+ ({ chname, chngid, srcurl } = obj);
563
+ } else {
564
+ chnid = _getXmlChildElementParam(obj, XEPG_CHNID_ETAG_NAME).trim();
565
+ chname = _getXmlChildElementParam(obj, XEPG_CHNNAME_ETAG_NAME).trim();
566
+ chngid = _getXmlChildElementParam(obj, XEPG_CHNGID_ETAG_NAME).trim();
567
+ srcurl = _getXmlChildElementParam(obj, XEPG_CHNURL_ETAG_NAME).trim();
568
+ };
569
+ } else if (typeof obj === 'string') {
570
+ chnid = obj;
571
+ } else {
572
+ return;
573
+ };
574
+ chnid = typeof chnid === 'string' ? chnid.trim() : '';
575
+ if (chnid === '') {
576
+ chname = '';
577
+ chngid = '';
578
+ srcurl = '';
579
+ } else {
580
+ chname = typeof chname === 'string' ? chname.trim() : '';
581
+ chngid = typeof chngid === 'string' ? chngid.trim() : '';
582
+ srcurl = typeof srcurl === 'string' ? srcurl.trim() : '';
583
+ };
584
+ let item = null;
585
+ const _content = this.#_content;
586
+ item = insertXObjElement(_content, XEPG_CHNID_ETAG_NAME, true);
587
+ if (item) writeXObjParam(item, chnid);
588
+ item = insertXObjElement(_content, XEPG_CHNNAME_ETAG_NAME, true);
589
+ if (item) writeXObjParam(item, chname);
590
+ item = insertXObjElement(_content, XEPG_CHNGID_ETAG_NAME, true);
591
+ if (item) writeXObjParam(item, chngid);
592
+ item = insertXObjElement(_content, XEPG_CHNURL_ETAG_NAME, true);
593
+ if (item) writeXObjParam(item, srcurl);
594
+ }
595
+
596
+ getProviderInfo(){
597
+ const docProv = this.Provider;
598
+ return docProv ? docProv.getInfo() : null;
599
+ }
600
+
601
+ setProviderInfo(obj){
602
+ if (isArray(obj) || isObject(obj)) {
603
+ let docProv = this.Provider;
604
+ if (!docProv) {
605
+ docProv = this.#_initProv();
606
+ if (docProv) docProv = this.Provider;
607
+ };
608
+ if (docProv) docProv.setInfo(obj);
609
+ };
610
+ }
611
+
612
+ };
613
+
614
+ class TXEpgContentProvider {
615
+ #_content = null;
616
+ #_options = null;
617
+
618
+ constructor(opt){
619
+ // load options
620
+ const _options = isPlainObject(opt) ? opt : {};
621
+ let {
622
+ parseOptions,
623
+ autoBindRoot,
624
+ } = _options;
625
+ if (!(parseOptions instanceof TXmlContentParseOptions)) {
626
+ parseOptions = new TXmlContentParseOptions(parseOptions);
627
+ _options.parseOptions = parseOptions;
628
+ };
629
+ if (typeof autoBindRoot !== 'boolean') autoBindRoot = false;
630
+ // save options
631
+ //_options.autoBindRoot = autoBindRoot; //* // TODO:
632
+ this.#_options = _options;
633
+ // init document content
634
+ this.#_content = {};
635
+ this.init();
636
+ }
637
+
638
+ #_getRoot(){
639
+ const docRoot = getXObjElement(this.#_content, XEPG_ROOT_ETAG_NAME);
640
+ return isPlainObject(docRoot) ? docRoot : null;
641
+ }
642
+
643
+ #_initRoot(){
644
+ const _content = this.#_content;
645
+ let docRoot = getXObjElement(_content, XEPG_ROOT_ETAG_NAME);
646
+ if (!docRoot) {
647
+ docRoot = insertXObjElement(_content, XEPG_ROOT_ETAG_NAME);
648
+ if (docRoot) {
649
+ writeXObjAttr(docRoot, `xmlns:${XEPG_DEF_NS_NAME}`, XEPG_DEF_NS_PATH);
650
+ };
651
+ };
652
+ return isPlainObject(docRoot) ? docRoot : null;
653
+ }
654
+
655
+ #_getHdr(){
656
+ const docRoot = this.#_getRoot();
657
+ let docHdr = null;
658
+ if (docRoot) {
659
+ docHdr = getXObjElement(docRoot, XEPG_HEADER_ETAG_NAME);
660
+ };
661
+ return isPlainObject(docHdr) ? docHdr : null;
662
+ }
663
+
664
+ #_initHdr(){
665
+ let docHdr = this.#_getHdr();
666
+ if (!docHdr) {
667
+ let docRoot = this.#_getRoot();
668
+ if (!docRoot) docRoot = this.#_initRoot();
669
+ if (docRoot) {
670
+ docHdr = insertXObjElement(docRoot, XEPG_HEADER_ETAG_NAME);
671
+ };
672
+ };
673
+ return isPlainObject(docHdr) ? docHdr : null;
674
+ }
675
+
676
+ #_getBody(){
677
+ const docRoot = this.#_getRoot();
678
+ let docBody = null;
679
+ if (docRoot) {
680
+ docBody = getXObjElement(docRoot, XEPG_BODY_ETAG_NAME);
681
+ };
682
+ return isPlainObject(docBody) ? docBody : null;
683
+ }
684
+
685
+ #_initBody(){
686
+ let docBody = this.#_getBody();
687
+ if (!docBody) {
688
+ let docRoot = this.#_getRoot();
689
+ if (!docRoot) docRoot = this.#_initRoot();
690
+ if (docRoot) {
691
+ docBody = insertXObjElement(docRoot, XEPG_BODY_ETAG_NAME);
692
+ };
693
+ };
694
+ return isPlainObject(docBody) ? docBody : null;
695
+ }
696
+
697
+ get Header(){
698
+ const docHdr = this.#_getHdr();
699
+ return (
700
+ docHdr
701
+ ? new TXEpgHeaderContainer(docHdr, this.#_options)
702
+ : null
703
+ );
704
+ }
705
+
706
+ get Provider(){
707
+ const docHdr = this.Header;
708
+ return docHdr ? docHdr.Provider : null;
709
+ }
710
+
711
+ get dts(){
712
+ const docHdr = this.Header;
713
+ return docHdr ? docHdr.dts : null;
714
+ }
715
+
716
+ /* [!] a temporary special method */
717
+ /* will deprecate */
718
+ get Content(){ return this; }
719
+
720
+ get SchedulesList(){
721
+ const _options = this.#_options;
722
+ const docBody = this.#_getBody();
723
+ if (docBody && isArray(docBody[XEPG_SCHED_ETAG_NAME])) {
724
+ const docHdr = this.#_getHdr();
725
+ return new TXEpgSchedulesList(
726
+ docBody[XEPG_SCHED_ETAG_NAME],
727
+ {
728
+ dts_src: getXObjElement(docHdr, XEPG_DTSINFO_ETAG_NAME),
729
+ tz_src: getXObjElement(docHdr, XEPG_DOCTZ_ETAG_NAME),
730
+ },
731
+ );
732
+ };
733
+ }
734
+
735
+ init(){
736
+ const _options = this.#_options;
737
+ const _content = this.#_content;
738
+ const {
739
+ parseOptions,
740
+ } = _options;
741
+ const { settings } = parseOptions;
742
+ const { ignoreDeclaration } = settings;
743
+ if (!ignoreDeclaration) {
744
+ // write document declaration section
745
+ writeXEpgDocDeclSection(_content);
746
+ };
747
+ // initiate document root element
748
+ let docRoot = this.#_getRoot();
749
+ if (!docRoot) docRoot = this.#_initRoot();
750
+ if (docRoot) {
751
+ // initiate document header element
752
+ let docHdr = this.#_getHdr();
753
+ if (!docHdr) docHdr = this.#_initHdr();
754
+ // initiate document provider element
755
+ let docProv = insertXObjElement(
756
+ docHdr,
757
+ XEPG_PRVINFO_ETAG_NAME,
758
+ );
759
+ if (docProv) this.Provider.init();
760
+ // initiate document body element
761
+ let docBody = this.#_getBody();
762
+ if (!docBody) docBody = this.#_initBody();
763
+ if (
764
+ docBody && !isArray(docBody[XEPG_SCHED_ETAG_NAME])
765
+ ) {
766
+ docBody[XEPG_SCHED_ETAG_NAME] = [];
767
+ };
768
+ };
769
+ }
770
+
771
+ saveToXMLString(){
772
+ return xmlParser.js2xml(
773
+ this.#_content,
774
+ this.#_options.parseOptions.js2xml,
775
+ );
776
+ }
777
+
778
+ saveToFile(src_link){
779
+ let saveFile = function(obj){
780
+ return new Promise(function(resolve, reject) {
781
+ let { src_link } = obj;
782
+ if (
783
+ typeof src_link !== 'string'
784
+ || ((src_link = src_link.trim()) === '')
785
+ ) {
786
+ resolve(false);
787
+ };
788
+ fs.writeFile(src_link, obj.content, (err) => {
789
+ if (err) reject(err);
790
+ resolve(true);
791
+ });
792
+ });
793
+ };
794
+ let loadContent = (opt) => { return this.asXML(opt); };
795
+ return new Promise(function(resolve, reject){
796
+ let tmpObj = { src_link: src_link };
797
+ tmpObj.content = loadContent();
798
+ saveFile(tmpObj).then(result => {
799
+ resolve(result);
800
+ }).catch(err => { reject(err); });
801
+ });
802
+ }
803
+
804
+ saveToFileSync(source){
805
+ //console.log('CHECK: TXEpgContentProvider.saveToFileSync() => was called...');
806
+ let data = {
807
+ isSucceed: false,
808
+ source: typeof source === 'string' ? source.trim() : '',
809
+ content: '',
810
+ isERR: false,
811
+ errEvent: '',
812
+ };
813
+ if (data.source !== '') {
814
+ try {
815
+ data.content = this.asXML();
816
+ fs.writeFileSync(data.source, data.content, 'utf8');
817
+ } catch (err) {
818
+ console.log('CHECK: TXEpgContentProvider.saveToFileSync() => Error => '+err);
819
+ console.log('CHECK: TXEpgContentProvider.saveToFileSync() => Error => '+err.code);
820
+ throw err;
821
+ };
822
+ } else {
823
+ data.isERR = true;
824
+ data.errEvent = 'EMPTY_SRCLINK';
825
+ };
826
+ //console.log('CHECK: TXEpgContentProvider.saveToFileSync() => was left...');
827
+ return data;
828
+ }
829
+
830
+ loadFromString(xmlString, opt){
831
+ let isSUCCEED = false;
832
+ if (typeof xmlString === 'string') {
833
+ let _options = this.#_options;
834
+ let parseOptions = null;
835
+ if (isPlainObject(opt)) {
836
+ parseOptions = new TXmlContentParseOptions(opt);
837
+ // // TODO: init user options
838
+ } else {
839
+ parseOptions = _options.parseOptions;
840
+ };
841
+ try {
842
+ this.#_content = xmlParser.xml2js(xmlString, parseOptions.xml2js);
843
+ // init a document header element
844
+ let docHdr = this.#_getHdr();
845
+ if (!docHdr) docHdr = this.#_initHdr();
846
+ // init a document body element
847
+ let docBody = this.#_getBody();
848
+ if (!docBody) docBody = this.#_initBody();
849
+ if (docBody) {
850
+ if (typeof docBody[XEPG_SCHED_ETAG_NAME] !== 'object') {
851
+ docBody[XEPG_SCHED_ETAG_NAME] = [];
852
+ } else if (!isArray(docBody[XEPG_SCHED_ETAG_NAME])) {
853
+ let tmpObj = [];
854
+ tmpObj.push(docBody[XEPG_SCHED_ETAG_NAME]);
855
+ docBody[XEPG_SCHED_ETAG_NAME] = tmpObj;
856
+ };
857
+ isSUCCEED = true;
858
+ };
859
+ } catch (err) {
860
+ console.log('CHECK: TXEpgContentProvider.loadFromString() => err => '+err);
861
+ throw err;
862
+ };
863
+ };
864
+ return isSUCCEED;
865
+ }
866
+
867
+ loadFromFile(source){
868
+ /**/// extend part that return promise as a result
869
+ const loadFile = function(source){
870
+ return new Promise((resolve, reject) => {
871
+ let data = {
872
+ isLoaded: false,
873
+ source: typeof source === 'string' ? source.trim() : '',
874
+ content: '',
875
+ isERR: false,
876
+ errEvent: '',
877
+ };
878
+ if (data.source === '') {
879
+ data.isERR = true;
880
+ data.errEvent = (
881
+ typeof source === 'string' ? 'EMPTY_SRCLINK' : 'NO_SRCLINK'
882
+ );
883
+ resolve(data);
884
+ } else {
885
+ fse.readFile(data.source, 'utf8').then(result => {
886
+ data.content = result;
887
+ if (result != '') {
888
+ data.isLoaded = true;
889
+ data.errEvent = 'OPS_IS_SUCCEED';
890
+ } else {
891
+ data.isERR = true;
892
+ data.errEvent = 'NO_CONTENT';
893
+ };
894
+ resolve(data);
895
+ }).catch(err => {
896
+ switch (err.code) {
897
+ case 'ENOENT':
898
+ case 'EISDIR':
899
+ data.isERR = true;
900
+ data.errEvent = err.code;
901
+ resolve(data);
902
+ break;
903
+ default:
904
+ console.log('CHECK: TXEpgContentProvider.loadFromFile() => [1] loadFile() => Error => '+err.code);
905
+ reject(err);
906
+ break;
907
+ };
908
+ });
909
+ };
910
+ });
911
+ };
912
+ /**/// main part that return promise as a result
913
+ return new Promise((resolve, reject) => {
914
+ loadFile(source).then(data => {
915
+ if (data.isLoaded) {
916
+ if (this.loadFromString(data.content)) {
917
+ data.isLoaded = true;
918
+ data.errEvent = 'OPS_IS_SUCCEED';
919
+ } else {
920
+ data.isERR = true;
921
+ data.errEvent = 'OPS_IS_FAILED';
922
+ };
923
+ } else {
924
+ //console.log('CHECK: TXEpgContentProvider.loadFromFile() => result.isERR:['+data.isERR+']');
925
+ //console.log('CHECK: TXEpgContentProvider.loadFromFile() => result.errEvent:['+data.errEvent+']');
926
+ };
927
+ resolve(data);
928
+ }).catch(err => {
929
+ console.log('CHECK: TXEpgContentProvider.loadFromFile() => loadFile().err() => '+err);
930
+ reject(err);
931
+ });
932
+ });
933
+ }
934
+
935
+ loadFromFileSync(source){
936
+ const loadFile = function(source){
937
+ let data = {
938
+ isLoaded: false,
939
+ source: typeof source === 'string' ? source.trim() : '',
940
+ content: '',
941
+ isERR: false,
942
+ errEvent: '',
943
+ };
944
+ if (data.source === '') {
945
+ data.isERR = true;
946
+ data.errEvent = (
947
+ typeof source === 'string' ? 'EMPTY_SRCLINK' : 'NO_SRCLINK'
948
+ );
949
+ } else {
950
+ try {
951
+ data.content = fs.readFileSync(data.source, 'utf8');
952
+ if (data.content !== '') {
953
+ data.isLoaded = true;
954
+ data.errEvent = 'OPS_IS_SUCCEED';
955
+ } else {
956
+ data.isERR = true;
957
+ data.errEvent = 'NO_CONTENT';
958
+ };
959
+ } catch (err) {
960
+ switch (err.code) {
961
+ case 'ENOENT':
962
+ case 'EISDIR':
963
+ data.isERR = true;
964
+ data.errEvent = err.code;
965
+ break;
966
+ default:
967
+ console.log('CHECK: TXEpgContentProvider.loadFromFileSync() => [1] loadFile() => Error => '+err.code);
968
+ throw err;
969
+ break;
970
+ };
971
+ };
972
+ };
973
+ return data;
974
+ };
975
+ let result = {
976
+ isLoaded: false,
977
+ isERR: false,
978
+ errEvent: '',
979
+ };
980
+ try {
981
+ result = loadFile(source);
982
+ if (result.isLoaded) {
983
+ if (this.loadFromString(result.content)) {
984
+ result.isLoaded = true;
985
+ result.errEvent = 'OPS_IS_SUCCEED';
986
+ } else {
987
+ result.isERR = true;
988
+ result.errEvent = 'OPS_IS_FAILED';
989
+ };
990
+ } else {
991
+ //console.log('CHECK: TXEpgContentProvider.loadFromFileSync() => result.isERR:['+result.isERR+']');
992
+ //console.log('CHECK: TXEpgContentProvider.loadFromFileSync() => result.errEvent:['+result.errEvent+']');
993
+ };
994
+ } catch (err) {
995
+ console.log('CHECK: TXEpgContentProvider.loadFromFileSync() => loadFile().err() => '+err);
996
+ throw err;
997
+ };
998
+ return result;
999
+ }
1000
+
1001
+ // will deprecate
1002
+ asXML(opt){
1003
+ let parseOptions = isPlainObject(opt) ? opt : defParseOptions.js2xml;
1004
+ return xmlParser.js2xml(this.#_content, parseOptions);
1005
+ }
1006
+
1007
+ asJSON(){
1008
+ return JSON.stringify(this.#_content, null, 2);
1009
+ }
1010
+
1011
+ }
1012
+
1013
+ // === module exports block ===
1014
+
1015
+ exports.TXepgDTSProvider = TXepgDTSProvider;
1016
+ exports.TXEpgSchedulesList = TXEpgSchedulesList;
1017
+ exports.TXEpgProviderContainer = TXEpgProviderContainer;
1018
+ exports.TXEpgHeaderContainer = TXEpgHeaderContainer;
1019
+ exports.TXEpgContentProvider = TXEpgContentProvider;
1020
+
1021
+ exports.XEPG_DEF_PROVIDER_NAME = XEPG_DEF_PROVIDER_NAME;
1022
+ exports.XEPG_DEF_PROVIDER_VER = XEPG_DEF_PROVIDER_VER;
1023
+ exports.XEPG_DEF_DOCUMENT_TYPE = XEPG_DEF_DOCUMENT_TYPE;
1024
+ exports.XEPG_DEF_DOCUMENT_SCHEMA = XEPG_DEF_DOCUMENT_SCHEMA;