Add preliminary support for NickServ authentication
(remove everything else)
This commit is contained in:
154
irc_caps.go
Normal file
154
irc_caps.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package hbot
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ircCaps struct {
|
||||
saslOn bool
|
||||
saslUser string
|
||||
saslPass string
|
||||
caps []string
|
||||
capsEnabled map[string]bool
|
||||
mu sync.Mutex
|
||||
done bool
|
||||
}
|
||||
|
||||
func (c *ircCaps) saslEnable() {
|
||||
c.mu.Lock()
|
||||
c.saslOn = true
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *ircCaps) saslCreds(user, pass string) {
|
||||
c.mu.Lock()
|
||||
c.saslUser = user
|
||||
c.saslPass = pass
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *ircCaps) reset() {
|
||||
c.mu.Lock()
|
||||
c.saslOn = false
|
||||
c.done = false
|
||||
c.caps = []string{}
|
||||
c.capsEnabled = make(map[string]bool)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *ircCaps) saslAuth(m *Message) bool {
|
||||
return m.Command == "AUTHENTICATE" && m.Param(0) == "+"
|
||||
}
|
||||
|
||||
func (c *ircCaps) capLS(m *Message) bool {
|
||||
return m.Command == "CAP" && m.Param(1) == "LS"
|
||||
}
|
||||
|
||||
func (c *ircCaps) capACK(m *Message) bool {
|
||||
return m.Command == "CAP" && m.Param(1) == "ACK"
|
||||
}
|
||||
|
||||
func (c *ircCaps) Handle(bot *Bot, m *Message) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.done {
|
||||
return
|
||||
}
|
||||
|
||||
if c.capLS(m) {
|
||||
for _, cap := range strings.Split(m.Trailing(), " ") {
|
||||
if _, ok := allowedCAPs[cap]; ok {
|
||||
c.capsEnabled[cap] = true
|
||||
c.caps = append(c.caps, cap)
|
||||
} else {
|
||||
c.capsEnabled[cap] = false
|
||||
}
|
||||
}
|
||||
bot.Send("CAP REQ :" + strings.Join(c.caps, " "))
|
||||
}
|
||||
|
||||
if c.capACK(m) {
|
||||
if c.saslOn && strings.Contains(m.Trailing(), "sasl") {
|
||||
bot.Send("AUTHENTICATE PLAIN")
|
||||
} else {
|
||||
if c.saslOn {
|
||||
bot.config.Logger.Errorf("SASL is not supported, despite request")
|
||||
}
|
||||
bot.Send("CAP END")
|
||||
c.done = true
|
||||
}
|
||||
}
|
||||
|
||||
if c.saslAuth(m) {
|
||||
out := bytes.Join([][]byte{[]byte(c.saslUser), []byte(c.saslUser), []byte(c.saslPass)}, []byte{0})
|
||||
encpass := base64.StdEncoding.EncodeToString(out)
|
||||
bot.Send("AUTHENTICATE " + encpass)
|
||||
bot.Send("CAP END")
|
||||
c.done = true
|
||||
}
|
||||
}
|
||||
|
||||
// Capabilities we can deal with
|
||||
// without doing crazy things in the library
|
||||
var allowedCAPs = map[string]struct{}{
|
||||
CapAccountNotify: {},
|
||||
CapAwayNotify: {},
|
||||
CapExtendedJoin: {},
|
||||
CapSASL: {},
|
||||
CapChghost: {},
|
||||
CapInviteNotify: {},
|
||||
CapMultiPrefix: {},
|
||||
CapCapNotify: {},
|
||||
CapSetName: {},
|
||||
CapServerTime: {},
|
||||
CapAccountTag: {},
|
||||
CapMessageTags: {},
|
||||
}
|
||||
|
||||
// CapAccountNotify is account-notify CAP
|
||||
const CapAccountNotify = "account-notify"
|
||||
|
||||
// CapAwayNotify is away-notify CAP
|
||||
const CapAwayNotify = "away-notify"
|
||||
|
||||
// CapExtendedJoin is extended-join CAP
|
||||
const CapExtendedJoin = "extended-join"
|
||||
|
||||
// CapSASL is SASL CAP
|
||||
const CapSASL = "sasl"
|
||||
|
||||
// CapChghost is chghost CAP
|
||||
const CapChghost = "chghost"
|
||||
|
||||
// CapInviteNotify is invite-notify CAP
|
||||
const CapInviteNotify = "invite-notify"
|
||||
|
||||
// CapMultiPrefix is multi-prefix CAP
|
||||
const CapMultiPrefix = "multi-prefix"
|
||||
|
||||
// CapUserhostInNames is userhost-in-names CAP
|
||||
const CapUserhostInNames = "userhost-in-names"
|
||||
|
||||
// CapCapNotify is cap-notify CAP
|
||||
const CapCapNotify = "cap-notify"
|
||||
|
||||
// CapIdentifyMsg is identify-msg CAP
|
||||
const CapIdentifyMsg = "identify-msg"
|
||||
|
||||
// CapTLS is tls CAP
|
||||
const CapTLS = "tls"
|
||||
|
||||
// CapSetName is setname CAP
|
||||
const CapSetName = "setname"
|
||||
|
||||
// CapServerTime is server-time CAP
|
||||
const CapServerTime = "server-time"
|
||||
|
||||
// CapAccountTag is account-tag CAP
|
||||
const CapAccountTag = "account-tag"
|
||||
|
||||
// CapMessageTags is message-tags CAP
|
||||
const CapMessageTags = "message-tags"
|
||||
Reference in New Issue
Block a user