/**
* query-rooms.mjs — List all rooms and their current metadata
* Usage: bare tests/query-rooms.mjs
*/
import Pipe from 'bare-pipe'
import FramedStream from 'framed-stream'
import b4a from 'b4a'
const SOCKET = '/tmp/keet-daemon.sock'
let rpcId = 0
function connect () {
const pipe = new Pipe(SOCKET)
const framed = new FramedStream(pipe)
const pending = new Map()
framed.on('data', (buf) => {
try {
const msg = JSON.parse(b4a.toString(buf))
const cb = pending.get(msg.id)
if (cb) {
pending.delete(msg.id)
if (msg.ok !== undefined && msg.data !== undefined) msg.result = msg.data
cb(msg)
}
} catch {}
})
function call (method, params = {}) {
return new Promise((resolve, reject) => {
const id = ++rpcId
const timeout = setTimeout(() => {
pending.delete(id)
reject(new Error(`RPC timeout: ${method}`))
}, 15000)
pending.set(id, (msg) => {
clearTimeout(timeout)
if (msg.error) reject(new Error(msg.error.message || msg.error))
else resolve(msg.result)
})
const payload = JSON.stringify({ jsonrpc: '2.0', id, method, params })
framed.write(b4a.from(payload))
})
}
function close () { framed.destroy(); pipe.destroy() }
return { call, close }
}
async function run () {
const client = connect()
// Check available meta routes
let hasList = true
try {
await client.call('introspect')
} catch {}
const rooms = await client.call('rooms')
// Try meta.list, fall back to per-room meta.get
let allMeta = {}
try {
allMeta = await client.call('meta.list')
} catch {
// meta.list not available, fetch per room
for (const room of rooms) {
const id = room.roomId || room.id
try {
const meta = await client.call('meta.get', { roomId: id })
if (meta && Object.keys(meta).length > 0) {
allMeta[id] = meta
}
} catch {}
}
}
console.log(`\n=== ${rooms.length} rooms total, ${Object.keys(allMeta).length} have metadata ===\n`)
const withMeta = []
const withoutMeta = []
for (const room of rooms) {
const id = room.roomId || room.id
const title = room.title || '(untitled)'
const meta = allMeta[id]
if (meta && Object.keys(meta).filter(k => !k.startsWith('_')).length > 0) {
withMeta.push({ id, title, meta })
} else {
withoutMeta.push({ id, title })
}
}
if (withMeta.length > 0) {
console.log('--- ROOMS WITH METADATA ---\n')
for (const { id, title, meta } of withMeta) {
const clean = {}
for (const [k, v] of Object.entries(meta)) {
if (!k.startsWith('_')) clean[k] = v
}
console.log(` "${title}" (${id.slice(0, 16)}...)`)
console.log(` ${JSON.stringify(clean)}`)
}
}
if (withoutMeta.length > 0) {
console.log('\n--- ROOMS WITHOUT METADATA ---\n')
for (const { id, title } of withoutMeta) {
console.log(` "${title}" (${id.slice(0, 16)}...)`)
}
}
// Get room details for ALL rooms
console.log('\n--- ROOM DETAILS ---\n')
for (const room of rooms) {
const id = room.roomId || room.id
const title = room.title || '(untitled)'
try {
const info = await client.call('room', { roomId: id })
const roomType = info.digest?.settings?.roomType
const memberCount = info.status?.memberCount || info.digest?.memberCount || '?'
const connected = info.status?.connectedPeers || '?'
const isWritable = info.status?.isWritable
const hasMeta = !!allMeta[id]
const typeLabel = roomType === 1 ? 'Default' : roomType === 2 ? 'Broadcast' : roomType === 3 ? 'DM' : `type=${roomType}`
console.log(` "${title}" [${typeLabel}] members=${memberCount} connected=${connected} writable=${isWritable} meta=${hasMeta}`)
console.log(` id: ${id}`)
} catch (err) {
console.log(` "${title}" — error: ${err.message}`)
}
}
console.log('\n=== SUMMARY ===')
console.log(` With metadata: ${withMeta.length}`)
console.log(` Without metadata: ${withoutMeta.length}`)
console.log(` Total rooms: ${rooms.length}`)
client.close()
setTimeout(() => Bare.exit(0), 500)
}
run().catch(err => { console.error('FATAL:', err.message); Bare.exit(1) })