diff --git a/.gitignore b/.gitignore index ebf1164e..e31b99df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /node_modules/ /logs/ /guide.xml +/guide.xml.gz /.artifacts/ \ No newline at end of file diff --git a/.readme/template.md b/.readme/template.md index 9dc85d98..6ad25984 100644 --- a/.readme/template.md +++ b/.readme/template.md @@ -9,6 +9,8 @@ To load a program guide, all you need to do is copy the link to one or more of t #include "./.readme/_countries.md" +To use a compressed version of the files, add `.gz` to the end of the filename. + ## API The API documentation can be found in the [iptv-org/api](https://github.com/iptv-org/api) repository. diff --git a/package-lock.json b/package-lock.json index 5799aadd..946423fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,14 @@ "name": "epg", "license": "MIT", "dependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", "axios": "^0.21.1", "chalk": "^4.1.2", "cheerio": "^1.0.0-rc.10", "commander": "^8.2.0", "csv-parser": "^3.0.0", "dayjs": "^1.10.8", - "epg-grabber": "^0.23.0", + "epg-grabber": "^0.24.0", "epg-parser": "^0.1.6", "form-data": "^4.0.0", "fs-extra": "^10.0.1", @@ -27,6 +28,7 @@ "mockdate": "^3.0.5", "nedb-promises": "^5.0.3", "node-cleanup": "^2.1.2", + "node-gzip": "^1.1.2", "parse-duration": "^1.0.0", "pdf-parse": "^1.1.1", "signale": "^1.4.0", @@ -36,6 +38,11 @@ "wildcard-match": "^5.1.2" } }, + "node_modules/@alex_neo/jest-expect-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", + "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==" + }, "node_modules/@babel/code-frame": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", @@ -2206,9 +2213,9 @@ } }, "node_modules/epg-grabber": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.23.0.tgz", - "integrity": "sha512-tjMH8+UxguXNkI30gwISeXRvErlByXHGpvLBLq/eDHAPT9pQ6G96R7UHHJ+vZ4fIaMTZEh3aiTKnzjO+trlGhw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.24.0.tgz", + "integrity": "sha512-TrFKHF3kUjffJDCASBv/gyjlIcahbIJf02TgmgKzFQjSZYCLhqR87U7MXbWkioftdM5BLoQKbuaI/OQGbIJsBQ==", "dependencies": { "axios": "^0.21.1", "axios-cookiejar-support": "^1.0.1", @@ -2218,6 +2225,7 @@ "dayjs": "^1.10.4", "glob": "^7.1.6", "lodash": "^4.17.21", + "node-gzip": "^1.1.2", "tough-cookie": "^4.0.0", "winston": "^3.3.3", "xml-js": "^1.6.11" @@ -4232,6 +4240,11 @@ "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=" }, + "node_modules/node-gzip": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/node-gzip/-/node-gzip-1.1.2.tgz", + "integrity": "sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==" + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -5890,6 +5903,11 @@ } }, "dependencies": { + "@alex_neo/jest-expect-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", + "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==" + }, "@babel/code-frame": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", @@ -7573,9 +7591,9 @@ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, "epg-grabber": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.23.0.tgz", - "integrity": "sha512-tjMH8+UxguXNkI30gwISeXRvErlByXHGpvLBLq/eDHAPT9pQ6G96R7UHHJ+vZ4fIaMTZEh3aiTKnzjO+trlGhw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.24.0.tgz", + "integrity": "sha512-TrFKHF3kUjffJDCASBv/gyjlIcahbIJf02TgmgKzFQjSZYCLhqR87U7MXbWkioftdM5BLoQKbuaI/OQGbIJsBQ==", "requires": { "axios": "^0.21.1", "axios-cookiejar-support": "^1.0.1", @@ -7585,6 +7603,7 @@ "dayjs": "^1.10.4", "glob": "^7.1.6", "lodash": "^4.17.21", + "node-gzip": "^1.1.2", "tough-cookie": "^4.0.0", "winston": "^3.3.3", "xml-js": "^1.6.11" @@ -9102,6 +9121,11 @@ "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=" }, + "node-gzip": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/node-gzip/-/node-gzip-1.1.2.tgz", + "integrity": "sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==" + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", diff --git a/package.json b/package.json index 0e8af9ef..f05cc50a 100644 --- a/package.json +++ b/package.json @@ -23,16 +23,20 @@ "author": "Arhey", "license": "MIT", "jest": { - "testRegex": "(sites|tests)/(.*?/)?.*test.js$" + "testRegex": "(sites|tests)/(.*?/)?.*test.js$", + "setupFilesAfterEnv": [ + "@alex_neo/jest-expect-message" + ] }, "dependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", "axios": "^0.21.1", "chalk": "^4.1.2", "cheerio": "^1.0.0-rc.10", "commander": "^8.2.0", "csv-parser": "^3.0.0", "dayjs": "^1.10.8", - "epg-grabber": "^0.23.0", + "epg-grabber": "^0.24.0", "epg-parser": "^0.1.6", "form-data": "^4.0.0", "fs-extra": "^10.0.1", @@ -46,6 +50,7 @@ "mockdate": "^3.0.5", "nedb-promises": "^5.0.3", "node-cleanup": "^2.1.2", + "node-gzip": "^1.1.2", "parse-duration": "^1.0.0", "pdf-parse": "^1.1.1", "signale": "^1.4.0", diff --git a/scripts/commands/guides/update.js b/scripts/commands/guides/update.js index f7de932e..4c0727c8 100644 --- a/scripts/commands/guides/update.js +++ b/scripts/commands/guides/update.js @@ -1,4 +1,4 @@ -const { db, logger, file, api } = require('../../core') +const { db, logger, file, api, zip } = require('../../core') const grabber = require('epg-grabber') const _ = require('lodash') @@ -42,6 +42,8 @@ async function main() { logger.info(`Creating "${filepath}"...`) const output = grabber.convertToXMLTV({ channels, programs }) await file.create(filepath, output) + const compressed = await zip.compress(output) + await file.create(filepath + '.gz', compressed) } if (!total) { diff --git a/scripts/core/index.js b/scripts/core/index.js index 807edaad..c6c607a5 100644 --- a/scripts/core/index.js +++ b/scripts/core/index.js @@ -8,3 +8,4 @@ exports.api = require('./api') exports.date = require('./date') exports.table = require('./table') exports.xml = require('./xml') +exports.zip = require('./zip') diff --git a/scripts/core/zip.js b/scripts/core/zip.js new file mode 100644 index 00000000..7099f15a --- /dev/null +++ b/scripts/core/zip.js @@ -0,0 +1,13 @@ +const { gzip, ungzip } = require('node-gzip') + +const zip = {} + +zip.compress = async function (string) { + return gzip(string) +} + +zip.decompress = async function (string) { + return ungzip(string) +} + +module.exports = zip diff --git a/tests/__data__/expected/guides/bh/chaines-tv.orange.fr.epg.xml.gz b/tests/__data__/expected/guides/bh/chaines-tv.orange.fr.epg.xml.gz new file mode 100644 index 00000000..ed76f067 Binary files /dev/null and b/tests/__data__/expected/guides/bh/chaines-tv.orange.fr.epg.xml.gz differ diff --git a/tests/__data__/expected/guides/fr/chaines-tv.orange.fr.epg.xml.gz b/tests/__data__/expected/guides/fr/chaines-tv.orange.fr.epg.xml.gz new file mode 100644 index 00000000..ed76f067 Binary files /dev/null and b/tests/__data__/expected/guides/fr/chaines-tv.orange.fr.epg.xml.gz differ diff --git a/tests/__data__/expected/guides/ge/magticom.ge.epg.xml b/tests/__data__/expected/guides/ge/magticom.ge.epg.xml new file mode 100644 index 00000000..472cb95a --- /dev/null +++ b/tests/__data__/expected/guides/ge/magticom.ge.epg.xml @@ -0,0 +1,3 @@ + +CNN Internationalhttps://magticom.ge + \ No newline at end of file diff --git a/tests/__data__/expected/guides/ge/magticom.ge.epg.xml.gz b/tests/__data__/expected/guides/ge/magticom.ge.epg.xml.gz new file mode 100644 index 00000000..e2a7b5ab Binary files /dev/null and b/tests/__data__/expected/guides/ge/magticom.ge.epg.xml.gz differ diff --git a/tests/__data__/expected/guides/ru/yandex.ru.epg.xml b/tests/__data__/expected/guides/ru/yandex.ru.epg.xml new file mode 100644 index 00000000..dcf44bec --- /dev/null +++ b/tests/__data__/expected/guides/ru/yandex.ru.epg.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/tests/__data__/expected/guides/ru/yandex.ru.epg.xml.gz b/tests/__data__/expected/guides/ru/yandex.ru.epg.xml.gz new file mode 100644 index 00000000..188a49e0 Binary files /dev/null and b/tests/__data__/expected/guides/ru/yandex.ru.epg.xml.gz differ diff --git a/tests/__data__/expected/guides/us/directv.com.epg.xml b/tests/__data__/expected/guides/us/directv.com.epg.xml new file mode 100644 index 00000000..dcf44bec --- /dev/null +++ b/tests/__data__/expected/guides/us/directv.com.epg.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/tests/__data__/expected/guides/us/directv.com.epg.xml.gz b/tests/__data__/expected/guides/us/directv.com.epg.xml.gz new file mode 100644 index 00000000..188a49e0 Binary files /dev/null and b/tests/__data__/expected/guides/us/directv.com.epg.xml.gz differ diff --git a/tests/__data__/expected/guides/zw/dstv.com.epg.xml.gz b/tests/__data__/expected/guides/zw/dstv.com.epg.xml.gz new file mode 100644 index 00000000..d5436ab5 Binary files /dev/null and b/tests/__data__/expected/guides/zw/dstv.com.epg.xml.gz differ diff --git a/tests/commands/guides/update.test.js b/tests/commands/guides/update.test.js index 665bbf5b..b19102fe 100644 --- a/tests/commands/guides/update.test.js +++ b/tests/commands/guides/update.test.js @@ -1,6 +1,7 @@ const { execSync } = require('child_process') const fs = require('fs-extra') const path = require('path') +const glob = require('glob') beforeEach(() => { fs.emptyDirSync('tests/__data__/output') @@ -14,13 +15,21 @@ it('can generate /guides', () => { { encoding: 'utf8' } ) - expect(content('tests/__data__/output/guides/fr/chaines-tv.orange.fr.epg.xml')).toBe( - content('tests/__data__/expected/guides/fr/chaines-tv.orange.fr.epg.xml') - ) + const guides = glob + .sync('tests/__data__/expected/guides/**/*.xml') + .map(f => f.replace('tests/__data__/expected/', '')) - expect(content('tests/__data__/output/guides/zw/dstv.com.epg.xml')).toBe( - content('tests/__data__/expected/guides/zw/dstv.com.epg.xml') - ) + guides.forEach(filepath => { + expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`)) + }) + + const compressed = glob + .sync('tests/__data__/expected/guides/**/*.xml.gz') + .map(f => f.replace('tests/__data__/expected/', '')) + + compressed.forEach(filepath => { + expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`)) + }) }) it('will terminate process if programs not found', () => { @@ -57,9 +66,7 @@ Error: No programs found }) function content(filepath) { - const data = fs.readFileSync(path.resolve(filepath), { + return fs.readFileSync(`tests/__data__/${filepath}`, { encoding: 'utf8' }) - - return JSON.stringify(data) }