Add support for chghost

This commit is contained in:
Simon Ser 2022-03-21 16:30:58 +01:00
parent 86f08ec35d
commit e403b88a3d
2 changed files with 59 additions and 5 deletions

View file

@ -235,11 +235,12 @@ var permanentDownstreamCaps = map[string]string{
} }
// needAllDownstreamCaps is the list of downstream capabilities that // needAllDownstreamCaps is the list of downstream capabilities that
// require support from all upstreams to be enabled // require support from all upstreams to be enabled.
var needAllDownstreamCaps = map[string]string{ var needAllDownstreamCaps = map[string]string{
"account-notify": "", "account-notify": "",
"account-tag": "", "account-tag": "",
"away-notify": "", "away-notify": "",
"chghost": "",
"extended-join": "", "extended-join": "",
"multi-prefix": "", "multi-prefix": "",
@ -312,6 +313,7 @@ type downstreamConn struct {
nick string nick string
nickCM string nickCM string
realname string realname string
username string
hostname string hostname string
account string // RPL_LOGGEDIN/OUT state account string // RPL_LOGGEDIN/OUT state
@ -359,7 +361,7 @@ func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn {
func (dc *downstreamConn) prefix() *irc.Prefix { func (dc *downstreamConn) prefix() *irc.Prefix {
return &irc.Prefix{ return &irc.Prefix{
Name: dc.nick, Name: dc.nick,
User: dc.user.Username, User: dc.username,
Host: dc.hostname, Host: dc.hostname,
} }
} }
@ -564,6 +566,9 @@ func (dc *downstreamConn) SendMessage(msg *irc.Message) {
if msg.Command == "SETNAME" && !dc.caps.IsEnabled("setname") { if msg.Command == "SETNAME" && !dc.caps.IsEnabled("setname") {
return return
} }
if msg.Command == "CHGHOST" && !dc.caps.IsEnabled("chghost") {
return
}
if msg.Command == "AWAY" && !dc.caps.IsEnabled("away-notify") { if msg.Command == "AWAY" && !dc.caps.IsEnabled("away-notify") {
return return
} }
@ -682,7 +687,7 @@ func (dc *downstreamConn) marshalMessage(msg *irc.Message, net *network) *irc.Me
msg.Params[1] = dc.marshalEntity(net, msg.Params[1]) msg.Params[1] = dc.marshalEntity(net, msg.Params[1])
case "TOPIC": case "TOPIC":
msg.Params[0] = dc.marshalEntity(net, msg.Params[0]) msg.Params[0] = dc.marshalEntity(net, msg.Params[0])
case "QUIT", "SETNAME": case "QUIT", "SETNAME", "CHGHOST":
// This space is intentionally left blank // This space is intentionally left blank
default: default:
panic(fmt.Sprintf("unexpected %q message", msg.Command)) panic(fmt.Sprintf("unexpected %q message", msg.Command))
@ -1133,14 +1138,31 @@ func (dc *downstreamConn) updateNick() {
} }
func (dc *downstreamConn) updateHost() { func (dc *downstreamConn) updateHost() {
if uc := dc.upstream(); uc != nil && uc.hostname != "" && uc.hostname != dc.hostname { uc := dc.upstream()
if uc == nil || uc.hostname == "" {
return
}
if uc.hostname == dc.hostname && uc.username == dc.username {
return
}
if dc.caps.IsEnabled("chghost") {
dc.SendMessage(&irc.Message{
Prefix: dc.prefix(),
Command: "CHGHOST",
Params: []string{uc.username, uc.hostname},
})
} else if uc.hostname != dc.hostname {
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.prefix(), Prefix: dc.prefix(),
Command: rpl_visiblehost, Command: rpl_visiblehost,
Params: []string{dc.nick, uc.hostname, "is now your visible host"}, Params: []string{dc.nick, uc.hostname, "is now your visible host"},
}) })
dc.hostname = uc.hostname
} }
dc.hostname = uc.hostname
dc.username = uc.username
} }
func (dc *downstreamConn) updateRealname() { func (dc *downstreamConn) updateRealname() {
@ -1309,6 +1331,7 @@ func (dc *downstreamConn) register(ctx context.Context) error {
} }
dc.registered = true dc.registered = true
dc.username = dc.user.Username
dc.logger.Printf("registration complete for user %q", dc.user.Username) dc.logger.Printf("registration complete for user %q", dc.user.Username)
return nil return nil
} }

View file

@ -26,6 +26,7 @@ var permanentUpstreamCaps = map[string]bool{
"account-tag": true, "account-tag": true,
"away-notify": true, "away-notify": true,
"batch": true, "batch": true,
"chghost": true,
"extended-join": true, "extended-join": true,
"invite-notify": true, "invite-notify": true,
"labeled-response": true, "labeled-response": true,
@ -951,6 +952,36 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
dc.SendMessage(dc.marshalMessage(msg, uc.network)) dc.SendMessage(dc.marshalMessage(msg, uc.network))
}) })
} }
case "CHGHOST":
if msg.Prefix == nil {
return fmt.Errorf("expected a prefix")
}
var newUsername, newHostname string
if err := parseMessageParams(msg, &newUsername, &newHostname); err != nil {
return err
}
newPrefix := &irc.Prefix{
Name: uc.nick,
User: newUsername,
Host: newHostname,
}
if uc.isOurNick(msg.Prefix.Name) {
uc.logger.Printf("changed prefix from %q to %q", msg.Prefix.Host, newPrefix)
uc.username = newUsername
uc.hostname = newHostname
uc.forEachDownstream(func(dc *downstreamConn) {
dc.updateHost()
})
} else {
uc.forEachDownstream(func(dc *downstreamConn) {
// TODO: add fallback with QUIT/JOIN/MODE messages
dc.SendMessage(dc.marshalMessage(msg, uc.network))
})
}
case "JOIN": case "JOIN":
if msg.Prefix == nil { if msg.Prefix == nil {
return fmt.Errorf("expected a prefix") return fmt.Errorf("expected a prefix")