feat: implement bidirectional message bridge system with XMPP-Mattermost integration

This commit implements a comprehensive bridge-agnostic message routing system that enables
real-time bidirectional message synchronization between XMPP and Mattermost platforms.

Key features:
- Bridge-agnostic message types and structures for extensibility
- Central message bus system with publisher-subscriber pattern
- Complete Bridge interface implementation for both XMPP and Mattermost
- Message aggregation from multiple sources for scalability
- Loop prevention mechanisms to avoid infinite message cycles
- Buffered channels for high-performance message processing

Architecture highlights:
- Producer-consumer pattern for message routing between bridges
- Thread-safe goroutine lifecycle management with context cancellation
- Message handlers separated into dedicated files for maintainability
- Support for future bridge implementations (Slack, Discord, etc.)
- Markdown content standardization across all bridges

Files added:
- server/model/message.go: Core bridge-agnostic message structures
- server/bridge/messagebus.go: Central message routing system
- server/bridge/mattermost/message_handler.go: Mattermost-specific message processing
- server/bridge/xmpp/message_handler.go: XMPP-specific message processing

Files modified:
- server/bridge/manager.go: Integration with message bus and routing
- server/bridge/mattermost/bridge.go: Complete Bridge interface implementation
- server/bridge/xmpp/bridge.go: Message aggregation and interface completion
- server/model/bridge.go: Extended Bridge interface for bidirectional messaging
- server/xmpp/client.go: Enhanced message listening with mellium.im/xmpp

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Felipe M 2025-08-04 21:52:28 +02:00
parent 69a67704f4
commit 7b56cb34c6
No known key found for this signature in database
GPG key ID: 52E5D65FCF99808A
9 changed files with 1119 additions and 41 deletions

88
server/model/message.go Normal file
View file

@ -0,0 +1,88 @@
package model
import (
"time"
)
// MessageDirection indicates the direction of message flow
type MessageDirection string
const (
DirectionIncoming MessageDirection = "incoming" // From external system to us
DirectionOutgoing MessageDirection = "outgoing" // From us to external system
)
// BridgeMessage represents a message that can be passed between any bridge types
type BridgeMessage struct {
// Source information
SourceBridge string // "xmpp", "mattermost", "slack", etc.
SourceChannelID string // Channel ID in source system
SourceUserID string // User ID in source system (JID, user ID, etc.)
SourceUserName string // Display name in source system
// Message content (standardized on Markdown)
Content string // Markdown formatted message content
MessageType string // "text", "image", "file", etc.
// Metadata
Timestamp time.Time // When message was received
MessageID string // Unique message ID from source
ThreadID string // Thread/reply ID (if applicable)
// Routing hints
TargetBridges []string // Which bridges should receive this
Metadata map[string]any // Bridge-specific metadata
}
// DirectionalMessage wraps a BridgeMessage with direction information
type DirectionalMessage struct {
*BridgeMessage
Direction MessageDirection
}
// ExternalUser represents a user from any bridge system
type ExternalUser struct {
BridgeType string // "xmpp", "slack", etc.
ExternalUserID string // JID, Slack user ID, etc.
DisplayName string // How to display this user
MattermostUserID string // Mapped Mattermost user (if exists)
}
// UserResolver handles user resolution for a specific bridge
type UserResolver interface {
// ResolveUser converts an external user ID to an ExternalUser
ResolveUser(externalUserID string) (*ExternalUser, error)
// FormatUserMention formats a user mention for Markdown content
FormatUserMention(user *ExternalUser) string
// GetDisplayName extracts display name from external user ID
GetDisplayName(externalUserID string) string
}
// MessageBus handles routing messages between bridges
type MessageBus interface {
// Subscribe returns a channel that receives messages for the specified bridge
Subscribe(bridgeName string) <-chan *DirectionalMessage
// Publish sends a message to the message bus for routing
Publish(msg *DirectionalMessage) error
// Start begins message routing
Start() error
// Stop ends message routing and cleans up resources
Stop() error
}
// MessageHandler processes incoming messages for a bridge
type MessageHandler interface {
// ProcessMessage handles an incoming message
ProcessMessage(msg *DirectionalMessage) error
// CanHandleMessage determines if this handler can process the message
CanHandleMessage(msg *BridgeMessage) bool
// GetSupportedMessageTypes returns the message types this handler supports
GetSupportedMessageTypes() []string
}