// Runs one console command on a rig through the panel's websocket and prints the console lines // that follow — the way to read a command's reply, which rig.js's `cmd` cannot. // // node tools/console.js "" [seconds=6] [filter] // // node tools/console.js oxide "oxide.plugins" 6 RunicNPC // node tools/console.js carbon "rnpc.status" // // Needs Node 22+ for the global WebSocket. const { load, serverId, unmsys } = require('./panel') const config = load() const [rig, command, secs = '6', filter] = process.argv.slice(2).map(unmsys) const strip = (s) => s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '') async function main() { if (!command) { console.error('usage: node tools/console.js "" [seconds=6] [filter]') process.exit(2) } const r = await fetch(`${config.panel}/api/client/servers/${serverId(config, rig)}/websocket`, { headers: { Authorization: 'Bearer ' + config.key, Accept: 'application/json' }, }) if (!r.ok) { console.error(r.status, await r.text()) process.exit(1) } const { data } = await r.json() const ws = new WebSocket(data.socket, { headers: { Origin: config.panel } }) let sent = false ws.onopen = () => ws.send(JSON.stringify({ event: 'auth', args: [data.token] })) ws.onmessage = (m) => { const msg = JSON.parse(m.data) if (msg.event === 'auth success' && !sent) { sent = true // The panel replays recent history on connect; let it pass, then send. setTimeout(() => ws.send(JSON.stringify({ event: 'send command', args: [command] })), 800) setTimeout(() => { ws.close() process.exit(0) }, Number(secs) * 1000) } else if (msg.event === 'console output' && sent) { for (const line of strip(String(msg.args[0])).split('\n')) { if (!filter || line.toLowerCase().includes(filter.toLowerCase())) console.log(line) } } else if (msg.event === 'jwt error' || msg.event === 'token expired') { console.error('ws:', msg.event, msg.args) } } ws.onerror = (e) => console.error('ws error', e.message || e) } main().catch((e) => { console.error(e.message || e) process.exit(1) })