bouncer-networks: Add a read-only error attribute

This is useful for clients to display additional info abotu why a
network is disconnected.
This commit is contained in:
delthas 2022-04-08 22:33:38 +02:00 committed by Simon Ser
parent d8ca6d2222
commit f7a468194d
3 changed files with 34 additions and 1 deletions

View File

@ -242,6 +242,10 @@ Bouncers MUST recognise the following network attributes:
* `realname`: the realname to use during registration. * `realname`: the realname to use during registration.
* `pass`: the server password (PASS) to use during registration. * `pass`: the server password (PASS) to use during registration.
Bouncers MAY recognise the following network attributes:
* `error` (read-only): a human-readable short text describing an error with the current network.
This is typically used when the bouncer state is `disconnected` to describe the reason why the bouncer is disconnected.
TODO: more attributes TODO: more attributes
### Examples ### Examples

View File

@ -142,6 +142,10 @@ func getNetworkAttrs(network *network) irc.Tags {
attrs["realname"] = irc.TagValue(realname) attrs["realname"] = irc.TagValue(realname)
} }
if network.lastError != nil {
attrs["error"] = irc.TagValue(network.lastError.Error())
}
fillNetworkAddrAttrs(attrs, &network.Network) fillNetworkAddrAttrs(attrs, &network.Network)
return attrs return attrs

27
user.go
View File

@ -576,7 +576,10 @@ func (u *user) run() {
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(), Prefix: dc.srv.prefix(),
Command: "BOUNCER", Command: "BOUNCER",
Params: []string{"NETWORK", netIDStr, "state=connected"}, Params: []string{"NETWORK", netIDStr, irc.Tags{
"state": "connected",
"error": "",
}.String()},
}) })
} }
}) })
@ -599,6 +602,17 @@ func (u *user) run() {
}) })
} }
net.lastError = e.err net.lastError = e.err
u.forEachDownstream(func(dc *downstreamConn) {
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(),
Command: "BOUNCER",
Params: []string{"NETWORK", fmt.Sprintf("%v", net.ID), irc.Tags{
"error": irc.TagValue(net.lastError.Error()),
}.String()},
})
}
})
case eventUpstreamError: case eventUpstreamError:
uc := e.uc uc := e.uc
@ -606,6 +620,17 @@ func (u *user) run() {
sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s: %v", uc.network.GetName(), e.err)) sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s: %v", uc.network.GetName(), e.err))
}) })
uc.network.lastError = e.err uc.network.lastError = e.err
u.forEachDownstream(func(dc *downstreamConn) {
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(),
Command: "BOUNCER",
Params: []string{"NETWORK", fmt.Sprintf("%v", uc.network.ID), irc.Tags{
"error": irc.TagValue(uc.network.lastError.Error()),
}.String()},
})
}
})
case eventUpstreamMessage: case eventUpstreamMessage:
msg, uc := e.msg, e.uc msg, uc := e.msg, e.uc
if uc.isClosed() { if uc.isClosed() {