use pino
Some checks failed
ci / build (push) Failing after 1s
ci / Tests & Checks (push) Failing after 1s

This commit is contained in:
CJ_Clippy 2025-06-27 21:36:34 -08:00
parent 53908bc666
commit 3157c993bf
8 changed files with 200 additions and 12 deletions

1
services/scout/.nvmrc Normal file
View File

@ -0,0 +1 @@
lts/jod

View File

@ -5,4 +5,10 @@
* [x] listen to Chaturbate chat
* [x] touch a file when stream is live
* [x] JS (not TS)
* [x] commonjs
* [x] commonjs
### Ideas
There is the url `https://chaturbate.com/api/public/affiliates/onlinerooms/?wm=DiPkB&client_ip=request_ip` which shows all live channels. We could query this.

View File

@ -4,16 +4,19 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@dotenvx/dotenvx": "^1.44.1",
"pino": "^9.7.0",
"pino-pretty": "^13.0.0",
"puppeteer": "^24.11.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"zod": "^3.25.49"
}
}
}

View File

@ -11,6 +11,12 @@ importers:
'@dotenvx/dotenvx':
specifier: ^1.44.1
version: 1.45.1
pino:
specifier: ^9.7.0
version: 9.7.0
pino-pretty:
specifier: ^13.0.0
version: 13.0.0
puppeteer:
specifier: ^24.11.0
version: 24.11.0
@ -99,6 +105,10 @@ packages:
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
engines: {node: '>=4'}
atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
b4a@1.6.7:
resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
@ -169,6 +179,9 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
@ -193,6 +206,9 @@ packages:
resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
engines: {node: '>= 14'}
dateformat@4.6.3:
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
debug@4.4.1:
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
@ -265,9 +281,19 @@ packages:
engines: {node: '>= 10.17.0'}
hasBin: true
fast-copy@3.0.2:
resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==}
fast-fifo@1.3.2:
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
fast-redact@3.5.0:
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
engines: {node: '>=6'}
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
@ -321,6 +347,9 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
help-me@5.0.0:
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@ -385,6 +414,10 @@ packages:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
engines: {node: '>=0.10.0'}
joycon@3.1.1:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@ -438,6 +471,9 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
@ -460,6 +496,10 @@ packages:
resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==}
engines: {node: '>= 10'}
on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@ -501,6 +541,23 @@ packages:
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
engines: {node: '>=12'}
pino-abstract-transport@2.0.0:
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
pino-pretty@13.0.0:
resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==}
hasBin: true
pino-std-serializers@7.0.0:
resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==}
pino@9.7.0:
resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==}
hasBin: true
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
progress@2.0.3:
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
engines: {node: '>=0.4.0'}
@ -587,6 +644,13 @@ packages:
engines: {node: '>=18'}
hasBin: true
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@ -600,6 +664,13 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
safe-stable-stringify@2.5.0:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
secure-json-parse@2.7.0:
resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
semver@7.7.2:
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
engines: {node: '>=10'}
@ -632,10 +703,17 @@ packages:
resolution: {integrity: sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
sonic-boom@4.2.0:
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
@ -654,6 +732,10 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
tar-fs@3.0.10:
resolution: {integrity: sha512-C1SwlQGNLe/jPNqapK8epDsXME7CAJR5RL3GcE6KWx1d9OUByzoHVcbu1VPI8tevg9H8Alae0AApHHFGzrD5zA==}
@ -663,6 +745,9 @@ packages:
text-decoder@1.2.3:
resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==}
thread-stream@3.1.0:
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@ -804,6 +889,8 @@ snapshots:
dependencies:
tslib: 2.8.1
atomic-sleep@1.0.0: {}
b4a@1.6.7: {}
balanced-match@1.0.2: {}
@ -870,6 +957,8 @@ snapshots:
color-name@1.1.4: {}
colorette@2.0.20: {}
commander@11.1.0: {}
concat-map@0.0.1: {}
@ -889,6 +978,8 @@ snapshots:
data-uri-to-buffer@6.0.2: {}
dateformat@4.6.3: {}
debug@4.4.1:
dependencies:
ms: 2.1.3
@ -962,8 +1053,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
fast-copy@3.0.2: {}
fast-fifo@1.3.2: {}
fast-redact@3.5.0: {}
fast-safe-stringify@2.1.1: {}
fd-slicer@1.1.0:
dependencies:
pend: 1.2.0
@ -1015,6 +1112,8 @@ snapshots:
graceful-fs@4.2.11: {}
help-me@5.0.0: {}
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.3
@ -1070,6 +1169,8 @@ snapshots:
isobject@3.0.1: {}
joycon@3.1.1: {}
js-tokens@4.0.0: {}
js-yaml@4.1.0:
@ -1116,6 +1217,8 @@ snapshots:
dependencies:
brace-expansion: 1.1.12
minimist@1.2.8: {}
mitt@3.0.1: {}
mixin-object@2.0.1:
@ -1133,6 +1236,8 @@ snapshots:
object-treeify@1.1.33: {}
on-exit-leak-free@2.1.2: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
@ -1180,6 +1285,44 @@ snapshots:
picomatch@4.0.2: {}
pino-abstract-transport@2.0.0:
dependencies:
split2: 4.2.0
pino-pretty@13.0.0:
dependencies:
colorette: 2.0.20
dateformat: 4.6.3
fast-copy: 3.0.2
fast-safe-stringify: 2.1.1
help-me: 5.0.0
joycon: 3.1.1
minimist: 1.2.8
on-exit-leak-free: 2.1.2
pino-abstract-transport: 2.0.0
pump: 3.0.3
secure-json-parse: 2.7.0
sonic-boom: 4.2.0
strip-json-comments: 3.1.1
pino-std-serializers@7.0.0: {}
pino@9.7.0:
dependencies:
atomic-sleep: 1.0.0
fast-redact: 3.5.0
on-exit-leak-free: 2.1.2
pino-abstract-transport: 2.0.0
pino-std-serializers: 7.0.0
process-warning: 5.0.0
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.5.0
sonic-boom: 4.2.0
thread-stream: 3.1.0
process-warning@5.0.0: {}
progress@2.0.3: {}
proxy-agent@6.5.0:
@ -1284,6 +1427,10 @@ snapshots:
- typescript
- utf-8-validate
quick-format-unescaped@4.0.4: {}
real-require@0.2.0: {}
require-directory@2.1.1: {}
resolve-from@4.0.0: {}
@ -1292,6 +1439,10 @@ snapshots:
dependencies:
glob: 7.2.3
safe-stable-stringify@2.5.0: {}
secure-json-parse@2.7.0: {}
semver@7.7.2: {}
shallow-clone@0.1.2:
@ -1324,9 +1475,15 @@ snapshots:
ip-address: 9.0.5
smart-buffer: 4.2.0
sonic-boom@4.2.0:
dependencies:
atomic-sleep: 1.0.0
source-map@0.6.1:
optional: true
split2@4.2.0: {}
sprintf-js@1.1.3: {}
streamx@2.22.1:
@ -1348,6 +1505,8 @@ snapshots:
strip-final-newline@2.0.0: {}
strip-json-comments@3.1.1: {}
tar-fs@3.0.10:
dependencies:
pump: 3.0.3
@ -1368,6 +1527,10 @@ snapshots:
dependencies:
b4a: 1.6.7
thread-stream@3.1.0:
dependencies:
real-require: 0.2.0
tslib@2.8.1: {}
typed-query-selector@2.12.0: {}

View File

@ -1,5 +1,6 @@
const { env } = require('./config.js');
const puppeteer = require('puppeteer-extra');
const logger = require('./logger.js');
// add stealth plugin and use defaults (all evasion techniques)
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
@ -53,20 +54,20 @@ function createWebSocketIterator() {
await client.send('Network.enable');
client.on('Network.webSocketCreated', ({ requestId, url }) => {
console.debug('webSocketCreated:', url);
logger.debug(`webSocketCreated: ${url}`);
});
client.on('Network.webSocketClosed', ({ requestId, timestamp }) => {
console.debug('webSocketClosed:', requestId);
logger.debug(`webSocketClosed: ${requestId}`);
});
client.on('Network.webSocketFrameReceived', ({ requestId, timestamp, response }) => {
// console.debug('FrameReceived:', response.payloadData);
// logger.debug('FrameReceived:', response.payloadData);
push(response.payloadData);
});
client.on('Network.webSocketFrameSent', ({ requestId, timestamp, response }) => {
console.debug('FrameSent:', response.payloadData);
logger.debug(`FrameSent: ${response.payloadData}`);
});
await page.goto(env.CB_ROOM);
@ -78,7 +79,7 @@ function createWebSocketIterator() {
});
})().catch((err) => {
console.error('Fatal error:', err);
logger.error('Fatal error:', err);
close();
});

View File

@ -5,6 +5,8 @@ const { z } = require('zod');
const EnvSchema = z.object({
VODDO_RETRY_FILE: z.string(),
CB_ROOM: z.string(),
NODE_ENV: z.enum(['development', 'production', 'test']),
LOG_LEVEL: z.enum(['debug', 'info']).optional(),
});
const parsed = EnvSchema.safeParse(process.env);

View File

@ -1,7 +1,7 @@
const { env } = require('./config.js');
const browser = require('./browser.js');
const fs = require('fs/promises');
const logger = require('./logger.js');
function parseEvent(evt) {
if (evt?.action) {
@ -15,16 +15,17 @@ function parseEvent(evt) {
const gen = browser(); // this is an async generator
for await (const event of gen) {
console.log('Received event from browser:', event);
logger.debug(`Received event from browser: ${event}`);
const signal = parseEvent(event)
if (signal) {
try {
await fs.writeFile(env.VODDO_RETRY_FILE, `reset ${Date.now()}\n`);
console.log(`Touched retry file at ${env.VODDO_RETRY_FILE}`);
logger.debug(`Touched retry file at ${env.VODDO_RETRY_FILE}`);
} catch (err) {
console.error(`Failed to write retry file: ${err.message}`);
logger.error(`Failed to write retry file: ${err.message}`);
}
}
}

View File

@ -0,0 +1,11 @@
const { env } = require('./config.js')
const pino = require('pino')
const logger = pino({
transport: {
target: env.NODE_ENV === 'production' ? 'pino' : 'pino-pretty'
},
level: env.LOG_LEVEL || 'info'
})
module.exports = logger