Add support for TAGMSG and client message tags
Previously we dropped all TAGMSG as well as any client message tag sent from downstream. This adds support for properly forwarding TAGMSG and client message tags from downstreams and upstreams. TAGMSG messages are intentionally not logged, because they are currently typically used for +typing, which can generate a lot of traffic and is only useful for a few seconds after it is sent.
This commit is contained in:
parent
cdef46d0da
commit
f4e0c51366
@ -250,6 +250,9 @@ func (dc *downstreamConn) readMessages(ch chan<- event) error {
|
|||||||
// This can only called from the user goroutine.
|
// This can only called from the user goroutine.
|
||||||
func (dc *downstreamConn) SendMessage(msg *irc.Message) {
|
func (dc *downstreamConn) SendMessage(msg *irc.Message) {
|
||||||
if !dc.caps["message-tags"] {
|
if !dc.caps["message-tags"] {
|
||||||
|
if msg.Command == "TAGMSG" {
|
||||||
|
return
|
||||||
|
}
|
||||||
msg = msg.Copy()
|
msg = msg.Copy()
|
||||||
for name := range msg.Tags {
|
for name := range msg.Tags {
|
||||||
supported := false
|
supported := false
|
||||||
@ -274,7 +277,7 @@ func (dc *downstreamConn) marshalMessage(msg *irc.Message, net *network) *irc.Me
|
|||||||
msg.Prefix = dc.marshalUserPrefix(net, msg.Prefix)
|
msg.Prefix = dc.marshalUserPrefix(net, msg.Prefix)
|
||||||
|
|
||||||
switch msg.Command {
|
switch msg.Command {
|
||||||
case "PRIVMSG", "NOTICE":
|
case "PRIVMSG", "NOTICE", "TAGMSG":
|
||||||
msg.Params[0] = dc.marshalEntity(net, msg.Params[0])
|
msg.Params[0] = dc.marshalEntity(net, msg.Params[0])
|
||||||
case "NICK":
|
case "NICK":
|
||||||
// Nick change for another user
|
// Nick change for another user
|
||||||
@ -1397,6 +1400,7 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
|
|||||||
if err := parseMessageParams(msg, &targetsStr, &text); err != nil {
|
if err := parseMessageParams(msg, &targetsStr, &text); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
tags := copyClientTags(msg.Tags)
|
||||||
|
|
||||||
for _, name := range strings.Split(targetsStr, ",") {
|
for _, name := range strings.Split(targetsStr, ",") {
|
||||||
if name == serviceNick {
|
if name == serviceNick {
|
||||||
@ -1418,14 +1422,15 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
|
|||||||
unmarshaledText = dc.unmarshalText(uc, text)
|
unmarshaledText = dc.unmarshalText(uc, text)
|
||||||
}
|
}
|
||||||
uc.SendMessageLabeled(dc.id, &irc.Message{
|
uc.SendMessageLabeled(dc.id, &irc.Message{
|
||||||
|
Tags: tags,
|
||||||
Command: "PRIVMSG",
|
Command: "PRIVMSG",
|
||||||
Params: []string{upstreamName, unmarshaledText},
|
Params: []string{upstreamName, unmarshaledText},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
echoTags := tags.Copy()
|
||||||
|
echoTags["time"] = irc.TagValue(time.Now().UTC().Format(serverTimeLayout))
|
||||||
echoMsg := &irc.Message{
|
echoMsg := &irc.Message{
|
||||||
Tags: irc.Tags{
|
Tags: echoTags,
|
||||||
"time": irc.TagValue(time.Now().UTC().Format(serverTimeLayout)),
|
|
||||||
},
|
|
||||||
Prefix: &irc.Prefix{
|
Prefix: &irc.Prefix{
|
||||||
Name: uc.nick,
|
Name: uc.nick,
|
||||||
User: uc.username,
|
User: uc.username,
|
||||||
@ -1440,6 +1445,7 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
|
|||||||
if err := parseMessageParams(msg, &targetsStr, &text); err != nil {
|
if err := parseMessageParams(msg, &targetsStr, &text); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
tags := copyClientTags(msg.Tags)
|
||||||
|
|
||||||
for _, name := range strings.Split(targetsStr, ",") {
|
for _, name := range strings.Split(targetsStr, ",") {
|
||||||
uc, upstreamName, err := dc.unmarshalEntity(name)
|
uc, upstreamName, err := dc.unmarshalEntity(name)
|
||||||
@ -1452,10 +1458,30 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
|
|||||||
unmarshaledText = dc.unmarshalText(uc, text)
|
unmarshaledText = dc.unmarshalText(uc, text)
|
||||||
}
|
}
|
||||||
uc.SendMessageLabeled(dc.id, &irc.Message{
|
uc.SendMessageLabeled(dc.id, &irc.Message{
|
||||||
|
Tags: tags,
|
||||||
Command: "NOTICE",
|
Command: "NOTICE",
|
||||||
Params: []string{upstreamName, unmarshaledText},
|
Params: []string{upstreamName, unmarshaledText},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
case "TAGMSG":
|
||||||
|
var targetsStr string
|
||||||
|
if err := parseMessageParams(msg, &targetsStr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tags := copyClientTags(msg.Tags)
|
||||||
|
|
||||||
|
for _, name := range strings.Split(targetsStr, ",") {
|
||||||
|
uc, upstreamName, err := dc.unmarshalEntity(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uc.SendMessageLabeled(dc.id, &irc.Message{
|
||||||
|
Tags: tags,
|
||||||
|
Command: "TAGMSG",
|
||||||
|
Params: []string{upstreamName},
|
||||||
|
})
|
||||||
|
}
|
||||||
case "INVITE":
|
case "INVITE":
|
||||||
var user, channel string
|
var user, channel string
|
||||||
if err := parseMessageParams(msg, &user, &channel); err != nil {
|
if err := parseMessageParams(msg, &user, &channel); err != nil {
|
||||||
|
10
irc.go
10
irc.go
@ -274,6 +274,16 @@ func parseMessageParams(msg *irc.Message, out ...*string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyClientTags(tags irc.Tags) irc.Tags {
|
||||||
|
t := make(irc.Tags, len(tags))
|
||||||
|
for k, v := range tags {
|
||||||
|
if strings.HasPrefix(k, "+") {
|
||||||
|
t[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
type batch struct {
|
type batch struct {
|
||||||
Type string
|
Type string
|
||||||
Params []string
|
Params []string
|
||||||
|
21
upstream.go
21
upstream.go
@ -320,15 +320,21 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
Params: msg.Params,
|
Params: msg.Params,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
case "NOTICE", "PRIVMSG":
|
case "NOTICE", "PRIVMSG", "TAGMSG":
|
||||||
if msg.Prefix == nil {
|
if msg.Prefix == nil {
|
||||||
return fmt.Errorf("expected a prefix")
|
return fmt.Errorf("expected a prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity, text string
|
var entity, text string
|
||||||
|
if msg.Command != "TAGMSG" {
|
||||||
if err := parseMessageParams(msg, &entity, &text); err != nil {
|
if err := parseMessageParams(msg, &entity, &text); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err := parseMessageParams(msg, &entity); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if msg.Prefix.Name == serviceNick {
|
if msg.Prefix.Name == serviceNick {
|
||||||
uc.logger.Printf("skipping %v from soju's service: %v", msg.Command, msg)
|
uc.logger.Printf("skipping %v from soju's service: %v", msg.Command, msg)
|
||||||
@ -341,7 +347,7 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
|
|
||||||
if msg.Prefix.User == "" && msg.Prefix.Host == "" { // server message
|
if msg.Prefix.User == "" && msg.Prefix.Host == "" { // server message
|
||||||
uc.produce("", msg, nil)
|
uc.produce("", msg, nil)
|
||||||
} else { // regular user NOTICE or PRIVMSG
|
} else { // regular user message
|
||||||
target := entity
|
target := entity
|
||||||
if target == uc.nick {
|
if target == uc.nick {
|
||||||
target = msg.Prefix.Name
|
target = msg.Prefix.Name
|
||||||
@ -1274,8 +1280,6 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case "TAGMSG":
|
|
||||||
// TODO: relay to downstream connections that accept message-tags
|
|
||||||
case "ACK":
|
case "ACK":
|
||||||
// Ignore
|
// Ignore
|
||||||
case irc.RPL_NOWAWAY, irc.RPL_UNAWAY:
|
case irc.RPL_NOWAWAY, irc.RPL_UNAWAY:
|
||||||
@ -1487,6 +1491,15 @@ func (uc *upstreamConn) readMessages(ch chan<- event) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (uc *upstreamConn) SendMessage(msg *irc.Message) {
|
||||||
|
if !uc.caps["message-tags"] {
|
||||||
|
msg = msg.Copy()
|
||||||
|
msg.Tags = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
uc.conn.SendMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
func (uc *upstreamConn) SendMessageLabeled(downstreamID uint64, msg *irc.Message) {
|
func (uc *upstreamConn) SendMessageLabeled(downstreamID uint64, msg *irc.Message) {
|
||||||
if uc.caps["labeled-response"] {
|
if uc.caps["labeled-response"] {
|
||||||
if msg.Tags == nil {
|
if msg.Tags == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user