feat(mesh): guild channel settings gossip sync-ready (Phase 794)

Apply slowmode on CHANNEL_SETTINGS gossip, count channelSettings in GUILD_SYNC
ingest/wire handlers, and emit guild-sync-ready for remote settings propagation.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-03 22:21:44 -04:00
co-authored by Cursor
parent 0ac42af467
commit 8d23288b41
4 changed files with 41 additions and 6 deletions
+2
View File
@@ -2,6 +2,8 @@
Application facade: one `PearcordPlatform` class that wires identity, database, guild mesh, DMs, invites, voice, discovery, bots, and dozens of feature modules for the Pearcord desktop sidecar and companion. **Mixin sources:** [`mixins/README.md`](mixins/README.md) — `domain/`, `json-export/`, `runtime/{core,mesh,guild-sync,search-discovery,partition-heal,view,voice-dm,features}/`. Architecture: [PLATFORM_MIXINS.md](../../docs/PLATFORM_MIXINS.md). Regenerate after manifest edits: `cd apps/pearcord && npm run regenerate:platform-mixins`. OTA prestage recursively verifies symbols under `mixins/` — [RELEASE.md](../../docs/RELEASE.md#prestage-sync-file-deps).
**Phase 794 (v0.8.761):** Channel-settings gossip + GUILD_SYNC `channelSettings` slice → `guild-sync-ready`. Bundle: `npm run test:ci-phase794`.
**Phase 793 (v0.8.760):** Sound gossip + GUILD_SYNC `guildSounds` slice → `guild-sync-ready`. Bundle: `npm run test:ci-phase793`.
**Phase 792 (v0.8.759):** Pin gossip + GUILD_SYNC `pins` slice → `guild-sync-ready`. Bundle: `npm run test:ci-phase792`.
@@ -450,7 +450,8 @@ async _ingestGuildSync (payload) {
if (ch?.topic != null) this.emit('channel-update', ch)
}
if (channelRows.length) this.emit('channel')
if (this.channelDescriptions && payload.channelSettings?.length) {
let channelSettingsApplied = 0
if (payload.channelSettings?.length) {
const settingsByChannel = new Map(
payload.channelSettings.map((r) => [r.channelId, r])
)
@@ -474,7 +475,8 @@ async _ingestGuildSync (payload) {
channelId: row.channelId,
slowmodeSeconds
})
if (row.description !== undefined) {
channelSettingsApplied += 1
if (row.description !== undefined && this.channelDescriptions) {
await this.channelDescriptions.set(
row.guildId,
row.channelId,
@@ -483,6 +485,7 @@ async _ingestGuildSync (payload) {
}
}
this.emit('channel-settings-sync', { guildId: payload.guildId })
if (channelSettingsApplied > 0) this.emit('channel-settings', { batch: true })
}
for (const att of payload.attachments || []) {
await this.attachments?.ingestGossip(att).catch(() => {})
@@ -637,6 +640,7 @@ async _ingestGuildSync (payload) {
stickers: stickerChanges,
sounds: soundChanges,
pins: pinsApplied,
channelSettings: channelSettingsApplied,
sparse,
attachPull,
ingestMs
@@ -36,6 +36,12 @@ const platformGuildSyncWireSparseMixin = {
updatedAt: hyperdbScope.coerceSyncUint(s.updatedAt, 0)
}))
}
if (Array.isArray(next.channelSettings)) {
next.channelSettings = next.channelSettings.map((r) => ({
...r,
slowmodeSeconds: hyperdbScope.coerceSyncUint(r.slowmodeSeconds, 0)
}))
}
if (Array.isArray(next.pins)) {
next.pins = next.pins.map((p) => ({
...p,
@@ -143,10 +143,25 @@ _wireGuild (guildInstance) {
})
guildInstance.on('ban', (p) => this._onBanGossip(p))
guildInstance.on('channel-settings', (p) => {
if (p?.guildId && p?.channelId && p.description !== undefined) {
this.channelDescriptions.set(p.guildId, p.channelId, p.description).catch(() => {})
if (p?.guildId && p?.channelId) {
if (p.slowmodeSeconds !== undefined) {
this.db
.insert(sharedScope.COLLECTIONS.CHANNEL_SETTINGS, {
guildId: p.guildId,
channelId: p.channelId,
slowmodeSeconds: p.slowmodeSeconds || 0
})
.catch(() => {})
}
if (p.description !== undefined) {
this.channelDescriptions
?.set(p.guildId, p.channelId, p.description)
.catch(() => {})
}
}
this.emit('channel-settings', p)
const gid = this.guild?.guild?.id
if (gid) this.emit('guild-sync-ready', { guildId: gid, channelSettings: 1 })
})
guildInstance.on('member', (p) => {
this._fanoutBotEvent(BOT_EVENTS.MEMBER_JOIN, { member: p })
@@ -267,6 +282,7 @@ _wireGuild (guildInstance) {
const payloadStickers = payload?.guildStickers?.length || 0
const payloadSounds = payload?.guildSounds?.length || 0
const payloadPins = payload?.pins?.length || 0
const payloadChannelSettings = payload?.channelSettings?.length || 0
const hasSlice =
payloadMsgs > 0 ||
payloadMems > 0 ||
@@ -278,7 +294,8 @@ _wireGuild (guildInstance) {
payloadEmojis > 0 ||
payloadStickers > 0 ||
payloadSounds > 0 ||
payloadPins > 0
payloadPins > 0 ||
payloadChannelSettings > 0
if (!result && !hasSlice) return
this._lastGuildSyncIngestAt = Date.now()
const msgCount =
@@ -325,6 +342,10 @@ _wireGuild (guildInstance) {
typeof result === 'object'
? Math.max(result.pins || 0, payloadPins)
: payloadPins
const channelSettingsCount =
typeof result === 'object'
? Math.max(result.channelSettings || 0, payloadChannelSettings)
: payloadChannelSettings
if (
msgCount > 0 ||
memCount > 0 ||
@@ -337,6 +358,7 @@ _wireGuild (guildInstance) {
stickersCount > 0 ||
soundsCount > 0 ||
pinsCount > 0 ||
channelSettingsCount > 0 ||
hasSlice
) {
this.emit('guild-sync-ready', {
@@ -351,7 +373,8 @@ _wireGuild (guildInstance) {
emojis: emojisCount,
stickers: stickersCount,
sounds: soundsCount,
pins: pinsCount
pins: pinsCount,
channelSettings: channelSettingsCount
})
if (payload?.guildId === this.guild?.guild?.id) {
this._touchAllGuildMeshPeersSeen(payload.guildId, 'guild-sync')