Introduce soju.im/pre-away
The IRCv3 spec is stalled, so let's just ship a vendored extension for now. References: https://github.com/ircv3/ircv3-specifications/pull/514
This commit is contained in:
parent
0ee94759f7
commit
c36bb342fb
91
doc/ext/pre-away.md
Normal file
91
doc/ext/pre-away.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
title: "`pre-away` Extension"
|
||||||
|
layout: spec
|
||||||
|
meta-description: A capability allowing client connections to be marked AWAY during connection registration
|
||||||
|
work-in-progress: true
|
||||||
|
copyrights:
|
||||||
|
-
|
||||||
|
name: "Shivaram Lingamneni"
|
||||||
|
period: "2023"
|
||||||
|
email: "slingamn@cs.stanford.edu"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes for implementing experimental vendor version
|
||||||
|
|
||||||
|
This is an experimental specification for a vendored extension.
|
||||||
|
|
||||||
|
No guarantees are made regarding the stability of this extension.
|
||||||
|
Backwards-incompatible changes can be made at any time without prior notice.
|
||||||
|
|
||||||
|
Software implementing this work-in-progress specification MUST NOT use the
|
||||||
|
unprefixed `pre-away` CAP name. Instead, implementations SHOULD use the
|
||||||
|
`soju.im/pre-away` CAP name to be interoperable with other software implementing
|
||||||
|
a compatible work-in-progress version.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Some IRC server implementations offer a mode of operation where a single
|
||||||
|
nickname can be associated with multiple concurrent client connections, or no
|
||||||
|
client connections. Typically, such implementations are bouncers (i.e.,
|
||||||
|
intermediaries between the client and another server), but some are full server
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
Such implementations may wish to update publicly visible state depending on the
|
||||||
|
status of the user's actual client connections. For example, if the user has no
|
||||||
|
active connections, it may be desirable to mark them as AWAY, then mark them
|
||||||
|
un-AWAY if they reconnect. However, a client implementation may wish to connect
|
||||||
|
without active involvement from the user, e.g. to retrieve
|
||||||
|
[chathistory][], in which case it would be undesirable to suggest
|
||||||
|
that the user is present. This extension provides a mechanism for such clients
|
||||||
|
to flag their connections as automatically initiated, so servers can disregard
|
||||||
|
them for this or other purposes related to user presence.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
This specification introduces a new capability, `soju.im/pre-away`. Clients
|
||||||
|
wishing to make use of this specification MUST negotiate the capability; this
|
||||||
|
gives the server more information about the context and meaning of the client's
|
||||||
|
`AWAY` commands.
|
||||||
|
|
||||||
|
If the capability has been negotiated, servers MUST accept the `AWAY` command
|
||||||
|
before connection registration has completed. The `AWAY` command has its normal
|
||||||
|
semantics, except that servers SHOULD treat the form:
|
||||||
|
|
||||||
|
AWAY *
|
||||||
|
|
||||||
|
i.e. an `AWAY` message consisting of the single character `*`, as indicating
|
||||||
|
that the user is not present for an unspecified reason. Clients MAY also send
|
||||||
|
`AWAY *` post-registration to indicate that the user is no longer present for an
|
||||||
|
unspecified reason.
|
||||||
|
|
||||||
|
In its conventional form:
|
||||||
|
|
||||||
|
AWAY :Gone to lunch. Back in 5
|
||||||
|
|
||||||
|
the `AWAY` command MAY be used pre-registration to set a human-readable away
|
||||||
|
message associated with the connection as usual. Similarly, `AWAY` with no
|
||||||
|
parameters indicates that the user is present.
|
||||||
|
|
||||||
|
If the client's nickname was not already present on the server, then `AWAY`
|
||||||
|
pre-registration sets the away message but does not inhibit reporting of the
|
||||||
|
change in nickname status, e.g. via [monitor][].
|
||||||
|
|
||||||
|
Clients that have negotiated this capability and subsequently receive `*` as an
|
||||||
|
away message (for example, in `301 RPL_AWAY` or [away-notify][])
|
||||||
|
SHOULD treat it as indicating that the user is not present for an unspecified
|
||||||
|
reason. Servers MAY substitute a human-readable message for the `*` if it would
|
||||||
|
otherwise be relayed as an away message.
|
||||||
|
|
||||||
|
## Implementation considerations
|
||||||
|
|
||||||
|
This section is non-normative.
|
||||||
|
|
||||||
|
In general, the server-side aggregation of away statuses across multiple
|
||||||
|
connections is outside the scope of this specification. However, in most cases,
|
||||||
|
an away message of `*` should be treated as though the connection did not exist
|
||||||
|
at all (for example, it should not supersede a human-readable `AWAY` message set
|
||||||
|
by another connection, even if it is more recent).
|
||||||
|
|
||||||
|
[chathistory]: https://ircv3.net/specs/extensions/chathistory
|
||||||
|
[monitor]: https://ircv3.net/specs/extensions/monitor
|
||||||
|
[away-notify]: https://ircv3.net/specs/extensions/away-notify
|
@ -229,11 +229,12 @@ var permanentDownstreamCaps = map[string]string{
|
|||||||
|
|
||||||
"draft/read-marker": "",
|
"draft/read-marker": "",
|
||||||
|
|
||||||
|
"soju.im/account-required": "",
|
||||||
"soju.im/bouncer-networks": "",
|
"soju.im/bouncer-networks": "",
|
||||||
"soju.im/bouncer-networks-notify": "",
|
"soju.im/bouncer-networks-notify": "",
|
||||||
"soju.im/no-implicit-names": "",
|
"soju.im/no-implicit-names": "",
|
||||||
|
"soju.im/pre-away": "",
|
||||||
"soju.im/read": "",
|
"soju.im/read": "",
|
||||||
"soju.im/account-required": "",
|
|
||||||
"soju.im/webpush": "",
|
"soju.im/webpush": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,6 +742,14 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
Params: []string{"BOUNCER", "UNKNOWN_COMMAND", subcommand, "Unknown subcommand"},
|
Params: []string{"BOUNCER", "UNKNOWN_COMMAND", subcommand, "Unknown subcommand"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
case "AWAY":
|
||||||
|
if len(msg.Params) > 0 {
|
||||||
|
dc.away = &msg.Params[0]
|
||||||
|
} else {
|
||||||
|
dc.away = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.SendMessage(ctx, generateAwayReply(dc.away != nil))
|
||||||
default:
|
default:
|
||||||
dc.logger.Printf("unhandled message: %v", msg)
|
dc.logger.Printf("unhandled message: %v", msg)
|
||||||
return newUnknownCommandError(msg.Command)
|
return newUnknownCommandError(msg.Command)
|
||||||
@ -2575,16 +2584,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
|||||||
dc.away = nil
|
dc.away = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := irc.RPL_NOWAWAY
|
dc.SendMessage(ctx, generateAwayReply(dc.away != nil))
|
||||||
desc := "You have been marked as being away"
|
|
||||||
if dc.away == nil {
|
|
||||||
cmd = irc.RPL_UNAWAY
|
|
||||||
desc = "You are no longer marked as being away"
|
|
||||||
}
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
|
||||||
Command: cmd,
|
|
||||||
Params: []string{dc.nick, desc},
|
|
||||||
})
|
|
||||||
|
|
||||||
uc := dc.upstream()
|
uc := dc.upstream()
|
||||||
if uc != nil {
|
if uc != nil {
|
||||||
|
13
irc.go
13
irc.go
@ -278,3 +278,16 @@ func isNumeric(cmd string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateAwayReply(away bool) *irc.Message {
|
||||||
|
cmd := irc.RPL_NOWAWAY
|
||||||
|
desc := "You have been marked as being away"
|
||||||
|
if !away {
|
||||||
|
cmd = irc.RPL_UNAWAY
|
||||||
|
desc = "You are no longer marked as being away"
|
||||||
|
}
|
||||||
|
return &irc.Message{
|
||||||
|
Command: cmd,
|
||||||
|
Params: []string{"*", desc},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user