feat(platform): extend messaging span metadata for Phase 477
Add hasMention/isSlash on message.send, priorLength on message.edit, hadAttachments on message.delete, emojiLength on reaction.toggle, and channelId on pin.message/pin.unpin span start for richer diagnostics. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -39,6 +39,10 @@ Expose a single `EventEmitter` API the UI drives over IPC (`apps/pearcord/index.
|
||||
|
||||
**v0.8.430 (Phase 467):** `voice.leave` span `end` includes `leavingIsStage`; `screen.start` span `end` includes `label`. Bundle: `npm run test:phase467-voice-stage`. See [VOICE.md](../../docs/VOICE.md), [STAGE_CHANNELS.md](../../docs/STAGE_CHANNELS.md).
|
||||
|
||||
**v0.8.440 (Phase 477):** `message.send` `hasMention`/`isSlash`; `message.edit` `priorLength`; `message.delete` `hadAttachments`; `reaction.toggle` `emojiLength`; `pin.message`/`pin.unpin` span start `channelId`. UI `syncMessagingPanelsDuringGuildLoading`. Bundle: `npm run test:phase477-messaging`. See [MESSAGING.md](../../docs/MESSAGING.md), [REACTIONS.md](../../docs/REACTIONS.md).
|
||||
|
||||
**v0.8.439 (Phase 476):** `attachment.stage` span.end adds `mimeType`; `attachment.read` adds `filename`/`mimeType`; `embed.resolve` adds `hasTitle`/`hasImage`. UI `syncAttachmentsPanelsDuringGuildLoading`. Bundle: `npm run test:phase476-attachments-embeds`. See [ATTACHMENTS.md](../../docs/ATTACHMENTS.md), [EMBEDS.md](../../docs/EMBEDS.md).
|
||||
|
||||
**v0.8.429 (Phase 466):** `attachment.read` span.end includes `byteLength`; `embed.resolve` includes `urlHost`. Bundle: `npm run test:phase466-attachments-embeds`. See [ATTACHMENTS.md](../../docs/ATTACHMENTS.md), [EMBEDS.md](../../docs/EMBEDS.md).
|
||||
|
||||
**v0.8.428 (Phase 465):** `message.send`/`message.edit` span.end includes `contentLength`; `reaction.toggle` includes `removed`. Bundle: `npm run test:phase465-messaging-reactions`. See [MESSAGING.md](../../docs/MESSAGING.md), [REACTIONS.md](../../docs/REACTIONS.md).
|
||||
@@ -188,6 +192,8 @@ Primary consumer: `apps/pearcord/index.js` sidecar reading pear-pipe JSON.
|
||||
|
||||
**v0.8.436 (Phase 473):** `role.create`/`role.update` span.end adds `hasColor` and `permissionMask`; `permission.overwrite` adds `allowBits`/`denyBits`; `permission.overwrite.delete` adds `deleted`. UI `syncRolesPanelsDuringGuildLoading` + composer roles hint. Smokes: `test:platform-role-span-metadata-extend`, `test:platform-permission-span-metadata-extend`. Bundle: `test:phase473-roles-permissions`.
|
||||
|
||||
**v0.8.439 (Phase 476):** `attachment.stage`/`attachment.read`/`embed.resolve` span.end metadata extend (`mimeType`, `filename`, `hasTitle`, `hasImage`). UI `syncAttachmentsPanelsDuringGuildLoading`. Smokes: `test:platform-attachment-span-metadata-extend`, `test:platform-embed-span-metadata-extend`. Bundle: `test:phase476-attachments-embeds`.
|
||||
|
||||
**v0.8.438 (Phase 475):** `slash.invoke` span.end adds `argCount`/`ephemeral`/`builtin`; `bot.install` adds `botName`/`permissionMask`; `bot.message` adds `contentLength`/`botId`. UI `syncSlashBotsPanelsDuringGuildLoading` + `ensureComposerContextHints` + `#composer-slash-hint`. IPC `bot-installed`/`slash-invoked`. Bundle: `test:phase475-slash-bots`.
|
||||
|
||||
**v0.8.437 (Phase 474):** `webhook.create` span.end adds `webhookName`/`channelId`; `webhook.delete` adds `deleted`; `webhook.execute` adds `contentLength`/`hasUsername`; `slash.register` adds `firstName`. UI `syncWebhooksPanelsDuringGuildLoading` + composer webhooks hint. Smokes: `test:platform-webhook-span-metadata-extend`, `test:platform-slash-span-metadata-extend`. Bundle: `test:phase474-webhooks-integrations`.
|
||||
|
||||
@@ -5006,7 +5006,13 @@ class PearcordPlatform extends EventEmitter {
|
||||
channelId: this.activeChannelId,
|
||||
authorId: user.id
|
||||
})
|
||||
span.end({ attachmentId: row?.id, size: row?.size, guildId, channelId })
|
||||
span.end({
|
||||
attachmentId: row?.id,
|
||||
size: row?.size,
|
||||
guildId,
|
||||
channelId,
|
||||
mimeType: row?.mimeType || mimeType || null
|
||||
})
|
||||
return row
|
||||
} catch (err) {
|
||||
this.log.error('attachment.stage error', {
|
||||
@@ -7727,7 +7733,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
fetchSource: source,
|
||||
guildId,
|
||||
channelId,
|
||||
byteLength: buf?.length ?? 0
|
||||
byteLength: buf?.length ?? 0,
|
||||
filename: row?.filename || null,
|
||||
mimeType: row?.mimeType || null
|
||||
})
|
||||
return preview
|
||||
} catch (err) {
|
||||
@@ -7841,7 +7849,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
resolved: !!row,
|
||||
guildId,
|
||||
channelId,
|
||||
urlHost
|
||||
urlHost,
|
||||
hasTitle: !!(row?.title),
|
||||
hasImage: !!(row?.image || row?.thumbnail)
|
||||
})
|
||||
} catch (err) {
|
||||
this.log.error('embed.resolve error', {
|
||||
@@ -10671,11 +10681,17 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (this._readOnly) throw new Error('read-only companion mode cannot send messages')
|
||||
if (!this.messages) throw new Error('no channel')
|
||||
const msg = await this._sendPlainMessage(content, opts)
|
||||
const body = String(content || '')
|
||||
span.end({
|
||||
messageId: msg?.id,
|
||||
guildId,
|
||||
channelId,
|
||||
contentLength: String(content || '').length
|
||||
contentLength: body.length,
|
||||
hasReply: !!opts.replyToId,
|
||||
hasMention: /(?:<@[^>]+>|@\w)/.test(body),
|
||||
isSlash: body.trimStart().startsWith('/'),
|
||||
attachmentCount: (opts.attachmentIds || []).length,
|
||||
stickerCount: (opts.stickerNames || []).length
|
||||
})
|
||||
return msg
|
||||
} catch (err) {
|
||||
@@ -10813,6 +10829,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
const span = this.log.time('message.edit', { messageId, guildId, channelId })
|
||||
try {
|
||||
await this._assertCanModifyMessage(messageId, 'edit')
|
||||
const prior = await this.db.get(COLLECTIONS.MESSAGES, {
|
||||
channelId,
|
||||
id: messageId
|
||||
})
|
||||
const priorLength = String(prior?.content || '').length
|
||||
const msg = await this.messages.edit(messageId, content)
|
||||
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageUpdate(msg)
|
||||
else if (this.guild) this.guild.gossipMessageUpdate(msg)
|
||||
@@ -10821,7 +10842,9 @@ class PearcordPlatform extends EventEmitter {
|
||||
messageId: msg?.id,
|
||||
guildId,
|
||||
channelId,
|
||||
contentLength: String(content || '').length
|
||||
contentLength: String(content || '').length,
|
||||
priorLength,
|
||||
edited: true
|
||||
})
|
||||
return msg
|
||||
} catch (err) {
|
||||
@@ -11285,7 +11308,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
|
||||
async pinMessage (messageId) {
|
||||
const guildId = this.guild?.guild?.id || null
|
||||
const span = this.log.time('pin.message', { messageId, guildId })
|
||||
const span = this.log.time('pin.message', {
|
||||
messageId,
|
||||
guildId,
|
||||
channelId: this.activeChannelId
|
||||
})
|
||||
try {
|
||||
const user = this.identity.user
|
||||
if (!user || !this.guild?.guild) throw new Error('no guild')
|
||||
@@ -11315,6 +11342,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
this.log.error('pin.message error', {
|
||||
messageId,
|
||||
guildId,
|
||||
channelId: this.activeChannelId,
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
@@ -11324,7 +11352,11 @@ class PearcordPlatform extends EventEmitter {
|
||||
|
||||
async unpinMessage (messageId) {
|
||||
const guildId = this.guild?.guild?.id || null
|
||||
const span = this.log.time('pin.unpin', { messageId, guildId })
|
||||
const span = this.log.time('pin.unpin', {
|
||||
messageId,
|
||||
guildId,
|
||||
channelId: this.activeChannelId
|
||||
})
|
||||
try {
|
||||
const roles = await this._memberRoles()
|
||||
if (!roleHasPermission(roles, PERMISSION.MANAGE_MESSAGES)) {
|
||||
@@ -11341,6 +11373,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
this.log.error('pin.unpin error', {
|
||||
messageId,
|
||||
guildId,
|
||||
channelId: this.activeChannelId,
|
||||
error: err?.message || String(err)
|
||||
})
|
||||
span.fail(err)
|
||||
@@ -11446,12 +11479,19 @@ class PearcordPlatform extends EventEmitter {
|
||||
const result = await this.messages.toggleReaction(messageId, emoji, user.id)
|
||||
if (this.mode !== 'dm' && this.guild) this.guild.gossipReaction(result)
|
||||
this.emit('reaction', result)
|
||||
const emojiKey = String(emoji || '').slice(0, 16)
|
||||
const reactionRows = await this.messages.listReactions()
|
||||
const reactionCount = reactionRows.filter(
|
||||
(r) => r.messageId === messageId && r.emoji === emojiKey
|
||||
).length
|
||||
span.end({
|
||||
messageId,
|
||||
emoji: String(emoji || '').slice(0, 16),
|
||||
emoji: emojiKey,
|
||||
emojiLength: emojiKey.length,
|
||||
guildId,
|
||||
channelId,
|
||||
removed: result?.removed === true
|
||||
removed: result?.removed === true,
|
||||
reactionCount
|
||||
})
|
||||
return result
|
||||
} catch (err) {
|
||||
@@ -11489,6 +11529,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
const span = this.log.time('message.delete', { messageId, guildId, channelId })
|
||||
try {
|
||||
await this._assertCanModifyMessage(messageId, 'delete')
|
||||
const existing = await this.db.get(COLLECTIONS.MESSAGES, {
|
||||
channelId,
|
||||
id: messageId
|
||||
})
|
||||
const contentLength = String(existing?.content || '').length
|
||||
const hadAttachments = !!(existing?.attachmentIds?.length || existing?.attachments?.length)
|
||||
await this.messages.remove(messageId)
|
||||
const payload = {
|
||||
id: messageId,
|
||||
@@ -11498,7 +11544,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageDelete(payload)
|
||||
else if (this.guild) this.guild.gossipMessageDelete(payload)
|
||||
this.emit('message-delete', payload)
|
||||
span.end({ messageId, guildId, channelId })
|
||||
span.end({ messageId, guildId, channelId, contentLength, hadAttachments })
|
||||
} catch (err) {
|
||||
this.log.error('message.delete error', {
|
||||
messageId,
|
||||
|
||||
Reference in New Issue
Block a user