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:
parent
69a67704f4
commit
7b56cb34c6
9 changed files with 1119 additions and 41 deletions
|
@ -14,6 +14,11 @@ import (
|
|||
"github.com/mattermost/mattermost/server/public/plugin"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultMessageBufferSize is the buffer size for incoming message channels
|
||||
defaultMessageBufferSize = 1000
|
||||
)
|
||||
|
||||
// mattermostBridge handles syncing messages between Mattermost instances
|
||||
type mattermostBridge struct {
|
||||
logger logger.Logger
|
||||
|
@ -21,6 +26,11 @@ type mattermostBridge struct {
|
|||
kvstore kvstore.KVStore
|
||||
userManager pluginModel.BridgeUserManager
|
||||
|
||||
// Message handling
|
||||
messageHandler *mattermostMessageHandler
|
||||
userResolver *mattermostUserResolver
|
||||
incomingMessages chan *pluginModel.DirectionalMessage
|
||||
|
||||
// Connection management
|
||||
connected atomic.Bool
|
||||
ctx context.Context
|
||||
|
@ -38,18 +48,23 @@ type mattermostBridge struct {
|
|||
// NewBridge creates a new Mattermost bridge
|
||||
func NewBridge(log logger.Logger, api plugin.API, kvstore kvstore.KVStore, cfg *config.Configuration) pluginModel.Bridge {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
bridge := &mattermostBridge{
|
||||
logger: log,
|
||||
api: api,
|
||||
kvstore: kvstore,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
channelMappings: make(map[string]string),
|
||||
config: cfg,
|
||||
userManager: bridge.NewUserManager("mattermost", log),
|
||||
b := &mattermostBridge{
|
||||
logger: log,
|
||||
api: api,
|
||||
kvstore: kvstore,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
channelMappings: make(map[string]string),
|
||||
config: cfg,
|
||||
userManager: bridge.NewUserManager("mattermost", log),
|
||||
incomingMessages: make(chan *pluginModel.DirectionalMessage, defaultMessageBufferSize),
|
||||
}
|
||||
|
||||
return bridge
|
||||
// Initialize handlers after bridge is created
|
||||
b.messageHandler = newMessageHandler(b)
|
||||
b.userResolver = newUserResolver(b)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// getConfiguration safely retrieves the current configuration
|
||||
|
@ -343,3 +358,23 @@ func (b *mattermostBridge) GetRoomMapping(roomID string) (string, error) {
|
|||
func (b *mattermostBridge) GetUserManager() pluginModel.BridgeUserManager {
|
||||
return b.userManager
|
||||
}
|
||||
|
||||
// GetMessageChannel returns the channel for incoming messages from Mattermost
|
||||
func (b *mattermostBridge) GetMessageChannel() <-chan *pluginModel.DirectionalMessage {
|
||||
return b.incomingMessages
|
||||
}
|
||||
|
||||
// SendMessage sends a message to a Mattermost channel
|
||||
func (b *mattermostBridge) SendMessage(msg *pluginModel.BridgeMessage) error {
|
||||
return b.messageHandler.postMessageToMattermost(msg)
|
||||
}
|
||||
|
||||
// GetMessageHandler returns the message handler for this bridge
|
||||
func (b *mattermostBridge) GetMessageHandler() pluginModel.MessageHandler {
|
||||
return b.messageHandler
|
||||
}
|
||||
|
||||
// GetUserResolver returns the user resolver for this bridge
|
||||
func (b *mattermostBridge) GetUserResolver() pluginModel.UserResolver {
|
||||
return b.userResolver
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue