package protocol import ( "strings" ) // Command Parsing Helpers func ParseCommand(data []byte) (string, map[string]string) { s := string(data) parts := strings.Split(s, " ") cmd := parts[0] args := make(map[string]string) for _, p := range parts[1:] { kv := strings.SplitN(p, "=", 2) if len(kv) == 2 { val := Unescape(kv[1]) args[kv[0]] = val } else { args[p] = "" } } return cmd, args } // Unescape TS3 string func Unescape(s string) string { r := strings.NewReplacer( `\/`, `/`, `\s`, ` `, `\p`, `|`, `\a`, "\a", `\b`, "\b", `\f`, "\f", `\n`, "\n", `\r`, "\r", `\t`, "\t", `\v`, "\v", `\\`, `\`, ) return r.Replace(s) } func Escape(s string) string { r := strings.NewReplacer( `\`, `\\`, `/`, `\/`, ` `, `\s`, `|`, `\p`, "\a", `\a`, "\b", `\b`, "\f", `\f`, "\n", `\n`, "\r", `\r`, "\t", `\t`, "\v", `\v`, ) return r.Replace(s) } // Command represents a TeamSpeak 3 command for building/encoding type Command struct { Name string Params map[string]string } func NewCommand(name string) *Command { return &Command{ Name: name, Params: make(map[string]string), } } func (c *Command) AddParam(key, value string) { c.Params[key] = value } func (c *Command) Encode() string { var sb strings.Builder sb.WriteString(c.Name) for k, v := range c.Params { sb.WriteString(" ") sb.WriteString(k) if v != "" { sb.WriteString("=") sb.WriteString(Escape(v)) } } return sb.String() }