feat(platform): GUILD_SYNC channel meta + SEND_MESSAGES enforcement
Bundle channelSettings (description + slowmode) and all topic-bearing channel types in GUILD_SYNC; ingest into ChannelDescriptionStore on peer join. Push mesh sync after topic/description edits. _participationMask applies channel overwrites for send, voice join, and view.canPostInActiveChannel.
This commit is contained in:
@@ -134,7 +134,8 @@ const { PearcordGuildRoles, PERMISSION_META } = require('pearcord-guild-roles')
|
||||
const {
|
||||
PearcordChannelPermissions,
|
||||
memberHasChannelPermission,
|
||||
effectivePermissionView
|
||||
effectivePermissionView,
|
||||
effectivePermissionMask
|
||||
} = require('pearcord-channel-permissions')
|
||||
const { viewToMask } = require('pearcord-guild-roles/permissions')
|
||||
const { maskToPermissionView, memberPermissionMask } = require('pearcord-guild-roles/permissions')
|
||||
@@ -1051,8 +1052,19 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (!guild?.id) return null
|
||||
const channels = await this.guild.listChannels()
|
||||
const syncChannels = channels.filter((c) =>
|
||||
c.type === 'text' || c.type === 'announcement' || c.type === 'forum'
|
||||
['text', 'voice', 'announcement', 'stage', 'forum'].includes(c.type)
|
||||
)
|
||||
const channelSettings = []
|
||||
await this._initChannelPermissions(guild.id)
|
||||
for (const ch of channels) {
|
||||
const settings = await this.getChannelSettings(ch.id, guild.id)
|
||||
channelSettings.push({
|
||||
guildId: guild.id,
|
||||
channelId: ch.id,
|
||||
slowmodeSeconds: settings.slowmodeSeconds || 0,
|
||||
description: settings.description ?? null
|
||||
})
|
||||
}
|
||||
const messages = []
|
||||
for (const ch of syncChannels) {
|
||||
const rows = await this.db.find(COLLECTIONS.MESSAGES, { channelId: ch.id })
|
||||
@@ -1106,7 +1118,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
members,
|
||||
guildRoles: roleBundle.guildRoles,
|
||||
memberRoleLinks: roleBundle.memberRoleLinks,
|
||||
channelOverwrites: permBundle.channelOverwrites
|
||||
channelOverwrites: permBundle.channelOverwrites,
|
||||
channelSettings
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,6 +1172,25 @@ class PearcordPlatform extends EventEmitter {
|
||||
}
|
||||
for (const ch of payload.channels || []) {
|
||||
await this.guild.ingestChannel(ch).catch(() => {})
|
||||
if (ch?.topic != null) this.emit('channel-update', ch)
|
||||
}
|
||||
if (this.channelDescriptions && payload.channelSettings?.length) {
|
||||
for (const row of payload.channelSettings) {
|
||||
if (row?.guildId !== payload.guildId || !row?.channelId) continue
|
||||
await this.db.insert(COLLECTIONS.CHANNEL_SETTINGS, {
|
||||
guildId: row.guildId,
|
||||
channelId: row.channelId,
|
||||
slowmodeSeconds: row.slowmodeSeconds || 0
|
||||
})
|
||||
if (row.description !== undefined) {
|
||||
await this.channelDescriptions.set(
|
||||
row.guildId,
|
||||
row.channelId,
|
||||
row.description
|
||||
)
|
||||
}
|
||||
}
|
||||
this.emit('channel-settings-sync', { guildId: payload.guildId })
|
||||
}
|
||||
for (const att of payload.attachments || []) {
|
||||
await this.attachments?.ingestGossip(att).catch(() => {})
|
||||
@@ -1919,6 +1951,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
targetId: channelId
|
||||
})
|
||||
this.emit('channel-update', updated)
|
||||
setTimeout(() => this._pushGuildSyncToMesh().catch(() => {}), 400)
|
||||
return updated
|
||||
}
|
||||
|
||||
@@ -1937,6 +1970,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
description: normalizeDescription(description)
|
||||
})
|
||||
await this._audit('channel.description', { guildId, targetId: channelId })
|
||||
setTimeout(() => this._pushGuildSyncToMesh().catch(() => {}), 400)
|
||||
return settings
|
||||
}
|
||||
|
||||
@@ -2119,6 +2153,19 @@ class PearcordPlatform extends EventEmitter {
|
||||
return this.channelPermissions.listForChannel(this.guild.guild.id, channelId)
|
||||
}
|
||||
|
||||
async _participationMask (channelId) {
|
||||
const member = await this._resolveMemberRecord()
|
||||
if (!member) return 0
|
||||
const customRoles = this.guildRoles
|
||||
? await this.guildRoles.listRoles(this.guild.guild.id)
|
||||
: []
|
||||
const base = memberPermissionMask(member, customRoles)
|
||||
const chId = channelId || this.activeChannelId
|
||||
if (!chId || this.mode !== 'guild') return base
|
||||
const overwrites = await this._channelOverwrites(chId)
|
||||
return effectivePermissionMask(member, customRoles, overwrites)
|
||||
}
|
||||
|
||||
async _initBotEvents (guildId) {
|
||||
this.botEvents = new BotEventFanout({
|
||||
guildId,
|
||||
@@ -2485,7 +2532,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
const customRoles = this.guildRoles && this.guild?.guild
|
||||
? await this.guildRoles.listRoles(this.guild.guild.id)
|
||||
: []
|
||||
const canParticipate = memberCanParticipate(member, customRoles)
|
||||
const mask = await this._participationMask(channelId)
|
||||
const canParticipate = memberCanParticipate(member, customRoles, mask)
|
||||
if (!listenOnly && !canParticipate) {
|
||||
if (memberCanJoinVoiceListenOnly(member, customRoles)) listenOnly = true
|
||||
else throw new Error('read-only role cannot join voice')
|
||||
@@ -4342,7 +4390,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
const customRoles = this.guildRoles
|
||||
? await this.guildRoles.listRoles(this.guild.guild.id)
|
||||
: []
|
||||
if (!memberCanParticipate(member, customRoles)) {
|
||||
const mask = await this._participationMask(this.activeChannelId)
|
||||
if (!memberCanParticipate(member, customRoles, mask)) {
|
||||
throw new Error('read-only role cannot send messages or reactions')
|
||||
}
|
||||
}
|
||||
@@ -5022,7 +5071,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
const customRolesForSelf = this.guildRoles && guild
|
||||
? await this.guildRoles.listRoles(guild.id)
|
||||
: []
|
||||
canPostInActiveChannel = memberCanParticipate(selfMember, customRolesForSelf)
|
||||
const partMask = await this._participationMask(this.activeChannelId)
|
||||
canPostInActiveChannel = memberCanParticipate(
|
||||
selfMember,
|
||||
customRolesForSelf,
|
||||
partMask
|
||||
)
|
||||
canJoinVoiceListenOnly = memberCanJoinVoiceListenOnly(selfMember, customRolesForSelf)
|
||||
if (activeChannel && isAnnouncementChannel(activeChannel)) {
|
||||
canPostInActiveChannel = canPostInActiveChannel && !!myPermissions?.manageMessages
|
||||
|
||||
+42
-42
@@ -7,56 +7,56 @@
|
||||
"bare-events": "^2.8.0",
|
||||
"bare-path": "^3.0.0",
|
||||
"bare-process": "^4.4.0",
|
||||
"pearcord-db": "file:../pearcord-db",
|
||||
"pearcord-identity": "file:../pearcord-identity",
|
||||
"pearcord-guild": "file:../pearcord-guild",
|
||||
"pearcord-message": "file:../pearcord-message",
|
||||
"pearcord-message-layout": "file:../pearcord-message-layout",
|
||||
"pearcord-profile-assets": "file:../pearcord-profile-assets",
|
||||
"pearcord-lottie": "file:../pearcord-lottie",
|
||||
"pearcord-presence": "file:../pearcord-presence",
|
||||
"hyperswarm": "^4.11.6",
|
||||
"pearcord-activity": "file:../pearcord-activity",
|
||||
"pearcord-channel-meta": "file:../pearcord-channel-meta",
|
||||
"pearcord-invite": "file:../pearcord-invite",
|
||||
"pearcord-dm": "file:../pearcord-dm",
|
||||
"pearcord-announcement-hub": "file:../pearcord-announcement-hub",
|
||||
"pearcord-announcements": "file:../pearcord-announcements",
|
||||
"pearcord-attachments": "file:../pearcord-attachments",
|
||||
"pearcord-drive": "file:../pearcord-drive",
|
||||
"pearcord-moderation": "file:../pearcord-moderation",
|
||||
"pearcord-voice": "file:../pearcord-voice",
|
||||
"pearcord-voice-media": "file:../pearcord-voice-media",
|
||||
"pearcord-discovery": "file:../pearcord-discovery",
|
||||
"pearcord-embed": "file:../pearcord-embed",
|
||||
"pearcord-crypto": "file:../pearcord-crypto",
|
||||
"pearcord-threads": "file:../pearcord-threads",
|
||||
"pearcord-commands": "file:../pearcord-commands",
|
||||
"pearcord-emoji": "file:../pearcord-emoji",
|
||||
"pearcord-guild-roles": "file:../pearcord-guild-roles",
|
||||
"pearcord-channel-permissions": "file:../pearcord-channel-permissions",
|
||||
"pearcord-bot-events": "file:../pearcord-bot-events",
|
||||
"pearcord-bot-sdk": "file:../pearcord-bot-sdk",
|
||||
"pearcord-bot-limits": "file:../pearcord-bot-limits",
|
||||
"pearcord-automod": "file:../pearcord-automod",
|
||||
"pearcord-boosts": "file:../pearcord-boosts",
|
||||
"pearcord-bot-auth": "file:../pearcord-bot-auth",
|
||||
"pearcord-bot-events": "file:../pearcord-bot-events",
|
||||
"pearcord-bot-limits": "file:../pearcord-bot-limits",
|
||||
"pearcord-bot-sdk": "file:../pearcord-bot-sdk",
|
||||
"pearcord-channel-meta": "file:../pearcord-channel-meta",
|
||||
"pearcord-channel-permissions": "file:../pearcord-channel-permissions",
|
||||
"pearcord-commands": "file:../pearcord-commands",
|
||||
"pearcord-contacts": "file:../pearcord-contacts",
|
||||
"pearcord-notifications": "file:../pearcord-notifications",
|
||||
"pearcord-settings": "file:../pearcord-settings",
|
||||
"pearcord-server-folders": "file:../pearcord-server-folders",
|
||||
"pearcord-profile-cosmetics": "file:../pearcord-profile-cosmetics",
|
||||
"pearcord-crypto": "file:../pearcord-crypto",
|
||||
"pearcord-db": "file:../pearcord-db",
|
||||
"pearcord-device-sync": "file:../pearcord-device-sync",
|
||||
"pearcord-step-up": "file:../pearcord-step-up",
|
||||
"pearcord-discovery": "file:../pearcord-discovery",
|
||||
"pearcord-display-capture": "file:../pearcord-display-capture",
|
||||
"pearcord-dm": "file:../pearcord-dm",
|
||||
"pearcord-drive": "file:../pearcord-drive",
|
||||
"pearcord-embed": "file:../pearcord-embed",
|
||||
"pearcord-emoji": "file:../pearcord-emoji",
|
||||
"pearcord-forum": "file:../pearcord-forum",
|
||||
"pearcord-forum-search": "file:../pearcord-forum-search",
|
||||
"pearcord-stage": "file:../pearcord-stage",
|
||||
"pearcord-automod": "file:../pearcord-automod",
|
||||
"pearcord-screen-share": "file:../pearcord-screen-share",
|
||||
"pearcord-display-capture": "file:../pearcord-display-capture",
|
||||
"pearcord-stickers": "file:../pearcord-stickers",
|
||||
"pearcord-soundboard": "file:../pearcord-soundboard",
|
||||
"pearcord-announcement-hub": "file:../pearcord-announcement-hub",
|
||||
"pearcord-guild": "file:../pearcord-guild",
|
||||
"pearcord-guild-roles": "file:../pearcord-guild-roles",
|
||||
"pearcord-hub-cards": "file:../pearcord-hub-cards",
|
||||
"pearcord-announcements": "file:../pearcord-announcements",
|
||||
"pearcord-boosts": "file:../pearcord-boosts",
|
||||
"pearcord-identity": "file:../pearcord-identity",
|
||||
"pearcord-invite": "file:../pearcord-invite",
|
||||
"pearcord-lottie": "file:../pearcord-lottie",
|
||||
"pearcord-message": "file:../pearcord-message",
|
||||
"pearcord-message-layout": "file:../pearcord-message-layout",
|
||||
"pearcord-moderation": "file:../pearcord-moderation",
|
||||
"pearcord-notifications": "file:../pearcord-notifications",
|
||||
"pearcord-presence": "file:../pearcord-presence",
|
||||
"pearcord-profile-assets": "file:../pearcord-profile-assets",
|
||||
"pearcord-profile-cosmetics": "file:../pearcord-profile-cosmetics",
|
||||
"pearcord-screen-share": "file:../pearcord-screen-share",
|
||||
"pearcord-server-folders": "file:../pearcord-server-folders",
|
||||
"pearcord-settings": "file:../pearcord-settings",
|
||||
"pearcord-shared": "file:../pearcord-shared",
|
||||
"pearcord-soundboard": "file:../pearcord-soundboard",
|
||||
"pearcord-stage": "file:../pearcord-stage",
|
||||
"pearcord-step-up": "file:../pearcord-step-up",
|
||||
"pearcord-stickers": "file:../pearcord-stickers",
|
||||
"pearcord-threads": "file:../pearcord-threads",
|
||||
"pearcord-voice": "file:../pearcord-voice",
|
||||
"pearcord-voice-capture": "file:../pearcord-voice-capture",
|
||||
"hyperswarm": "^4.11.6",
|
||||
"pearcord-shared": "file:../pearcord-shared"
|
||||
"pearcord-voice-media": "file:../pearcord-voice-media"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user