feat(phase699): emoji registry CSV and sticker pack export mesh parity (v0.8.674)
Add signed emoji registry CSV mesh (RPC 116) and sticker pack export CSV (RPC 117) with emoji-csv UI, platform mixin, delivery receipts, ui-flow IPC, agentctl journeys, and test:ci-phase699 regression bundle including phase698 chain.
This commit is contained in:
@@ -2,8 +2,12 @@
|
||||
|
||||
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.
|
||||
|
||||
**Phase 699 (v0.8.674):** Emoji registry CSV & sticker pack export — `emoji-csv-mixin.js`, `emoji.csv` spans (`guildEmojiCsvCount`), `pushEmojiRegistryCsvToMesh`, `pushStickerPackExportToMesh`, deep link `openEmojiCsv`. Bundle: `npm run test:ci-phase699`.
|
||||
|
||||
**Phase 698 (v0.8.673):** Role override CSV & effective permission export — `permission-csv-mixin.js`, `permission.csv` spans (`guildPermissionCsvCount`), `pushRoleOverrideCsvToMesh`, `pushEffectivePermissionExportToMesh`, deep link `openPermissionCsv`. Bundle: `npm run test:ci-phase698`.
|
||||
|
||||
**Phase 699 (v0.8.674):** Emoji registry CSV & sticker pack export — `emoji-csv-mixin.js`, `emoji.csv` spans (`guildEmojiCsvCount`), `pushEmojiRegistryCsvToMesh`, `pushStickerPackExportToMesh`, deep link `openEmojiCsv`. Bundle: `npm run test:ci-phase699`.
|
||||
|
||||
**Phase 698 (v0.8.673):** Role override CSV & effective permission export — `permission-csv-mixin.js`, `permission.csv` spans (`guildPermissionCsvCount`), `pushRoleOverrideCsvToMesh`, `pushEffectivePermissionExportToMesh`, deep link `openPermissionCsv`. Bundle: `npm run test:ci-phase698`.
|
||||
|
||||
**Phase 697 (v0.8.672):** Invite link CSV & vanity URL export — `invite-csv-mixin.js`, `invite.csv` spans (`guildInviteCsvCount`), `pushInviteLinkCsvToMesh`, `pushVanityUrlExportToMesh`, deep link `openInviteCsv`. Bundle: `npm run test:ci-phase697`.
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
'use strict'
|
||||
|
||||
const emojiCsvMixin = {
|
||||
_emojiRegistryCsvGossipKeys: null,
|
||||
_emojiCsvHealWatermark: null,
|
||||
_stickerPackCsvHealWatermark: null,
|
||||
|
||||
_initPermissionCsvMixinState () {
|
||||
if (!this._emojiRegistryCsvGossipKeys) {
|
||||
this._emojiRegistryCsvGossipKeys = new Set()
|
||||
}
|
||||
},
|
||||
|
||||
_shouldGossipEmojiRegistryCsv (slice) {
|
||||
this._initPermissionCsvMixinState()
|
||||
if (!slice?.guildId || !slice?.signature) return true
|
||||
const hash = `${slice.guildId}:${slice.exportedAt || 0}:${slice.signature}`
|
||||
if (this._emojiRegistryCsvGossipKeys.has(hash)) return false
|
||||
this._emojiRegistryCsvGossipKeys.add(hash)
|
||||
if (this._emojiRegistryCsvGossipKeys.size > 8192) {
|
||||
const first = this._emojiRegistryCsvGossipKeys.values().next().value
|
||||
if (first) this._emojiRegistryCsvGossipKeys.delete(first)
|
||||
}
|
||||
return true
|
||||
},
|
||||
|
||||
_shouldGossipStickerPackExportCsv (slice) {
|
||||
this._initPermissionCsvMixinState()
|
||||
if (!slice?.guildId || !slice?.signature) return true
|
||||
const hash = `effective:${slice.guildId}:${slice.exportedAt || 0}:${slice.signature}`
|
||||
if (this._emojiRegistryCsvGossipKeys.has(hash)) return false
|
||||
this._emojiRegistryCsvGossipKeys.add(hash)
|
||||
return true
|
||||
},
|
||||
|
||||
async _healEmojiRegistryExportCursorOnPartition (guildId) {
|
||||
const gid = guildId || this.guild?.guild?.id || null
|
||||
const span = this.log.time('emoji.csv', {
|
||||
spanKind: 'emoji.csv',
|
||||
guildId: gid,
|
||||
context: 'heal.emoji'
|
||||
})
|
||||
try {
|
||||
if (!gid || !this.deliveryReceipts) {
|
||||
span.end({ relisted: 0, skipped: true, guildEmojiCsvCount: 0 })
|
||||
return { relisted: 0, skipped: true }
|
||||
}
|
||||
await this._initDeliveryReceipts(gid)
|
||||
const rows = await this.deliveryReceipts.listEmojiRegistryCsvExports(64)
|
||||
let relisted = 0
|
||||
for (const row of rows) {
|
||||
if (this._shouldGossipEmojiRegistryCsv(row)) relisted++
|
||||
}
|
||||
const watermark = Date.now()
|
||||
this._emojiCsvHealWatermark = watermark
|
||||
span.end({
|
||||
relisted,
|
||||
watermark,
|
||||
guildEmojiCsvCount: rows.length,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return { relisted, watermark, guildEmojiCsvCount: rows.length }
|
||||
} catch (err) {
|
||||
this.log.error('emoji.csv error', {
|
||||
guildId: gid,
|
||||
context: 'heal.emoji',
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
return { relisted: 0, error: err?.message || String(err) }
|
||||
}
|
||||
},
|
||||
|
||||
async _healStickerPackExportCursorOnPartition (guildId) {
|
||||
const gid = guildId || this.guild?.guild?.id || null
|
||||
const span = this.log.time('emoji.csv', {
|
||||
spanKind: 'emoji.csv',
|
||||
guildId: gid,
|
||||
context: 'heal.sticker'
|
||||
})
|
||||
try {
|
||||
if (!gid || !this.deliveryReceipts) {
|
||||
span.end({ relisted: 0, skipped: true, guildEmojiCsvCount: 0 })
|
||||
return { relisted: 0, skipped: true }
|
||||
}
|
||||
await this._initDeliveryReceipts(gid)
|
||||
const rows = await this.deliveryReceipts.listStickerPackExportCsvExports(64)
|
||||
let relisted = 0
|
||||
for (const row of rows) {
|
||||
if (this._shouldGossipStickerPackExportCsv(row)) relisted++
|
||||
}
|
||||
const watermark = Date.now()
|
||||
this._stickerPackCsvHealWatermark = watermark
|
||||
span.end({
|
||||
relisted,
|
||||
watermark,
|
||||
guildEmojiCsvCount: rows.length,
|
||||
emojiCount: rows[0]?.emojiCount || 0,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return { relisted, watermark, emojiCount: rows[0]?.emojiCount || 0 }
|
||||
} catch (err) {
|
||||
this.log.error('emoji.csv error', {
|
||||
guildId: gid,
|
||||
context: 'heal.sticker',
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
return { relisted: 0, error: err?.message || String(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { emojiCsvMixin }
|
||||
@@ -116,6 +116,12 @@ const {
|
||||
buildEffectivePermissionExportCsvBody,
|
||||
signEffectivePermissionExportCsv,
|
||||
verifyEffectivePermissionExportCsv,
|
||||
buildEmojiRegistryCsvBody,
|
||||
signEmojiRegistryCsv,
|
||||
verifyEmojiRegistryCsv,
|
||||
buildStickerPackExportCsvBody,
|
||||
signStickerPackExportCsv,
|
||||
verifyStickerPackExportCsv,
|
||||
formatAutomationScheduleDigestExport,
|
||||
mergeHookFailureDigests,
|
||||
buildAutomationScheduleDashboard,
|
||||
@@ -18459,7 +18465,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
openSlashCsv: !!parsed.openSlashCsv,
|
||||
openOAuthCsv: !!parsed.openOAuthCsv,
|
||||
openInviteCsv: !!parsed.openInviteCsv,
|
||||
openPermissionCsv: !!parsed.openPermissionCsv
|
||||
openPermissionCsv: !!parsed.openPermissionCsv,
|
||||
openEmojiCsv: !!parsed.openEmojiCsv
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23173,6 +23180,310 @@ class PearcordPlatform extends EventEmitter {
|
||||
return row
|
||||
}
|
||||
|
||||
async _emojiCsvRegistryEntries () {
|
||||
const guild = this.guild?.guild
|
||||
if (!guild) return []
|
||||
if (!this.emojiRegistry) await this._initEmojiRegistry(guild.id)
|
||||
const emojis = await this.emojiRegistry.list().catch(() => [])
|
||||
return emojis.map((em) => ({
|
||||
name: em.name,
|
||||
kind: em.kind || 'unicode',
|
||||
glyph: em.glyph || '',
|
||||
packName: em.packName || '',
|
||||
animated: !!em.animated,
|
||||
exportedAt: Date.now()
|
||||
}))
|
||||
}
|
||||
|
||||
async getEmojiRegistryCsvExport () {
|
||||
const gid = this.guild?.guild?.id || null
|
||||
const span = this.log.time('emoji.csv', {
|
||||
spanKind: 'emoji.csv',
|
||||
guildId: gid,
|
||||
context: 'read'
|
||||
})
|
||||
try {
|
||||
if (!this.guild?.guild) {
|
||||
span.end({ guildEmojiCsvCount: 0, skipped: true })
|
||||
return null
|
||||
}
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
const row = await this.deliveryReceipts.getEmojiRegistryCsvExport()
|
||||
if (!row?.signature) {
|
||||
span.end({
|
||||
guildEmojiCsvCount: row ? 1 : 0,
|
||||
hasSignature: false,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return row
|
||||
}
|
||||
const verified = verifyEmojiRegistryCsv(row.csvBody, row.signature, {
|
||||
guildId: this.guild.guild.id,
|
||||
relaySecret: this.guild.guild.id
|
||||
})
|
||||
const out = { ...row, signatureValid: verified.ok }
|
||||
span.end({
|
||||
guildEmojiCsvCount: 1,
|
||||
hasSignature: true,
|
||||
signatureValid: verified.ok,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return out
|
||||
} catch (err) {
|
||||
this.log.error('emoji.csv error', {
|
||||
guildId: gid,
|
||||
context: 'read',
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async exportEmojiRegistryCsv (opts = {}) {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
const entries = await this._emojiCsvRegistryEntries()
|
||||
const csvBody = buildEmojiRegistryCsvBody(entries)
|
||||
const signed = signEmojiRegistryCsv(csvBody, {
|
||||
guildId: this.guild.guild.id,
|
||||
relaySecret: this.guild.guild.id
|
||||
})
|
||||
const exportedAt = Date.now()
|
||||
if (opts.recordMesh !== false) {
|
||||
await this.deliveryReceipts.recordEmojiRegistryCsvExport({
|
||||
csvBody: signed.csv,
|
||||
signature: signed.signature,
|
||||
signatureAlg: signed.signatureAlg,
|
||||
exportedAt,
|
||||
emojiCount: entries.length
|
||||
})
|
||||
}
|
||||
return {
|
||||
format: 'csv',
|
||||
body: signed.csv,
|
||||
signature: signed.signature,
|
||||
signatureAlg: signed.signatureAlg,
|
||||
exportedAt,
|
||||
emojiCount: entries.length
|
||||
}
|
||||
}
|
||||
|
||||
async pushEmojiRegistryCsvToMesh () {
|
||||
const gid = this.guild?.guild?.id || null
|
||||
const span = this.log.time('emoji.csv', {
|
||||
spanKind: 'emoji.csv',
|
||||
guildId: gid,
|
||||
context: 'mesh.push'
|
||||
})
|
||||
try {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
|
||||
throw new Error('no permission to sync emoji registry CSV')
|
||||
}
|
||||
const exported = await this.exportEmojiRegistryCsv({ recordMesh: false })
|
||||
if (!exported.signature) throw new Error('emoji registry csv export not signed')
|
||||
const payload = {
|
||||
guildId: this.guild.guild.id,
|
||||
exportedAt: exported.exportedAt || Date.now(),
|
||||
exportedBy: this.identity.user?.id || null,
|
||||
csvBody: exported.body,
|
||||
signature: exported.signature,
|
||||
signatureAlg: exported.signatureAlg,
|
||||
emojiCount: exported.emojiCount || 0
|
||||
}
|
||||
if (this.guild.gossipEmojiRegistryCsvSync) {
|
||||
this.guild.gossipEmojiRegistryCsvSync(payload)
|
||||
}
|
||||
this.emit('emoji-registry-csv-sync', payload)
|
||||
await this.deliveryReceipts.recordEmojiRegistryCsvExport({
|
||||
csvBody: exported.body,
|
||||
signature: exported.signature,
|
||||
signatureAlg: exported.signatureAlg,
|
||||
exportedAt: exported.exportedAt,
|
||||
emojiCount: exported.emojiCount
|
||||
})
|
||||
span.end({
|
||||
guildEmojiCsvCount: exported.emojiCount || 1,
|
||||
meshPushed: true,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return exported
|
||||
} catch (err) {
|
||||
this.log.error('emoji.csv error', {
|
||||
guildId: gid,
|
||||
context: 'mesh.push',
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async clearEmojiRegistryCsvExports () {
|
||||
if (!this.guild?.guild) throw new Error('no guild')
|
||||
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
|
||||
throw new Error('no permission to clear emoji registry CSV exports')
|
||||
}
|
||||
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||
const removed = await this.deliveryReceipts.clearEmojiRegistryCsvExports()
|
||||
this.emit('emoji-registry-csv-cleared', { removed })
|
||||
return { removed }
|
||||
}
|
||||
|
||||
async getLastStickerPackExport () {
|
||||
if (!this.guild?.guild) return null
|
||||
const snap = this._lastStickerPackExport
|
||||
if (snap?.guildId === this.guild.guild.id) return snap
|
||||
if (!this.stickerRegistry) await this._initStickerRegistry(this.guild.guild.id)
|
||||
const packs = await this.stickerRegistry.listPacks().catch(() => [])
|
||||
const stickers = await this.stickerRegistry.list().catch(() => [])
|
||||
return {
|
||||
guildId: this.guild.guild.id,
|
||||
exportedAt: Date.now(),
|
||||
stickerCount: stickers.length,
|
||||
packCount: packs.length,
|
||||
signed: false,
|
||||
meshPushed: false
|
||||
}
|
||||
}
|
||||
|
||||
async exportStickerPackMesh (opts = {}) {
|
||||
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 export sticker pack mesh')
|
||||
}
|
||||
if (!this.stickerRegistry) await this._initStickerRegistry(this.guild.guild.id)
|
||||
const packs = await this.stickerRegistry.listPacks().catch(() => [])
|
||||
const stickers = await this.stickerRegistry.list().catch(() => [])
|
||||
const byPack = {}
|
||||
for (const s of stickers) {
|
||||
const p = s.packName || 'default'
|
||||
byPack[p] = (byPack[p] || 0) + 1
|
||||
}
|
||||
const entries = packs.length
|
||||
? packs.map((p) => ({
|
||||
packName: p.name,
|
||||
stickerCount: byPack[p.name] || 0,
|
||||
exportedAt: Date.now()
|
||||
}))
|
||||
: [{ packName: 'default', stickerCount: stickers.length, exportedAt: Date.now() }]
|
||||
const csvBody = buildStickerPackExportCsvBody(entries)
|
||||
const signed = signStickerPackExportCsv(csvBody, {
|
||||
guildId: this.guild.guild.id,
|
||||
relaySecret: this.guild.guild.id
|
||||
})
|
||||
const exportedAt = Date.now()
|
||||
const meta = {
|
||||
guildId: this.guild.guild.id,
|
||||
exportedAt,
|
||||
exportedBy: this.identity.user?.id || null,
|
||||
stickerCount: stickers.length,
|
||||
signed: !!signed.signature,
|
||||
meshPushed: false
|
||||
}
|
||||
this._lastStickerPackExport = meta
|
||||
if (opts.recordMesh !== false) {
|
||||
await this.deliveryReceipts.recordStickerPackExportCsv({
|
||||
csvBody: signed.csv,
|
||||
signature: signed.signature,
|
||||
signatureAlg: signed.signatureAlg,
|
||||
exportedAt,
|
||||
stickerCount: stickers.length
|
||||
})
|
||||
}
|
||||
return {
|
||||
format: 'csv',
|
||||
body: signed.csv,
|
||||
signature: signed.signature,
|
||||
signatureAlg: signed.signatureAlg,
|
||||
exportedAt,
|
||||
stickerCount: stickers.length,
|
||||
meta
|
||||
}
|
||||
}
|
||||
|
||||
async pushStickerPackExportToMesh () {
|
||||
const gid = this.guild?.guild?.id || null
|
||||
const span = this.log.time('emoji.csv', {
|
||||
spanKind: 'emoji.csv',
|
||||
guildId: gid,
|
||||
context: 'mesh.sticker'
|
||||
})
|
||||
try {
|
||||
const exported = await this.exportStickerPackMesh({ recordMesh: false })
|
||||
if (!exported.signature) throw new Error('sticker pack csv export not signed')
|
||||
const payload = {
|
||||
guildId: this.guild.guild.id,
|
||||
exportedAt: exported.exportedAt || Date.now(),
|
||||
exportedBy: this.identity.user?.id || null,
|
||||
csvBody: exported.body,
|
||||
signature: exported.signature,
|
||||
signatureAlg: exported.signatureAlg,
|
||||
emojiCount: exported.emojiCount || 0
|
||||
}
|
||||
if (this.guild.gossipStickerPackExportCsvSync) {
|
||||
this.guild.gossipStickerPackExportCsvSync(payload)
|
||||
}
|
||||
this.emit('sticker-pack-export-csv-sync', payload)
|
||||
await this.deliveryReceipts.recordStickerPackExportCsv({
|
||||
csvBody: exported.body,
|
||||
signature: exported.signature,
|
||||
signatureAlg: exported.signatureAlg,
|
||||
exportedAt: exported.exportedAt,
|
||||
emojiCount: exported.emojiCount
|
||||
})
|
||||
this._lastStickerPackExport = {
|
||||
...exported.meta,
|
||||
meshPushed: true
|
||||
}
|
||||
span.end({
|
||||
guildEmojiCsvCount: exported.emojiCount || 1 || 0,
|
||||
meshPushed: true,
|
||||
bridgeKind: 'emoji.csv'
|
||||
})
|
||||
return exported
|
||||
} catch (err) {
|
||||
this.log.error('emoji.csv error', {
|
||||
guildId: gid,
|
||||
context: 'mesh.sticker',
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async _onEmojiRegistryCsvGossip (payload) {
|
||||
if (!payload?.guildId || !payload?.csvBody || !payload?.signature) return null
|
||||
if (this.guild?.guild?.id !== payload.guildId) return null
|
||||
await this._initDeliveryReceipts(payload.guildId)
|
||||
this._shouldGossipEmojiRegistryCsv(payload)
|
||||
const row = await this.deliveryReceipts.ingestEmojiRegistryCsvSlice(payload.guildId, payload)
|
||||
if (row?.duplicate) {
|
||||
this._emojiRegistryCsvDuplicateAt = row.exportedAt || payload.exportedAt || null
|
||||
}
|
||||
if (row) this.emit('emoji-registry-csv-sync', payload)
|
||||
return row
|
||||
}
|
||||
|
||||
async _onStickerPackExportCsvGossip (payload) {
|
||||
if (!payload?.guildId || !payload?.csvBody || !payload?.signature) return null
|
||||
if (this.guild?.guild?.id !== payload.guildId) return null
|
||||
await this._initDeliveryReceipts(payload.guildId)
|
||||
this._shouldGossipStickerPackExportCsv(payload)
|
||||
const row = await this.deliveryReceipts.ingestStickerPackExportCsvSlice(
|
||||
payload.guildId,
|
||||
payload
|
||||
)
|
||||
if (row?.duplicate) {
|
||||
this._stickerPackExportCsvDuplicateAt = row.exportedAt || payload.exportedAt || null
|
||||
}
|
||||
if (row) this.emit('sticker-pack-export-csv-sync', payload)
|
||||
return row
|
||||
}
|
||||
|
||||
async getAuditExportSchedule () {
|
||||
if (!this.guild?.guild) {
|
||||
return { enabled: false, intervalHours: 24, filter: 'all', lastExportAt: 0 }
|
||||
@@ -28045,6 +28356,10 @@ class PearcordPlatform extends EventEmitter {
|
||||
let effectivePermissionExportCsvRows = []
|
||||
let lastEffectivePermissionExport = null
|
||||
let guildPermissionOverwrites = []
|
||||
let emojiRegistryCsvMeta = null
|
||||
let emojiRegistryCsvRows = []
|
||||
let stickerPackExportCsvRows = []
|
||||
let lastStickerPackExport = null
|
||||
let lastComplianceSnapshot = null
|
||||
let lastArchivePeerExport = null
|
||||
let automationScheduleDashboard = null
|
||||
@@ -28228,6 +28543,26 @@ class PearcordPlatform extends EventEmitter {
|
||||
return { ...row, signatureValid: verified.ok }
|
||||
})
|
||||
lastEffectivePermissionExport = await this.getLastEffectivePermissionExport()
|
||||
emojiRegistryCsvMeta = await this.getEmojiRegistryCsvExport().catch(() => null)
|
||||
const emojiCsvHistory = await this.deliveryReceipts.listEmojiRegistryCsvExports(32)
|
||||
emojiRegistryCsvRows = emojiCsvHistory.map((row) => {
|
||||
if (!row?.signature || !guild?.id) return row
|
||||
const verified = verifyEmojiRegistryCsv(row.csvBody, row.signature, {
|
||||
guildId: guild.id,
|
||||
relaySecret: guild.id
|
||||
})
|
||||
return { ...row, signatureValid: verified.ok }
|
||||
})
|
||||
const stickerCsvHistory = await this.deliveryReceipts.listStickerPackExportCsvExports(32)
|
||||
stickerPackExportCsvRows = stickerCsvHistory.map((row) => {
|
||||
if (!row?.signature || !guild?.id) return row
|
||||
const verified = verifyStickerPackExportCsv(row.csvBody, row.signature, {
|
||||
guildId: guild.id,
|
||||
relaySecret: guild.id
|
||||
})
|
||||
return { ...row, signatureValid: verified.ok }
|
||||
})
|
||||
lastStickerPackExport = await this.getLastStickerPackExport()
|
||||
if (this.channelPermissions) {
|
||||
await this._initChannelPermissions(guild.id)
|
||||
guildPermissionOverwrites = await this.channelPermissions.listForGuild(guild.id).catch(() => [])
|
||||
@@ -28736,6 +29071,13 @@ class PearcordPlatform extends EventEmitter {
|
||||
guildPermissionOverwrites,
|
||||
guildPermissionCsvCount:
|
||||
(roleOverrideCsvRows || []).length + (guildPermissionOverwrites || []).length,
|
||||
emojiRegistryCsvMeta,
|
||||
emojiRegistryCsvRows,
|
||||
stickerPackExportCsvRows,
|
||||
lastStickerPackExport,
|
||||
guildEmojiCsvCount:
|
||||
(emojiRegistryCsvRows || []).length +
|
||||
(this.emojiRegistry ? (await this.emojiRegistry.list().catch(() => [])).length : 0),
|
||||
automationScheduleDashboard,
|
||||
automationHealthDashboard,
|
||||
automationDigestNotifyPrefs,
|
||||
@@ -29345,6 +29687,7 @@ const { slashCsvMixin } = require('./slash-csv-mixin')
|
||||
const { oauthCsvMixin } = require('./oauth-csv-mixin')
|
||||
const { inviteCsvMixin } = require('./invite-csv-mixin')
|
||||
const { permissionCsvMixin } = require('./permission-csv-mixin')
|
||||
const { emojiCsvMixin } = require('./emoji-csv-mixin')
|
||||
Object.assign(PearcordPlatform.prototype, pollSchedulingMixin)
|
||||
Object.assign(PearcordPlatform.prototype, notificationsActivityMixin)
|
||||
Object.assign(PearcordPlatform.prototype, userSettingsMixin)
|
||||
@@ -29370,3 +29713,4 @@ Object.assign(PearcordPlatform.prototype, slashCsvMixin)
|
||||
Object.assign(PearcordPlatform.prototype, oauthCsvMixin)
|
||||
Object.assign(PearcordPlatform.prototype, inviteCsvMixin)
|
||||
Object.assign(PearcordPlatform.prototype, permissionCsvMixin)
|
||||
Object.assign(PearcordPlatform.prototype, emojiCsvMixin)
|
||||
|
||||
Reference in New Issue
Block a user