Skip to content

fix(messages): extract text from legacy attachments/blocks when content is empty - #18

Open
nulligence wants to merge 1 commit into
Nullify-Platform:mainfrom
nulligence:fix/slack-cli-attachments-content
Open

nulligence wants to merge 1 commit into
Nullify-Platform:mainfrom
nulligence:fix/slack-cli-attachments-content

Conversation

@nulligence

@nulligence nulligence commented Sep 11, 2026 •

Copy link
Copy Markdown

Problem

`slack-cli message list`/`message get` return an empty `content`/`text` field for any message whose body lives entirely in a legacy Slack `attachments` block (or top-level Block Kit `blocks`) rather than the plain `text` field. `parseRawMessage` in `internal/slack/messages.go` only ever read `raw["text"]`.

This is common traffic for exactly the channels you'd most want reliable visibility into: Grafana-style alerting bots and other integrations that post via legacy `attachments` (e.g. a "critical-alerts-prod" style channel) consistently came back with a stub or empty body, forcing a manual `curl` against `conversations.history` to recover the actual alert text every time. The same empty-content symptom also showed up on an unrelated bot/integration whose real content lived in `attachments[0].blocks[]` rather than the legacy attachment fields at all, confirming this isn't integration-specific — it's any bot that doesn't populate plain `text`.

Fix

`parseRawMessage` now falls back to extracting human-readable text when `text` is empty:

  1. From legacy `attachments` — `title`, `pretext`, `text`/`fallback`, `fields[].title`/`.value`, `footer`, and (since some integrations attach Block Kit content instead of the legacy fields) any nested `attachments[].blocks[]`.
  2. From top-level Block Kit `blocks` — `text.text`, `fields[].text`, and recursively through `elements` (context/rich-text blocks).

Messages that already have a plain `text` field are completely unaffected — the fallback only runs when `text` is empty, so normal user/bot messages behave exactly as before.

Added unit tests in `internal/slack/messages_test.go` covering: plain-text messages (unaffected), legacy-attachment-only messages, attachment-with-only-`fallback`, an attachment carrying nested `blocks` instead of legacy fields, and top-level-`blocks`-only messages.

Test plan

  • `go build ./...`
  • `go test ./...` (all packages pass, including new `internal/slack` tests)
  • `gofmt` clean on touched files

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…is empty

Bot integrations that post via legacy Slack "attachments" or top-level
Block Kit "blocks" (Grafana alerts, threat-investigation bots, etc.)
often never populate the plain "text" field. parseRawMessage only ever
read raw["text"], so message list/get returned an empty content string
for these posts even though the full alert/body was present in
attachments[].text/.fallback/.title/.fields or blocks[].text.text —
forcing a manual curl fallback against conversations.history to recover
the content.

Fall back to extracting human-readable text from attachments (including
attachments that carry nested Block Kit content instead of legacy
fields) and then from top-level blocks, only when "text" is empty, so
normal messages are unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant