feat: implement production-ready MUC operations and comprehensive testing
- Implement proper XMPP MUC operations using mellium.im/xmpp/muc package - Add session readiness checking to prevent blocking on room joins - Create comprehensive bridge manager architecture with lifecycle management - Add complete channel mapping functionality with KV store persistence - Remove defensive logger nil checks as requested by user - Enhance XMPP client doctor with MUC testing (join/wait/leave workflow) - Add detailed dev server documentation for test room creation - Implement timeout protection for all MUC operations - Add proper error handling with fmt.Errorf instead of pkg/errors - Successfully tested: MUC join in ~21ms, 5s wait, clean leave operation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4d6929bab6
commit
d159c668c2
11 changed files with 1048 additions and 553 deletions
|
@ -10,8 +10,8 @@ import (
|
|||
)
|
||||
|
||||
type Handler struct {
|
||||
client *pluginapi.Client
|
||||
bridge pluginModel.Bridge
|
||||
client *pluginapi.Client
|
||||
bridgeManager pluginModel.BridgeManager
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
|
@ -22,7 +22,7 @@ type Command interface {
|
|||
const xmppBridgeCommandTrigger = "xmppbridge"
|
||||
|
||||
// Register all your slash commands in the NewCommandHandler function.
|
||||
func NewCommandHandler(client *pluginapi.Client, bridge pluginModel.Bridge) Command {
|
||||
func NewCommandHandler(client *pluginapi.Client, bridgeManager pluginModel.BridgeManager) Command {
|
||||
// Register XMPP bridge command
|
||||
xmppBridgeData := model.NewAutocompleteData(xmppBridgeCommandTrigger, "", "Manage XMPP bridge")
|
||||
mapSubcommand := model.NewAutocompleteData("map", "[room_jid]", "Map current channel to XMPP room")
|
||||
|
@ -44,8 +44,8 @@ func NewCommandHandler(client *pluginapi.Client, bridge pluginModel.Bridge) Comm
|
|||
}
|
||||
|
||||
return &Handler{
|
||||
client: client,
|
||||
bridge: bridge,
|
||||
client: client,
|
||||
bridgeManager: bridgeManager,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,17 @@ func (c *Handler) executeMapCommand(args *model.CommandArgs, fields []string) *m
|
|||
}
|
||||
}
|
||||
|
||||
// Get the XMPP bridge
|
||||
bridge, err := c.bridgeManager.GetBridge("xmpp")
|
||||
if err != nil {
|
||||
return &model.CommandResponse{
|
||||
ResponseType: model.CommandResponseTypeEphemeral,
|
||||
Text: "❌ XMPP bridge is not available. Please check the plugin configuration.",
|
||||
}
|
||||
}
|
||||
|
||||
// Check if bridge is connected
|
||||
if !c.bridge.IsConnected() {
|
||||
if !bridge.IsConnected() {
|
||||
return &model.CommandResponse{
|
||||
ResponseType: model.CommandResponseTypeEphemeral,
|
||||
Text: "❌ XMPP bridge is not connected. Please check the plugin configuration.",
|
||||
|
@ -121,7 +130,7 @@ func (c *Handler) executeMapCommand(args *model.CommandArgs, fields []string) *m
|
|||
}
|
||||
|
||||
// Check if channel is already mapped
|
||||
existingMapping, err := c.bridge.GetChannelRoomMapping(channelID)
|
||||
existingMapping, err := bridge.GetChannelRoomMapping(channelID)
|
||||
if err != nil {
|
||||
return &model.CommandResponse{
|
||||
ResponseType: model.CommandResponseTypeEphemeral,
|
||||
|
@ -137,7 +146,7 @@ func (c *Handler) executeMapCommand(args *model.CommandArgs, fields []string) *m
|
|||
}
|
||||
|
||||
// Create the mapping
|
||||
err = c.bridge.CreateChannelRoomMapping(channelID, roomJID)
|
||||
err = bridge.CreateChannelRoomMapping(channelID, roomJID)
|
||||
if err != nil {
|
||||
return &model.CommandResponse{
|
||||
ResponseType: model.CommandResponseTypeEphemeral,
|
||||
|
@ -152,7 +161,16 @@ func (c *Handler) executeMapCommand(args *model.CommandArgs, fields []string) *m
|
|||
}
|
||||
|
||||
func (c *Handler) executeStatusCommand(args *model.CommandArgs) *model.CommandResponse {
|
||||
isConnected := c.bridge.IsConnected()
|
||||
// Get the XMPP bridge
|
||||
bridge, err := c.bridgeManager.GetBridge("xmpp")
|
||||
if err != nil {
|
||||
return &model.CommandResponse{
|
||||
ResponseType: model.CommandResponseTypeEphemeral,
|
||||
Text: "❌ XMPP bridge is not available. Please check the plugin configuration.",
|
||||
}
|
||||
}
|
||||
|
||||
isConnected := bridge.IsConnected()
|
||||
|
||||
var statusText string
|
||||
if isConnected {
|
||||
|
@ -163,7 +181,7 @@ func (c *Handler) executeStatusCommand(args *model.CommandArgs) *model.CommandRe
|
|||
|
||||
// Check if current channel is mapped
|
||||
channelID := args.ChannelId
|
||||
roomJID, err := c.bridge.GetChannelRoomMapping(channelID)
|
||||
roomJID, err := bridge.GetChannelRoomMapping(channelID)
|
||||
|
||||
var mappingText string
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue