diff --git a/index.js b/index.js index b79145e..21796e9 100644 --- a/index.js +++ b/index.js @@ -19,6 +19,11 @@ const { VoiceCaptureFeed } = require('pearcord-voice-capture') const { PearcordSlashRegistry, parseSlashInvocation } = require('pearcord-commands') const { PearcordEmojiRegistry, buildEmojiSlotSnapshot } = require('pearcord-emoji') const { BotEventFanout, BOT_EVENTS } = require('pearcord-bot-events') +const { + AppEventBridge, + APP_EVENTS, + APP_EVENT_CATEGORIES +} = require('pearcord-app-events') const { INTENTS } = require('pearcord-bot-sdk') const { BotRateLimits } = require('pearcord-bot-limits') const { PearcordStepUp } = require('pearcord-step-up') @@ -210,6 +215,7 @@ class PearcordPlatform extends EventEmitter { this.channelPermissions = null this._recentSoundPlays = [] this.botEvents = null + this.appEvents = null this.discovery = null this.contacts = null this.botLimits = null @@ -1354,19 +1360,33 @@ class PearcordPlatform extends EventEmitter { guildInstance.on('guild-member-roles', (payload) => { this.guildRoles?.ingestMemberRolesGossip(payload).catch(() => {}) this.emit('guild-member-roles', payload) + this._fanoutAppEvent(APP_EVENTS.MEMBER_ROLE_UPDATE, { memberRoles: payload }).catch( + () => {} + ) }) guildInstance.on('channel-overwrite', (row) => { this.channelPermissions?.ingestOverwriteGossip(row).catch(() => {}) this.emit('channel-overwrite', row) + this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_UPDATE, { overwrite: row }).catch( + () => {} + ) }) guildInstance.on('channel-overwrite-delete', (payload) => { this.channelPermissions?.ingestOverwriteDelete(payload).catch(() => {}) this.emit('channel-overwrite-delete', payload) + this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_DELETE, { delete: payload }).catch( + () => {} + ) }) guildInstance.on('bot-event', (payload) => { this.botEvents?.ingest(payload) + this.appEvents?.bridgeFromBot(payload) this.emit('bot-event', payload) }) + guildInstance.on('app-event', (payload) => { + this.appEvents?.ingest(payload) + this.emit('app-event', payload) + }) guildInstance.on('bot-install', (bot) => { this._ingestGuildBot(bot).catch(() => {}) this.emit('bot', bot) @@ -1870,6 +1890,7 @@ class PearcordPlatform extends EventEmitter { ) this.guild.gossipMemberCustomRoles(link) this.emit('guild-member-roles', link) + await this._fanoutAppEvent(APP_EVENTS.MEMBER_ROLE_UPDATE, { memberRoles: link }) this.emit('member', await this.db.get(COLLECTIONS.MEMBERS, { guildId: this.guild.guild.id, userId @@ -2019,6 +2040,7 @@ class PearcordPlatform extends EventEmitter { this.guild.gossipChannelOverwriteUpsert(row) await this._audit('channel.overwrite', { guildId: this.guild.guild.id, targetId: chId }) this.emit('channel-overwrite', row) + await this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_UPDATE, { overwrite: row }) return row } @@ -2044,6 +2066,9 @@ class PearcordPlatform extends EventEmitter { }) } this.emit('channel-overwrite-delete', { channelId: chId, targetType, targetId }) + await this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_DELETE, { + delete: { channelId: chId, targetType, targetId } + }) return prev } @@ -2204,6 +2229,13 @@ class PearcordPlatform extends EventEmitter { }) } + async _initAppEvents (guildId) { + this.appEvents = new AppEventBridge({ + guildId, + categories: APP_EVENT_CATEGORIES.ALL + }) + } + async _fanoutBotEvent (type, data) { if (!this.botEvents || !this.guild?.guild) return null if (!this.botLimits) { @@ -2214,11 +2246,21 @@ class PearcordPlatform extends EventEmitter { if (!allowed) return null const payload = this.botEvents.createPayload(type, data) this.botEvents.deliverLocal(payload) + this.appEvents?.bridgeFromBot(payload) this.guild.gossipBotEvent(payload) this.emit('bot-event', payload) return payload } + async _fanoutAppEvent (type, data) { + if (!this.appEvents || !this.guild?.guild) return null + const payload = this.appEvents.createPayload(type, data) + this.appEvents.deliverLocal(payload) + if (this.guild.gossipAppEvent) this.guild.gossipAppEvent(payload) + this.emit('app-event', payload) + return payload + } + async _initGuildVoice (guildId) { const user = this.identity.user if (!user) return @@ -2228,6 +2270,7 @@ class PearcordPlatform extends EventEmitter { await this._initSoundboardRegistry(guildId) await this._initGuildRoles(guildId) await this._initBotEvents(guildId) + await this._initAppEvents(guildId) this.voice = new PearcordVoice({ storagePath: this.storagePath, guildId, @@ -3882,6 +3925,18 @@ class PearcordPlatform extends EventEmitter { return listener } + createAppListener (categories = APP_EVENT_CATEGORIES.ALL) { + if (!this.guild?.guild) throw new Error('no guild') + const listener = new AppEventBridge({ + guildId: this.guild.guild.id, + categories: categories ?? APP_EVENT_CATEGORIES.ALL + }) + const onRemote = (payload) => listener.ingest(payload) + this.guild.on('app-event', onRemote) + listener._unwire = () => this.guild.removeListener('app-event', onRemote) + return listener + } + async executeSlashCommand (content, opts = {}) { if (!this.slashCommands || !this.messages) throw new Error('no channel') const inv = parseSlashInvocation(content) @@ -5353,6 +5408,7 @@ class PearcordPlatform extends EventEmitter { ? await this.emojiRegistry.reactionGlyphs() : ['👍', '❤️', '😂'], botEvents: this.botEvents?.snapshot() || null, + appEvents: this.appEvents?.snapshot() || null, bots: this.guild ? (await this.db.find(COLLECTIONS.GUILD_BOTS, { guildId: this.guild.id })).map((b) => ({ ...b, diff --git a/package.json b/package.json index 6b8d6e0..1b45200 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "pearcord-activity": "file:../pearcord-activity", "pearcord-announcement-hub": "file:../pearcord-announcement-hub", "pearcord-announcements": "file:../pearcord-announcements", + "pearcord-app-events": "file:../pearcord-app-events", "pearcord-attachments": "file:../pearcord-attachments", "pearcord-automod": "file:../pearcord-automod", "pearcord-boosts": "file:../pearcord-boosts",