Skip to content

Normalized message - #9

Merged
lao merged 22 commits into
mainfrom
worktree-normalized-message
Jun 27, 2026
Merged

Normalized message#9
lao merged 22 commits into
mainfrom
worktree-normalized-message

Conversation

@lao

@lao lao commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added platform-agnostic message fields such as timestamps, reply references, and mentioned users for better consistency across bots.
    • Added access to raw platform data and platform-specific clients when normalized fields aren’t enough.
  • Bug Fixes

    • Improved message conversion across Discord, Slack, Telegram, and CLI so more message details are preserved reliably.
    • Fixed attachment handling and mention parsing in several platforms.
  • Documentation

    • Updated docs and examples to show the new message fields and raw access patterns.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4ecf5ebd-eb79-4294-a9f0-c908b98889fc

📥 Commits

Reviewing files that changed from the base of the PR and between f96f3c0 and e7519d0.

📒 Files selected for processing (17)
  • .gitignore
  • CLAUDE.md
  • README.md
  • botbooter.go
  • botbooter_test.go
  • examples/v1/main.go
  • internal/cli/cli.go
  • internal/cli/cli_test.go
  • internal/core/core.go
  • internal/core/core_test.go
  • internal/core/imports_test.go
  • internal/discord/discord.go
  • internal/discord/discord_test.go
  • internal/slack/slack.go
  • internal/slack/slack_test.go
  • internal/telegram/telegram.go
  • internal/telegram/telegram_test.go

📝 Walkthrough

Walkthrough

The PR normalizes message data into core.Message.Raw plus shared fields, moves Discord, Slack, Telegram, and CLI adapters to adapter-backed raw/client accessors, and updates the facade, docs, tests, and example logging to use the new access path.

Changes

Raw payload normalization and facade accessors

Layer / File(s) Summary
Normalized message contract
internal/core/core.go, internal/core/core_test.go, internal/core/imports_test.go
Message now uses normalized fields and Raw any; Bot keeps an adapter; AdapterAs[T] is added and covered by tests and the core import check.
Discord adapter mapping
internal/discord/discord.go, internal/discord/discord_test.go, botbooter_test.go
Discord messages now dispatch through toMessage, store the raw event in Raw, read attachments from Raw, expose Session/RawEvent, and update attachment tests to use Raw.
Slack adapter mapping
internal/slack/slack.go, internal/slack/slack_test.go, botbooter_test.go
Slack messages now dispatch through toMessage, parse timestamps and mentions, read attachments from Raw, expose client/session/raw helpers, and update attachment tests to use Raw.
Telegram adapter mapping
internal/telegram/telegram.go, internal/telegram/telegram_test.go
Telegram messages now dispatch through toMessage, store the raw update in Raw, read attachments from Raw, expose Client/RawUpdate, and extend message and mention tests.
CLI raw payload handling
internal/cli/cli.go, internal/cli/cli_test.go
CLI dispatch now stores parsed input in Raw; Attachments and RawData read the raw CLI message through a type assertion, and the new accessor is tested.
Facade accessors and docs
botbooter.go, botbooter_test.go, README.md, CLAUDE.md, examples/v1/main.go
Facade helpers re-export raw-event and client/session accessors, the tests call those accessors, and the README, CLAUDE.md, and example log the normalized fields and raw access path.

Sequence Diagram(s)

sequenceDiagram
  participant "botbooter.DiscordRawEvent" as DR
  participant "internal.discord.RawEvent" as IR
  participant "botbooter.DiscordSession" as DS
  participant "core.AdapterAs[T]" as AA
  participant "internal.discord.Session" as IS

  DR->>IR: inspect m.Raw
  IR-->>DR: *discordgo.MessageCreate, ok
  DS->>AA: recover adapter from *core.Bot
  AA-->>DS: concrete adapter, ok
  DS->>IS: return session or nil
  IS-->>DS: *discordgo.Session
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • lao/botbooter#2: Both PRs work in the same facade/internal split and adapter-based access path around botbooter.go and internal/core.
  • lao/botbooter#6: Both PRs touch the Telegram adapter and the shared message-shape changes that move platform data into Raw.

Poem

Hop, I ferried the Raw payload home,
with timestamps tucked in a carrot-patch dome.
Discord, Slack, Telegram, and CLI all hum,
while AdapterAs[T] twitches like a drum.
The bot burrows deep, and the docs go yum. 🐰

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-normalized-message

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

lao added 6 commits June 26, 2026 22:53
Move the per-message field and attachment logging out of echoHandler and
into loggingMiddleware so it runs for every message, not only those matching
"^echo ". Media-only uploads (Slack file shares, captionless Telegram photos)
arrive with empty Content and never reached the command handler, so their
attachments were never logged. Also print Attachment.ExtraData (Telegram
delivers media by FileID, leaving URL empty) and log a startup line naming
the bot type.
- delegate each adapter's Attachments to its Raw accessor, so the typed
  accessor is the single place that knows Raw's concrete type
- rename Message.Mentions -> MentionedUserIDs, matching the *ID sibling
  fields and making the slice's contents self-evident at the use site
- fix Slack IsImage prefix "image" -> "image/" to match telegram/cli and
  avoid matching non-image MIME types
- use cmp.Or for the telegram text/caption fallback
- document Slack's ts reuse as ID and thread/reply key in toMessage
@lao
lao marked this pull request as ready for review June 27, 2026 07:06
@lao
lao merged commit cf03f6e into main Jun 27, 2026
2 checks passed
@lao
lao deleted the worktree-normalized-message branch June 27, 2026 07:41
lao added a commit that referenced this pull request Jun 27, 2026
Adopt main's normalized-message refactor (PR #9) in the WhatsApp adapter and
keep both the Telegram and WhatsApp additions across core, the facade and the
v1 example.

- migrate off the removed core.Message *Data fields to Raw + a
  whatsapp.RawMessage accessor, re-exported as botbooter.WhatsAppRawEvent
- populate ID, Timestamp and AuthorName (contacts-correlated) on inbound
  messages; carry them on core.WhatsAppMessage
- re-export whatsapp.ErrMissingConfig as botbooter.ErrMissingWhatsAppConfig
- cap the Send error-body read, set text/plain on the verify handshake, and
  guard Attachments against a typed-nil Raw
- document WhatsApp in README and docs/platforms.md; add adapter, facade and
  String() tests

make all and make test-race green.
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