Torrent downloads are coming soon.
Futureporn is no longer using IPFS. Read more
diff --git a/services/pocketbase/pb_hooks/pages/(site)/vods/[id]/index.ejs b/services/pocketbase/pb_hooks/pages/(site)/vods/[id]/index.ejs
index 60f96349..2c2f3d7f 100644
--- a/services/pocketbase/pb_hooks/pages/(site)/vods/[id]/index.ejs
+++ b/services/pocketbase/pb_hooks/pages/(site)/vods/[id]/index.ejs
@@ -41,11 +41,13 @@
diff --git a/services/pocketbase/pb_hooks/pages/_private/vod-list.ejs b/services/pocketbase/pb_hooks/pages/_private/vod-list.ejs
index b8ef5731..e13088ff 100644
--- a/services/pocketbase/pb_hooks/pages/_private/vod-list.ejs
+++ b/services/pocketbase/pb_hooks/pages/_private/vod-list.ejs
@@ -6,6 +6,7 @@
Stream Date |
VTuber |
Thumbnail |
+
DL |
@@ -37,6 +38,18 @@
No thumbnail
<% } %>
+
+ <% if (vod?.magnetLink) { %>
+
+
+
+ <% } %>
+ |
<% } %>
diff --git a/services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs b/services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs
index 1f1bfa20..9896bcf6 100644
--- a/services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs
+++ b/services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs
@@ -1,18 +1,22 @@
<%#
index.ejs — RSS Feed Generator (RSS 2.0)
-Expects: data.vods = [{ id, title, notes, thumbnail, streamDate }]
+Expects: data.vods = [{ id, title, notes, thumbnail, streamDate, magnetLink }]
+When in doubt, copy https://nyaa.si/?page=rss
%>
<%
-response.header("Content-Type", "application/rss+xml")
+response.header("Content-Type", "application/rss+xml");
-// Build RSS XML as a string
let rss = `
-
+
+
Futureporn.net VODs
https://futureporn.net
- Dedication to the preservaton of lewdtuber history
+ Dedication to the preservation of lewdtuber history
${new Date().toUTCString()}
https://validator.w3.org/feed/docs/rss2.html
pocketpages
@@ -22,26 +26,42 @@ let rss = `
https://futureporn.net/images/futureporn-icon.png
https://futureporn.net
`;
-
+
for (const vod of data.vods) {
- const url = `${env('ORIGIN')}/vods/${vod.id}`;
+ const vodId = vod.get('id');
+ const title =
+ (vod?.get('expand')?.vtubers?.map(v => v.get('displayName')).join(', '))
+ || vod.get('streamDate');
+
+ const vodUrl = `${env('ORIGIN')}/vods/${vodId}`;
+ const pubDate = new Date(vod.get('streamDate')).toUTCString();
+ const notes = vod.get('notes');
+ const thumbnail = vod.get('thumbnail');
+ const magnetLink = vod.get('magnetLink');
+
+ // @TODO the must contain a .torrent, NOT a magnetLink.
rss += `
-
+
+ ${vodUrl}
+ ${vodUrl}
+ ${vodUrl}
+ ${pubDate}`;
- vt.get('displayName')) || []).join(', ')
- || vod.get('streamDate'))
- }]]>
- ${url}
- ${url}
- ${new Date(vod.get('streamDate')).toUTCString()}`;
- if (vod.get('notes')) {
+ // Description
+ if (notes) {
rss += `
- `;
+ ${vodUrl} ${notes}]]>`;
}
- if (vod.get('thumbnail')) {
- rss += `${env('ORIGIN')}/api/files/vods/${vod.get('id')}/${vod.get('thumbnail')}`
+
+ // Thumbnail (custom tag — allowed)
+ if (thumbnail) {
+ rss += `
+ ${env('ORIGIN')}/api/files/vods/${vodId}/${thumbnail}`;
}
+
+
+
rss += `
`;
}
@@ -50,6 +70,5 @@ rss += `
`;
-// Send the RSS
response.html(200, rss);
%>
\ No newline at end of file
diff --git a/services/worker/.config/env.ts b/services/worker/.config/env.ts
index 51bb9a30..b83a2dc1 100644
--- a/services/worker/.config/env.ts
+++ b/services/worker/.config/env.ts
@@ -1,3 +1,5 @@
+import envPaths from 'env-paths';
+const paths = envPaths('futureporn', { suffix: '' });
const env = (() => {
if (!process.env.POCKETBASE_URL) throw new Error('POCKETBASE_URL missing in env');
@@ -27,7 +29,6 @@ const env = (() => {
if (!process.env.FANSLY_PASSWORD) throw new Error('FANSLY_PASSWORD missing in env');
if (!process.env.APIFY_TOKEN) throw new Error('APIFY_TOKEN missing in env');
if (!process.env.NODE_ENV) throw new Error('APIFY_TOKEN missing in env');
- if (!process.env.CACHE_ROOT) throw new Error('CACHE_ROOT missing in env');
if (!process.env.SEEDBOX_SFTP_HOST) throw new Error('SEEDBOX_SFTP_HOST missing in env');
if (!process.env.SEEDBOX_SFTP_PORT) throw new Error('SEEDBOX_SFTP_PORT missing in env');
if (!process.env.SEEDBOX_SFTP_USERNAME) throw new Error('SEEDBOX_SFTP_USERNAME missing in env');
@@ -37,6 +38,10 @@ const env = (() => {
if (!process.env.QBT_PASSWORD) throw new Error('QBT_PASSWORD missing in env');
if (!process.env.QBT_USERNAME) throw new Error('QBT_USERNAME missing in env');
if (!process.env.WORKER_WORKERS) throw new Error('WORKER_WORKERS missing in env');
+ if (!process.env.BUNNY_ZONE_URL) throw new Error('BUNNY_ZONE_URL missing in env');
+ if (!process.env.BUNNY_TOKEN_KEY) throw new Error('BUNNY_TOKEN_KEY missing in env');
+
+ const CACHE_ROOT = process.env?.CACHE_ROOT || paths.cache;
const {
PORT,
@@ -65,7 +70,6 @@ const env = (() => {
FANSLY_PASSWORD,
APIFY_TOKEN,
NODE_ENV,
- CACHE_ROOT,
SEEDBOX_SFTP_HOST,
SEEDBOX_SFTP_PORT,
SEEDBOX_SFTP_USERNAME,
@@ -76,8 +80,11 @@ const env = (() => {
QBT_PASSWORD,
QBT_PORT,
WORKER_WORKERS,
+ BUNNY_ZONE_URL,
+ BUNNY_TOKEN_KEY,
} = process.env
return {
+ CACHE_ROOT,
PORT,
WORKER_PORT,
POCKETBASE_URL,
@@ -104,7 +111,6 @@ const env = (() => {
FANSLY_USERNAME,
APIFY_TOKEN,
NODE_ENV,
- CACHE_ROOT,
SEEDBOX_SFTP_HOST,
SEEDBOX_SFTP_PORT,
SEEDBOX_SFTP_USERNAME,
@@ -115,6 +121,8 @@ const env = (() => {
QBT_PASSWORD,
QBT_PORT,
WORKER_WORKERS,
+ BUNNY_ZONE_URL,
+ BUNNY_TOKEN_KEY,
}
})()
diff --git a/services/worker/package-lock.json b/services/worker/package-lock.json
index 3389c8da..c5b3ac2e 100644
--- a/services/worker/package-lock.json
+++ b/services/worker/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "worker",
- "version": "0.0.1",
+ "version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "worker",
- "version": "0.0.1",
+ "version": "0.1.0",
"dependencies": {
"@bull-board/express": "^6.14.0",
"@mux/mux-node": "^12.8.0",
@@ -15,7 +15,7 @@
"@types/node": "^24.10.1",
"@types/semver": "^7.7.1",
"@types/ssh2": "^1.15.5",
- "apify-client": "^2.19.0",
+ "apify-client": "^2.20.0",
"bullmq": "^5.63.0",
"date-fns": "^4.1.0",
"fs-extra": "^11.3.2",
@@ -24,14 +24,14 @@
"nanoid": "^5.1.6",
"onnxruntime-web": "^1.23.2",
"pocketbase": "^0.26.3",
- "puppeteer": "^24.30.0",
+ "puppeteer": "^24.31.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"semver": "^7.7.3",
"sharp": "^0.34.5",
"slugify": "^1.6.6",
"ssh2": "^1.17.0",
- "which": "^5.0.0"
+ "which": "^6.0.0"
},
"devDependencies": {
"tsx": "^4.20.6",
@@ -58,9 +58,9 @@
}
},
"node_modules/@apify/utilities": {
- "version": "2.23.0",
- "resolved": "https://registry.npmjs.org/@apify/utilities/-/utilities-2.23.0.tgz",
- "integrity": "sha512-WAyenlKvtXtvd6V8D2fYwbsmc3dMn3z02JaOhZNx/p8u0NuacNgoLk/+PW4IPWrNxhqgDQZqde4cpNfZOktvsQ==",
+ "version": "2.23.2",
+ "resolved": "https://registry.npmjs.org/@apify/utilities/-/utilities-2.23.2.tgz",
+ "integrity": "sha512-kNA9m7DN+6CW6OEadH43CZPz5dJ1UfimfXtkt2Oq0yU7ovN9kNZXOGrpGPGMxVwKmIeIghZEzMriuI6XVAFtfA==",
"license": "Apache-2.0",
"dependencies": {
"@apify/consts": "^2.47.0",
@@ -91,36 +91,36 @@
}
},
"node_modules/@bull-board/api": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-6.14.0.tgz",
- "integrity": "sha512-oMDwXwoPn0RsdZ3Y68/bOErZ/qGZE5H97vgE/Pc8Uul/OHajlvajKW4NV+ZGTix82liUfH9CkjYx7PpwvBWhxg==",
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-6.14.2.tgz",
+ "integrity": "sha512-UzkvN/wM+1qS73BS43a75LYkRzpBpCCUKlaGq0hp3dM5MNmdF1mx7LMGYgXPt91gqF8j4jq9Y/zCpC3Sqs3RLQ==",
"license": "MIT",
"dependencies": {
"redis-info": "^3.1.0"
},
"peerDependencies": {
- "@bull-board/ui": "6.14.0"
+ "@bull-board/ui": "6.14.2"
}
},
"node_modules/@bull-board/express": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-6.14.0.tgz",
- "integrity": "sha512-3H1ame2G1+eVnqqSsw6KfzTGYAWSpVsIx6EPwg9vPSP2eKfNAm12Cm4zvL6ZkwAvTCkAByt5PPDRWbbwWB6HHQ==",
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-6.14.2.tgz",
+ "integrity": "sha512-nghb4MpYDodYZpeiZvI9tXFDHqiAXE8FhrLOFDkuQL0GBhw0gEOuGSISjdKrnFDAW72LWVq0XfGKWYD8V5nF0w==",
"license": "MIT",
"dependencies": {
- "@bull-board/api": "6.14.0",
- "@bull-board/ui": "6.14.0",
+ "@bull-board/api": "6.14.2",
+ "@bull-board/ui": "6.14.2",
"ejs": "^3.1.10",
"express": "^4.21.1 || ^5.0.0"
}
},
"node_modules/@bull-board/ui": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-6.14.0.tgz",
- "integrity": "sha512-5yqfS9CwWR8DBxpReIbqv/VSPFM/zT4KZ75keyApMiejasRC2joaHqEzYWlMCjkMycbNNCvlQNlTbl+C3dE/dg==",
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-6.14.2.tgz",
+ "integrity": "sha512-OTCsBbMAhYoB2NJc6FxkkREWWPUFvEhL2Az1gAKpdNOBqup4CsKj7eBK3rcWSRLZ4LnaOaPK8E8tiogkhrRuOA==",
"license": "MIT",
"dependencies": {
- "@bull-board/api": "6.14.0"
+ "@bull-board/api": "6.14.2"
}
},
"node_modules/@crawlee/types": {
@@ -136,9 +136,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz",
- "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
+ "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1054,6 +1054,8 @@
},
"node_modules/@ioredis/commands": {
"version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.4.0.tgz",
+ "integrity": "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==",
"license": "MIT"
},
"node_modules/@jridgewell/sourcemap-codec": {
@@ -1063,8 +1065,62 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
+ "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
+ "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
+ "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
+ "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
"version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
+ "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
"cpu": [
"x64"
],
@@ -1074,8 +1130,23 @@
"linux"
]
},
+ "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
+ "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@mux/mux-node": {
"version": "12.8.0",
+ "resolved": "https://registry.npmjs.org/@mux/mux-node/-/mux-node-12.8.0.tgz",
+ "integrity": "sha512-J7Qe1JGlOWle+5huN27hBcAKujx0xgC8d3qQ1s9emyEETR+ubxlRf/9UOlN+GoPtoMPIDa5fWDRf2LDWzsiBOA==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
@@ -1189,9 +1260,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz",
- "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
+ "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
"cpu": [
"arm"
],
@@ -1203,9 +1274,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz",
- "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
+ "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
"cpu": [
"arm64"
],
@@ -1217,9 +1288,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz",
- "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
+ "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
"cpu": [
"arm64"
],
@@ -1231,9 +1302,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz",
- "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
+ "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
"cpu": [
"x64"
],
@@ -1245,9 +1316,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz",
- "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
+ "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
"cpu": [
"arm64"
],
@@ -1259,9 +1330,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz",
- "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
+ "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
"cpu": [
"x64"
],
@@ -1273,9 +1344,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz",
- "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
+ "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
"cpu": [
"arm"
],
@@ -1287,9 +1358,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz",
- "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
+ "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
"cpu": [
"arm"
],
@@ -1301,9 +1372,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz",
- "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
+ "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
"cpu": [
"arm64"
],
@@ -1315,9 +1386,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz",
- "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
+ "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
"cpu": [
"arm64"
],
@@ -1329,9 +1400,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz",
- "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
+ "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
"cpu": [
"loong64"
],
@@ -1343,9 +1414,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz",
- "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
+ "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
"cpu": [
"ppc64"
],
@@ -1357,9 +1428,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz",
- "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
+ "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
"cpu": [
"riscv64"
],
@@ -1371,9 +1442,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz",
- "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
+ "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
"cpu": [
"riscv64"
],
@@ -1385,9 +1456,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz",
- "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
+ "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
"cpu": [
"s390x"
],
@@ -1399,9 +1470,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz",
- "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
+ "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
"cpu": [
"x64"
],
@@ -1413,9 +1484,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz",
- "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
+ "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
"cpu": [
"x64"
],
@@ -1427,9 +1498,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz",
- "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
+ "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
"cpu": [
"arm64"
],
@@ -1441,9 +1512,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz",
- "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
+ "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
"cpu": [
"arm64"
],
@@ -1455,9 +1526,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz",
- "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
+ "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
"cpu": [
"ia32"
],
@@ -1469,9 +1540,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz",
- "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz",
+ "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==",
"cpu": [
"x64"
],
@@ -1483,9 +1554,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz",
- "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz",
+ "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==",
"cpu": [
"x64"
],
@@ -1632,6 +1703,8 @@
},
"node_modules/@types/node-fetch": {
"version": "2.6.13",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
+ "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
@@ -1721,17 +1794,17 @@
}
},
"node_modules/@vitest/expect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.8.tgz",
- "integrity": "sha512-Rv0eabdP/xjAHQGr8cjBm+NnLHNoL268lMDK85w2aAGLFoVKLd8QGnVon5lLtkXQCoYaNL0wg04EGnyKkkKhPA==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.13.tgz",
+ "integrity": "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"@types/chai": "^5.2.2",
- "@vitest/spy": "4.0.8",
- "@vitest/utils": "4.0.8",
- "chai": "^6.2.0",
+ "@vitest/spy": "4.0.13",
+ "@vitest/utils": "4.0.13",
+ "chai": "^6.2.1",
"tinyrainbow": "^3.0.3"
},
"funding": {
@@ -1739,13 +1812,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.8.tgz",
- "integrity": "sha512-9FRM3MZCedXH3+pIh+ME5Up2NBBHDq0wqwhOKkN4VnvCiKbVxddqH9mSGPZeawjd12pCOGnl+lo/ZGHt0/dQSg==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.13.tgz",
+ "integrity": "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.0.8",
+ "@vitest/spy": "4.0.13",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21"
},
@@ -1766,9 +1839,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.8.tgz",
- "integrity": "sha512-qRrjdRkINi9DaZHAimV+8ia9Gq6LeGz2CgIEmMLz3sBDYV53EsnLZbJMR1q84z1HZCMsf7s0orDgZn7ScXsZKg==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.13.tgz",
+ "integrity": "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1779,13 +1852,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.8.tgz",
- "integrity": "sha512-mdY8Sf1gsM8hKJUQfiPT3pn1n8RF4QBcJYFslgWh41JTfrK1cbqY8whpGCFzBl45LN028g0njLCYm0d7XxSaQQ==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.13.tgz",
+ "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "4.0.8",
+ "@vitest/utils": "4.0.13",
"pathe": "^2.0.3"
},
"funding": {
@@ -1793,13 +1866,13 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.8.tgz",
- "integrity": "sha512-Nar9OTU03KGiubrIOFhcfHg8FYaRaNT+bh5VUlNz8stFhCZPNrJvmZkhsr1jtaYvuefYFwK2Hwrq026u4uPWCw==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.13.tgz",
+ "integrity": "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.0.8",
+ "@vitest/pretty-format": "4.0.13",
"magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
@@ -1808,9 +1881,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.8.tgz",
- "integrity": "sha512-nvGVqUunyCgZH7kmo+Ord4WgZ7lN0sOULYXUOYuHr55dvg9YvMz3izfB189Pgp28w0vWFbEEfNc/c3VTrqrXeA==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.13.tgz",
+ "integrity": "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw==",
"dev": true,
"license": "MIT",
"funding": {
@@ -1818,13 +1891,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.8.tgz",
- "integrity": "sha512-pdk2phO5NDvEFfUTxcTP8RFYjVj/kfLSPIN5ebP2Mu9kcIMeAQTbknqcFEyBcC4z2pJlJI9aS5UQjcYfhmKAow==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.13.tgz",
+ "integrity": "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.0.8",
+ "@vitest/pretty-format": "4.0.13",
"tinyrainbow": "^3.0.3"
},
"funding": {
@@ -1833,6 +1906,8 @@
},
"node_modules/abort-controller": {
"version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"license": "MIT",
"dependencies": {
"event-target-shim": "^5.0.0"
@@ -1854,27 +1929,6 @@
"node": ">= 0.6"
}
},
- "node_modules/accepts/node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/accepts/node_modules/mime-types": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
- "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
@@ -1886,6 +1940,8 @@
},
"node_modules/agentkeepalive": {
"version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
+ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
"license": "MIT",
"dependencies": {
"humanize-ms": "^1.2.1"
@@ -1928,16 +1984,16 @@
}
},
"node_modules/apify-client": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/apify-client/-/apify-client-2.19.0.tgz",
- "integrity": "sha512-cDYwbygx/OplyF9MXTeb70nKwZHQQIp5OodsPeikWrh8sHmfeKWUu9jUUzeiWpHIPcwroYrP7KxA6UDSBGY3kQ==",
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/apify-client/-/apify-client-2.20.0.tgz",
+ "integrity": "sha512-oEMTImVVRZ5n8JkFV6dgbBFL3Xqz+GTwjUCjn/hwSNkow31Q8VNGk4qYDfRjkoqNQJ3ZirhtCwTnhkSXn1Tf+g==",
"license": "Apache-2.0",
"dependencies": {
"@apify/consts": "^2.42.0",
"@apify/log": "^2.2.6",
- "@apify/utilities": "^2.18.0",
+ "@apify/utilities": "^2.23.2",
"@crawlee/types": "^3.3.0",
- "agentkeepalive": "^4.2.1",
+ "ansi-colors": "^4.1.1",
"async-retry": "^1.3.3",
"axios": "^1.6.7",
"content-type": "^1.0.5",
@@ -2009,6 +2065,8 @@
},
"node_modules/asynckit": {
"version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
@@ -2199,11 +2257,13 @@
}
},
"node_modules/bullmq": {
- "version": "5.63.0",
+ "version": "5.64.1",
+ "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.64.1.tgz",
+ "integrity": "sha512-Tg4ORit8bQ1xLwcQrEfcDpG50pS30Onuz1ZA4rPLbL9QEsOaBbvFQMSEvXSgMnvRZRqDggJoSBGz9tck+1PixQ==",
"license": "MIT",
"dependencies": {
"cron-parser": "^4.9.0",
- "ioredis": "^5.4.1",
+ "ioredis": "^5.8.2",
"msgpackr": "^1.11.2",
"node-abort-controller": "^3.1.1",
"semver": "^7.5.4",
@@ -2222,6 +2282,8 @@
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -2311,6 +2373,8 @@
},
"node_modules/cluster-key-slot": {
"version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10.0"
@@ -2336,6 +2400,8 @@
},
"node_modules/combined-stream": {
"version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
@@ -2351,15 +2417,16 @@
"license": "MIT"
},
"node_modules/content-disposition": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
- "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
"license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
"engines": {
- "node": ">= 0.6"
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/content-type": {
@@ -2431,6 +2498,8 @@
},
"node_modules/cron-parser": {
"version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
+ "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
"license": "MIT",
"dependencies": {
"luxon": "^3.2.1"
@@ -2460,6 +2529,8 @@
},
"node_modules/debug": {
"version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -2498,6 +2569,8 @@
},
"node_modules/delayed-stream": {
"version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
@@ -2505,6 +2578,8 @@
},
"node_modules/denque": {
"version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
@@ -2521,6 +2596,8 @@
},
"node_modules/detect-libc": {
"version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -2549,6 +2626,8 @@
},
"node_modules/dunder-proto": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@@ -2624,6 +2703,8 @@
},
"node_modules/es-define-property": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -2631,6 +2712,8 @@
},
"node_modules/es-errors": {
"version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -2645,6 +2728,8 @@
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -2655,6 +2740,8 @@
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -2796,6 +2883,8 @@
},
"node_modules/event-target-shim": {
"version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"license": "MIT",
"engines": {
"node": ">=6"
@@ -2862,27 +2951,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/express/node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express/node_modules/mime-types": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
- "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -3010,7 +3078,9 @@
}
},
"node_modules/form-data": {
- "version": "4.0.4",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
@@ -3025,10 +3095,35 @@
},
"node_modules/form-data-encoder": {
"version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
+ "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
"license": "MIT"
},
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/formdata-node": {
"version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
+ "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
"license": "MIT",
"dependencies": {
"node-domexception": "1.0.0",
@@ -3093,6 +3188,8 @@
},
"node_modules/function-bind": {
"version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -3109,6 +3206,8 @@
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -3131,6 +3230,8 @@
},
"node_modules/get-proto": {
"version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@@ -3227,6 +3328,8 @@
},
"node_modules/gopd": {
"version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -3249,6 +3352,8 @@
},
"node_modules/has-symbols": {
"version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -3259,6 +3364,8 @@
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@@ -3272,6 +3379,8 @@
},
"node_modules/hasown": {
"version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -3281,28 +3390,23 @@
}
},
"node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
- }
- },
- "node_modules/http-errors/node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/http-proxy-agent": {
@@ -3333,6 +3437,8 @@
},
"node_modules/humanize-ms": {
"version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.0.0"
@@ -3385,6 +3491,8 @@
},
"node_modules/ioredis": {
"version": "5.8.2",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.8.2.tgz",
+ "integrity": "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==",
"license": "MIT",
"dependencies": {
"@ioredis/commands": "1.4.0",
@@ -3517,6 +3625,8 @@
},
"node_modules/jose": {
"version": "4.15.9",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
+ "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/panva"
@@ -3529,9 +3639,9 @@
"license": "MIT"
},
"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==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -3593,10 +3703,14 @@
},
"node_modules/lodash.defaults": {
"version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"license": "MIT"
},
"node_modules/lodash.isarguments": {
"version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==",
"license": "MIT"
},
"node_modules/lodash.isequal": {
@@ -3623,6 +3737,8 @@
},
"node_modules/luxon": {
"version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
+ "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -3640,6 +3756,8 @@
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -3681,20 +3799,28 @@
}
},
"node_modules/mime-db": {
- "version": "1.52.0",
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
- "version": "2.1.35",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
"license": "MIT",
"dependencies": {
- "mime-db": "1.52.0"
+ "mime-db": "^1.54.0"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/minimatch": {
@@ -3739,10 +3865,14 @@
},
"node_modules/ms": {
"version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/msgpackr": {
"version": "1.11.5",
+ "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.5.tgz",
+ "integrity": "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==",
"license": "MIT",
"optionalDependencies": {
"msgpackr-extract": "^3.0.2"
@@ -3750,6 +3880,8 @@
},
"node_modules/msgpackr-extract": {
"version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
+ "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -3825,10 +3957,15 @@
},
"node_modules/node-abort-controller": {
"version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
+ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
"license": "MIT"
},
"node_modules/node-domexception": {
"version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
@@ -3846,6 +3983,8 @@
},
"node_modules/node-fetch": {
"version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
@@ -3864,6 +4003,8 @@
},
"node_modules/node-gyp-build-optional-packages": {
"version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
+ "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -4211,9 +4352,9 @@
}
},
"node_modules/puppeteer": {
- "version": "24.30.0",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.30.0.tgz",
- "integrity": "sha512-A5OtCi9WpiXBQgJ2vQiZHSyrAzQmO/WDsvghqlN4kgw21PhxA5knHUaUQq/N3EMt8CcvSS0RM+kmYLJmedR3TQ==",
+ "version": "24.31.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.31.0.tgz",
+ "integrity": "sha512-q8y5yLxLD8xdZdzNWqdOL43NbfvUOp60SYhaLZQwHC9CdKldxQKXOyJAciOr7oUJfyAH/KgB2wKvqT2sFKoVXA==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -4221,7 +4362,7 @@
"chromium-bidi": "11.0.0",
"cosmiconfig": "^9.0.0",
"devtools-protocol": "0.0.1521046",
- "puppeteer-core": "24.30.0",
+ "puppeteer-core": "24.31.0",
"typed-query-selector": "^2.12.0"
},
"bin": {
@@ -4232,9 +4373,9 @@
}
},
"node_modules/puppeteer-core": {
- "version": "24.30.0",
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.30.0.tgz",
- "integrity": "sha512-2S3Smy0t0W4wJnNvDe7W0bE7wDmZjfZ3ljfMgJd6hn2Hq/f0jgN+x9PULZo2U3fu5UUIJ+JP8cNUGllu8P91Pg==",
+ "version": "24.31.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.31.0.tgz",
+ "integrity": "sha512-pnAohhSZipWQoFpXuGV7xCZfaGhqcBR9C4pVrU0QSrcMi7tQMH9J9lDBqBvyMAHQqe8HCARuREqFuVKRQOgTvg==",
"license": "Apache-2.0",
"dependencies": {
"@puppeteer/browsers": "2.10.13",
@@ -4242,7 +4383,7 @@
"debug": "^4.4.3",
"devtools-protocol": "0.0.1521046",
"typed-query-selector": "^2.12.0",
- "webdriver-bidi-protocol": "0.3.8",
+ "webdriver-bidi-protocol": "0.3.9",
"ws": "^8.18.3"
},
"engines": {
@@ -4424,15 +4565,15 @@
}
},
"node_modules/raw-body": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz",
- "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
"license": "MIT",
"dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.7.0",
- "unpipe": "1.0.0"
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.10"
@@ -4456,6 +4597,8 @@
},
"node_modules/redis-errors": {
"version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
"license": "MIT",
"engines": {
"node": ">=4"
@@ -4472,6 +4615,8 @@
},
"node_modules/redis-parser": {
"version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"license": "MIT",
"dependencies": {
"redis-errors": "^1.0.0"
@@ -4534,9 +4679,9 @@
}
},
"node_modules/rollup": {
- "version": "4.53.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz",
- "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz",
+ "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4550,28 +4695,28 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.53.2",
- "@rollup/rollup-android-arm64": "4.53.2",
- "@rollup/rollup-darwin-arm64": "4.53.2",
- "@rollup/rollup-darwin-x64": "4.53.2",
- "@rollup/rollup-freebsd-arm64": "4.53.2",
- "@rollup/rollup-freebsd-x64": "4.53.2",
- "@rollup/rollup-linux-arm-gnueabihf": "4.53.2",
- "@rollup/rollup-linux-arm-musleabihf": "4.53.2",
- "@rollup/rollup-linux-arm64-gnu": "4.53.2",
- "@rollup/rollup-linux-arm64-musl": "4.53.2",
- "@rollup/rollup-linux-loong64-gnu": "4.53.2",
- "@rollup/rollup-linux-ppc64-gnu": "4.53.2",
- "@rollup/rollup-linux-riscv64-gnu": "4.53.2",
- "@rollup/rollup-linux-riscv64-musl": "4.53.2",
- "@rollup/rollup-linux-s390x-gnu": "4.53.2",
- "@rollup/rollup-linux-x64-gnu": "4.53.2",
- "@rollup/rollup-linux-x64-musl": "4.53.2",
- "@rollup/rollup-openharmony-arm64": "4.53.2",
- "@rollup/rollup-win32-arm64-msvc": "4.53.2",
- "@rollup/rollup-win32-ia32-msvc": "4.53.2",
- "@rollup/rollup-win32-x64-gnu": "4.53.2",
- "@rollup/rollup-win32-x64-msvc": "4.53.2",
+ "@rollup/rollup-android-arm-eabi": "4.53.3",
+ "@rollup/rollup-android-arm64": "4.53.3",
+ "@rollup/rollup-darwin-arm64": "4.53.3",
+ "@rollup/rollup-darwin-x64": "4.53.3",
+ "@rollup/rollup-freebsd-arm64": "4.53.3",
+ "@rollup/rollup-freebsd-x64": "4.53.3",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
+ "@rollup/rollup-linux-arm-musleabihf": "4.53.3",
+ "@rollup/rollup-linux-arm64-gnu": "4.53.3",
+ "@rollup/rollup-linux-arm64-musl": "4.53.3",
+ "@rollup/rollup-linux-loong64-gnu": "4.53.3",
+ "@rollup/rollup-linux-ppc64-gnu": "4.53.3",
+ "@rollup/rollup-linux-riscv64-gnu": "4.53.3",
+ "@rollup/rollup-linux-riscv64-musl": "4.53.3",
+ "@rollup/rollup-linux-s390x-gnu": "4.53.3",
+ "@rollup/rollup-linux-x64-gnu": "4.53.3",
+ "@rollup/rollup-linux-x64-musl": "4.53.3",
+ "@rollup/rollup-openharmony-arm64": "4.53.3",
+ "@rollup/rollup-win32-arm64-msvc": "4.53.3",
+ "@rollup/rollup-win32-ia32-msvc": "4.53.3",
+ "@rollup/rollup-win32-x64-gnu": "4.53.3",
+ "@rollup/rollup-win32-x64-msvc": "4.53.3",
"fsevents": "~2.3.2"
}
},
@@ -4591,26 +4736,6 @@
"node": ">= 18"
}
},
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -4651,27 +4776,6 @@
"node": ">= 18"
}
},
- "node_modules/send/node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/send/node_modules/mime-types": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
- "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
@@ -4945,6 +5049,8 @@
},
"node_modules/standard-as-callback": {
"version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
+ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==",
"license": "MIT"
},
"node_modules/statuses": {
@@ -5086,10 +5192,14 @@
},
"node_modules/tr46": {
"version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/tsx": {
@@ -5144,27 +5254,6 @@
"node": ">= 0.6"
}
},
- "node_modules/type-is/node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/type-is/node_modules/mime-types": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
- "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/typed-query-selector": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
@@ -5173,6 +5262,8 @@
},
"node_modules/typescript": {
"version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
@@ -5209,6 +5300,8 @@
},
"node_modules/uuid": {
"version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
+ "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
@@ -5237,9 +5330,9 @@
}
},
"node_modules/vite": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz",
- "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
+ "version": "7.2.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz",
+ "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5312,19 +5405,19 @@
}
},
"node_modules/vitest": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.8.tgz",
- "integrity": "sha512-urzu3NCEV0Qa0Y2PwvBtRgmNtxhj5t5ULw7cuKhIHh3OrkKTLlut0lnBOv9qe5OvbkMH2g38G7KPDCTpIytBVg==",
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz",
+ "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.0.8",
- "@vitest/mocker": "4.0.8",
- "@vitest/pretty-format": "4.0.8",
- "@vitest/runner": "4.0.8",
- "@vitest/snapshot": "4.0.8",
- "@vitest/spy": "4.0.8",
- "@vitest/utils": "4.0.8",
+ "@vitest/expect": "4.0.13",
+ "@vitest/mocker": "4.0.13",
+ "@vitest/pretty-format": "4.0.13",
+ "@vitest/runner": "4.0.13",
+ "@vitest/snapshot": "4.0.13",
+ "@vitest/spy": "4.0.13",
+ "@vitest/utils": "4.0.13",
"debug": "^4.4.3",
"es-module-lexer": "^1.7.0",
"expect-type": "^1.2.2",
@@ -5350,12 +5443,13 @@
},
"peerDependencies": {
"@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
"@types/debug": "^4.1.12",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.0.8",
- "@vitest/browser-preview": "4.0.8",
- "@vitest/browser-webdriverio": "4.0.8",
- "@vitest/ui": "4.0.8",
+ "@vitest/browser-playwright": "4.0.13",
+ "@vitest/browser-preview": "4.0.13",
+ "@vitest/browser-webdriverio": "4.0.13",
+ "@vitest/ui": "4.0.13",
"happy-dom": "*",
"jsdom": "*"
},
@@ -5363,6 +5457,9 @@
"@edge-runtime/vm": {
"optional": true
},
+ "@opentelemetry/api": {
+ "optional": true
+ },
"@types/debug": {
"optional": true
},
@@ -5391,23 +5488,29 @@
},
"node_modules/web-streams-polyfill": {
"version": "4.0.0-beta.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
+ "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/webdriver-bidi-protocol": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.8.tgz",
- "integrity": "sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==",
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.9.tgz",
+ "integrity": "sha512-uIYvlRQ0PwtZR1EzHlTMol1G0lAlmOe6wPykF9a77AK3bkpvZHzIVxRE2ThOx5vjy2zISe0zhwf5rzuUfbo1PQ==",
"license": "Apache-2.0"
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
@@ -5415,9 +5518,9 @@
}
},
"node_modules/which": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
- "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz",
+ "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==",
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
@@ -5426,7 +5529,7 @@
"node-which": "bin/which.js"
},
"engines": {
- "node": "^18.17.0 || >=20.5.0"
+ "node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/why-is-node-running": {
diff --git a/services/worker/package.json b/services/worker/package.json
index 153e9e1b..410d7582 100644
--- a/services/worker/package.json
+++ b/services/worker/package.json
@@ -6,7 +6,7 @@
"peerDependencies": {
"typescript": "^5"
},
- "version": "0.0.1",
+ "version": "0.2.0",
"dependencies": {
"@bull-board/express": "^6.14.0",
"@mux/mux-node": "^12.8.0",
@@ -15,7 +15,7 @@
"@types/node": "^24.10.1",
"@types/semver": "^7.7.1",
"@types/ssh2": "^1.15.5",
- "apify-client": "^2.19.0",
+ "apify-client": "^2.20.0",
"bullmq": "^5.63.0",
"date-fns": "^4.1.0",
"fs-extra": "^11.3.2",
@@ -24,14 +24,14 @@
"nanoid": "^5.1.6",
"onnxruntime-web": "^1.23.2",
"pocketbase": "^0.26.3",
- "puppeteer": "^24.30.0",
+ "puppeteer": "^24.31.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"semver": "^7.7.3",
"sharp": "^0.34.5",
"slugify": "^1.6.6",
"ssh2": "^1.17.0",
- "which": "^5.0.0"
+ "which": "^6.0.0"
},
"devDependencies": {
"tsx": "^4.20.6",
@@ -40,4 +40,4 @@
"scripts": {
"start": "tsx src/index.ts"
}
-}
+}
\ No newline at end of file
diff --git a/services/worker/src/fixtures/sftp/data/.gitignore b/services/worker/src/fixtures/sftp/data/.gitignore
new file mode 100644
index 00000000..a53d9628
--- /dev/null
+++ b/services/worker/src/fixtures/sftp/data/.gitignore
@@ -0,0 +1 @@
+*.mp4
\ No newline at end of file
diff --git a/services/worker/src/fixtures/sftp/watch/.gitignore b/services/worker/src/fixtures/sftp/watch/.gitignore
new file mode 100644
index 00000000..954eb7b9
--- /dev/null
+++ b/services/worker/src/fixtures/sftp/watch/.gitignore
@@ -0,0 +1 @@
+*.torrent
\ No newline at end of file
diff --git a/services/worker/src/index.ts b/services/worker/src/index.ts
index c686f344..c54d9cce 100644
--- a/services/worker/src/index.ts
+++ b/services/worker/src/index.ts
@@ -10,6 +10,7 @@ import env from '../.config/env.ts';
import { version } from '../package.json';
import { downloadQueue } from './queues/downloadQueue.ts';
import { cacheQueue } from './queues/cacheQueue.ts';
+import { muxQueue } from './queues/muxQueue.ts';
const run = async () => {
@@ -28,6 +29,7 @@ const run = async () => {
new BullMQAdapter(gpuQueue),
new BullMQAdapter(downloadQueue),
new BullMQAdapter(cacheQueue),
+ new BullMQAdapter(muxQueue),
],
serverAdapter,
});
diff --git a/services/worker/src/processors/cacheCleanup.ts b/services/worker/src/processors/cacheCleanup.ts
index e7d51006..020714d1 100644
--- a/services/worker/src/processors/cacheCleanup.ts
+++ b/services/worker/src/processors/cacheCleanup.ts
@@ -1,9 +1,9 @@
import { Job } from "bullmq";
import fs from "node:fs/promises";
-import path from "node:path";
+import { join } from "node:path";
import env from "../../.config/env";
-const retainmentDayCount = 7;
+const retainmentDayCount = 90;
/**
* cacheCleanup
@@ -11,7 +11,7 @@ const retainmentDayCount = 7;
* Deletes files in the cache directory that are older than retainmentDayCount days
*/
export default async function cacheCleanup(job: Job) {
- const cacheDir = env.CACHE_ROOT;
+ const cacheDir = join(env.CACHE_ROOT, 'worker');
let cleanedCount = 0;
try {
@@ -22,7 +22,7 @@ export default async function cacheCleanup(job: Job) {
const retainMs = retainmentDayCount * 24 * 60 * 60 * 1000; // days → ms
for (const file of files) {
- const filePath = path.join(cacheDir, file);
+ const filePath = join(cacheDir, file);
try {
const stat = await fs.stat(filePath);
// only delete files older than retainment
diff --git a/services/worker/src/processors/cacheGet.ts b/services/worker/src/processors/cacheGet.ts
index 1c55c51c..f508910a 100644
--- a/services/worker/src/processors/cacheGet.ts
+++ b/services/worker/src/processors/cacheGet.ts
@@ -18,7 +18,7 @@ interface FileInfo {
fileId: string;
}
-const cacheRoot = env.CACHE_ROOT;
+const cacheRoot = join(env?.CACHE_ROOT, 'worker');
function assertPayload(payload: any): asserts payload is Payload {
if (typeof payload !== "object" || !payload) throw new Error("invalid payload-- was not an object.");
@@ -53,13 +53,13 @@ export async function getB2FileInfo(job: Job, s3Key: string): Promise
const args = ["file", "info", `b2://${env.AWS_BUCKET}/${s3Key}`];
let stdout: string;
- await job.log(`Running ${cmd}, ${args.join(' ')}`);
+ await job.log(`Running ${cmd} ${args.join(' ')}`);
try {
const result = await spawn(cmd, args);
stdout = result.stdout;
} catch (err: any) {
- throw new Error(`Failed to run 'b2 file info': ${err.stderr || err.message}`);
+ throw new Error(`Failed to run 'b2 file info': stderr:${err.stderr} message:${err.message}`);
}
let data: any;
diff --git a/services/worker/src/processors/copyV1S3ToV2.ts b/services/worker/src/processors/copyV1S3ToV2.ts
index 6daafdc0..c383f8e5 100644
--- a/services/worker/src/processors/copyV1S3ToV2.ts
+++ b/services/worker/src/processors/copyV1S3ToV2.ts
@@ -1,6 +1,3 @@
-// Copy futureporn.net s3 asset to future.porn s3 bucket.
-// ex: https://futureporn-b2.b-cdn.net/(...) -> https://fp-usc.b-cdn.net/(...)
-
import logger from "../utils/logger";
import { Task } from "graphile-worker";
import { PrismaClient } from "../../generated/prisma";
@@ -81,8 +78,14 @@ async function copyFromBucketToBucket(spawn: typeof NanoSpawn, v1Url: string, v2
return v2Url;
}
-// example v1 https://futureporn-b2.b-cdn.net/projektmelody-chaturbate-2023-01-01.mp4
-// example v2 https://fp-usc.b-cdn.net/projektmelody-chaturbate-2023-01-01.mp4
+/**
+ * Copy futureporn.net s3 asset to future.porn s3 bucket.
+ * example: https://futureporn-b2.b-cdn.net/(...) -> https://fppbpro.b-cdn.net/(...)
+ *
+ * example of Futureporn v1 asset https://futureporn-b2.b-cdn.net/projektmelody-chaturbate-2023-01-01.mp4
+ * example of Futureporn v2 asset https://fp-usc.b-cdn.net/projektmelody-chaturbate-2023-01-01.mp4
+ * example of Futureporn v3 asset https://fppbpro.b-cdn.net/pbc_144770472/oj0lkw4it4f5mzx/projektmelody-fansly-2025-11-12.mp4
+ */
const copyV1S3ToV2: Task = async (payload: any) => {
logger.info(`copyV1S3ToV2 with vodId=${payload.vodId}`);
diff --git a/services/worker/src/processors/copyV1VideoToV3.ts b/services/worker/src/processors/copyV1VideoToV3.ts
index 7c6f5c5c..0bb62ad8 100644
--- a/services/worker/src/processors/copyV1VideoToV3.ts
+++ b/services/worker/src/processors/copyV1VideoToV3.ts
@@ -1,12 +1,10 @@
import { Job } from "bullmq";
import { getPocketBaseClient } from "../util/pocketbase";
import Client, { RecordModel } from "pocketbase";
-import { Vod } from "../types";
import { basename } from 'node:path';
import env from "../../.config/env";
import spawn from 'nano-spawn';
-const foo = 'bar';
/**
* barFunction
@@ -62,7 +60,7 @@ export async function copyV1VideoToV3(job: Job) {
if (!vodId) throw new Error('vodId was missing from input data');
const pb = await getPocketBaseClient();
- const vod = await pb.collection('vods').getOne(job.data.vodId)
+ const vod = await pb.collection('vods').getOne(vodId)
const sourceVideo = await copyBetweenBuckets(job, vod);
diff --git a/services/worker/src/processors/createMuxAsset.ts b/services/worker/src/processors/createMuxAsset.ts
index ace868b4..d2322520 100644
--- a/services/worker/src/processors/createMuxAsset.ts
+++ b/services/worker/src/processors/createMuxAsset.ts
@@ -2,7 +2,12 @@ import { Job } from "bullmq";
import { getPocketBaseClient } from "../util/pocketbase";
import Client, { RecordModel } from "pocketbase";
import { Vod } from "../types";
-
+import { signUrl } from "../util/bunnyCDN";
+import env from "../../.config/env";
+import { basename } from "path";
+import { add, getUnixTime } from 'date-fns';
+import { generalQueue } from "../queues/generalQueue";
+import { highPriorityQueue } from "../queues/highPriorityQueue";
interface MuxAssetCreationResponse {
data: {
@@ -32,15 +37,22 @@ interface MuxAssetCreationResponse {
*/
export async function __createMuxAsset(vod: RecordModel) {
- const { videoSrcB2, muxAssetId, muxPlaybackId } = vod;
- if (!videoSrcB2) throw new Error(`vod ${vod.id} was missing videoSrcB2`);
-
+ const { sourceVideo, muxAssetId, muxPlaybackId } = vod;
+ if (!sourceVideo) throw new Error(`vod ${vod.id} was missing sourceVideo`);
if (muxAssetId !== '') throw new Error('this vod already has a muxAssetId');
if (muxPlaybackId !== '') throw new Error('this vod already has a muxPlaybackId');
+ const expiry = getUnixTime(add(new Date(), { days: 30 }));
+ const b2Url = signUrl(env.BUNNY_TOKEN_KEY, env.BUNNY_ZONE_URL, sourceVideo, undefined, expiry);
+
const res = await fetch('https://api.mux.com/video/v1/assets', {
+ method: 'POST',
+ headers: {
+ 'Authorization': 'Basic ' + Buffer.from(`${env.MUX_TOKEN_ID}:${env.MUX_TOKEN_SECRET}`).toString('base64'),
+ 'Content-Type': 'application/json'
+ },
body: JSON.stringify({
- "input": videoSrcB2,
+ "input": b2Url,
"playback_policy": [
"signed"
]
@@ -81,6 +93,10 @@ export async function createMuxAsset(job: Job) {
const { assetId, playbackId } = (await __createMuxAsset(vod));
job.log(`Created assetId=${assetId}, playbackId=${playbackId}`);
pb.collection('vods').update(vodId, { muxAssetId: assetId, muxPlaybackId: playbackId });
+
+ // we need to sign the mux asset so it's playable on the webpage.
+ await highPriorityQueue.add('presignMuxAsset', { vodId });
+
job.log('Vod record updated. All done.');
}
diff --git a/services/worker/src/processors/createTorrent.ts b/services/worker/src/processors/createTorrent.ts
index 56298580..fc595ad9 100644
--- a/services/worker/src/processors/createTorrent.ts
+++ b/services/worker/src/processors/createTorrent.ts
@@ -84,15 +84,29 @@ function assertPayload(payload: any): asserts payload is Payload {
// }
+/**
+ *
+ * Create a v1/v2 hybrid torrent using bittorrent.
+ * The default is to immediately delete the torrent from qBittorrent afterwards
+ * Because we seed from a seedbox instead.
+ *
+ * @param videoFilePath
+ * @param persist - whether or not to keep the torrent in qbittorrent after we have created it.
+ * @returns
+ */
async function createQBittorrentTorrent(
- vodId: string,
- videoFilePath: string
+ videoFilePath: string,
+ persist: boolean = false,
): Promise<{
magnetLink: string,
torrentFilePath: string,
info: QBTorrentInfo,
}> {
- return qbtClient.createTorrent(videoFilePath);
+ const torrent = await qbtClient.createTorrent(videoFilePath);
+ if (!persist) {
+ await qbtClient.deleteTorrent(torrent.info.hash);
+ }
+ return torrent;
}
// async function createTorrentfileTorrent(
@@ -150,8 +164,14 @@ async function createQBittorrentTorrent(
async function uploadTorrentToSeedbox(job: Job, videoFilePath: string, torrentFilePath: string) {
job.log(`Uploading ${videoFilePath} to seedbox...`);
+ let lastLog = 0; // timestamp in ms
+
await sshClient.uploadFile(videoFilePath, './data', async ({ percent }) => {
- await job.log(`Video upload progress: ${percent.toFixed(1)}%`);
+ const now = Date.now();
+ if (now - lastLog >= 1_000) { // 10 seconds
+ lastLog = now;
+ await job.updateProgress(percent.toFixed(1))
+ }
});
job.log(`Uploading ${torrentFilePath} to seedbox...`);
@@ -200,9 +220,13 @@ export async function createTorrent(job: Job) {
await job.log(`cacheGet results: ${JSON.stringify(results)}`);
const { cachePath } = results;
- await job.log(`cachePath=${cachePath}. vodId=${vodId}. NEXT UP, create QBittorrentTorrent...`);
+ await job.log(`cachePath=${cachePath}. vodId=${vodId}.`);
+ await job.log(`Creating v1/v2 hybrid torrent using QBittorrentTorrent...`);
+
+ // 4.5 Create a torrent using the local qBittorrent
+ const { magnetLink, torrentFilePath } = await createQBittorrentTorrent(cachePath);
+
- const { magnetLink, torrentFilePath } = await createQBittorrentTorrent(vodId, cachePath);
await job.log(`great! torrent created at ${torrentFilePath}. Now let's upload that torrent and the VOD to the seedbox. This will take some time...`);
await uploadTorrentToSeedbox(job, cachePath, torrentFilePath);
@@ -211,7 +235,9 @@ export async function createTorrent(job: Job) {
magnetLink
});
- job.log(`🏆 torrent creation complete.`);
+ job.log(`Torrent creation complete.`);
+ await job.updateProgress(100);
+
return { magnetLink, cachePath, torrentFilePath, vodId };
diff --git a/services/worker/src/processors/download.ts b/services/worker/src/processors/download.ts
index c4b73779..c556391b 100644
--- a/services/worker/src/processors/download.ts
+++ b/services/worker/src/processors/download.ts
@@ -49,8 +49,8 @@ async function monitorProgress(cachePath: string, expectedSize: number, job: Job
try {
const { size } = await stat(cachePath);
- const progress = Math.min((size / expectedSize) * 100, 100);
- await job.log(`size:${size}, expectedSize:${expectedSize}, progress:${progress}`);
+ const progress = Math.floor((size / expectedSize) * 100);
+ // await job.log(`size:${size}, expectedSize:${expectedSize}, progress:${progress}`);
await job.updateProgress(progress);
} catch {
// file might not exist yet
@@ -90,6 +90,7 @@ export async function __download(job: Job, s3Key: string, cachePath: string) {
stopMonitor(); // always stop monitor, even on error
}
+ await job.updateProgress(100);
job.log('Download complete.');
}
diff --git a/services/worker/src/processors/findWork.ts b/services/worker/src/processors/findWork.ts
index 547b1c0d..54316cb0 100644
--- a/services/worker/src/processors/findWork.ts
+++ b/services/worker/src/processors/findWork.ts
@@ -1,41 +1,156 @@
-import { Job } from "bullmq";
+import { Job, Queue } from "bullmq";
import { getPocketBaseClient } from "../util/pocketbase";
import Client from "pocketbase";
import { generalQueue } from "../queues/generalQueue";
+import { muxQueue } from "../queues/muxQueue";
+const queues: Record = {
+ generalQueue: generalQueue,
+ muxQueue: muxQueue,
+};
-export async function findMissingTorrent(job: Job, pb: Client) {
+type VodJobConfig = {
+ filter: string;
+ queueName: string;
+ processorName: string;
+ logMessage: (vodId: string) => string;
+};
+async function handleMissing(job: Job, pb: Client, config: VodJobConfig) {
const results = await pb.collection('vods').getList(1, 1, {
- filter: "videoSrcB2 != '' && magnetLink = ''",
- sort: '-streamDate'
+ filter: config.filter,
+ sort: '-created',
});
+
const vods = results.items;
+ if (!vods.length) return; // nothing to do
+
const vod = vods[0];
+ const vodId = vod.id;
- job.log(`findWork found ${vod.id} in need of a torrent.`);
+ job.log(config.logMessage(vodId));
- const jobId = `createTorrent-${vod.id}`;
+ const jobId = `${config.processorName}-${vodId}`;
- const existingJob = await generalQueue.getJob(jobId);
+ const queue = queues[config.queueName]; // <-- look here
+ await queue.add(config.processorName, { vodId }, { jobId });
+}
- // only add a createTorrent job if there isn't one queued
- if (existingJob?.isActive) {
- job.log(`refusing to add createTorrent job for vod ${vod.id} because a similar job is active`);
- } else {
+// export async function handleMissingTorrent(job: Job, pb: Client) {
- await generalQueue.add('createTorrent', {
- vodId: vod.id
- }, {
- jobId
- });
- }
+// const results = await pb.collection('vods').getList(1, 1, {
+// filter: "sourceVideo != '' && magnetLink = ''",
+// sort: '-created'
+// });
+// const vods = results.items;
+// const vod = vods[0];
+
+// job.log(`findWork found ${vod.id} in need of a torrent.`);
+
+// const jobId = `createTorrent-${vod.id}`;
+
+// await generalQueue.add('createTorrent', {
+// vodId: vod.id
+// }, {
+// jobId
+// });
+// }
+
+// export async function handleMissingStreamDate(job: Job, pb: Client) {
+// const results = await pb.collection('vods').getList(1, 1, {
+// filter: "announceUrl != '' && streamDate = ''",
+// sort: '-created'
+// });
+// const vods = results.items;
+// if (vods.length === 0) return; // no vods with missing streamDate.
+
+// const vod = vods[0];
+// const vodId = vod.id;
+// job.log(`findWork found ${vodId} in need of a stream date.`);
+// const jobId = `getAnnounceUrlDetails-${vodId}`;
+
+// await generalQueue.add('getAnnounceUrlDetails', {
+// vodId: vodId
+// }, {
+// jobId
+// });
+// }
+
+// export async function handleMissingSourceVideo(job: Job, pb: Client) {
+// const results = await pb.collection('vods').getList(1, 1, {
+// filter: "videoSrcB2 != '' && sourceVideo = ''",
+// sort: '-created',
+// });
+// const vods = results.items;
+// if (vods.length === 0) return; // no vods with missing sourceVideo
+// const vod = vods[0];
+// const vodId = vod.id;
+// job.log(`findWork found ${vodId} in need of a source video.`);
+// const jobId = `handleMissingSourceVideo-${vodId}`;
+// await generalQueue.add('copyV1VideoToV3', {
+// vodId
+// }, {
+// jobId
+// });
+// }
+
+// export async function handleMissingMuxAsset(job: Job, pb: Client) {
+// const results = await pb.collection('vods').getList(1, 1, {
+// filter: "muxAssetId = '' && muxPlaybackId = '' && sourceVideo != ''",
+// sort: '-created',
+// });
+// // ...
+// }
+
+
+
+export async function handleMissingTorrent(job: Job, pb: Client) {
+ return handleMissing(job, pb, {
+ filter: "sourceVideo != '' && magnetLink = ''",
+ queueName: 'generalQueue',
+ processorName: 'createTorrent',
+ logMessage: (id) => `findWork found ${id} in need of a torrent.`
+ });
+}
+
+export async function handleMissingStreamDate(job: Job, pb: Client) {
+ return handleMissing(job, pb, {
+ filter: "announceUrl != '' && streamDate = ''",
+ queueName: 'generalQueue',
+ processorName: 'getAnnounceUrlDetails',
+ logMessage: (id) => `findWork found ${id} in need of a stream date.`
+ });
+}
+
+export async function handleMissingSourceVideo(job: Job, pb: Client) {
+ return handleMissing(job, pb, {
+ filter: "videoSrcB2 != '' && sourceVideo = ''",
+ queueName: 'generalQueue',
+ processorName: 'copyV1VideoToV3',
+ logMessage: (id) => `findWork found ${id} in need of a source video.`
+ });
+}
+
+/**
+ * handleMissingMuxAsset
+ *
+ * We only add Mux assets to new vods because Mux cost a lot of money.
+ * Future plan is to build our own Mux alternative and remove Mux.
+ */
+export async function handleMissingMuxAsset(job: Job, pb: Client) {
+ const sinceDate = '2025-11-01';
+ return handleMissing(job, pb, {
+ filter: `created > '${sinceDate}' && muxAssetId = '' && muxPlaybackId = '' && sourceVideo != ''`,
+ queueName: 'muxQueue', // whatever queue name you use
+ processorName: 'createMuxAsset',
+ logMessage: (id) => `findWork found ${id} in need of a Mux asset.`
+ });
}
/**
*
- * findWork
+ * This processor is all about identifying known issues in the database and handling them by delegating the work to a processor.
*
* Remember to makes processors
* * idempotent
@@ -46,7 +161,11 @@ export async function findWork(job: Job) {
const pb = await getPocketBaseClient();
- await findMissingTorrent(job, pb);
+ await handleMissingTorrent(job, pb);
+ await handleMissingStreamDate(job, pb);
+ await handleMissingSourceVideo(job, pb);
+ await handleMissingMuxAsset(job, pb);
+
// findMissingThumbnail
// findMissingAudioAnalysis
diff --git a/services/worker/src/processors/getAnnounceUrlDetails.ts b/services/worker/src/processors/getAnnounceUrlDetails.ts
index 291cb20e..18fa3757 100644
--- a/services/worker/src/processors/getAnnounceUrlDetails.ts
+++ b/services/worker/src/processors/getAnnounceUrlDetails.ts
@@ -32,11 +32,12 @@ export function getTweetDates(tweetUrls: string[]): Date[] {
}
export async function getVodsWithAnnounceUrlAndNoStreamDate() {
- const pb = await getPocketBaseClient()
+ const pb = await getPocketBaseClient();
const results = await pb.collection('vods').getList(1, 25, {
- filter: "announceUrl != '' && streamDate = ''"
- })
+ filter: "announceUrl != '' && streamDate = ''",
+ requestKey: `getAnnounceUrlDetails-1..25`
+ });
const vods = results.items;
return vods;
diff --git a/services/worker/src/processors/presignMuxAssets.ts b/services/worker/src/processors/presignMuxAssets.ts
index 0ac82595..629460b7 100644
--- a/services/worker/src/processors/presignMuxAssets.ts
+++ b/services/worker/src/processors/presignMuxAssets.ts
@@ -1,6 +1,6 @@
import Mux from '@mux/mux-node';
import env from '../../.config/env';
-import { type QueueOptions, type Job } from 'bullmq';
+import { type Job } from 'bullmq';
import { getPocketBaseClient } from '../util/pocketbase';
@@ -25,8 +25,21 @@ async function createToken(playbackId: string) {
return token
}
+export async function presignMuxAsset(job: Job) {
+ const pb = await getPocketBaseClient();
+ const vodId = job.data.vodId as string;
+ const vod = await pb.collection('vods').getOne(vodId);
-export async function presignMuxAssets(job: Job) {
+ const muxPlaybackId = vod?.muxPlaybackId;
+ if (!muxPlaybackId) throw new Error(`presignMuxAsset called with vodId ${vodId} failed because this vod is missing a muxPlaybackId.`);
+ const muxPlaybackToken = await createToken(muxPlaybackId);
+ await pb.collection('vods').update(vod.id, {
+ muxPlaybackToken
+ });
+}
+
+
+export async function presignAllMuxAssets(job: Job) {
const pb = await getPocketBaseClient();
diff --git a/services/worker/src/queues/generalQueue.ts b/services/worker/src/queues/generalQueue.ts
index d1b1c3a0..00b79a68 100644
--- a/services/worker/src/queues/generalQueue.ts
+++ b/services/worker/src/queues/generalQueue.ts
@@ -8,14 +8,14 @@ await generalQueue.upsertJobScheduler(
pattern: '3 7 * * *', // Runs at 07:03 every day
},
{
- name: 'presignMuxAsset',
+ name: 'presignAllMuxAssets',
data: {},
opts: {}, // Optional additional job options
},
);
-// await generalQueue.upsertJobScheduler(
-// 'find-work-every-one-minute',
-// { every: 1000 * 60 },
-// { name: 'findWork' }
-// )
\ No newline at end of file
+await generalQueue.upsertJobScheduler(
+ 'find-work-often',
+ { every: 1000 * 30 },
+ { name: 'findWork' }
+)
\ No newline at end of file
diff --git a/services/worker/src/queues/gpuQueue.ts b/services/worker/src/queues/gpuQueue.ts
index d229af46..2cdd7ae7 100644
--- a/services/worker/src/queues/gpuQueue.ts
+++ b/services/worker/src/queues/gpuQueue.ts
@@ -3,15 +3,3 @@ import { Queue } from "bullmq";
import { connection } from "../../.config/bullmq.config";
export const gpuQueue = new Queue('gpuQueue', { connection });
-await gpuQueue.upsertJobScheduler(
- 'schedule-vod-processing-recurring',
- {
- pattern: '* * * * *'
- },
- {
- name: 'cron-schedule-vod-processing',
- data: {},
- opts: {}
- },
-)
-
diff --git a/services/worker/src/queues/highPriorityQueue.ts b/services/worker/src/queues/highPriorityQueue.ts
index dd23bc17..e7c22e94 100644
--- a/services/worker/src/queues/highPriorityQueue.ts
+++ b/services/worker/src/queues/highPriorityQueue.ts
@@ -13,15 +13,3 @@ await highPriorityQueue.upsertJobScheduler(
opts: {}
},
)
-
-await highPriorityQueue.upsertJobScheduler(
- 'get-announce-url-details',
- {
- every: 1000 * 63
- },
- {
- name: 'getAnnounceUrlDetails',
- data: {},
- opts: {},
- },
-);
\ No newline at end of file
diff --git a/services/worker/src/queues/muxQueue.ts b/services/worker/src/queues/muxQueue.ts
new file mode 100644
index 00000000..4d98f089
--- /dev/null
+++ b/services/worker/src/queues/muxQueue.ts
@@ -0,0 +1,6 @@
+import { Queue, QueueEvents } from 'bullmq';
+import { connection } from '../../.config/bullmq.config';
+export const muxQueue = new Queue('muxQueue', { connection });
+export const muxQueueEvents = new QueueEvents("muxQueue", {
+ connection
+});
\ No newline at end of file
diff --git a/services/worker/src/util/b2.README.md b/services/worker/src/util/b2.README.md
new file mode 100644
index 00000000..c815f24f
--- /dev/null
+++ b/services/worker/src/util/b2.README.md
@@ -0,0 +1,101 @@
+## Known errors
+
+### Error: Failed to run 'b2 file info': b2: tar_extract_all() failed: Invalid argument
+
+This one is weird. It happens when several failed b2cli are running in the background. I came across this during testing and first I thought my executable was somehow corrupted.
+
+```
+cj@cj54hd:~/Downloads$ b2 file info b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ b2 file ls b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ b2 ls b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ b2 ls
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ b2 -h
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ b2
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ which b2
+/home/cj/.local/bin/b2
+cj@cj54hd:~/Downloads$ head b2
+head: cannot open 'b2' for reading: No such file or directory
+cj@cj54hd:~/Downloads$ ~/.local/bin/b2
+b2: tar_extract_all() failed: Invalid argument
+cj@cj54hd:~/Downloads$ ls -la ~/.local/bin/b2
+-rwxrwxr-x 1 cj cj 32597952 Aug 23 17:07 /home/cj/.local/bin/b2
+cj@cj54hd:~/Downloads$ file ~/.local/bin/b2
+/home/cj/.local/bin/b2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
+cj@cj54hd:~/Downloads$ cp b2v3-linux ~/.local/bin/b2
+cp: cannot create regular file '/home/cj/.local/bin/b2': Text file busy
+
+```
+
+apparently there were a shitton of b2 instances running in the background!
+
+```
+cj@cj54hd:~/Downloads$ ps aux | grep 'b2:/[/]'
+cj 191334 0.0 0.0 292 148 pts/11 S+ Nov21 0:00 b2 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 191335 0.0 0.0 2840 2004 pts/11 S+ Nov21 0:00 /tmp/staticx-gDLAjK/b2v3 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 191336 0.2 0.3 950960 90496 pts/11 Sl+ Nov21 5:48 /tmp/staticx-gDLAjK/b2v3 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 205138 0.0 0.0 292 152 pts/11 S+ Nov21 0:00 b2 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 205139 0.0 0.0 2840 1988 pts/11 S+ Nov21 0:00 /tmp/staticx-OMOMPi/b2v3 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 205140 0.0 0.3 950960 90528 pts/11 Sl+ Nov21 0:18 /tmp/staticx-OMOMPi/b2v3 file download b2://fppbdev/pbc_144770472/6v80rae2m128yw1/projektmelody-chaturbate-2025-10-19.mp4 /tmp/vods/6v80rae2m128yw1/sourceVideo/13629592283.mp4
+cj 257781 0.0 0.0 292 96 pts/11 S+ Nov21 0:00 b2 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 257782 0.0 0.0 2840 2028 pts/11 S+ Nov21 0:00 /tmp/staticx-GFFmLI/b2v3 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 257783 0.0 0.3 951984 90080 pts/11 Sl+ Nov21 1:37 /tmp/staticx-GFFmLI/b2v3 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 264819 0.0 0.0 292 148 pts/11 S+ Nov21 0:00 b2 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/vods/4csbaj06u481x9t/sourceVideo/3835045469/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 264820 0.0 0.0 2840 2032 pts/11 S+ Nov21 0:00 /tmp/staticx-NFonPF/b2v3 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/vods/4csbaj06u481x9t/sourceVideo/3835045469/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 264821 0.1 0.3 950956 90488 pts/11 Sl+ Nov21 2:47 /tmp/staticx-NFonPF/b2v3 file download b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4 /tmp/vods/4csbaj06u481x9t/sourceVideo/3835045469/2024-03-10-el_xox-4csbaj06u481x9t.mp4
+cj 607425 0.0 0.0 292 148 pts/11 S+ Nov22 0:00 b2 file download b2://fppbdev/pbc_144770472/2ct5pnh3fdx91ks/projektmelody-chaturbate-2024-03-04.mp4 /tmp/vods/2ct5pnh3fdx91ks/sourceVideo/4784598000/2024-03-03-projektmelody-2ct5pnh3fdx91ks.mp4
+cj 607426 0.0 0.0 2840 1972 pts/11 S+ Nov22 0:00 /tmp/staticx-cjcddG/b2v3 file download b2://fppbdev/pbc_144770472/2ct5pnh3fdx91ks/projektmelody-chaturbate-2024-03-04.mp4 /tmp/vods/2ct5pnh3fdx91ks/sourceVideo/4784598000/2024-03-03-projektmelody-2ct5pnh3fdx91ks.mp4
+cj 607427 0.1 0.3 950956 90492 pts/11 Sl+ Nov22 1:09 /tmp/staticx-cjcddG/b2v3 file download b2://fppbdev/pbc_144770472/2ct5pnh3fdx91ks/projektmelody-chaturbate-2024-03-04.mp4 /tmp/vods/2ct5pnh3fdx91ks/sourceVideo/4784598000/2024-03-03-projektmelody-2ct5pnh3fdx91ks.mp4
+```
+
+kill 'em!
+
+```
+cj@cj54hd:~/Downloads$ killall b2
+cj@cj54hd:~/Downloads$ ps aux | grep 'b2:/[/]'
+cj@cj54hd:~/Downloads$
+```
+
+and now it works. holy shit!
+
+```
+cj@cj54hd:~/Downloads$ b2 file info b2://fppbdev/pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4
+{
+ "cacheControl": "max-age=604800",
+ "contentSha1": "84bbd4218b16184f6204eeb8094720150c8479d5",
+ "contentType": "video/mp4",
+ "fileId": "4_zad63b74f11035a9993a30b18_f100aec8c206f88f4_d20251116_m225322_c000_v0001417_t0037_u01763333602168",
+ "fileInfo": {
+ "large_file_sha1": "84bbd4218b16184f6204eeb8094720150c8479d5",
+ "src_last_modified_millis": "1710056557459"
+ },
+ "fileName": "pbc_144770472/4csbaj06u481x9t/el_xox-chaturbate-2024-03-10.mp4",
+ "fileRetention": {
+ "mode": null,
+ "retainUntilTimestamp": null
+ },
+ "legalHold": null,
+ "replicationStatus": null,
+ "serverSideEncryption": {
+ "mode": "none"
+ },
+ "size": 3835045469,
+ "uploadTimestamp": 1763333602168
+}
+```
+
+But it still failed when run by BullMQ.
+
+```
+Error: Failed to run 'b2 file info': b2: tar_extract_all() failed: Invalid argument
+ at onFailed (/home/cj/Documents/futureporn-monorepo/services/worker/node_modules/bullmq/src/classes/job.ts:1295:16)
+ at (/home/cj/Documents/futureporn-monorepo/services/worker/node_modules/bullmq/src/classes/job.ts:1324:11)
+ at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
+```
+
+OH, it is actually that my /tmp dir doesn't have enough space to store the file being downloaded! @see https://github.com/JonathonReinhart/staticx/issues/244
\ No newline at end of file
diff --git a/services/worker/src/util/bunnyCDN.spec.ts b/services/worker/src/util/bunnyCDN.spec.ts
new file mode 100644
index 00000000..69f0eb7f
--- /dev/null
+++ b/services/worker/src/util/bunnyCDN.spec.ts
@@ -0,0 +1,30 @@
+import { describe, it, expect } from "vitest";
+import { signUrl } from "./bunnyCDN.ts";
+
+describe("signUrl", () => {
+ it("generates a correct signed BunnyCDN URL", () => {
+ const securityKey = "my-secret";
+ const baseUrl = "https://cdn.example.com";
+ const path = "/videos/test.mp4";
+ const rawQuery = "width=500&quality=80";
+ const expires = 1732600000;
+
+ const signed = signUrl(securityKey, baseUrl, path, rawQuery, expires);
+
+ // token part is deterministic but long, so let's just check it contains required parts
+ expect(signed).toContain(baseUrl + path);
+ expect(signed).toContain("token=");
+ expect(signed).toContain("quality=80&width=500");
+ expect(signed).toContain(`expires=${expires}`);
+ });
+
+ it("throws if baseUrl ends with slash", () => {
+ expect(() => signUrl("k", "https://example.com/", "/file.jpg", "", 123))
+ .toThrow(/must not end with a slash/);
+ });
+
+ it("prepends slash if path does not start with one", () => {
+ const out = signUrl("k", "https://x", "file.jpg", "", 1);
+ expect(out.startsWith("https://x/file.jpg")).toBe(true);
+ });
+});
diff --git a/services/worker/src/util/bunnyCDN.ts b/services/worker/src/util/bunnyCDN.ts
new file mode 100644
index 00000000..cad26fce
--- /dev/null
+++ b/services/worker/src/util/bunnyCDN.ts
@@ -0,0 +1,49 @@
+
+import crypto from "node:crypto";
+
+
+/**
+ * Generate a signed BunnyCDN URL.
+ *
+ * @see https://support.bunny.net/hc/en-us/articles/360016055099-How-to-sign-URLs-for-BunnyCDN-Token-Authentication
+ */
+export function signUrl(securityKey: string, baseUrl: string, path: string, rawQuery = "", expires: number) {
+ if (!path) throw new Error('signUrl requires a path argument, but it was falsy.');
+ if (!path.startsWith('/')) path = '/' + path;
+ if (baseUrl.endsWith('/')) throw new Error(`baseUrl must not end with a slash. got baseUrl=${baseUrl}`);
+
+ // Build parameter string (sort keys alphabetically)
+ let parameterData = "";
+ if (rawQuery) {
+ const params = rawQuery
+ .split("&")
+ .map(p => p.split("="))
+ .filter(([key]) => key && key !== "token" && key !== "expires")
+ .sort(([a], [b]) => a.localeCompare(b));
+
+ if (params.length) {
+ parameterData = params.map(([k, v]) => `${k}=${v}`).join("&");
+ }
+ }
+
+ // Build hashable base
+ const hashableBase = securityKey + path + expires + parameterData;
+ // console.log(`hashableBase`, hashableBase)
+
+ // Compute token using your $security.sha256 workflow
+
+ const tokenH = crypto.createHash("sha256").update(hashableBase).digest("hex");
+ const token = Buffer.from(tokenH, "hex")
+ .toString("base64")
+ .replace(/\n/g, "")
+ .replace(/\+/g, "-")
+ .replace(/\//g, "_")
+ .replace(/=/g, "");
+
+ // Build final signed URL
+ let tokenUrl = baseUrl + path + "?token=" + token;
+ if (parameterData) tokenUrl += "&" + parameterData;
+ tokenUrl += "&expires=" + expires;
+
+ return tokenUrl;
+}
\ No newline at end of file
diff --git a/services/worker/src/util/qbittorrent.ts b/services/worker/src/util/qbittorrent.ts
index 057640c5..7d8f5166 100644
--- a/services/worker/src/util/qbittorrent.ts
+++ b/services/worker/src/util/qbittorrent.ts
@@ -383,6 +383,28 @@ export class QBittorrentClient {
return filePath;
}
+
+ /**
+ * get torrent info from qBittorrent
+ * When a torrent is created, It can take some time before it appears in the list. So we retry it.
+ *
+ * @param torrentName
+ * @returns
+ */
+ async getTorrentInfos(torrentName: string): Promise {
+ return retry(
+ () => this.__getTorrentInfos(torrentName),
+ 6,
+ 500
+ );
+ }
+
+ /**
+ * Generally it's preferred to use this.getTorrentInfos over this.__getTorrentInfos because it is more fault tolerant.
+ *
+ * @param torrentName
+ * @returns
+ */
private async __getTorrentInfos(torrentName: string): Promise {
if (!torrentName) throw new Error('__getTorrentInfos requires torrentName as first arg. However, arg was falsy. ');
// ensure we're logged in
@@ -412,12 +434,8 @@ export class QBittorrentClient {
async getInfoHashV2(torrentName: string): Promise {
console.log(`getInfoHashV2 using torrentName=${torrentName}`)
- // __getTorrentInfos can take some time. So we retry it every 1/2 second up to 6 times
- const torrent = await retry(
- () => this.__getTorrentInfos(torrentName),
- 6,
- 500
- );
+
+ const torrent = await this.getTorrentInfos(torrentName);
return torrent.infohash_v2;
}
@@ -430,7 +448,7 @@ export class QBittorrentClient {
const bn = basename(localFilePath).replace('.torrent', '');
await this.connect();
await this.__addTorrent(localFilePath);
- return (await this.__getTorrentInfos(bn));
+ return (await this.getTorrentInfos(bn));
}
/**
@@ -480,6 +498,7 @@ export class QBittorrentClient {
*/
async deleteTorrent(id: string): Promise {
await this.connect();
+ console.log(`Deleting torrent ${id}...`);
if (!this.sidCookie) {
throw new Error('Not logged in. sidCookie missing.');
@@ -495,7 +514,7 @@ export class QBittorrentClient {
hashToDelete = id;
} else {
// Not a hash → treat as name → look up hash
- const info = await this.__getTorrentInfos(id);
+ const info = await this.getTorrentInfos(id);
console.log('info', info);
hashToDelete = info.hash;
}
@@ -537,14 +556,14 @@ export class QBittorrentClient {
/**
*
- * @deprecated use __getTorrentInfos instead
+ * @deprecated use getTorrentInfos instead
*/
async getMagnetLink(fileName: string): Promise {
console.log(`getMagnetLink using fileName=${fileName}`)
// qBittorrent does NOT return infoHash directly here
// we have to get it by querying the torrents list
- const torrent = await this.__getTorrentInfos(fileName);
+ const torrent = await this.getTorrentInfos(fileName);
if (!torrent) {
throw new Error(`Torrent ${fileName} not found in qBittorrent after adding`);
@@ -579,7 +598,7 @@ export class QBittorrentClient {
// 5. Get magnet link
console.log('lets get the torrent infos');
- const info = await this.__getTorrentInfos(basename(localFilePath))
+ const info = await this.getTorrentInfos(basename(localFilePath))
const magnetLink = info.magnet_uri;
return {
diff --git a/services/worker/src/workers/generalWorker.ts b/services/worker/src/workers/generalWorker.ts
index a9631b46..13aee5a9 100644
--- a/services/worker/src/workers/generalWorker.ts
+++ b/services/worker/src/workers/generalWorker.ts
@@ -2,18 +2,23 @@
import { Worker } from 'bullmq';
import { connection } from '../../.config/bullmq.config.ts';
-import { presignMuxAssets } from '../processors/presignMuxAssets.ts';
+import { presignAllMuxAssets, presignMuxAsset } from '../processors/presignMuxAssets.ts';
import { copyV1VideoAll } from '../processors/copyV1VideoAll.ts';
import { copyV2ThumbToV3 } from '../processors/copyV2ThumbToV3.ts';
import { copyV1VideoToV3 } from '../processors/copyV1VideoToV3.ts';
import { createTorrent } from '../processors/createTorrent.ts';
import { analyzeAudio } from '../processors/analyzeAudio.ts';
import { findWork } from '../processors/findWork.ts';
+import { getAnnounceUrlDetails } from '../processors/getAnnounceUrlDetails.ts';
+
new Worker(
'generalQueue',
async (job) => {
console.log('generalWorker. we got a job on the generalQueue.', job.data, job.name);
switch (job.name) {
+ case 'getAnnounceUrlDetails':
+ return await getAnnounceUrlDetails(job);
+
case 'findWork':
return await findWork(job);
@@ -23,8 +28,11 @@ new Worker(
case 'copyV1VideoToV3':
return await copyV1VideoToV3(job);
- case 'presignMuxAssets':
- return await presignMuxAssets(job);
+ case 'presignAllMuxAssets':
+ return await presignAllMuxAssets(job);
+
+ case 'presignMuxAsset':
+ return await presignMuxAsset(job);
case 'copyV2ThumbToV3':
return await copyV2ThumbToV3(job);
diff --git a/services/worker/src/workers/highPriorityWorker.ts b/services/worker/src/workers/highPriorityWorker.ts
index b64c8fb1..2c016b57 100644
--- a/services/worker/src/workers/highPriorityWorker.ts
+++ b/services/worker/src/workers/highPriorityWorker.ts
@@ -15,13 +15,17 @@ new Worker(
case '':
throw new Error('missing job name.')
case 'syncronizePatreon':
- return await syncronizePatreon(job);
+ await syncronizePatreon(job);
+ break;
case 'getAnnounceUrlDetails':
- return await getAnnounceUrlDetails(job);
+ await getAnnounceUrlDetails(job);
+ break;
case 'createTorrent':
- return await createTorrent(job);
+ await createTorrent(job);
+ break;
case 'copyV1VideoToV3':
- return await copyV1VideoToV3(job);
+ await copyV1VideoToV3(job);
+ break;
default:
throw new Error(`Unknown job name: ${job.name}`);
}
diff --git a/services/worker/src/workers/muxWorker.ts b/services/worker/src/workers/muxWorker.ts
new file mode 100644
index 00000000..4abb03e3
--- /dev/null
+++ b/services/worker/src/workers/muxWorker.ts
@@ -0,0 +1,23 @@
+import { Worker } from 'bullmq';
+import { connection } from '../../.config/bullmq.config.ts';
+import { createMuxAsset } from '../processors/createMuxAsset.ts';
+
+const workerName = 'muxWorker';
+const queueName = 'muxQueue';
+
+new Worker(
+ queueName,
+ async (job) => {
+ console.log(`${workerName}. we got a job on the ${queueName}. data=${JSON.stringify(job.data)}, job name=${job.name}`);
+ switch (job.name) {
+ case 'createMuxAsset':
+ return await createMuxAsset(job);
+
+ default:
+ throw new Error(`${workerName} Unknown job name: ${job.name}`);
+ }
+ },
+ { connection }
+);
+
+console.log(`${workerName} is running...`);