Add support for draft/read-marker

References: https://github.com/ircv3/ircv3-specifications/pull/489
This commit is contained in:
Simon Ser 2022-06-27 15:51:56 +02:00
parent f5d57e415f
commit 71d639699e
2 changed files with 22 additions and 11 deletions

View File

@ -1,6 +1,6 @@
# read # read
This is a work-in-progress specification. This specification has been superseded by the IRC `draft/read-marker` extension.
## Description ## Description

View File

@ -237,6 +237,8 @@ var permanentDownstreamCaps = map[string]string{
"server-time": "", "server-time": "",
"setname": "", "setname": "",
"draft/read-marker",
"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": "",
@ -593,6 +595,9 @@ func (dc *downstreamConn) SendMessage(msg *irc.Message) {
if msg.Command == "ACCOUNT" && !dc.caps.IsEnabled("account-notify") { if msg.Command == "ACCOUNT" && !dc.caps.IsEnabled("account-notify") {
return return
} }
if msg.Command == "MARKREAD" && !dc.caps.IsEnabled("draft/read-marker") {
return
}
if msg.Command == "READ" && !dc.caps.IsEnabled("soju.im/read") { if msg.Command == "READ" && !dc.caps.IsEnabled("soju.im/read") {
return return
} }
@ -2896,12 +2901,12 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
dc.SendMessage(dc.marshalMessage(msg, network)) dc.SendMessage(dc.marshalMessage(msg, network))
} }
}) })
case "READ": case "READ", "MARKREAD":
var target, criteria string var target, criteria string
if err := parseMessageParams(msg, &target); err != nil { if err := parseMessageParams(msg, &target); err != nil {
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: "FAIL", Command: "FAIL",
Params: []string{"READ", "NEED_MORE_PARAMS", "Missing parameters"}, Params: []string{msg.Command, "NEED_MORE_PARAMS", "Missing parameters"},
}} }}
} }
if len(msg.Params) > 1 { if len(msg.Params) > 1 {
@ -2912,7 +2917,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
if casemapASCII(target) == serviceNickCM { if casemapASCII(target) == serviceNickCM {
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.prefix(), Prefix: dc.prefix(),
Command: "READ", Command: msg.Command,
Params: []string{target, "*"}, Params: []string{target, "*"},
}) })
return nil return nil
@ -2929,7 +2934,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
dc.logger.Printf("failed to get the read receipt for %q: %v", entity, err) dc.logger.Printf("failed to get the read receipt for %q: %v", entity, err)
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: "FAIL", Command: "FAIL",
Params: []string{"READ", "INTERNAL_ERROR", target, "Internal error"}, Params: []string{msg.Command, "INTERNAL_ERROR", target, "Internal error"},
}} }}
} else if r == nil { } else if r == nil {
r = &database.ReadReceipt{ r = &database.ReadReceipt{
@ -2944,7 +2949,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
if len(criteriaParts) != 2 || criteriaParts[0] != "timestamp" { if len(criteriaParts) != 2 || criteriaParts[0] != "timestamp" {
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: "FAIL", Command: "FAIL",
Params: []string{"READ", "INVALID_PARAMS", criteria, "Unknown criteria"}, Params: []string{msg.Command, "INVALID_PARAMS", criteria, "Unknown criteria"},
}} }}
} }
@ -2952,7 +2957,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
if err != nil { if err != nil {
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: "FAIL", Command: "FAIL",
Params: []string{"READ", "INVALID_PARAMS", criteria, "Invalid criteria"}, Params: []string{msg.Command, "INVALID_PARAMS", criteria, "Invalid criteria"},
}} }}
} }
now := time.Now() now := time.Now()
@ -2965,7 +2970,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
dc.logger.Printf("failed to store receipt for %q: %v", entity, err) dc.logger.Printf("failed to store receipt for %q: %v", entity, err)
return ircError{&irc.Message{ return ircError{&irc.Message{
Command: "FAIL", Command: "FAIL",
Params: []string{"READ", "INTERNAL_ERROR", target, "Internal error"}, Params: []string{msg.Command, "INTERNAL_ERROR", target, "Internal error"},
}} }}
} }
broadcast = true broadcast = true
@ -2980,7 +2985,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
if broadcast || dc.id == d.id { if broadcast || dc.id == d.id {
d.SendMessage(&irc.Message{ d.SendMessage(&irc.Message{
Prefix: d.prefix(), Prefix: d.prefix(),
Command: "READ", Command: msg.Command,
Params: []string{d.marshalEntity(network, entity), timestampStr}, Params: []string{d.marshalEntity(network, entity), timestampStr},
}) })
} }
@ -3435,7 +3440,13 @@ func forwardChannel(ctx context.Context, dc *downstreamConn, ch *upstreamChannel
sendTopic(dc, ch) sendTopic(dc, ch)
} }
if dc.caps.IsEnabled("soju.im/read") { var markReadCmd string
if dc.caps.IsEnabled("draft/read-marker") {
markReadCmd = "MARKREAD"
} else if dc.caps.IsEnabled("soju.im/read") {
markReadCmd = "READ"
}
if markReadCmd != "" {
channelCM := ch.conn.network.casemap(ch.Name) channelCM := ch.conn.network.casemap(ch.Name)
r, err := dc.srv.db.GetReadReceipt(ctx, ch.conn.network.ID, channelCM) r, err := dc.srv.db.GetReadReceipt(ctx, ch.conn.network.ID, channelCM)
if err != nil { if err != nil {
@ -3447,7 +3458,7 @@ func forwardChannel(ctx context.Context, dc *downstreamConn, ch *upstreamChannel
} }
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.prefix(), Prefix: dc.prefix(),
Command: "READ", Command: markReadCmd,
Params: []string{dc.marshalEntity(ch.conn.network, ch.Name), timestampStr}, Params: []string{dc.marshalEntity(ch.conn.network, ch.Name), timestampStr},
}) })
} }