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.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.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).
|
**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.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.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`.
|
**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,
|
channelId: this.activeChannelId,
|
||||||
authorId: user.id
|
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
|
return row
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log.error('attachment.stage error', {
|
this.log.error('attachment.stage error', {
|
||||||
@@ -7727,7 +7733,9 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
fetchSource: source,
|
fetchSource: source,
|
||||||
guildId,
|
guildId,
|
||||||
channelId,
|
channelId,
|
||||||
byteLength: buf?.length ?? 0
|
byteLength: buf?.length ?? 0,
|
||||||
|
filename: row?.filename || null,
|
||||||
|
mimeType: row?.mimeType || null
|
||||||
})
|
})
|
||||||
return preview
|
return preview
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -7841,7 +7849,9 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
resolved: !!row,
|
resolved: !!row,
|
||||||
guildId,
|
guildId,
|
||||||
channelId,
|
channelId,
|
||||||
urlHost
|
urlHost,
|
||||||
|
hasTitle: !!(row?.title),
|
||||||
|
hasImage: !!(row?.image || row?.thumbnail)
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log.error('embed.resolve error', {
|
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._readOnly) throw new Error('read-only companion mode cannot send messages')
|
||||||
if (!this.messages) throw new Error('no channel')
|
if (!this.messages) throw new Error('no channel')
|
||||||
const msg = await this._sendPlainMessage(content, opts)
|
const msg = await this._sendPlainMessage(content, opts)
|
||||||
|
const body = String(content || '')
|
||||||
span.end({
|
span.end({
|
||||||
messageId: msg?.id,
|
messageId: msg?.id,
|
||||||
guildId,
|
guildId,
|
||||||
channelId,
|
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
|
return msg
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -10813,6 +10829,11 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
const span = this.log.time('message.edit', { messageId, guildId, channelId })
|
const span = this.log.time('message.edit', { messageId, guildId, channelId })
|
||||||
try {
|
try {
|
||||||
await this._assertCanModifyMessage(messageId, 'edit')
|
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)
|
const msg = await this.messages.edit(messageId, content)
|
||||||
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageUpdate(msg)
|
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageUpdate(msg)
|
||||||
else if (this.guild) this.guild.gossipMessageUpdate(msg)
|
else if (this.guild) this.guild.gossipMessageUpdate(msg)
|
||||||
@@ -10821,7 +10842,9 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
messageId: msg?.id,
|
messageId: msg?.id,
|
||||||
guildId,
|
guildId,
|
||||||
channelId,
|
channelId,
|
||||||
contentLength: String(content || '').length
|
contentLength: String(content || '').length,
|
||||||
|
priorLength,
|
||||||
|
edited: true
|
||||||
})
|
})
|
||||||
return msg
|
return msg
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -11285,7 +11308,11 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
|
|
||||||
async pinMessage (messageId) {
|
async pinMessage (messageId) {
|
||||||
const guildId = this.guild?.guild?.id || null
|
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 {
|
try {
|
||||||
const user = this.identity.user
|
const user = this.identity.user
|
||||||
if (!user || !this.guild?.guild) throw new Error('no guild')
|
if (!user || !this.guild?.guild) throw new Error('no guild')
|
||||||
@@ -11315,6 +11342,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
this.log.error('pin.message error', {
|
this.log.error('pin.message error', {
|
||||||
messageId,
|
messageId,
|
||||||
guildId,
|
guildId,
|
||||||
|
channelId: this.activeChannelId,
|
||||||
error: err?.message || String(err)
|
error: err?.message || String(err)
|
||||||
})
|
})
|
||||||
span.fail(err)
|
span.fail(err)
|
||||||
@@ -11324,7 +11352,11 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
|
|
||||||
async unpinMessage (messageId) {
|
async unpinMessage (messageId) {
|
||||||
const guildId = this.guild?.guild?.id || null
|
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 {
|
try {
|
||||||
const roles = await this._memberRoles()
|
const roles = await this._memberRoles()
|
||||||
if (!roleHasPermission(roles, PERMISSION.MANAGE_MESSAGES)) {
|
if (!roleHasPermission(roles, PERMISSION.MANAGE_MESSAGES)) {
|
||||||
@@ -11341,6 +11373,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
this.log.error('pin.unpin error', {
|
this.log.error('pin.unpin error', {
|
||||||
messageId,
|
messageId,
|
||||||
guildId,
|
guildId,
|
||||||
|
channelId: this.activeChannelId,
|
||||||
error: err?.message || String(err)
|
error: err?.message || String(err)
|
||||||
})
|
})
|
||||||
span.fail(err)
|
span.fail(err)
|
||||||
@@ -11446,12 +11479,19 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
const result = await this.messages.toggleReaction(messageId, emoji, user.id)
|
const result = await this.messages.toggleReaction(messageId, emoji, user.id)
|
||||||
if (this.mode !== 'dm' && this.guild) this.guild.gossipReaction(result)
|
if (this.mode !== 'dm' && this.guild) this.guild.gossipReaction(result)
|
||||||
this.emit('reaction', 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({
|
span.end({
|
||||||
messageId,
|
messageId,
|
||||||
emoji: String(emoji || '').slice(0, 16),
|
emoji: emojiKey,
|
||||||
|
emojiLength: emojiKey.length,
|
||||||
guildId,
|
guildId,
|
||||||
channelId,
|
channelId,
|
||||||
removed: result?.removed === true
|
removed: result?.removed === true,
|
||||||
|
reactionCount
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -11489,6 +11529,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
const span = this.log.time('message.delete', { messageId, guildId, channelId })
|
const span = this.log.time('message.delete', { messageId, guildId, channelId })
|
||||||
try {
|
try {
|
||||||
await this._assertCanModifyMessage(messageId, 'delete')
|
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)
|
await this.messages.remove(messageId)
|
||||||
const payload = {
|
const payload = {
|
||||||
id: messageId,
|
id: messageId,
|
||||||
@@ -11498,7 +11544,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageDelete(payload)
|
if (this.mode === 'dm' && this.dm) this.dm.gossipMessageDelete(payload)
|
||||||
else if (this.guild) this.guild.gossipMessageDelete(payload)
|
else if (this.guild) this.guild.gossipMessageDelete(payload)
|
||||||
this.emit('message-delete', payload)
|
this.emit('message-delete', payload)
|
||||||
span.end({ messageId, guildId, channelId })
|
span.end({ messageId, guildId, channelId, contentLength, hadAttachments })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log.error('message.delete error', {
|
this.log.error('message.delete error', {
|
||||||
messageId,
|
messageId,
|
||||||
|
|||||||
Reference in New Issue
Block a user