dispatch/pkg/irc/cap.go
2020-05-23 09:42:20 +02:00

130 lines
2.4 KiB
Go

package irc
import (
"strings"
)
func (c *Client) HasCapability(name string, values ...string) bool {
if capValues, ok := c.enabledCapabilities[name]; ok {
if len(values) == 0 || capValues == nil {
return true
}
for _, v := range values {
for _, vCap := range capValues {
if v == vCap {
return true
}
}
}
}
return false
}
var clientWantedCaps = []string{}
func (c *Client) writeCAP() {
c.write("CAP LS 302")
}
func (c *Client) handleCAP(msg *Message) {
if len(msg.Params) < 3 {
c.write("CAP END")
return
}
caps := parseCaps(msg.LastParam())
c.lock.Lock()
defer c.lock.Unlock()
switch msg.Params[1] {
case "LS":
for cap, values := range caps {
for _, wanted := range c.wantedCapabilities {
if cap == wanted {
c.requestedCapabilities[cap] = values
}
}
}
if len(msg.Params) == 3 {
if len(c.requestedCapabilities) == 0 {
c.write("CAP END")
return
}
reqCaps := []string{}
for cap := range c.requestedCapabilities {
reqCaps = append(reqCaps, cap)
}
c.write("CAP REQ :" + strings.Join(reqCaps, " "))
}
case "ACK":
for cap := range caps {
if v, ok := c.requestedCapabilities[cap]; ok {
c.enabledCapabilities[cap] = v
delete(c.requestedCapabilities, cap)
}
}
if len(c.requestedCapabilities) == 0 {
if c.Config.SASL != nil && c.HasCapability("sasl", c.Config.SASL.Name()) {
c.write("AUTHENTICATE " + c.Config.SASL.Name())
} else {
c.write("CAP END")
}
}
case "NAK":
for cap := range caps {
delete(c.requestedCapabilities, cap)
}
if len(c.requestedCapabilities) == 0 {
c.write("CAP END")
}
case "NEW":
reqCaps := []string{}
for cap, values := range caps {
for _, wanted := range c.wantedCapabilities {
if cap == wanted && !c.HasCapability(cap) {
c.requestedCapabilities[cap] = values
reqCaps = append(reqCaps, cap)
}
}
}
if len(reqCaps) > 0 {
c.write("CAP REQ :" + strings.Join(reqCaps, " "))
}
case "DEL":
for cap := range caps {
delete(c.enabledCapabilities, cap)
}
}
}
func parseCaps(caps string) map[string][]string {
result := map[string][]string{}
parts := strings.Split(caps, " ")
for _, part := range parts {
capParts := strings.Split(part, "=")
name := capParts[0]
if len(capParts) > 1 {
result[name] = strings.Split(capParts[1], ",")
} else {
result[name] = nil
}
}
return result
}