diff --git a/index.js b/index.js index 484e691..cfe1f39 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,7 @@ const ChannelDB = require("./src/dao/channel-db"); const M3uService = require("./src/services/m3u-service"); const FillerDB = require("./src/dao/filler-db"); const CustomShowDB = require("./src/dao/custom-show-db"); -const TVGuideService = require("./src/tv-guide-service"); +const TVGuideService = require("./src/services/tv-guide-service"); const EventService = require("./src/services/event-service"); const onShutdown = require("node-graceful-shutdown").onShutdown; diff --git a/package-lock.json b/package-lock.json index 895b66e..8783f5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1104,12 +1104,11 @@ "dev": true }, "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.5.tgz", + "integrity": "sha1-TePmwDnKp/8Cc9jIG5mRd50sZMk=", "requires": { - "jsonparse": "^1.2.0", + "jsonparse": "^1.1.0", "through": ">=2.2.7 <3" } }, @@ -1173,9 +1172,9 @@ } }, "angular": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.7.9.tgz", - "integrity": "sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.0.tgz", + "integrity": "sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg==" }, "angular-router-browserify": { "version": "0.0.2", @@ -1419,11 +1418,11 @@ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10" + "follow-redirects": "^1.10.0" } }, "babel-plugin-dynamic-import-node": { @@ -1844,15 +1843,36 @@ } }, "browserslist": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", - "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001043", - "electron-to-chromium": "^1.3.413", - "node-releases": "^1.1.53", - "pkg-up": "^2.0.0" + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.742", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz", + "integrity": "sha512-ihL14knI9FikJmH2XUIDdZFWJxvr14rPSdOhJ7PpS27xbz8qmaRwCwyg/bmFwjWKmWK9QyamiCZVCvXm5CH//Q==", + "dev": true + }, + "node-releases": { + "version": "1.1.72", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", + "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "dev": true + } } }, "buffer": { @@ -2010,12 +2030,6 @@ } } }, - "caniuse-lite": { - "version": "1.0.30001046", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001046.tgz", - "integrity": "sha512-CsGjBRYWG6FvgbyGy+hBbaezpwiqIOLkxQPY4A4Ea49g1eNsnQuESB+n4QM0BKii1j80MyJ26Ir5ywTQkbRE4g==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -2175,6 +2189,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, "combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", @@ -3188,25 +3208,33 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "electron-to-chromium": { - "version": "1.3.415", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.415.tgz", - "integrity": "sha512-GbtYqKffx3sU8G0HxwXuJFfs58Q7+iwLa5rBwaULwET6jWW8IAQSrVnu7vEfiUIcMVfbYyFg7cw3zdm+EbBJmw==", - "dev": true - }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } } }, "emoji-regex": { @@ -3258,6 +3286,12 @@ "is-arrayish": "^0.2.1" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -3667,22 +3701,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=", - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" }, "for-in": { "version": "1.0.2", @@ -3950,12 +3971,6 @@ "dev": true, "optional": true }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, @@ -4583,9 +4598,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "htmlescape": { @@ -4688,9 +4703,9 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "inline-source-map": { @@ -5073,8 +5088,7 @@ "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" }, "jsprim": { "version": "1.4.1", @@ -5155,9 +5169,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.memoize": { "version": "3.0.4", @@ -5742,12 +5756,6 @@ "resolved": "https://registry.npmjs.org/node-graceful-shutdown/-/node-graceful-shutdown-1.1.0.tgz", "integrity": "sha512-g1tq/R8ie/At5xRHGfF+chTge1jVPxf1NEClLpZIPxOPi6PJ9II81T35ms1u+s4N/mqOCp60CFd+ps+DIWRigQ==" }, - "node-releases": { - "version": "1.1.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", - "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", - "dev": true - }, "node-ssdp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/node-ssdp/-/node-ssdp-4.0.0.tgz", @@ -6397,26 +6405,6 @@ "pinkie": "^2.0.0" } }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -7544,8 +7532,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", diff --git a/package.json b/package.json index 5990b96..708d509 100644 --- a/package.json +++ b/package.json @@ -13,16 +13,17 @@ "package": "sh ./make_dist.sh", "clean": "del-cli --force ./bin ./dist ./.dizquetv ./web/public/bundle.js" }, - "author": "Dan Ferguson", - "license": "ISC", + "author": "vexorian", + "license": "Zlib", "dependencies": { "JSONStream": "1.0.5", - "angular": "^1.7.9", + "angular": "^1.8.0", "angular-router-browserify": "0.0.2", "angular-vs-repeat": "2.0.13", - "axios": "^0.19.2", + "axios": "^0.21.1", "body-parser": "^1.19.0", - "diskdb": "^0.1.17", + "merge" : "2.1.1", + "diskdb": "0.1.17", "express": "^4.17.1", "express-fileupload": "^1.2.1", "node-graceful-shutdown": "1.1.0", diff --git a/pull_request_template.md b/pull_request_template.md index 951ac4e..b45a9ec 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -7,8 +7,8 @@ * [ ] I have read the code of conduct. * [ ] I am submitting to the correct base branch ### Changes that modify the db structure diff --git a/src/api.js b/src/api.js index a00501a..64599bc 100644 --- a/src/api.js +++ b/src/api.js @@ -12,6 +12,7 @@ const Plex = require("./plex.js"); const timeSlotsService = require('./services/time-slots-service'); const randomSlotsService = require('./services/random-slots-service'); +const throttle = require('./services/throttle'); function safeString(object) { let o = object; @@ -280,10 +281,10 @@ function api(db, channelDB, fillerDB, customShowDB, xmltvInterval, guideService return res.status(404).send("Channel doesn't have programs?"); } res.writeHead(200, { - 'Content-Type': 'application.json' + 'Content-Type': 'application/json' }); - let transformStream = JSONStream.stringify(); //false makes it not add 'separators' + let transformStream = JSONStream.stringify(); transformStream.pipe(res); for (let i = 0; i < programs.length; i++) { @@ -1002,7 +1003,7 @@ function api(db, channelDB, fillerDB, customShowDB, xmltvInterval, guideService console.error("time slots error: " + toolRes.userError); return res.status(400).send(toolRes.userError); } - res.status(200).send(toolRes); + await streamToolResult(toolRes, res); } catch(err) { console.error(err); res.status(500).send("Internal error"); @@ -1016,7 +1017,7 @@ function api(db, channelDB, fillerDB, customShowDB, xmltvInterval, guideService console.error("random slots error: " + toolRes.userError); return res.status(400).send(toolRes.userError); } - res.status(200).send(toolRes); + await streamToolResult(toolRes, res); } catch(err) { console.error(err); res.status(500).send("Internal error"); @@ -1068,13 +1069,32 @@ function api(db, channelDB, fillerDB, customShowDB, xmltvInterval, guideService channel.fallback.forEach( cleanUpProgram ); } + async function streamToolResult(toolRes, res) { + let programs = toolRes.programs; + delete toolRes.programs; + let s = JSON.stringify(toolRes); + s = s.slice(0, -1); + console.log( JSON.stringify(toolRes)); + + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + let transformStream = JSONStream.stringify( + s + ',"programs":[', + ',' , + ']}'); + transformStream.pipe(res); + + for (let i = 0; i < programs.length; i++) { + transformStream.write( programs[i] ); + await throttle(); + } + transformStream.end(); + } + return router } -async function throttle() { - return new Promise((resolve) => { - setImmediate(() => resolve()); - }); -} diff --git a/src/helperFuncs.js b/src/helperFuncs.js index df9915d..343d02c 100644 --- a/src/helperFuncs.js +++ b/src/helperFuncs.js @@ -56,6 +56,7 @@ function createLineup(obj, channel, fillers, isFirst) { // When within 30 seconds of start time, just make the time 0 to smooth things out // Helps prevents loosing first few seconds of an episode upon lineup change let activeProgram = obj.program + let beginningOffset = 0; let lineup = [] @@ -67,7 +68,8 @@ function createLineup(obj, channel, fillers, isFirst) { err: activeProgram.err, streamDuration: remaining, duration: remaining, - start: 0 + start: 0, + beginningOffset: beginningOffset, }) return lineup; } @@ -120,6 +122,7 @@ function createLineup(obj, channel, fillers, isFirst) { streamDuration: Math.max(1, Math.min(filler.duration - fillerstart, remaining) ), duration: filler.duration, fillerId: filler.fillerId, + beginningOffset: beginningOffset, serverKey: filler.serverKey }); return lineup; @@ -133,14 +136,17 @@ function createLineup(obj, channel, fillers, isFirst) { type: 'offline', title: 'Channel Offline', streamDuration: remaining, + beginningOffset: beginningOffset, duration: remaining, start: 0 }) return lineup; } + let originalTimeElapsed = timeElapsed; if (timeElapsed < 30000) { timeElapsed = 0 } + beginningOffset = Math.max(0, originalTimeElapsed - timeElapsed); return [ { type: 'program', @@ -151,6 +157,7 @@ function createLineup(obj, channel, fillers, isFirst) { ratingKey: activeProgram.ratingKey, start: timeElapsed, streamDuration: activeProgram.duration - timeElapsed, + beginningOffset: beginningOffset, duration: activeProgram.duration, serverKey: activeProgram.serverKey } ]; diff --git a/src/services/random-slots-service.js b/src/services/random-slots-service.js index 2cc6064..5cac49c 100644 --- a/src/services/random-slots-service.js +++ b/src/services/random-slots-service.js @@ -1,6 +1,8 @@ const constants = require("../constants"); const getShowData = require("./get-show-data")(); const random = require('../helperFuncs').random; +const throttle = require('./throttle'); + const MINUTE = 60*1000; const DAY = 24*60*MINUTE; @@ -192,12 +194,6 @@ module.exports = async( programs, schedule ) => { // throttle so that the stream is not affected negatively let steps = 0; - let throttle = async() => { - if (steps++ == 10) { - steps = 0; - await _wait(1); - } - } let showsById = {}; let shows = []; diff --git a/src/services/throttle.js b/src/services/throttle.js new file mode 100644 index 0000000..80e34f1 --- /dev/null +++ b/src/services/throttle.js @@ -0,0 +1,6 @@ +//Adds a slight pause so that long operations +module.exports = function() { + return new Promise((resolve) => { + setImmediate(() => resolve()); + }); +} diff --git a/src/services/time-slots-service.js b/src/services/time-slots-service.js index 64b6115..fe6b6a8 100644 --- a/src/services/time-slots-service.js +++ b/src/services/time-slots-service.js @@ -3,6 +3,7 @@ const constants = require("../constants"); const getShowData = require("./get-show-data")(); const random = require('../helperFuncs').random; +const throttle = require('./throttle'); const MINUTE = 60*1000; const DAY = 24*60*MINUTE; @@ -200,12 +201,6 @@ module.exports = async( programs, schedule ) => { // throttle so that the stream is not affected negatively let steps = 0; - let throttle = async() => { - if (steps++ == 10) { - steps = 0; - await _wait(1); - } - } let showsById = {}; let shows = []; diff --git a/src/tv-guide-service.js b/src/services/tv-guide-service.js similarity index 99% rename from src/tv-guide-service.js rename to src/services/tv-guide-service.js index 84027be..cd3160d 100644 --- a/src/tv-guide-service.js +++ b/src/services/tv-guide-service.js @@ -1,6 +1,7 @@ -const constants = require("./constants"); +const constants = require("../constants"); const FALLBACK_ICON = "https://raw.githubusercontent.com/vexorain/dizquetv/main/resources/dizquetv.png"; +const throttle = require('./throttle'); class TVGuideService { @@ -18,6 +19,7 @@ class TVGuideService this.db = db; this.cacheImageService = cacheImageService; this.eventService = eventService; + this._throttle = throttle; } async get() { @@ -355,11 +357,6 @@ class TVGuideService } } - _throttle() { - return new Promise((resolve) => { - setImmediate(() => resolve()); - }); - } async refreshXML() { let xmltvSettings = this.db['xmltv-settings'].find()[0]; diff --git a/src/video.js b/src/video.js index 6cf31f6..c2d7897 100644 --- a/src/video.js +++ b/src/video.js @@ -254,15 +254,19 @@ function video( channelDB , fillerDB, db) { } let fillers = await fillerDB.getFillersFromChannel(brandChannel); let lineup = helperFuncs.createLineup(prog, brandChannel, fillers, isFirst) - lineupItem = lineup.shift() + lineupItem = lineup.shift(); } if ( !isLoading && (lineupItem != null) ) { let upperBound = 1000000000; + let beginningOffset = 0; + if (typeof(lineupItem.beginningOffset) !== 'undefined') { + beginningOffset = lineupItem.beginningOffset; + } //adjust upper bounds and record playbacks for (let i = redirectChannels.length-1; i >= 0; i--) { lineupItem = JSON.parse( JSON.stringify(lineupItem )); - let u = upperBounds[i]; + let u = upperBounds[i] + beginningOffset; if (typeof(u) !== 'undefined') { let u2 = upperBound; if ( typeof(lineupItem.streamDuration) !== 'undefined') { diff --git a/web/public/index.html b/web/public/index.html index f198895..201bd08 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -15,7 +15,7 @@

- + dizqueTV @@ -42,7 +42,7 @@ M3U -
+

diff --git a/web/public/templates/channel-config.html b/web/public/templates/channel-config.html index 2b37c3c..baf082d 100644 --- a/web/public/templates/channel-config.html +++ b/web/public/templates/channel-config.html @@ -24,21 +24,21 @@
- + {{error.number}}
- + {{error.name}}
- + This is used by iptv clients to categorize the channels. You can leave it as dizqueTV if you don't need this sort of classification.
@@ -48,7 +48,7 @@
- +
-
+

Preview
- {{channel.name}} + {{channel.name}} {{channel.name}}
@@ -75,12 +75,12 @@
- + {{error.startTime}}
- +
Programming will restart from the beginning. @@ -99,7 +99,7 @@
Fallback: {{describeFallback()}}
-
+
{{ dateForGuide(x.start) }}
-
+
{{ getProgramDisplayTitle(x) }} @@ -318,9 +318,9 @@
-
+
Filler
- + {{error.blockRepeats}}
@@ -609,10 +609,10 @@  
-
+
Filler Lists
-
+

@@ -681,14 +681,14 @@

- + This is the name of the fake program that will appear in the TV guide when there are no programs to display in that time slot guide. E.g when a large Flex block is scheduled.
- + Programs shorter than this value will be treated the same as Flex time. Meaning that the TV Guide will try to meld them with the previous program or display the block of programs as the "place holder program" if they make a large continuous group. Use 0 to disable this feature or use a large value to make the channel report only the placeholder program and not the real programming.
@@ -698,7 +698,7 @@ -
+
Transcoding settings
diff --git a/web/public/templates/ffmpeg-settings.html b/web/public/templates/ffmpeg-settings.html index 8ebd3ff..ac6032b 100644 --- a/web/public/templates/ffmpeg-settings.html +++ b/web/public/templates/ffmpeg-settings.html @@ -9,16 +9,16 @@
FFMPEG Executable Path (eg: C:\ffmpeg\bin\ffmpeg.exe || /usr/bin/ffmpeg)
- + FFMPEG version 4.2+ required. Check by opening the version tab -
+
Miscellaneous Options
- +
@@ -26,7 +26,7 @@

- +
@@ -36,35 +36,35 @@
Note: If you experience playback issues upon stream start, try increasing this.
-
+
Transcoding Features
- + Transcoding is required for some features like channel overlay and measures to prevent issues when switching episodes. The trade-off is quality loss and additional computing resource requirements.
-
+

-
- + Some possible values are: h264 with Intel Quick Sync: h264_qsv MPEG2 with Intel Quick Sync: mpeg2_qsv @@ -73,10 +73,10 @@ H264: libx264 MacOS: h264_videotoolbox
-
+
- + Some possible values are: aac ac3 (default), ac3_fixed @@ -84,26 +84,26 @@ libmp3lame
-
+

- -
+ +

- -
+ +

Will transcode videos that have FPS higher than this. -
+

Scaling algorithm to use when the transcoder needs to change the video size. -
+

@@ -112,20 +112,20 @@
- -
+ +

- -
+ +

- + Values higher than 100 will boost the audio. -
+

- -
+ +

- +
@@ -133,10 +133,10 @@
If there are issues playing a video, dizqueTV will try to use an error screen as a placeholder while retrying loading the video every 60 seconds. @@ -146,7 +146,7 @@
- + Some clients experience issues when the video stream changes resolution. This option will make dizqueTV convert all videos to the preferred resolution selected above. Otherwise, the preferred resolution will be used as a maximum resolution for transcoding. @@ -154,16 +154,16 @@
-
+

- +
- +
@@ -172,11 +172,11 @@
-
+

- + This will force the preferred number of audio channels and sample rate, in addition it will align the lengths of the audio and video channels. This will prevent audio-related episode transition issues in many clients. Audio will always be transcoded. @@ -184,11 +184,11 @@
-
+

- + Toggling this option will disable channel watermarks regardless of channel settings. diff --git a/web/public/templates/filler-config.html b/web/public/templates/filler-config.html index ca73a27..148506a 100644 --- a/web/public/templates/filler-config.html +++ b/web/public/templates/filler-config.html @@ -19,7 +19,7 @@
Total: {{content.length}}
-
+
-
+
{{x.title}}
diff --git a/web/public/templates/flex-config.html b/web/public/templates/flex-config.html index 090d463..0ea110a 100644 --- a/web/public/templates/flex-config.html +++ b/web/public/templates/flex-config.html @@ -10,7 +10,7 @@
-
-
-
-
+

+

+

+

Configure your Plex Server(s) in Settings

-
-
-
-
-
+

+

+

+

+

@@ -24,18 +24,18 @@   -   +  
@@ -190,11 +190,11 @@
Path Replacements
- +
- +
diff --git a/web/public/templates/program-config.html b/web/public/templates/program-config.html index 015e6d1..5ba9c7f 100644 --- a/web/public/templates/program-config.html +++ b/web/public/templates/program-config.html @@ -17,80 +17,80 @@ - + - + - + - +
Icon Preview
- +
- + - + - + - +
Icon Preview
- +
- + - + - + - + - + - +
Icon Preview
- +
- +
- +
- +
diff --git a/web/public/templates/show-config.html b/web/public/templates/show-config.html index e6af075..44ed9f0 100644 --- a/web/public/templates/show-config.html +++ b/web/public/templates/show-config.html @@ -19,7 +19,7 @@
Total: {{content.length}}
-
+
-
+
{{ getProgramDisplayTitle(x) }}
diff --git a/web/public/templates/xmltv-settings.html b/web/public/templates/xmltv-settings.html index cfd3b97..2826a1b 100644 --- a/web/public/templates/xmltv-settings.html +++ b/web/public/templates/xmltv-settings.html @@ -9,22 +9,22 @@
Output Path
- + You can edit this location in file xmltv-settings.json. -
+

- + How many hours of programming to include in the xmltv file.
- + How often should the xmltv file be updated.
-
+

diff --git a/web/public/views/channels.html b/web/public/views/channels.html index e566eb0..e78c09d 100644 --- a/web/public/views/channels.html +++ b/web/public/views/channels.html @@ -25,7 +25,7 @@ {{x.number}} - {{x.name}} + {{x.name}}
{{x.name}}
{{x.name}} (Stealth) diff --git a/web/public/views/settings.html b/web/public/views/settings.html index e7bcd65..fd901f3 100644 --- a/web/public/views/settings.html +++ b/web/public/views/settings.html @@ -21,7 +21,7 @@ -
+

diff --git a/web/services/plex.js b/web/services/plex.js index 7256a7f..a990a0d 100644 --- a/web/services/plex.js +++ b/web/services/plex.js @@ -158,7 +158,7 @@ module.exports = function ($http, $window, $interval) { }, getStreams: async (server, key) => { var client = new Plex(server) - return client.Get(key).then((res) => { + return client.Get(key).then((res) => { let streams = res.Metadata[0].Media[0].Part[0].Stream for (let i = 0, l = streams.length; i < l; i++) { if (typeof streams[i].key !== 'undefined') { @@ -278,6 +278,29 @@ module.exports = function ($http, $window, $interval) { } if (typeof (res.Metadata[i].Collection) !== 'undefined') { let coll = res.Metadata[i].Collection; + if (coll.length == 2) { + // the /all endpoint returns incomplete data, so we + // might have to complete the list of collections + // when there are already 2 collections there. + //console.log(res.Metadata[i]); + let complete = {} + try { + complete = await client.Get(`/library/metadata/${res.Metadata[i].ratingKey}`); + } catch (err) { + console.error("Error attempting to load collections", err); + } + if ( + (typeof(complete.Metadata) !== 'undefined') + && + (complete.Metadata.length == 1) + && + (typeof(complete.Metadata[0].Collection) !== 'undefined') + && + ( complete.Metadata[0].Collection.length > 2) + ) { + coll = complete.Metadata[0].Collection; + } + } for (let j = 0; j < coll.length; j++) { let tag = coll[j].tag; if ( (typeof(tag)!== "undefined") && (tag.length > 0) ) {