// Package message provides pure parsing and formatting for Matrix messages. package message import ( "strings" "github.com/enmanuel/agents/pkg/decision" ) // ParseOptions configures how messages are parsed. type ParseOptions struct { CommandPrefix string // e.g. "!" BotUserID string // for mention detection, e.g. "@bot:server" MentionedUserIDs []string // pre-extracted from m.mentions event field (modern Matrix spec) } // Parse converts a raw Matrix message body into a structured MessageContext. Pure. func Parse(body, senderID, roomID string, powerLevel int, isDM bool, opts ParseOptions) decision.MessageContext { ctx := decision.MessageContext{ SenderID: senderID, RoomID: roomID, Content: body, PowerLevel: powerLevel, IsDirectMsg: isDM, } // Detect mention: check m.mentions list first (modern Matrix spec). if opts.BotUserID != "" { for _, uid := range opts.MentionedUserIDs { if uid == opts.BotUserID { ctx.IsMention = true break } } // Fallback: check if full user ID appears in the plain text body. if !ctx.IsMention && strings.Contains(body, opts.BotUserID) { ctx.IsMention = true } } // Parse command. // When CommandPrefix is non-empty (e.g. "!"), only messages starting with that // prefix are treated as commands. // When CommandPrefix is empty, every message is a potential command: the first // token is the command name. If it starts with "!", the "!" is stripped for // backward compatibility (so both "help" and "!help" work the same). switch { case opts.CommandPrefix != "": // Standard mode: require prefix if strings.HasPrefix(body, opts.CommandPrefix) { parts := strings.Fields(strings.TrimPrefix(body, opts.CommandPrefix)) if len(parts) > 0 { ctx.Command = strings.ToLower(parts[0]) ctx.Args = parts[1:] } } case opts.CommandPrefix == "": // No-prefix mode: treat first token as command parts := strings.Fields(body) if len(parts) > 0 { cmd := parts[0] // Strip leading "!" for backward compatibility cmd = strings.TrimPrefix(cmd, "!") if cmd != "" { ctx.Command = strings.ToLower(cmd) ctx.Args = parts[1:] } } } return ctx }