The capability slightly varies between the old and new name, as a new
parameter was added. This adds support for both.
Fixes: #105
See: https://github.com/ircv3/ircv3-specifications/pull/435
---
downstream.go | 40 +++++++++++++++++++++++++++++++++++++++-
upstream.go | 30 ++++++++++++++++++++----------
2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/downstream.go b/downstream.go
index fee5134..540bace 100644
--- a/downstream.go
+++ b/downstream.go
@@ -137,6 +137,15 @@ var needAllDownstreamCaps = map[string]string{
"multi-prefix": "",
}
+// passthroughCaps is the list of downstream capabilities that are passed
+// through from the upstream server to downstream clients.
+//
+// This is only effective in single-upstream mode.
+var passthroughCaps = map[string]string{
+ "draft/account-registration": "",
+ "draft/register": "",
+}
+
// passthroughIsupport is the set of ISUPPORT tokens that are directly passed
// through from the upstream server to downstream clients.
//
@@ -894,6 +903,18 @@ func (dc *downstreamConn) updateSupportedCaps() {
dc.unsetSupportedCap(cap)
}
}
+
+ uc := dc.upstream()
+ for cap := range passthroughCaps {
+ if uc != nil {
+ v, ok := uc.supportedCaps[cap]
+ if ok && uc.caps[cap] {
+ dc.setSupportedCap(cap, v)
+ continue
+ }
+ }
+ dc.unsetSupportedCap(cap)
+ }
}
func (dc *downstreamConn) updateNick() {
@@ -2343,6 +2364,20 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
Params: []string{"BOUNCER", "UNKNOWN_COMMAND", subcommand, "Unknown subcommand"},
}}
}
+ case "REGISTER", "VERIFY":
+ uc := dc.upstream()
+ if uc == nil {
+ return newUnknownCommandError(msg.Command)
+ }
+ uc.SendMessageLabeled(dc.id, msg)
+ if msg.Command == "REGISTER" && len(msg.Params) >= 2 {
+ username := uc.nick
+ if len(msg.Params) >= 3 && msg.Params[0] != "*" {
+ username = msg.Params[0]
+ }
+ password := msg.Params[len(msg.Params)-1]
+ dc.updateCredentials(uc, username, password)
+ }
default:
dc.logger.Printf("unhandled message: %v", msg)
@@ -2362,14 +2397,17 @@ func (dc *downstreamConn) handleNickServPRIVMSG(uc *upstreamConn, text string) {
if !ok {
return
}
+ dc.updateCredentials(uc, username, password)
+}
+func (dc *downstreamConn) updateCredentials(uc *upstreamConn, username, password string) {
// User may have e.g. EXTERNAL mechanism configured. We do not want to
// automatically erase the key pair or any other credentials.
if uc.network.SASL.Mechanism != "" && uc.network.SASL.Mechanism != "PLAIN" {
return
}
- dc.logger.Printf("auto-saving NickServ credentials with username %q", username)
+ dc.logger.Printf("auto-saving credentials with username %q", username)
n := uc.network
n.SASL.Mechanism = "PLAIN"
n.SASL.Plain.Username = username
diff --git a/upstream.go b/upstream.go
index 104f330..46f96d1 100644
--- a/upstream.go
+++ b/upstream.go
@@ -21,16 +21,18 @@ import (
// permanentUpstreamCaps is the static list of upstream capabilities always
// requested when supported.
var permanentUpstreamCaps = map[string]bool{
- "account-tag": true,
- "away-notify": true,
- "batch": true,
- "extended-join": true,
- "invite-notify": true,
- "labeled-response": true,
- "message-tags": true,
- "multi-prefix": true,
- "server-time": true,
- "setname": true,
+ "account-tag": true,
+ "away-notify": true,
+ "batch": true,
+ "extended-join": true,
+ "invite-notify": true,
+ "labeled-response": true,
+ "message-tags": true,
+ "multi-prefix": true,
+ "server-time": true,
+ "setname": true,
+ "draft/account-registration": true,
+ "draft/register": true,
}
type registrationError string
@@ -1428,6 +1430,14 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
Params: []string{dc.nick, upstreamChannel, trailing},
})
})
+ case "REGISTER", "VERIFY":
+ uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) {
+ dc.SendMessage(&irc.Message{
+ Prefix: uc.srv.prefix(),
+ Command: msg.Command,
+ Params: msg.Params,
+ })
+ })
case irc.ERR_UNKNOWNCOMMAND, irc.RPL_TRYAGAIN:
var command, reason string
if err := parseMessageParams(msg, nil, &command, &reason); err != nil {
--
2.30.0