feat(platform): Phase 105 mesh peer indicator and digest export schedule
- listAuditArchiveFetchPeers returns meshConnected per member - automationDigestExportSchedule timer and snapshot persistence - GUILD_SYNC slices for schedule and snapshot metadata - runOverdueAutomationSchedules includes digest export task Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -1167,12 +1167,18 @@ class PearcordPlatform extends EventEmitter {
|
||||
const auditRecent = await this._exportAuditSyncSlice(guild.id)
|
||||
let auditExportSchedule = null
|
||||
let digestExportSchedule = null
|
||||
let automationDigestExportSchedule = null
|
||||
let automationDigestExportSnapshots = []
|
||||
let auditExportArchives = []
|
||||
let hookFailureDigest = null
|
||||
await this._initDeliveryReceipts(guild.id)
|
||||
if (this.deliveryReceipts) {
|
||||
auditExportSchedule = await this.deliveryReceipts.exportAuditExportScheduleSlice()
|
||||
digestExportSchedule = await this.deliveryReceipts.exportDigestExportScheduleSlice()
|
||||
automationDigestExportSchedule =
|
||||
await this.deliveryReceipts.exportAutomationDigestExportScheduleSlice()
|
||||
automationDigestExportSnapshots =
|
||||
await this.deliveryReceipts.exportAutomationDigestExportSnapshotsSlice(2)
|
||||
auditExportArchives = await this.deliveryReceipts.exportAuditExportArchivesSlice(3)
|
||||
const digestSnap = await this.deliveryReceipts.getHookFailureDigestSnapshot()
|
||||
if (digestSnap) {
|
||||
@@ -1232,6 +1238,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
auditRecent,
|
||||
auditExportSchedule,
|
||||
digestExportSchedule,
|
||||
automationDigestExportSchedule,
|
||||
automationDigestExportSnapshots,
|
||||
auditExportArchives,
|
||||
hookFailureDigest,
|
||||
workerReleaseHint,
|
||||
@@ -1342,6 +1350,13 @@ class PearcordPlatform extends EventEmitter {
|
||||
payload.digestExportSchedule
|
||||
)
|
||||
}
|
||||
if (payload.automationDigestExportSchedule) {
|
||||
await this._initDeliveryReceipts(payload.guildId)
|
||||
await this.deliveryReceipts.ingestAutomationDigestExportScheduleSlice(
|
||||
payload.guildId,
|
||||
payload.automationDigestExportSchedule
|
||||
)
|
||||
}
|
||||
for (const archive of payload.auditExportArchives || []) {
|
||||
if (!archive?.id || archive.guildId !== payload.guildId) continue
|
||||
await this._initDeliveryReceipts(payload.guildId)
|
||||
@@ -2057,8 +2072,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
}
|
||||
|
||||
async listAuditArchiveFetchPeers () {
|
||||
if (!this.guild?.guild) return { meshPeerCount: 0, options: [] }
|
||||
if (!this.guild?.guild) return { meshPeerCount: 0, meshLive: false, options: [] }
|
||||
const meshPeerCount = this.guild.getStats?.()?.peers || 0
|
||||
const meshLive = meshPeerCount > 0
|
||||
const selfId = this.identity.user?.id || null
|
||||
const presenceSnap = this.presence?.snapshot?.() || { peers: [] }
|
||||
const onlineIds = new Set(
|
||||
@@ -2068,8 +2084,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
const options = [
|
||||
{
|
||||
memberId: null,
|
||||
label: meshPeerCount > 0 ? `Any connected peer (${meshPeerCount} on mesh)` : 'Any peer (mesh offline)',
|
||||
online: meshPeerCount > 0,
|
||||
label: meshLive
|
||||
? `Any connected peer (${meshPeerCount} on mesh)`
|
||||
: 'Any peer (mesh offline)',
|
||||
online: meshLive,
|
||||
meshConnected: meshLive,
|
||||
isSelf: false
|
||||
}
|
||||
]
|
||||
@@ -2079,15 +2098,17 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (!userId) continue
|
||||
const user = await this.db.get(COLLECTIONS.USERS, { id: userId }).catch(() => null)
|
||||
const name = user?.displayName || user?.username || userId.slice(0, 8)
|
||||
const online = onlineIds.has(userId) || meshPeerCount > 0
|
||||
const presenceOnline = onlineIds.has(userId)
|
||||
const meshConnected = meshLive && presenceOnline
|
||||
options.push({
|
||||
memberId: userId,
|
||||
label: userId === selfId ? `${name} (you)` : name,
|
||||
online,
|
||||
online: presenceOnline || (userId === selfId && meshLive),
|
||||
meshConnected,
|
||||
isSelf: userId === selfId
|
||||
})
|
||||
}
|
||||
return { meshPeerCount, options }
|
||||
return { meshPeerCount, meshLive, options }
|
||||
}
|
||||
|
||||
_resolveAuditArchiveFetchWaiter (archive) {
|
||||
@@ -2348,11 +2369,17 @@ class PearcordPlatform extends EventEmitter {
|
||||
digestResult = await this.runScheduledDigestExportNow()
|
||||
if (digestResult) ran.push('digest-sync')
|
||||
}
|
||||
let automationDigestResult = null
|
||||
if (before.automationDigestExport?.overdue) {
|
||||
automationDigestResult = await this.runScheduledAutomationDigestExportNow()
|
||||
if (automationDigestResult) ran.push('automation-digest-export')
|
||||
}
|
||||
const dashboard = await this.getAutomationScheduleDashboard()
|
||||
return {
|
||||
ran,
|
||||
auditResult,
|
||||
digestResult,
|
||||
automationDigestResult,
|
||||
dashboard,
|
||||
guildId: this.guild.guild.id
|
||||
}
|
||||
@@ -2364,14 +2391,77 @@ class PearcordPlatform extends EventEmitter {
|
||||
}
|
||||
const auditExportSchedule = await this.getAuditExportSchedule()
|
||||
const digestExportSchedule = await this.getDigestExportSchedule()
|
||||
const automationDigestExportSchedule = await this.getAutomationDigestExportSchedule()
|
||||
const hookFailureDigest = await this.getHookFailureDigest()
|
||||
return buildAutomationScheduleDashboard({
|
||||
auditExportSchedule,
|
||||
digestExportSchedule,
|
||||
automationDigestExportSchedule,
|
||||
hookFailureDigest
|
||||
})
|
||||
}
|
||||
|
||||
async getAutomationDigestExportSchedule () {
|
||||
if (!this.guild?.guild) {
|
||||
return { enabled: false, intervalHours: 24, format: 'text', lastExportAt: 0 }
|
||||
}
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
return this.deliveryReceipts.getAutomationDigestExportSchedule()
|
||||
}
|
||||
|
||||
async setAutomationDigestExportSchedule (partial = {}) {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
const roles = await this._memberRoles()
|
||||
if (!roleHasPermission(roles, PERMISSION.MANAGE_GUILD)) {
|
||||
throw new Error('no permission to manage automation digest export schedule')
|
||||
}
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
const prefs = await this.deliveryReceipts.setAutomationDigestExportSchedule(partial)
|
||||
this.emit('automation-digest-export-schedule', prefs)
|
||||
this._startAuditExportScheduleTimer()
|
||||
setTimeout(() => this._pushGuildSyncToMesh().catch(() => {}), 400)
|
||||
return prefs
|
||||
}
|
||||
|
||||
async listAutomationDigestExportSnapshots (limit = 3) {
|
||||
if (!this.guild?.guild) return []
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
return this.deliveryReceipts.listAutomationDigestExportSnapshots(limit)
|
||||
}
|
||||
|
||||
async runScheduledAutomationDigestExportNow () {
|
||||
return this._runScheduledAutomationDigestExportIfDue(true)
|
||||
}
|
||||
|
||||
async _runScheduledAutomationDigestExportIfDue (force = false) {
|
||||
if (!this.guild?.guild) return null
|
||||
const roles = await this._memberRoles()
|
||||
if (!roleHasPermission(roles, PERMISSION.MANAGE_GUILD)) return null
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
const schedule = await this.deliveryReceipts.getAutomationDigestExportSchedule()
|
||||
if (!schedule.enabled && !force) return null
|
||||
const intervalMs = (schedule.intervalHours || 24) * 60 * 60 * 1000
|
||||
const last = schedule.lastExportAt || 0
|
||||
if (!force && Date.now() - last < intervalMs) return null
|
||||
const exported = await this.exportAutomationScheduleDigest({
|
||||
format: schedule.format || 'text'
|
||||
})
|
||||
const summaryLines = String(exported.body || '').split('\n').length
|
||||
const snap = await this.deliveryReceipts.appendAutomationDigestExportSnapshot({
|
||||
exportedAt: exported.exportedAt,
|
||||
exportedBy: this.identity.user?.id || null,
|
||||
format: exported.format,
|
||||
summaryLines,
|
||||
body: exported.body
|
||||
})
|
||||
await this.deliveryReceipts.setAutomationDigestExportSchedule({
|
||||
lastExportAt: exported.exportedAt
|
||||
})
|
||||
this.emit('automation-digest-export-scheduled', { exported, snap, schedule })
|
||||
setTimeout(() => this._pushGuildSyncToMesh().catch(() => {}), 400)
|
||||
return { ...exported, snapshotId: snap?.id || null }
|
||||
}
|
||||
|
||||
async exportHookFailureDigest (opts = {}) {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
const roles = await this._memberRoles()
|
||||
@@ -5084,9 +5174,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._auditScheduleTimer = setInterval(() => {
|
||||
this._runScheduledAuditExportIfDue().catch(() => {})
|
||||
this._runScheduledDigestExportIfDue().catch(() => {})
|
||||
this._runScheduledAutomationDigestExportIfDue().catch(() => {})
|
||||
}, 60 * 1000)
|
||||
this._runScheduledAuditExportIfDue().catch(() => {})
|
||||
this._runScheduledDigestExportIfDue().catch(() => {})
|
||||
this._runScheduledAutomationDigestExportIfDue().catch(() => {})
|
||||
}
|
||||
|
||||
async runScheduledAuditExportNow () {
|
||||
@@ -6652,6 +6744,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
let hookFailureDigest = null
|
||||
let auditExportSchedule = null
|
||||
let digestExportSchedule = null
|
||||
let automationDigestExportSchedule = null
|
||||
let automationDigestExportSnapshots = []
|
||||
let auditExportArchives = []
|
||||
let automationScheduleDashboard = null
|
||||
let auditArchiveFetchPeers = null
|
||||
@@ -6661,6 +6755,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
hookFailureDigest = await this.getHookFailureDigest()
|
||||
auditExportSchedule = await this.getAuditExportSchedule()
|
||||
digestExportSchedule = await this.getDigestExportSchedule()
|
||||
automationDigestExportSchedule = await this.getAutomationDigestExportSchedule()
|
||||
automationDigestExportSnapshots = await this.listAutomationDigestExportSnapshots(3)
|
||||
auditExportArchives = await this.listAuditExportArchives(6)
|
||||
automationScheduleDashboard = await this.getAutomationScheduleDashboard()
|
||||
auditArchiveFetchPeers = await this.listAuditArchiveFetchPeers()
|
||||
@@ -6835,6 +6931,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
hookFailureDigest,
|
||||
auditExportSchedule,
|
||||
digestExportSchedule,
|
||||
automationDigestExportSchedule,
|
||||
automationDigestExportSnapshots,
|
||||
auditExportArchives,
|
||||
automationScheduleDashboard,
|
||||
auditArchiveFetchPeers,
|
||||
|
||||
Reference in New Issue
Block a user