feat(channels): add Mattermost channel support#1288
feat(channels): add Mattermost channel support#1288lmorchard wants to merge 1 commit intosipeed:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Mattermost chat channel to PicoClaw, integrating with Mattermost’s WebSocket API v4 (inbound events) and REST API v4 (sending messages, editing posts, typing indicators, and file uploads), plus associated configuration and documentation updates.
Changes:
- Introduces
pkg/channels/mattermostwith WS receive loop, REST send/edit/upload, and unit tests. - Extends configuration (
MattermostConfig+ defaults) and wires channel registration/initialization. - Updates README and adds Chinese setup documentation for the new channel.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/config/defaults.go | Adds default values for channels.mattermost config. |
| pkg/config/config.go | Adds MattermostConfig and integrates it into ChannelsConfig. |
| pkg/channels/mattermost/mattermost.go | Implements Mattermost channel (WS receive, REST send/edit/upload, typing, placeholder). |
| pkg/channels/mattermost/mattermost_test.go | Adds unit tests for config validation and helper functions. |
| pkg/channels/mattermost/init.go | Registers the Mattermost channel factory. |
| pkg/channels/manager.go | Enables Mattermost channel initialization based on config. |
| cmd/picoclaw/internal/gateway/helpers.go | Ensures the Mattermost channel package is imported for registration. |
| README.md | Adds Mattermost to supported chat apps list and setup guide. |
| docs/channels/mattermost/README.zh.md | Adds Chinese documentation for Mattermost channel setup/config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
60f13ce to
373db05
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
373db05 to
fff773a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
fff773a to
55dc987
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
55dc987 to
76137ba
Compare
76137ba to
3d19097
Compare
23f5351 to
560df1a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
560df1a to
e54385e
Compare
|
|
e54385e to
b68efbd
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b68efbd to
e45c73c
Compare
e45c73c to
b43efcb
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
b43efcb to
b148285
Compare
|
|
||
| // "D" = direct message, "G" = group direct message; both bypass group-trigger | ||
| // filtering and threading, matching the intended "DMs stay flat" behavior. | ||
| isDM := d.ChannelType == "D" || d.ChannelType == "G" |
There was a problem hiding this comment.
Why set group direct messages as direct messages as well? What is the purpose behind this design?
There was a problem hiding this comment.
As far as I can tell, this is how other channels handle this too - group DMs are the same as single-user DMs with regard to when threading and addressing are used. But, I think that's because Slack & Discord don't distinguish between types of DMs
https://github.com/sipeed/picoclaw/blob/main/pkg/channels/slack/slack.go#L313-L314
https://github.com/sipeed/picoclaw/blob/main/pkg/channels/discord/discord.go#L347-L349
But, since Mattermost does distinguish between single-user DM and group DM - we could treat a group DM as an ad-hoc channel and switch over to threading and requiring addressing there. Would just be inconsistent with other channels
There was a problem hiding this comment.
I see~ Thank you for your answer~
b148285 to
f5a307a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Add Mattermost channel using WebSocket API v4 for receiving events and REST API v4 for sending. No external SDK — uses gorilla/websocket (existing dependency) and net/http. Features: - Thread-aware replies: channel messages auto-thread, DMs stay flat - Auto-reconnect with exponential backoff (5s-60s) - Message splitting at 4000 chars via channels.SplitMessage - Bot @mention stripping via configurable username field - Proper error classification using ClassifySendError/ClassifyNetError - MediaSender: file uploads via /api/v4/files - TypingCapable: typing indicator support - MessageEditor: edit existing posts - PlaceholderCapable: "Thinking..." placeholder that gets edited Config: channels.mattermost.enabled: bool channels.mattermost.url: server URL channels.mattermost.token: bot access token channels.mattermost.username: bot username for mention stripping channels.mattermost.reply_in_thread: auto-thread in channels (default true) channels.mattermost.allow_from: user ID allowlist channels.mattermost.group_trigger: group chat trigger config Includes: - Unit tests (TestNewMattermostChannel, TestParseChatID, TestBuildWSURL, TestStripBotMention) - README.md updates (chat apps table, collapsible setup guide) - Chinese docs at docs/channels/mattermost/README.zh.md (AI-generated, may need native speaker review) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f5a307a to
103c9b4
Compare
|
@lmorchard Hi! This PR has had no activity for over 2 weeks, so I'm closing it for now to keep things tidy. If it's still relevant, feel free to reopen it anytime and we'll pick it back up. |
📝 Description
Add Mattermost channel using WebSocket API v4 for receiving events and REST API v4 for sending. No external SDK — uses gorilla/websocket (existing dependency) and net/http.
Features:
Config:
channels.mattermost.enabled: boolchannels.mattermost.url: server URLchannels.mattermost.token: bot access tokenchannels.mattermost.username: bot username for mention strippingchannels.mattermost.reply_in_thread: auto-thread in channels (default true)channels.mattermost.allow_from: user ID allowlistchannels.mattermost.group_trigger: group chat trigger configIncludes:
🗣️ Type of Change
🤖 AI Code Generation
🔗 Related Issue
📚 Technical Context (Skip for Docs)
🧪 Test Environment
☑️ Checklist
make checkpasses locally.