From 0e61dff190c4b968c4eab39a11a6dedc5b7db884 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:50:19 +0300
Subject: [PATCH 01/13] Update pm2.config.js
---
pm2.config.js | 70 +++++++++++++++++++++++++--------------------------
1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/pm2.config.js b/pm2.config.js
index f1f901166..d06556d3b 100644
--- a/pm2.config.js
+++ b/pm2.config.js
@@ -1,35 +1,35 @@
-const grab = process.env.SITE
- ? `npm run grab -- --site=${process.env.SITE} ${process.env.CLANG ? `--lang=${process.env.CLANG}` : ''
- } --output=public/guide.xml`
- : 'npm run grab -- --channels=channels.xml --output=public/guide.xml'
-
-
-const apps = [
- {
- name: 'serve',
- script: 'npx serve -- public',
- instances: 1,
- watch: false,
- autorestart: true
- },
- {
- name: 'grab',
- script: `npx chronos -e "${grab}" -p "${process.env.CRON_SCHEDULE}" -l`,
- instances: 1,
- watch: false,
- autorestart: true
- }
-];
-
-if (process.env.RUN_AT_STARTUP === 'true') {
- apps.push({
- name: 'grab-at-startup',
- script: grab,
- instances: 1,
- autorestart: false,
- watch: false,
- max_restarts: 1
- });
-}
-
-module.exports = { apps };
\ No newline at end of file
+const grab = process.env.SITE
+ ? `npm run grab -- --site=${process.env.SITE} ${
+ process.env.CLANG ? `--lang=${process.env.CLANG}` : ''
+ } --output=public/guide.xml`
+ : 'npm run grab -- --channels=public/channels.xml --output=public/guide.xml'
+
+const apps = [
+ {
+ name: 'serve',
+ script: 'npx serve -- public',
+ instances: 1,
+ watch: false,
+ autorestart: true
+ },
+ {
+ name: 'grab',
+ script: `npx chronos -e "${grab}" -p "${process.env.CRON_SCHEDULE}" -l`,
+ instances: 1,
+ watch: false,
+ autorestart: true
+ }
+]
+
+if (process.env.RUN_AT_STARTUP === 'true') {
+ apps.push({
+ name: 'grab-at-startup',
+ script: grab,
+ instances: 1,
+ autorestart: false,
+ watch: false,
+ max_restarts: 1
+ })
+}
+
+module.exports = { apps }
From fdd25839b5d3807e93bedf67b94ca8e361858c6a Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:50:31 +0300
Subject: [PATCH 02/13] Update package-lock.json
---
package-lock.json | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index dc7fa85f4..f12b02df7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,6 +41,7 @@
"@typescript-eslint/parser": "^8.38.0",
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
+ "axios-mock-adapter": "^2.1.0",
"chalk": "^5.4.1",
"cheerio": "^1.1.2",
"cli-progress": "^3.12.0",
@@ -52,7 +53,7 @@
"cwait": "^1.1.2",
"dayjs": "^1.11.13",
"epg-grabber": "^0.46.1",
- "epg-parser": "^0.3.1",
+ "epg-parser": "^0.5.0",
"eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8",
"form-data": "^4.0.4",
@@ -5238,9 +5239,9 @@
}
},
"node_modules/dayjs": {
- "version": "1.11.18",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
- "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA=="
+ "version": "1.11.19",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
+ "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
},
"node_modules/debug": {
"version": "4.3.4",
@@ -5538,12 +5539,12 @@
}
},
"node_modules/epg-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/epg-parser/-/epg-parser-0.3.1.tgz",
- "integrity": "sha512-y131hXfDthUdSeKbN0Ru1wiFF5er4t/TLT+IaAnHF2CYB0cnygHTJteQMDYIlHWHDsGj+z9ejm1cU3saFNF3nQ==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/epg-parser/-/epg-parser-0.5.0.tgz",
+ "integrity": "sha512-NK9vSev/KkCVcKilJd35PmB9tP4+tN45dhcsSxHagVoUTINh8KLZ1yvgtoPDVYr0IaSPJXIIIZWcu1JPjS5HMw==",
"dependencies": {
- "dayjs": "^1.11.6",
- "lodash": "^4.17.21",
+ "dayjs": "^1.11.19",
+ "lodash.groupby": "^4.6.0",
"xml-js": "^1.6.11"
}
},
@@ -8694,6 +8695,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash.groupby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+ "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw=="
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -14838,9 +14844,9 @@
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="
},
"dayjs": {
- "version": "1.11.18",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
- "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA=="
+ "version": "1.11.19",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
+ "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
},
"debug": {
"version": "4.3.4",
@@ -15056,12 +15062,12 @@
}
},
"epg-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/epg-parser/-/epg-parser-0.3.1.tgz",
- "integrity": "sha512-y131hXfDthUdSeKbN0Ru1wiFF5er4t/TLT+IaAnHF2CYB0cnygHTJteQMDYIlHWHDsGj+z9ejm1cU3saFNF3nQ==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/epg-parser/-/epg-parser-0.5.0.tgz",
+ "integrity": "sha512-NK9vSev/KkCVcKilJd35PmB9tP4+tN45dhcsSxHagVoUTINh8KLZ1yvgtoPDVYr0IaSPJXIIIZWcu1JPjS5HMw==",
"requires": {
- "dayjs": "^1.11.6",
- "lodash": "^4.17.21",
+ "dayjs": "^1.11.19",
+ "lodash.groupby": "^4.6.0",
"xml-js": "^1.6.11"
}
},
@@ -17283,6 +17289,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "lodash.groupby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+ "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw=="
+ },
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
From 6490952f4e1d401afb2cd54ee94f1e4aff7ac305 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:50:36 +0300
Subject: [PATCH 03/13] Update package.json
---
package.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 6c6d8aa59..4f2be8a44 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"channels:validate": "tsx scripts/commands/channels/validate.ts",
"sites:init": "tsx scripts/commands/sites/init.ts",
"sites:update": "tsx scripts/commands/sites/update.ts",
+ "guides:update": "tsx scripts/commands/guides/update.ts",
"grab": "tsx scripts/commands/epg/grab.ts",
"lint": "npx eslint \"{scripts,tests,sites}/**/*.{ts,mts,js}\"",
"test": "cross-env TZ=Pacific/Nauru npx jest --runInBand",
@@ -71,6 +72,7 @@
"@typescript-eslint/parser": "^8.38.0",
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
+ "axios-mock-adapter": "^2.1.0",
"chalk": "^5.4.1",
"cheerio": "^1.1.2",
"cli-progress": "^3.12.0",
@@ -82,7 +84,7 @@
"cwait": "^1.1.2",
"dayjs": "^1.11.13",
"epg-grabber": "^0.46.1",
- "epg-parser": "^0.3.1",
+ "epg-parser": "^0.5.0",
"eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8",
"form-data": "^4.0.4",
From dd18056047b4bf4ba76492036002f992276e42d8 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:51:11 +0300
Subject: [PATCH 04/13] Update tests/__data__
---
.../__data__/expected/guides_update/GUIDES.md | 13 ++++++++
.../__data__/input/guides_update/channels.xml | 4 +++
tests/__data__/input/guides_update/guide.xml | 30 +++++++++++++++++++
.../__data__/input/guides_update/worker.json | 4 +++
.../__data__/input/guides_update/workers.txt | 2 ++
5 files changed, 53 insertions(+)
create mode 100644 tests/__data__/expected/guides_update/GUIDES.md
create mode 100644 tests/__data__/input/guides_update/channels.xml
create mode 100644 tests/__data__/input/guides_update/guide.xml
create mode 100644 tests/__data__/input/guides_update/worker.json
create mode 100644 tests/__data__/input/guides_update/workers.txt
diff --git a/tests/__data__/expected/guides_update/GUIDES.md b/tests/__data__/expected/guides_update/GUIDES.md
new file mode 100644
index 000000000..f6e86cfc8
--- /dev/null
+++ b/tests/__data__/expected/guides_update/GUIDES.md
@@ -0,0 +1,13 @@
+# Guides
+
+
+
+ | Host | Status | Channels | Last Updated | Links |
+
+
+ | example.com | 🔴 | 0 | - | |
+ | worker-9dd4.onrender.com | 🟢 | 1 | a day ago | channels.xml guide.xml |
+
+
+
+[How can I add my server to the list?](CONTRIBUTING.md#how-to-add-my-server-to-the-guides-md)
diff --git a/tests/__data__/input/guides_update/channels.xml b/tests/__data__/input/guides_update/channels.xml
new file mode 100644
index 000000000..46c1b2e93
--- /dev/null
+++ b/tests/__data__/input/guides_update/channels.xml
@@ -0,0 +1,4 @@
+
+
+ ANT1 Europe
+
\ No newline at end of file
diff --git a/tests/__data__/input/guides_update/guide.xml b/tests/__data__/input/guides_update/guide.xml
new file mode 100644
index 000000000..ed17438ed
--- /dev/null
+++ b/tests/__data__/input/guides_update/guide.xml
@@ -0,0 +1,30 @@
+
+ANT1 Europehttps://antennaeurope.gr
+ΚΑΛΗΜΕΡΑ ΕΛΛΑΔΑ
+ΤΟ ΠΡΩΙΝΟ
+ANT1 NEWS
+ΑΠΟΚΑΛΥΨΕΙΣ
+ΡΟΥΚ ΖΟΥΚ
+5 X 5
+ANT1 NEWS
+ΠΟΙΟΣ ΘΕΛΕΙ ΝΑ ΓΙΝΕΙ ΕΚΑΤΟΜΜΥΡΙΟΥΧΟΣ
+GRAND HOTEL
+ΓΙΑΤΙ ΡΕ ΠΑΤΕΡΑ ;
+THE ROADSHOW - BEST OF
+ΕΝΩΠΙΟΣ ΕΝΩΠΙΩ
+5 X 5
+ΤΟ ΠΡΩΙΝΟ
+ΚΑΛΗΜΕΡΑ ΕΛΛΑΔΑ
+ΤΟ ΠΡΩΙΝΟ
+ANT1 NEWS
+ΑΠΟΚΑΛΥΨΕΙΣ
+ΡΟΥΚ ΖΟΥΚ
+5 X 5
+ANT1 NEWS
+ΠΟΙΟΣ ΘΕΛΕΙ ΝΑ ΓΙΝΕΙ ΕΚΑΤΟΜΜΥΡΙΟΥΧΟΣ
+DON'T FORGET THE LYRICS
+VIΠ
+ΠΕΦΤΕΙ Η ΝΥΧΤΑ ΜΕ... ΡΥΘΜΟ
+5 X 5
+ΤΟ ΠΡΩΙΝΟ
+
\ No newline at end of file
diff --git a/tests/__data__/input/guides_update/worker.json b/tests/__data__/input/guides_update/worker.json
new file mode 100644
index 000000000..371feec07
--- /dev/null
+++ b/tests/__data__/input/guides_update/worker.json
@@ -0,0 +1,4 @@
+{
+ "channels": "channels.xml",
+ "guide": "guide.xml"
+}
\ No newline at end of file
diff --git a/tests/__data__/input/guides_update/workers.txt b/tests/__data__/input/guides_update/workers.txt
new file mode 100644
index 000000000..02ca158a1
--- /dev/null
+++ b/tests/__data__/input/guides_update/workers.txt
@@ -0,0 +1,2 @@
+example.com
+worker-9dd4.onrender.com
\ No newline at end of file
From 2ac41ec8cd48e5da2b3098413b917da691ca8392 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:51:24 +0300
Subject: [PATCH 05/13] Create update.test.ts
---
tests/commands/guides/update.test.ts | 29 ++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 tests/commands/guides/update.test.ts
diff --git a/tests/commands/guides/update.test.ts b/tests/commands/guides/update.test.ts
new file mode 100644
index 000000000..4f3d0f6ef
--- /dev/null
+++ b/tests/commands/guides/update.test.ts
@@ -0,0 +1,29 @@
+import { execSync } from 'child_process'
+import { pathToFileURL } from 'node:url'
+import fs from 'fs-extra'
+
+const ENV_VAR = 'cross-env ROOT_DIR=tests/__data__/output'
+
+beforeEach(() => {
+ fs.emptyDirSync('tests/__data__/output')
+ fs.copySync('tests/__data__/input/guides_update/workers.txt', 'tests/__data__/output/workers.txt')
+})
+
+it('can update GUIDES.md', () => {
+ const cmd = `${ENV_VAR} npm run guides:update`
+
+ const stdout = execSync(cmd, { encoding: 'utf8' })
+ if (process.env.DEBUG === 'true') console.log(cmd, stdout)
+
+ expect(content('tests/__data__/output/GUIDES.md')).toEqual(
+ content('tests/__data__/expected/guides_update/GUIDES.md')
+ )
+})
+
+function content(filepath: string) {
+ const data = fs.readFileSync(pathToFileURL(filepath), {
+ encoding: 'utf8'
+ })
+
+ return JSON.stringify(data)
+}
From d7916ceca2c2c73cc6cc7adcd003d719b2e7b2c6 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:52:15 +0300
Subject: [PATCH 06/13] Update scripts
---
scripts/commands/guides/update.ts | 144 ++++++++++++++++++++++++++++++
scripts/models/index.ts | 1 +
scripts/models/worker.ts | 68 ++++++++++++++
scripts/templates/_guides.md | 5 ++
4 files changed, 218 insertions(+)
create mode 100644 scripts/commands/guides/update.ts
create mode 100644 scripts/models/worker.ts
create mode 100644 scripts/templates/_guides.md
diff --git a/scripts/commands/guides/update.ts b/scripts/commands/guides/update.ts
new file mode 100644
index 000000000..f43b96b6c
--- /dev/null
+++ b/scripts/commands/guides/update.ts
@@ -0,0 +1,144 @@
+import { HTMLTableRow, HTMLTableDataItem, HTMLTableColumn } from '../../types/htmlTable'
+import epgGrabber, { EPGGrabber } from 'epg-grabber'
+import AxiosMockAdapter from 'axios-mock-adapter'
+import { Storage } from '@freearhey/storage-js'
+import { Channel, Worker } from '../../models'
+import { Collection } from '@freearhey/core'
+import { ROOT_DIR } from '../../constants'
+import { Logger } from '@freearhey/core'
+import { HTMLTable } from '../../core'
+import epgParser from 'epg-parser'
+import axios from 'axios'
+
+async function main() {
+ const logger = new Logger({ level: process.env.NODE_ENV === 'test' ? -999 : 3 })
+ const rootStorage = new Storage(ROOT_DIR)
+ const workers = new Map()
+
+ logger.info('loading workers.txt...')
+ const workersTxt = await rootStorage.load('workers.txt')
+
+ workersTxt.split('\r\n').forEach((host: string) => {
+ if (!host) return
+
+ const worker = new Worker({ host })
+
+ workers.set(host, worker)
+ })
+
+ for (const worker of workers.values()) {
+ logger.info(`processing "${worker.host}"...`)
+
+ const client = axios.create({
+ baseURL: worker.getBaseUrl(),
+ timeout: 60000
+ })
+
+ if (process.env.NODE_ENV === 'test') {
+ const mock = new AxiosMockAdapter(client)
+ if (worker.host === 'example.com') {
+ mock.onGet('worker.json').reply(404)
+ } else {
+ const testStorage = new Storage('tests/__data__/input/guides_update')
+ mock.onGet('worker.json').reply(200, await testStorage.load('worker.json'))
+ mock.onGet('channels.xml').reply(200, await testStorage.load('channels.xml'))
+ mock.onGet('guide.xml').reply(200, await testStorage.load('guide.xml'))
+ }
+ }
+
+ const workerJson = await client
+ .get('worker.json')
+ .then(res => res.data)
+ .catch(err => {
+ worker.status = err.status
+ logger.error(err.message)
+ })
+
+ if (!workerJson) {
+ worker.status = 'MISSING_WORKER_CONFIG'
+ logger.error('Unable to load "workers.json"')
+ continue
+ }
+
+ worker.channelsPath = workerJson.channels
+ worker.guidePath = workerJson.guide
+
+ if (!worker.channelsPath) {
+ worker.status = 'MISSING_CHANNELS_PATH'
+ logger.error('The "channels" property is missing from the workers config')
+ continue
+ }
+
+ if (!worker.guidePath) {
+ worker.status = 'MISSING_GUIDE_PATH'
+ logger.error('The "guide" property is missing from the workers config')
+ continue
+ }
+
+ const channelsXml = await client
+ .get(worker.channelsPath)
+ .then(res => res.data)
+ .catch(err => {
+ worker.status = err.status
+ logger.error(err.message)
+ })
+
+ if (!channelsXml) continue
+
+ const parsedChannels = EPGGrabber.parseChannelsXML(channelsXml)
+ worker.channels = new Collection(parsedChannels).map(
+ (channel: epgGrabber.Channel) => new Channel(channel.toObject())
+ )
+
+ const guideXml = await client
+ .get(worker.guidePath)
+ .then(res => res.data)
+ .catch(err => {
+ worker.status = err.status
+ logger.error(err.message)
+ })
+
+ if (!guideXml) continue
+
+ const parsedGuide = epgParser.parse(guideXml)
+ worker.lastUpdated = parsedGuide.date
+
+ worker.status = 'OK'
+ }
+
+ logger.info('creating guides table...')
+ const rows = new Collection()
+ workers.forEach((worker: Worker) => {
+ rows.add(
+ new Collection([
+ { value: worker.host },
+ { value: worker.getStatusEmoji(), align: 'center' },
+ { value: worker.getChannelsCount().toString(), align: 'right' },
+ { value: worker.getLastUpdated(), align: 'left' },
+ {
+ value:
+ worker.status === 'OK'
+ ? `${worker.channelsPath}
${worker.guidePath}`
+ : ''
+ }
+ ])
+ )
+ })
+
+ logger.info('updating guides.md...')
+ const table = new HTMLTable(
+ rows,
+ new Collection([
+ { name: 'Host', align: 'left' },
+ { name: 'Status', align: 'left' },
+ { name: 'Channels', align: 'left' },
+ { name: 'Last Updated', align: 'left' },
+ { name: 'Links', align: 'left' }
+ ])
+ )
+ const guidesTemplate = await new Storage().load('scripts/templates/_guides.md')
+ const guidesContent = guidesTemplate.replace('_TABLE_', table.toString())
+ await rootStorage.save('GUIDES.md', guidesContent)
+}
+
+main()
diff --git a/scripts/models/index.ts b/scripts/models/index.ts
index a05f13a89..c891f01bf 100644
--- a/scripts/models/index.ts
+++ b/scripts/models/index.ts
@@ -3,3 +3,4 @@ export * from './issue'
export * from './site'
export * from './channel'
export * from './program'
+export * from './worker'
diff --git a/scripts/models/worker.ts b/scripts/models/worker.ts
new file mode 100644
index 000000000..8b625ffa9
--- /dev/null
+++ b/scripts/models/worker.ts
@@ -0,0 +1,68 @@
+import relativeTime from 'dayjs/plugin/relativeTime'
+import { Collection } from '@freearhey/core'
+import { Channel } from './channel'
+import dayjs from 'dayjs'
+
+dayjs.extend(relativeTime)
+
+export interface WorkerData {
+ host: string
+}
+
+export class Worker {
+ host: string
+ channelsPath?: string
+ guidePath?: string
+ channels?: Collection
+ status?: string
+ lastUpdated?: string
+
+ constructor(data: WorkerData) {
+ this.host = data.host
+ }
+
+ getBaseUrl(): string {
+ return `https://${this.host}`
+ }
+
+ getConfigUrl(): string {
+ const url = new URL('worker.json', this.getBaseUrl())
+
+ return url.href
+ }
+
+ getChannelsUrl(): string {
+ if (!this.channelsPath) return ''
+
+ const url = new URL(this.channelsPath, this.getBaseUrl())
+
+ return url.href
+ }
+
+ getGuideUrl(): string {
+ if (!this.guidePath) return ''
+
+ const url = new URL(this.guidePath, this.getBaseUrl())
+
+ return url.href
+ }
+
+ getStatusEmoji(): string {
+ if (!this.status) return '⚪'
+ if (this.status === 'OK') return '🟢'
+
+ return '🔴'
+ }
+
+ getChannelsCount(): number {
+ if (!this.channels) return 0
+
+ return this.channels.count()
+ }
+
+ getLastUpdated(): string {
+ if (!this.lastUpdated) return '-'
+
+ return dayjs().to(dayjs(this.lastUpdated))
+ }
+}
diff --git a/scripts/templates/_guides.md b/scripts/templates/_guides.md
new file mode 100644
index 000000000..d643a4637
--- /dev/null
+++ b/scripts/templates/_guides.md
@@ -0,0 +1,5 @@
+# Guides
+
+_TABLE_
+
+[How can I add my server to the list?](CONTRIBUTING.md#how-to-add-my-server-to-the-guides-md)
From 8f43348a2fb23e3031131a37d1cfb77c93159512 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:52:23 +0300
Subject: [PATCH 07/13] Create workers.txt
---
workers.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 workers.txt
diff --git a/workers.txt b/workers.txt
new file mode 100644
index 000000000..d43ab81c3
--- /dev/null
+++ b/workers.txt
@@ -0,0 +1 @@
+worker-9dd4.onrender.com
\ No newline at end of file
From 2374fac9b4a602747768cac528b88b993bc66250 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:53:20 +0300
Subject: [PATCH 08/13] Update update.yml
---
.github/workflows/update.yml | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml
index 26255c8bd..cf94890a5 100644
--- a/.github/workflows/update.yml
+++ b/.github/workflows/update.yml
@@ -32,17 +32,28 @@ jobs:
run: npm run channels:lint
- name: update sites.md
run: npm run sites:update
- env:
- GH_TOKEN: ${{ steps.create-app-token.outputs.token }}
- run: git status
- name: commit changes to sites.md
if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
run: |
- SITE=SITES.md
- CHANGED=$(git diff ${SITE})
+ FILE=SITES.md
+ CHANGED=$(git diff ${FILE})
if [ -n "${CHANGED}" ]; then
- git add ${SITE}
- git commit -m "[Bot] Update ${SITE}" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/epg/actions/runs/${{ github.run_id }}) workflow." --no-verify
+ git add ${FILE}
+ git commit -m "[Bot] Update ${FILE}" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/epg/actions/runs/${{ github.run_id }}) workflow." --no-verify
+ git push
+ fi
+ - name: update guides.md
+ run: npm run guides:update
+ - run: git status
+ - name: commit changes to guides.md
+ if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
+ run: |
+ FILE=GUIDES.md
+ CHANGED=$(git diff ${FILE})
+ if [ -n "${CHANGED}" ]; then
+ git add ${FILE}
+ git commit -m "[Bot] Update ${FILE}" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/epg/actions/runs/${{ github.run_id }}) workflow." --no-verify
git push
fi
- name: generate .api/guides.json
From 3028757db322063297dfa609591847faaa9b5642 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:54:25 +0300
Subject: [PATCH 09/13] Update README.md
---
README.md | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 06a8bf352..d6aeecd9a 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Tools for downloading the EPG (Electronic Program Guide) for thousands of TV cha
- 🚀 [Usage](#usage)
- 💫 [Update](#update)
- 🐋 [Docker](#docker)
-- 📺 [Playlists](#playlists)
+- 📅 [Guides](#guides)
- 🗄 [Database](#database)
- 👨💻 [API](#api)
- 📚 [Resources](#resources)
@@ -155,7 +155,7 @@ docker pull ghcr.io/iptv-org/epg:master
### Create and run container
```sh
-docker run -p 3000:3000 -v /path/to/channels.xml:/epg/channels.xml ghcr.io/iptv-org/epg:master
+docker run -p 3000:3000 -v /path/to/channels.xml:/epg/public/channels.xml ghcr.io/iptv-org/epg:master
```
By default, the guide will be downloaded every day at 00:00 UTC and saved to the `/epg/public/guide.xml` file inside the container.
@@ -179,7 +179,7 @@ To fine-tune the execution, you can pass environment variables to the container
```sh
docker run \
-p 5000:3000 \
--v /path/to/channels.xml:/epg/channels.xml \
+-v /path/to/channels.xml:/epg/public/channels.xml \
-e CRON_SCHEDULE="0 0,12 * * *" \
-e MAX_CONNECTIONS=10 \
-e GZIP=true \
@@ -203,6 +203,10 @@ ghcr.io/iptv-org/epg:master
| DELAY | Delay between request in milliseconds (default: 0) |
| RUN_AT_STARTUP | Run grab on container startup (default: true) |
+## Guides
+
+Any user can share the guides they have created with the rest of the community. A complete list of these guides and their current status can be found in the [GUIDES.md](GUIDES.md) file.
+
## Database
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.
@@ -236,4 +240,3 @@ And thank you to everyone who has already contributed!
## License
[](LICENSE)
-
From 8d23c384a37befc8cf1512be325de52b2187cbdd Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:54:27 +0300
Subject: [PATCH 10/13] Update CONTRIBUTING.md
---
CONTRIBUTING.md | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e7089e053..5aae9de3a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -407,6 +407,27 @@ This way, you can map channels by simply selecting the proper ID from the list:
Once complete, [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
+### How to add my server to the GUIDES.md?
+
+To do this, you just need to place the `worker.json` file in a public directory on your server.
+
+
+worker.json
+
+
+```json
+{
+ "channels": "path/to/channels.xml",
+ "guide": "path/to/guide.xml"
+}
+```
+
+
+
+And then add server domain or IP address to the [workers.txt](workers.txt) file.
+
+Once your request is approved, it will automatically be added to the [GUIDES.md](GUIDES.md).
+
## Project Structure
- `.github/`
@@ -417,8 +438,10 @@ Once complete, [commit](https://docs.github.com/en/pull-requests/committing-chan
- `sites/`: contains configurations, channel lists and tests for all sites.
- `tests/`: contains tests to check the scripts.
- `CONTRIBUTING.md`: file you are currently reading.
+- `GUIDES.md`: list of all available guides and their current status.
- `README.md`: project description displayed on the home page.
- `SITES.md`: list of all supported sites and their current status.
+- `workers.txt`: list of all available community workers.
## Scripts
@@ -439,6 +462,7 @@ To run scripts use the `npm run ` command.
- `channels:validate`: checks the description of channels for errors.
- `sites:init`: creates a new site config from the template.
- `sites:update`: updates the list of sites and their status in [SITES.md](SITES.md).
+- `guides:update`: updates the list of guides and their status in [GUIDES.md](GUIDES.md).
- `grab`: downloads a program from a specified source.
- `serve`: starts the [web server](https://github.com/vercel/serve).
- `lint`: сhecks the scripts for syntax errors.
From b8655d926b0d2a4a058856207f8bb7eeb289b311 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 12:54:32 +0300
Subject: [PATCH 11/13] Create GUIDES.md
---
GUIDES.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 GUIDES.md
diff --git a/GUIDES.md b/GUIDES.md
new file mode 100644
index 000000000..46c58a37d
--- /dev/null
+++ b/GUIDES.md
@@ -0,0 +1,12 @@
+# Guides
+
+
+
+ | Host | Status | Channels | Last Updated | Links |
+
+
+ | worker-9dd4.onrender.com | 🟢 | 1 | a day ago | channels.xml guide.xml |
+
+
+
+[How can I add my server to the list?](CONTRIBUTING.md#how-to-add-my-server-to-the-guides-md)
From 122be1964495e9c7d85a959dc3cc7634d8687dca Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Fri, 13 Feb 2026 13:00:34 +0300
Subject: [PATCH 12/13] Update dependecies
---
package-lock.json | 488 ++++++++++++++++++++++++++--------------------
1 file changed, 272 insertions(+), 216 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f12b02df7..352f9b8b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1092,9 +1092,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -1611,27 +1611,6 @@
"node": ">=16.0.0"
}
},
- "node_modules/@isaacs/balanced-match": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
- "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
- "license": "MIT",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/@isaacs/brace-expansion": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
- "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
- "license": "MIT",
- "dependencies": {
- "@isaacs/balanced-match": "^4.0.1"
- },
- "engines": {
- "node": "20 || >=22"
- }
- },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -2229,9 +2208,10 @@
}
},
"node_modules/@jest/reporters/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -2846,6 +2826,17 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"license": "ISC"
},
+ "node_modules/@pm2/blessed": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@pm2/blessed/-/blessed-0.1.81.tgz",
+ "integrity": "sha512-ZcNHqQjMuNRcQ7Z1zJbFIQZO/BDKV3KbiTckWdfbUaYhj7uNmUwb+FbdDWSCkvxNr9dBJQwvV17o6QBkAvgO0g==",
+ "bin": {
+ "blessed": "bin/tput.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/@pm2/io": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.1.0.tgz",
@@ -4207,23 +4198,25 @@
}
},
"node_modules/axios": {
- "version": "1.12.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
- "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
+ "version": "1.13.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
+ "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
"dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.4",
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios-cache-interceptor": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.8.3.tgz",
- "integrity": "sha512-ifuSBoCEkVaiugg1UTjVuTdK+SjSOJ35pdv2OrzhRT3wDMr52QiayQxUqs7jd7GDsfPOjMcw3T3ek0TysbyZZw==",
+ "version": "1.11.4",
+ "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.11.4.tgz",
+ "integrity": "sha512-xZ4OZUxdpcFUpZjrqfYlGK0VglpPRKKSoE3vMHrstxolixQNs/MrbMezOAO5uS454hIEcWpnk75RZK26WkPW/g==",
"dependencies": {
- "cache-parser": "1.2.5",
- "fast-defer": "1.1.8",
- "object-code": "1.3.3"
+ "cache-parser": "^1.2.6",
+ "fast-defer": "^1.1.9",
+ "http-vary": "^1.0.3",
+ "object-code": "^2.0.0",
+ "try": "^1.0.3"
},
"engines": {
"node": ">=12"
@@ -4399,17 +4392,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/blessed": {
- "version": "0.1.81",
- "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz",
- "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==",
- "bin": {
- "blessed": "bin/tput.js"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -4615,9 +4597,9 @@
}
},
"node_modules/cache-parser": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.5.tgz",
- "integrity": "sha512-Md/4VhAHByQ9frQ15WD6LrMNiVw9AEl/J7vWIXw+sxT6fSOpbtt6LHTp76vy8+bOESPBO94117Hm2bIjlI7XjA=="
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.6.tgz",
+ "integrity": "sha512-SjjnKlWgrhDrAWKUxAvmZLRGDa6JExMfjSu59/pvpNoI6mEHYSLcLKUw2RtECEOINvf6dxJo35fY+T/scA0SUA=="
},
"node_modules/call-bind": {
"version": "1.0.8",
@@ -6023,9 +6005,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-defer": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.8.tgz",
- "integrity": "sha512-lEJeOH5VL5R09j6AA0D4Uvq7AgsHw0dAImQQ+F3iSyHZuAxyQfWobsagGpTcOPvJr3urmKRHrs+Gs9hV+/Qm/Q=="
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.9.tgz",
+ "integrity": "sha512-JP7Xm9HuePSeTT1DI78NeE9eAQvgNb9qNP2jlyQrcx4jiWM189omV6oyd0xaUPWHPlKmvDzz6H1FfPWIDU+xfg=="
},
"node_modules/fast-glob": {
"version": "3.3.3",
@@ -6153,9 +6135,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
- "version": "1.15.6",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
- "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"funding": [
{
"type": "individual",
@@ -6215,9 +6197,9 @@
}
},
"node_modules/form-data": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
- "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -6378,14 +6360,14 @@
"integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg=="
},
"node_modules/glob": {
- "version": "11.0.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
- "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
- "license": "ISC",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dependencies": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
- "minimatch": "^10.0.3",
+ "minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
@@ -6411,13 +6393,34 @@
"node": ">=10.13.0"
}
},
- "node_modules/glob/node_modules/minimatch": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
- "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
- "license": "ISC",
+ "node_modules/glob/node_modules/balanced-match": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz",
+ "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==",
"dependencies": {
- "@isaacs/brace-expansion": "^5.0.0"
+ "jackspeak": "^4.2.3"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz",
+ "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz",
+ "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==",
+ "dependencies": {
+ "brace-expansion": "^5.0.2"
},
"engines": {
"node": "20 || >=22"
@@ -6591,6 +6594,11 @@
"node": ">= 14"
}
},
+ "node_modules/http-vary": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/http-vary/-/http-vary-1.0.3.tgz",
+ "integrity": "sha512-sx7Y8YTqF3o0mFJJvF66n8dbaE8v3liV1RgCz46XP5xK7dnzyZHvwMWRA115q5kjbCPBV65/nOMlgW54WLyiag=="
+ },
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
@@ -7060,12 +7068,11 @@
}
},
"node_modules/jackspeak": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
- "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
- "license": "BlueOak-1.0.0",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
+ "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
"dependencies": {
- "@isaacs/cliui": "^8.0.2"
+ "@isaacs/cliui": "^9.0.0"
},
"engines": {
"node": "20 || >=22"
@@ -7074,6 +7081,14 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/jackspeak/node_modules/@isaacs/cliui": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
+ "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/jest": {
"version": "30.0.5",
"resolved": "https://registry.npmjs.org/jest/-/jest-30.0.5.tgz",
@@ -7361,9 +7376,10 @@
}
},
"node_modules/jest-config/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -8047,9 +8063,10 @@
}
},
"node_modules/jest-runtime/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -8691,9 +8708,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
},
"node_modules/lodash.groupby": {
"version": "4.6.0",
@@ -9094,9 +9111,9 @@
}
},
"node_modules/object-code": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/object-code/-/object-code-1.3.3.tgz",
- "integrity": "sha512-/Ds4Xd5xzrtUOJ+xJQ57iAy0BZsZltOHssnDgcZ8DOhgh41q1YJCnTPnWdWSLkNGNnxYzhYChjc5dgC9mEERCA=="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/object-code/-/object-code-2.0.0.tgz",
+ "integrity": "sha512-qOwMF43O/VAD51nJAB7MKsf1yWksql6O1i0DHRo1yaOQM6xJQH0NAE9UKJzYB7lyKw1jnpeb2BmB8qakjxiYZA=="
},
"node_modules/object-treeify": {
"version": "2.1.1",
@@ -9539,36 +9556,36 @@
}
},
"node_modules/pm2": {
- "version": "6.0.10",
- "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.10.tgz",
- "integrity": "sha512-sbk4HsnhtJMx1wJlhFQhYfDRzHtVK+cvdrIezbjM9WjSyc7kLtQ4nZ5K7JLOdLe3AevytmRcTiOa3VvAQrve2A==",
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.14.tgz",
+ "integrity": "sha512-wX1FiFkzuT2H/UUEA8QNXDAA9MMHDsK/3UHj6Dkd5U7kxyigKDA5gyDw78ycTQZAuGCLWyUX5FiXEuVQWafukA==",
"dependencies": {
"@pm2/agent": "~2.1.1",
+ "@pm2/blessed": "0.1.81",
"@pm2/io": "~6.1.0",
"@pm2/js-api": "~0.8.0",
- "@pm2/pm2-version-check": "latest",
+ "@pm2/pm2-version-check": "^1.0.4",
"ansis": "4.0.0-node10",
- "async": "~3.2.6",
- "blessed": "0.1.81",
- "chokidar": "^3.5.3",
- "cli-tableau": "^2.0.0",
+ "async": "3.2.6",
+ "chokidar": "3.6.0",
+ "cli-tableau": "2.0.1",
"commander": "2.15.1",
- "croner": "~4.1.92",
- "dayjs": "~1.11.13",
- "debug": "^4.3.7",
+ "croner": "4.1.97",
+ "dayjs": "1.11.15",
+ "debug": "4.4.3",
"enquirer": "2.3.6",
"eventemitter2": "5.0.1",
"fclone": "1.0.11",
- "js-yaml": "~4.1.0",
+ "js-yaml": "4.1.1",
"mkdirp": "1.0.4",
"needle": "2.4.0",
- "pidusage": "~3.0",
+ "pidusage": "3.0.2",
"pm2-axon": "~4.0.1",
"pm2-axon-rpc": "~0.7.1",
"pm2-deploy": "~1.0.2",
"pm2-multimeter": "^0.1.2",
- "promptly": "^2",
- "semver": "^7.6.2",
+ "promptly": "2.2.0",
+ "semver": "7.7.2",
"source-map-support": "0.5.21",
"sprintf-js": "1.1.2",
"vizion": "~2.2.1"
@@ -9680,11 +9697,15 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
},
+ "node_modules/pm2/node_modules/dayjs": {
+ "version": "1.11.15",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.15.tgz",
+ "integrity": "sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ=="
+ },
"node_modules/pm2/node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "license": "MIT",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -9698,9 +9719,9 @@
}
},
"node_modules/pm2/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -10649,9 +10670,9 @@
}
},
"node_modules/systeminformation": {
- "version": "5.25.11",
- "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz",
- "integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==",
+ "version": "5.30.7",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.7.tgz",
+ "integrity": "sha512-33B/cftpaWdpvH+Ho9U1b08ss8GQuLxrWHelbJT1yw4M48Taj8W3ezcPuaLoIHZz5V6tVHuQPr5BprEfnBLBMw==",
"optional": true,
"os": [
"darwin",
@@ -10806,6 +10827,14 @@
"node": ">= 14.0.0"
}
},
+ "node_modules/try": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/try/-/try-1.0.3.tgz",
+ "integrity": "sha512-AHA8khVCII6zKyRkyPo6pRwoR9v5jb7QFw6e5avtaVSkxVfaEucYIo06xnwB+pJaEarfYNbs7W3Vq+LZLZiWyA==",
+ "funding": {
+ "url": "https://github.com/arthurfiorette/try?sponsor=1"
+ }
+ },
"node_modules/ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
@@ -10902,9 +10931,9 @@
}
},
"node_modules/undici": {
- "version": "7.12.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz",
- "integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==",
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.21.0.tgz",
+ "integrity": "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==",
"engines": {
"node": ">=20.18.1"
}
@@ -12007,9 +12036,9 @@
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="
},
"js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"requires": {
"argparse": "^2.0.1"
}
@@ -12316,19 +12345,6 @@
}
}
},
- "@isaacs/balanced-match": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
- "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="
- },
- "@isaacs/brace-expansion": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
- "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
- "requires": {
- "@isaacs/balanced-match": "^4.0.1"
- }
- },
"@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -12766,9 +12782,9 @@
}
},
"glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"requires": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -13232,6 +13248,11 @@
}
}
},
+ "@pm2/blessed": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@pm2/blessed/-/blessed-0.1.81.tgz",
+ "integrity": "sha512-ZcNHqQjMuNRcQ7Z1zJbFIQZO/BDKV3KbiTckWdfbUaYhj7uNmUwb+FbdDWSCkvxNr9dBJQwvV17o6QBkAvgO0g=="
+ },
"@pm2/io": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.1.0.tgz",
@@ -14136,23 +14157,25 @@
}
},
"axios": {
- "version": "1.12.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
- "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
+ "version": "1.13.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
+ "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
"requires": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.4",
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
"axios-cache-interceptor": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.8.3.tgz",
- "integrity": "sha512-ifuSBoCEkVaiugg1UTjVuTdK+SjSOJ35pdv2OrzhRT3wDMr52QiayQxUqs7jd7GDsfPOjMcw3T3ek0TysbyZZw==",
+ "version": "1.11.4",
+ "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.11.4.tgz",
+ "integrity": "sha512-xZ4OZUxdpcFUpZjrqfYlGK0VglpPRKKSoE3vMHrstxolixQNs/MrbMezOAO5uS454hIEcWpnk75RZK26WkPW/g==",
"requires": {
- "cache-parser": "1.2.5",
- "fast-defer": "1.1.8",
- "object-code": "1.3.3"
+ "cache-parser": "^1.2.6",
+ "fast-defer": "^1.1.9",
+ "http-vary": "^1.0.3",
+ "object-code": "^2.0.0",
+ "try": "^1.0.3"
}
},
"axios-cookiejar-support": {
@@ -14270,11 +14293,6 @@
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="
},
- "blessed": {
- "version": "0.1.81",
- "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz",
- "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ=="
- },
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -14407,9 +14425,9 @@
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw=="
},
"cache-parser": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.5.tgz",
- "integrity": "sha512-Md/4VhAHByQ9frQ15WD6LrMNiVw9AEl/J7vWIXw+sxT6fSOpbtt6LHTp76vy8+bOESPBO94117Hm2bIjlI7XjA=="
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.6.tgz",
+ "integrity": "sha512-SjjnKlWgrhDrAWKUxAvmZLRGDa6JExMfjSu59/pvpNoI6mEHYSLcLKUw2RtECEOINvf6dxJo35fY+T/scA0SUA=="
},
"call-bind": {
"version": "1.0.8",
@@ -15375,9 +15393,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-defer": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.8.tgz",
- "integrity": "sha512-lEJeOH5VL5R09j6AA0D4Uvq7AgsHw0dAImQQ+F3iSyHZuAxyQfWobsagGpTcOPvJr3urmKRHrs+Gs9hV+/Qm/Q=="
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.9.tgz",
+ "integrity": "sha512-JP7Xm9HuePSeTT1DI78NeE9eAQvgNb9qNP2jlyQrcx4jiWM189omV6oyd0xaUPWHPlKmvDzz6H1FfPWIDU+xfg=="
},
"fast-glob": {
"version": "3.3.3",
@@ -15487,9 +15505,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
- "version": "1.15.6",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
- "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="
},
"for-each": {
"version": "0.3.5",
@@ -15516,9 +15534,9 @@
}
},
"form-data": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
- "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -15628,24 +15646,40 @@
"integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg=="
},
"glob": {
- "version": "11.0.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
- "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"requires": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
- "minimatch": "^10.0.3",
+ "minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"dependencies": {
- "minimatch": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
- "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
+ "balanced-match": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz",
+ "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==",
"requires": {
- "@isaacs/brace-expansion": "^5.0.0"
+ "jackspeak": "^4.2.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz",
+ "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==",
+ "requires": {
+ "balanced-match": "^4.0.2"
+ }
+ },
+ "minimatch": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz",
+ "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==",
+ "requires": {
+ "brace-expansion": "^5.0.2"
}
}
}
@@ -15752,6 +15786,11 @@
"debug": "^4.3.4"
}
},
+ "http-vary": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/http-vary/-/http-vary-1.0.3.tgz",
+ "integrity": "sha512-sx7Y8YTqF3o0mFJJvF66n8dbaE8v3liV1RgCz46XP5xK7dnzyZHvwMWRA115q5kjbCPBV65/nOMlgW54WLyiag=="
+ },
"https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
@@ -16048,11 +16087,18 @@
}
},
"jackspeak": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
- "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
+ "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
"requires": {
- "@isaacs/cliui": "^8.0.2"
+ "@isaacs/cliui": "^9.0.0"
+ },
+ "dependencies": {
+ "@isaacs/cliui": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
+ "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="
+ }
}
},
"jest": {
@@ -16290,9 +16336,9 @@
}
},
"glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"requires": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -16816,9 +16862,9 @@
}
},
"glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"requires": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -17285,9 +17331,9 @@
}
},
"lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
},
"lodash.groupby": {
"version": "4.6.0",
@@ -17584,9 +17630,9 @@
"integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA=="
},
"object-code": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/object-code/-/object-code-1.3.3.tgz",
- "integrity": "sha512-/Ds4Xd5xzrtUOJ+xJQ57iAy0BZsZltOHssnDgcZ8DOhgh41q1YJCnTPnWdWSLkNGNnxYzhYChjc5dgC9mEERCA=="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/object-code/-/object-code-2.0.0.tgz",
+ "integrity": "sha512-qOwMF43O/VAD51nJAB7MKsf1yWksql6O1i0DHRo1yaOQM6xJQH0NAE9UKJzYB7lyKw1jnpeb2BmB8qakjxiYZA=="
},
"object-treeify": {
"version": "2.1.1",
@@ -17907,37 +17953,37 @@
}
},
"pm2": {
- "version": "6.0.10",
- "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.10.tgz",
- "integrity": "sha512-sbk4HsnhtJMx1wJlhFQhYfDRzHtVK+cvdrIezbjM9WjSyc7kLtQ4nZ5K7JLOdLe3AevytmRcTiOa3VvAQrve2A==",
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.14.tgz",
+ "integrity": "sha512-wX1FiFkzuT2H/UUEA8QNXDAA9MMHDsK/3UHj6Dkd5U7kxyigKDA5gyDw78ycTQZAuGCLWyUX5FiXEuVQWafukA==",
"requires": {
"@pm2/agent": "~2.1.1",
+ "@pm2/blessed": "0.1.81",
"@pm2/io": "~6.1.0",
"@pm2/js-api": "~0.8.0",
- "@pm2/pm2-version-check": "latest",
+ "@pm2/pm2-version-check": "^1.0.4",
"ansis": "4.0.0-node10",
- "async": "~3.2.6",
- "blessed": "0.1.81",
- "chokidar": "^3.5.3",
- "cli-tableau": "^2.0.0",
+ "async": "3.2.6",
+ "chokidar": "3.6.0",
+ "cli-tableau": "2.0.1",
"commander": "2.15.1",
- "croner": "~4.1.92",
- "dayjs": "~1.11.13",
- "debug": "^4.3.7",
+ "croner": "4.1.97",
+ "dayjs": "1.11.15",
+ "debug": "4.4.3",
"enquirer": "2.3.6",
"eventemitter2": "5.0.1",
"fclone": "1.0.11",
- "js-yaml": "~4.1.0",
+ "js-yaml": "4.1.1",
"mkdirp": "1.0.4",
"needle": "2.4.0",
- "pidusage": "~3.0",
+ "pidusage": "3.0.2",
"pm2-axon": "~4.0.1",
"pm2-axon-rpc": "~0.7.1",
"pm2-deploy": "~1.0.2",
"pm2-multimeter": "^0.1.2",
"pm2-sysmonit": "^1.2.8",
- "promptly": "^2",
- "semver": "^7.6.2",
+ "promptly": "2.2.0",
+ "semver": "7.7.2",
"source-map-support": "0.5.21",
"sprintf-js": "1.1.2",
"vizion": "~2.2.1"
@@ -17953,18 +17999,23 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
},
+ "dayjs": {
+ "version": "1.11.15",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.15.tgz",
+ "integrity": "sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ=="
+ },
"debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"requires": {
"ms": "^2.1.3"
}
},
"js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"requires": {
"argparse": "^2.0.1"
}
@@ -18675,9 +18726,9 @@
}
},
"systeminformation": {
- "version": "5.25.11",
- "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz",
- "integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==",
+ "version": "5.30.7",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.7.tgz",
+ "integrity": "sha512-33B/cftpaWdpvH+Ho9U1b08ss8GQuLxrWHelbJT1yw4M48Taj8W3ezcPuaLoIHZz5V6tVHuQPr5BprEfnBLBMw==",
"optional": true
},
"table2array": {
@@ -18778,6 +18829,11 @@
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="
},
+ "try": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/try/-/try-1.0.3.tgz",
+ "integrity": "sha512-AHA8khVCII6zKyRkyPo6pRwoR9v5jb7QFw6e5avtaVSkxVfaEucYIo06xnwB+pJaEarfYNbs7W3Vq+LZLZiWyA=="
+ },
"ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
@@ -18837,9 +18893,9 @@
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="
},
"undici": {
- "version": "7.12.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz",
- "integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug=="
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.21.0.tgz",
+ "integrity": "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg=="
},
"undici-types": {
"version": "7.8.0",
From 16e7dd0eab7715428a66d481efd00216025648e4 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Sun, 15 Feb 2026 08:23:23 +0300
Subject: [PATCH 13/13] Update worker.ts
---
scripts/models/worker.ts | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/scripts/models/worker.ts b/scripts/models/worker.ts
index 8b625ffa9..94b94dfcb 100644
--- a/scripts/models/worker.ts
+++ b/scripts/models/worker.ts
@@ -1,9 +1,11 @@
import relativeTime from 'dayjs/plugin/relativeTime'
import { Collection } from '@freearhey/core'
import { Channel } from './channel'
+import utc from 'dayjs/plugin/utc'
import dayjs from 'dayjs'
dayjs.extend(relativeTime)
+dayjs.extend(utc)
export interface WorkerData {
host: string
@@ -63,6 +65,9 @@ export class Worker {
getLastUpdated(): string {
if (!this.lastUpdated) return '-'
- return dayjs().to(dayjs(this.lastUpdated))
+ let now = dayjs()
+ if (process.env.NODE_ENV === 'test') now = dayjs.utc('2026-02-13')
+
+ return dayjs.utc(this.lastUpdated).from(now)
}
}