Add adaptive poll helpers, discovery frame dedupe, poll DB read budget, view integrity (draft prune, pin fallback, cross-ref audit, prefs checksum), mesh quiet mode, topic merge counters, and discovery local-only guard. Co-authored-by: Cursor <[email protected]>
90 lines
2.2 KiB
JavaScript
90 lines
2.2 KiB
JavaScript
'use strict'
|
|
|
|
const crypto = require('hypercore-crypto')
|
|
const b4a = require('b4a')
|
|
|
|
function checksumSettingsSnapshot (obj) {
|
|
const json = JSON.stringify(obj || {})
|
|
return b4a.toString(crypto.hash(b4a.from(json)), 'hex').slice(0, 16)
|
|
}
|
|
|
|
/**
|
|
* Prune compose drafts for deleted or inaccessible channels (P409-18).
|
|
*/
|
|
function pruneStaleComposeDrafts (composeDrafts, { channelIds, canPostByChannel = {} } = {}) {
|
|
const allowed = new Set(channelIds || [])
|
|
const out = { ...(composeDrafts || {}) }
|
|
const removed = []
|
|
for (const chId of Object.keys(out)) {
|
|
if (!allowed.has(chId)) {
|
|
removed.push(chId)
|
|
delete out[chId]
|
|
continue
|
|
}
|
|
if (canPostByChannel[chId] === false) {
|
|
removed.push(chId)
|
|
delete out[chId]
|
|
}
|
|
}
|
|
return { composeDrafts: out, removed }
|
|
}
|
|
|
|
/**
|
|
* Cross-reference messages, reactions, pins before renderer (P409-17).
|
|
*/
|
|
function auditMessageReactionCrossRefs ({
|
|
messages = [],
|
|
messageById = {},
|
|
reactions = {},
|
|
pins = []
|
|
} = {}) {
|
|
const historyIds = new Set(messages.map((m) => m.id))
|
|
const issues = []
|
|
for (const messageId of Object.keys(reactions)) {
|
|
if (!messageById[messageId] && !historyIds.has(messageId)) {
|
|
issues.push({ kind: 'reaction-orphan', messageId })
|
|
}
|
|
}
|
|
for (const pin of pins) {
|
|
const mid = pin.messageId
|
|
if (!mid) continue
|
|
if (!pin.message && !messageById[mid] && !historyIds.has(mid)) {
|
|
issues.push({ kind: 'pin-missing-body', messageId: mid })
|
|
}
|
|
}
|
|
return {
|
|
ok: issues.length === 0,
|
|
issueCount: issues.length,
|
|
issues: issues.slice(0, 32)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Safe pin row when message body missing (P409-19).
|
|
*/
|
|
function pinWithMessageFallback (pin, messageById = {}) {
|
|
if (!pin?.messageId) return pin
|
|
if (pin.message) return pin
|
|
const embedded = messageById[pin.messageId]
|
|
if (!embedded) {
|
|
return {
|
|
...pin,
|
|
message: {
|
|
id: pin.messageId,
|
|
content: '(message unavailable)',
|
|
displayContent: '(message unavailable)',
|
|
authorId: pin.authorId || null,
|
|
missing: true
|
|
}
|
|
}
|
|
}
|
|
return { ...pin, message: embedded }
|
|
}
|
|
|
|
module.exports = {
|
|
checksumSettingsSnapshot,
|
|
pruneStaleComposeDrafts,
|
|
auditMessageReactionCrossRefs,
|
|
pinWithMessageFallback
|
|
}
|