epg-grabber 0.46.1 → 0.47.0

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/.prettierrc.js ADDED
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ tabWidth: 2,
3
+ useTabs: false,
4
+ endOfLine: "crlf",
5
+ semi: false,
6
+ singleQuote: true,
7
+ printWidth: 100,
8
+ trailingComma: "none",
9
+ arrowParens: "avoid",
10
+ };
package/README.md CHANGED
@@ -8,61 +8,6 @@ Node.js CLI tool for grabbing EPG from different websites.
8
8
  npm install -g epg-grabber
9
9
  ```
10
10
 
11
- ## Quick Start
12
-
13
- ```sh
14
- epg-grabber --config=example.com.config.js
15
- ```
16
-
17
- #### example.com.config.js
18
-
19
- ```js
20
- module.exports = {
21
- site: 'example.com',
22
- channels: 'example.com.channels.xml',
23
- url: function (context) {
24
- const { date, channel } = context
25
-
26
- return `https://api.example.com/${date.format('YYYY-MM-DD')}/channel/${channel.site_id}`
27
- },
28
- parser: function (context) {
29
- const programs = JSON.parse(context.content)
30
-
31
- return programs.map(program => {
32
- return {
33
- title: program.title,
34
- start: program.start,
35
- stop: program.stop
36
- }
37
- })
38
- }
39
- }
40
- ```
41
-
42
- #### example.com.channels.xml
43
-
44
- ```xml
45
- <?xml version="1.0" ?>
46
- <channels site="example.com">
47
- <channel site_id="cnn-23" xmltv_id="CNN.us">CNN</channel>
48
- </channels>
49
- ```
50
-
51
- ## Example Output
52
-
53
- ```xml
54
- <tv>
55
- <channel id="CNN.us">
56
- <display-name>CNN</display-name>
57
- <url>https://example.com</url>
58
- </channel>
59
- <programme start="20211116040000 +0000" stop="20211116050000 +0000" channel="CNN.us">
60
- <title lang="en">News at 10PM</title>
61
- </programme>
62
- // ...
63
- </tv>
64
- ```
65
-
66
11
  ## CLI
67
12
 
68
13
  ```sh
@@ -86,7 +31,15 @@ Arguments:
86
31
  - `--log`: path to log file (optional)
87
32
  - `--log-level`: set the log level (default: `info`)
88
33
 
89
- ## Site Config
34
+ ## How to use?
35
+
36
+ First, you need to create two files:
37
+
38
+ <details>
39
+ <summary>example.com.config.js</summary>
40
+ <br>
41
+
42
+ This file describes what kind of request we need to send to get the guide for a particular channel on a certain date and how to parse the response.
90
43
 
91
44
  ```js
92
45
  module.exports = {
@@ -182,14 +135,14 @@ module.exports = {
182
135
  }
183
136
  ```
184
137
 
185
- ## Request Context Object
138
+ ### Request Context Object
186
139
 
187
140
  Inside `url()`, `logo()`, `request.data()`, `request.headers()` functions in `config.js` you can access a `context` object containing the following data:
188
141
 
189
142
  - `channel`: The object describing the current channel (xmltv_id, site_id, name, lang)
190
143
  - `date`: The 'dayjs' instance with the requested date
191
144
 
192
- ## Parser Context Object
145
+ ### Parser Context Object
193
146
 
194
147
  Inside `parser()` function in `config.js` you can access a `context` object containing the following data:
195
148
 
@@ -201,7 +154,7 @@ Inside `parser()` function in `config.js` you can access a `context` object cont
201
154
  - `request`: The request config
202
155
  - `cached`: A boolean to check whether this request was cached or not
203
156
 
204
- ## Program Object
157
+ ### Program Object
205
158
 
206
159
  | Property | Aliases | Type | Required |
207
160
  | --------------- | -------------------------------- | ------------------------------------------------ | -------- |
@@ -371,7 +324,13 @@ Example:
371
324
  }
372
325
  ```
373
326
 
374
- ## Channels List
327
+ </details>
328
+
329
+ <details>
330
+ <summary>example.com.channels.xml</summary>
331
+ <br>
332
+
333
+ This file contains a list of channels available at the source.
375
334
 
376
335
  ```xml
377
336
  <?xml version="1.0" ?>
@@ -395,6 +354,28 @@ You can also specify the language, site, url, logo and LCN (Logical Channel Numb
395
354
  >France 24</channel>
396
355
  ```
397
356
 
357
+ </details>
358
+
359
+ After that, you just need to run the grabber with path to the config file:
360
+
361
+ ```sh
362
+ epg-grabber --config=path/to/example.com.config.js
363
+ ```
364
+
365
+ And when the download is complete, a ready-to-use guide will appear in the location you specified:
366
+
367
+ ```xml
368
+ <tv>
369
+ <channel id="CNN.us">
370
+ <display-name>CNN</display-name>
371
+ </channel>
372
+ <programme start="20211116040000 +0000" stop="20211116050000 +0000" channel="CNN.us">
373
+ <title lang="en">News at 10PM</title>
374
+ </programme>
375
+ // ...
376
+ </tv>
377
+ ```
378
+
398
379
  ## How to use SOCKS proxy?
399
380
 
400
381
  ```
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as name, v as version, d as description, p as parseNumber, l as loadJs, a as parseProxy, E as EPGGrabberMock, b as EPGGrabber, c as defaultConfig, i as isObject, g as getAbsPath, e as getUTCDate } from './index-Bnw63KMN.js';
2
+ import { n as name, v as version, d as description, p as parseNumber, l as loadJs, a as parseProxy, E as EPGGrabberMock, b as EPGGrabber, c as defaultConfig, i as isObject, g as getAbsPath, e as getUTCDate } from './index-Dm69fQTU.js';
3
3
  import { Collection, Template } from '@freearhey/core';
4
4
  import { Command, Option } from 'commander';
5
5
  import { SocksProxyAgent } from 'socks-proxy-agent';
@@ -220,7 +220,8 @@ async function main() {
220
220
  })
221
221
  );
222
222
  await Promise$1.all(requests.all());
223
- const xml = EPGGrabber.generateXMLTV(groupChannels.all(), programs.all(), utcDate);
223
+ const headers = { date: utcDate.format("YYYYMMDD") };
224
+ const xml = EPGGrabber.generateXMLTV(groupChannels.all(), programs.all(), headers);
224
225
  const channelSample = groupChannels.sample();
225
226
  let outputPath = template.format(channelSample.toObject());
226
227
  const outputDir = path$1.dirname(outputPath);
@@ -35,9 +35,6 @@ function parseNumber(value) {
35
35
  function sleep(ms) {
36
36
  return new Promise((resolve) => setTimeout(resolve, ms));
37
37
  }
38
- function isDate(date) {
39
- return dayjs(date).isValid();
40
- }
41
38
  function isObject(value) {
42
39
  return !!value && value.constructor === Object;
43
40
  }
@@ -65,9 +62,6 @@ function escapeString(value, defaultValue = "") {
65
62
  function formatDate(date, format) {
66
63
  return date ? dayjs.utc(date).format(format) : "";
67
64
  }
68
- function toURL(domain) {
69
- return domain ? `https://${domain}` : "";
70
- }
71
65
  function createXMLElement(name, attrs, children) {
72
66
  return convertXMLElementToString({ name, attrs, children });
73
67
  }
@@ -102,7 +96,7 @@ function toArray(value) {
102
96
  }
103
97
 
104
98
  var name = "epg-grabber";
105
- var version = "0.46.1";
99
+ var version = "0.47.0";
106
100
  var description = "Node.js CLI tool for grabbing EPG from different sites";
107
101
  var homepage = "https://github.com/freearhey/epg-grabber";
108
102
 
@@ -145,7 +139,7 @@ class Channel {
145
139
  this.site_id = data.site_id;
146
140
  this.lang = data.lang;
147
141
  this.logo = data.logo;
148
- this.url = data.url || toURL(data.site);
142
+ this.url = data.url;
149
143
  this.lcn = data.lcn;
150
144
  this.index = data.index !== void 0 ? data.index : -1;
151
145
  }
@@ -799,18 +793,15 @@ class EPGGrabber {
799
793
  ).filter(Boolean);
800
794
  return channels;
801
795
  }
802
- static generateXMLTV(channels, programs, date = getUTCDate()) {
796
+ static generateXMLTV(channels, programs, headers) {
803
797
  if (!channels.every((channel) => channel instanceof Channel)) {
804
798
  throw new Error('"channels" must be an array of Channels');
805
799
  }
806
800
  if (!programs.every((program) => program instanceof Program)) {
807
801
  throw new Error('"programs" must be an array of Programs');
808
802
  }
809
- if (!isDate(date)) {
810
- throw new Error('"date" must be a valid date');
811
- }
812
803
  let output = `<?xml version="1.0" encoding="UTF-8" ?>`;
813
- output += createXMLElement("tv", { date: formatDate(date, "YYYYMMDD") }, [
804
+ output += createXMLElement("tv", headers, [
814
805
  ...channels.map((channel) => "\r\n" + channel.toXML()),
815
806
  ...programs.map((program) => "\r\n" + program.toXML()),
816
807
  "\r\n"
package/dist/index.d.ts CHANGED
@@ -710,7 +710,7 @@ declare class EPGGrabber {
710
710
  loadLogo(channel: Channel, date: string | number | Date | Dayjs | null, config?: SiteConfig): Promise<string | null>;
711
711
  grab(channel: Channel, date: string | number | Date | Dayjs | null, config?: SiteConfig | GrabCallback, callback?: GrabCallback): Promise<Program[]>;
712
712
  static parseChannelsXML(xml: string): Channel[];
713
- static generateXMLTV(channels: Channel[], programs: Program[], date?: Dayjs): string;
713
+ static generateXMLTV(channels: Channel[], programs: Program[], headers?: Record<string, string>): string;
714
714
  }
715
715
  declare class EPGGrabberMock extends EPGGrabber {
716
716
  grab(channel: Channel, date: string | number | Date | Dayjs | null, config?: SiteConfig | GrabCallback, callback?: GrabCallback): Promise<Program[]>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- export { C as Channel, b as EPGGrabber, E as EPGGrabberMock, P as Program } from './index-Bnw63KMN.js';
2
+ export { C as Channel, b as EPGGrabber, E as EPGGrabberMock, P as Program } from './index-Dm69fQTU.js';
3
3
  import 'axios-mock-adapter';
4
4
  import 'lodash.merge';
5
5
  import 'xml-js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epg-grabber",
3
- "version": "0.46.1",
3
+ "version": "0.47.0",
4
4
  "description": "Node.js CLI tool for grabbing EPG from different sites",
5
5
  "homepage": "https://github.com/freearhey/epg-grabber",
6
6
  "preferGlobal": true,
@@ -18,7 +18,8 @@
18
18
  "build": "pkgroll --clean-dist",
19
19
  "dev": "pkgroll --watch",
20
20
  "lint": "npx eslint ./src/**/*.ts ./tests/**/*.ts",
21
- "test": "npx vitest run"
21
+ "test": "npx vitest run",
22
+ "prepublishOnly": "npm run build"
22
23
  },
23
24
  "publishConfig": {
24
25
  "registry": "https://registry.npmjs.org/"
@@ -34,7 +35,7 @@
34
35
  "url": "https://github.com/freearhey/epg-grabber.git"
35
36
  },
36
37
  "engines": {
37
- "node": ">=22.12.0"
38
+ "node": ">=20.20.0"
38
39
  },
39
40
  "dependencies": {
40
41
  "@freearhey/core": "^0.14.0",
@@ -70,5 +71,8 @@
70
71
  "typescript": "^5.9.2",
71
72
  "typescript-eslint": "^8.44.1",
72
73
  "vitest": "^3.2.4"
74
+ },
75
+ "overrides": {
76
+ "esbuild": "0.23.1"
73
77
  }
74
78
  }
package/src/cli.ts CHANGED
@@ -12,7 +12,6 @@ import defaultConfig from './default.config'
12
12
  import { Program, Channel } from './models'
13
13
  import { Logger } from './core/logger'
14
14
  import { SiteConfig } from './types'
15
- import { AxiosHeaders } from 'axios'
16
15
  import { TaskQueue } from 'cwait'
17
16
  import merge from 'lodash.merge'
18
17
  import Promise from 'bluebird'
@@ -265,7 +264,8 @@ async function main() {
265
264
 
266
265
  await Promise.all(requests.all())
267
266
 
268
- const xml = EPGGrabber.generateXMLTV(groupChannels.all(), programs.all(), utcDate)
267
+ const headers = { date: utcDate.format('YYYYMMDD') }
268
+ const xml = EPGGrabber.generateXMLTV(groupChannels.all(), programs.all(), headers)
269
269
  const channelSample = groupChannels.sample()
270
270
  let outputPath = template.format(channelSample.toObject() as { [key: string]: any })
271
271
  const outputDir = path.dirname(outputPath)
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { sleep, getUTCDate, isPromise, isDate, createXMLElement, formatDate } from './core/utils'
1
+ import { sleep, getUTCDate, isPromise, createXMLElement } from './core/utils'
2
2
  import { ProgramParserResult } from './types/program'
3
3
  import AxiosMockAdapter from 'axios-mock-adapter'
4
4
  import { SiteConfig } from './types/siteConfig'
@@ -136,7 +136,7 @@ export class EPGGrabber {
136
136
  static generateXMLTV(
137
137
  channels: Channel[],
138
138
  programs: Program[],
139
- date: Dayjs = getUTCDate()
139
+ headers?: Record<string, string>
140
140
  ): string {
141
141
  if (!channels.every((channel: Channel) => channel instanceof Channel)) {
142
142
  throw new Error('"channels" must be an array of Channels')
@@ -146,12 +146,8 @@ export class EPGGrabber {
146
146
  throw new Error('"programs" must be an array of Programs')
147
147
  }
148
148
 
149
- if (!isDate(date)) {
150
- throw new Error('"date" must be a valid date')
151
- }
152
-
153
149
  let output = `<?xml version="1.0" encoding="UTF-8" ?>`
154
- output += createXMLElement('tv', { date: formatDate(date, 'YYYYMMDD') }, [
150
+ output += createXMLElement('tv', headers, [
155
151
  ...channels.map((channel: Channel) => '\r\n' + channel.toXML()),
156
152
  ...programs.map((program: Program) => '\r\n' + program.toXML()),
157
153
  '\r\n'
@@ -1,4 +1,4 @@
1
- import { toURL, escapeString, createXMLElement } from '../core/utils'
1
+ import { escapeString, createXMLElement } from '../core/utils'
2
2
  import { ChannelData } from '../types/channel'
3
3
  import xmlJs from 'xml-js'
4
4
 
@@ -20,7 +20,7 @@ export class Channel {
20
20
  this.site_id = data.site_id
21
21
  this.lang = data.lang
22
22
  this.logo = data.logo
23
- this.url = data.url || toURL(data.site)
23
+ this.url = data.url
24
24
  this.lcn = data.lcn
25
25
  this.index = data.index !== undefined ? data.index : -1
26
26
  }
@@ -1,8 +1,8 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
3
- <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
4
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>
5
- <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example.com</url></channel>
2
+ <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
3
+ <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
4
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/></channel>
5
+ <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
6
6
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="3TV.com"><title>Program1</title></programme>
7
7
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="3TV.com"><title>Program1</title></programme>
8
8
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="2TV.com"><title>Program1</title></programme>
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url><lcn>36</lcn></channel>
3
- <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example.com</url></channel>
2
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><lcn>36</lcn></channel>
3
+ <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
4
4
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
5
5
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
6
6
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="2TV.com"><title>Program1</title></programme>
@@ -1,3 +1,3 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url><lcn>36</lcn></channel>
2
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><lcn>36</lcn></channel>
3
3
  </tv>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">
2
+ <channel id="1TV.co"><display-name>1 TV</display-name><icon src="https://example.com/channel_one_icon.jpg"/><url>https://example.com/channel_one?foo=foo&amp;bar=bar</url><lcn>36</lcn></channel>
3
+ <channel id="2TV.co"><display-name>2 TV</display-name><icon src="https://example.com/logos/2TV.png"/></channel>
4
+ <channel id="3TV.co"><display-name>3 TV</display-name></channel>
5
+ <programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.co"><title>Program 1</title><sub-title>Sub-title &amp; 1</sub-title><desc>Description for Program 1</desc><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url><image>https://example.com/image1.jpg</image><image type="person" size="2" orient="P" system="TestSystem">https://example.com/image2.jpg</image></director><director>Director 2</director><actor>Actor 1</actor><actor>Actor 2</actor><writer>Writer 1</writer></credits><date>20220506</date><category>Test</category><keyword lang="en">physical-comedy</keyword><keyword lang="en">romantic</keyword><language>English</language><orig-language lang="en">French</orig-language><length units="minutes">60</length><country>US</country><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><video><present>yes</present><colour>no</colour><aspect>16:9</aspect><quality>HDTV</quality></video><audio><present>yes</present><stereo>Dolby Digital</stereo></audio><previously-shown/><premiere>First time on British TV</premiere><last-chance lang="en">Last time on this channel</last-chance><new/><subtitles type="teletext"><language>English</language></subtitles><subtitles type="onscreen"><language lang="en">Spanish</language></subtitles><rating system="MPAA"><value>P&amp;G</value><icon src="http://example.com/pg_symbol.png"/></rating><star-rating system="TV Guide"><value>4/5</value><icon src="stars.png"/></star-rating><star-rating system="IMDB"><value>8/10</value></star-rating><review type="text" source="Rotten Tomatoes" reviewer="Joe Bloggs" lang="en">This is a fantastic show!</review><review type="text" source="IDMB" reviewer="Jane Doe" lang="en">I love this show!</review><review type="url" source="Rotten Tomatoes" reviewer="Joe Bloggs" lang="en">https://example.com/programme_one_review</review><image type="poster" size="1" orient="P" system="tvdb">https://tvdb.com/programme_one_poster_1.jpg?foo=foo&amp;bar=bar</image><image type="poster" size="2" orient="P" system="tmdb">https://tmdb.com/programme_one_poster_2.jpg</image><image type="backdrop" size="3" orient="L" system="tvdb">https://tvdb.com/programme_one_backdrop_3.jpg</image><image type="backdrop" size="3" orient="L" system="tmdb">https://tmdb.com/programme_one_backdrop_3.jpg</image><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/></programme>
6
+ <programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="2TV.co"><title lang="es">Program 2</title></programme>
7
+ </tv>
@@ -1,4 +1,4 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url><lcn>36</lcn></channel>
3
- <channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>
2
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><lcn>36</lcn></channel>
3
+ <channel id="2TV.com"><display-name>2 TV</display-name></channel>
4
4
  </tv>
@@ -1,3 +1,3 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>
2
+ <channel id="2TV.com"><display-name>2 TV</display-name></channel>
3
3
  </tv>
@@ -1,8 +1,8 @@
1
1
  <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>
3
- <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example.com</url></channel>
4
- <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
5
- <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
2
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/></channel>
3
+ <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
4
+ <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
5
+ <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/></channel>
6
6
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
7
7
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="4TV.com"><title>Program1</title></programme>
8
8
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="3TV.com"><title>Program1</title></programme>
@@ -7,8 +7,10 @@ import { EPGGrabber, EPGGrabberMock } from '../src/index'
7
7
  import { SiteConfig } from '../src/types/siteConfig'
8
8
  import * as epgGrabber from '../src/index'
9
9
  import { http, HttpResponse } from 'msw'
10
+ import { pathToFileURL } from 'node:url'
10
11
  import { setupServer } from 'msw/node'
11
12
  import path from 'node:path'
13
+ import dayjs from 'dayjs'
12
14
  import fs from 'fs-extra'
13
15
 
14
16
  describe('EPGGrabber', () => {
@@ -444,11 +446,11 @@ describe('EPGGrabber', () => {
444
446
  })
445
447
  ]
446
448
 
447
- const output = EPGGrabber.generateXMLTV(channels, programs)
449
+ const output = EPGGrabber.generateXMLTV(channels, programs, { date: dayjs.utc().format('YYYYMMDD') })
448
450
 
449
- expect(output).toBe(
450
- '<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.co"><display-name>1 TV</display-name><icon src="https://example.com/channel_one_icon.jpg"/><url>https://example.com/channel_one?foo=foo&amp;bar=bar</url><lcn>36</lcn></channel>\r\n<channel id="2TV.co"><display-name>2 TV</display-name><icon src="https://example.com/logos/2TV.png"/><url>https://example.com</url></channel>\r\n<channel id="3TV.co"><display-name>3 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.co"><title>Program 1</title><sub-title>Sub-title &amp; 1</sub-title><desc>Description for Program 1</desc><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url><image>https://example.com/image1.jpg</image><image type="person" size="2" orient="P" system="TestSystem">https://example.com/image2.jpg</image></director><director>Director 2</director><actor>Actor 1</actor><actor>Actor 2</actor><writer>Writer 1</writer></credits><date>20220506</date><category>Test</category><keyword lang="en">physical-comedy</keyword><keyword lang="en">romantic</keyword><language>English</language><orig-language lang="en">French</orig-language><length units="minutes">60</length><country>US</country><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><video><present>yes</present><colour>no</colour><aspect>16:9</aspect><quality>HDTV</quality></video><audio><present>yes</present><stereo>Dolby Digital</stereo></audio><previously-shown/><premiere>First time on British TV</premiere><last-chance lang="en">Last time on this channel</last-chance><new/><subtitles type="teletext"><language>English</language></subtitles><subtitles type="onscreen"><language lang="en">Spanish</language></subtitles><rating system="MPAA"><value>P&amp;G</value><icon src="http://example.com/pg_symbol.png"/></rating><star-rating system="TV Guide"><value>4/5</value><icon src="stars.png"/></star-rating><star-rating system="IMDB"><value>8/10</value></star-rating><review type="text" source="Rotten Tomatoes" reviewer="Joe Bloggs" lang="en">This is a fantastic show!</review><review type="text" source="IDMB" reviewer="Jane Doe" lang="en">I love this show!</review><review type="url" source="Rotten Tomatoes" reviewer="Joe Bloggs" lang="en">https://example.com/programme_one_review</review><image type="poster" size="1" orient="P" system="tvdb">https://tvdb.com/programme_one_poster_1.jpg?foo=foo&amp;bar=bar</image><image type="poster" size="2" orient="P" system="tmdb">https://tmdb.com/programme_one_poster_2.jpg</image><image type="backdrop" size="3" orient="L" system="tvdb">https://tvdb.com/programme_one_backdrop_3.jpg</image><image type="backdrop" size="3" orient="L" system="tmdb">https://tmdb.com/programme_one_backdrop_3.jpg</image><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/></programme>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="2TV.co"><title lang="es">Program 2</title></programme>\r\n</tv>'
451
- )
451
+ expect(output).toEqual(
452
+ fs.readFileSync(pathToFileURL('tests/__data__/expected/index.guide.xml'), 'utf8')
453
+ )
452
454
  })
453
455
  })
454
456
  })
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" ?><tv date="20251028">
2
- <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
3
- <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
4
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>
5
- <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example.com</url></channel>
6
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="3TV.com"><title>Program1</title></programme>
7
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="3TV.com"><title>Program1</title></programme>
8
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="2TV.com"><title>Program1</title></programme>
9
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="2TV.com"><title>Program1</title></programme>
10
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
11
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
12
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="4TV.com"><title>Program1</title></programme>
13
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="4TV.com"><title>Program1</title></programme>
14
- </tv>