downstream: unify PRIVMSG/NOTICE and TAGMSG codepaths

They are nearly identical, the only difference is that TAGMSG has
no text parameter.

Inspired from a patch from delthas:
https://lists.sr.ht/~emersion/soju-dev/patches/30651
This commit is contained in:
Simon Ser 2022-04-05 10:06:31 +02:00
parent fb20cff45b
commit 9513c28208

View File

@ -2424,14 +2424,26 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Command: "WHOIS", Command: "WHOIS",
Params: params, Params: params,
}) })
case "PRIVMSG", "NOTICE": case "PRIVMSG", "NOTICE", "TAGMSG":
var targetsStr, text string var targetsStr, text string
if err := parseMessageParams(msg, &targetsStr, &text); err != nil { if msg.Command != "TAGMSG" {
return err if err := parseMessageParams(msg, &targetsStr, &text); err != nil {
return err
}
} else {
if err := parseMessageParams(msg, &targetsStr); err != nil {
return err
}
} }
tags := copyClientTags(msg.Tags) tags := copyClientTags(msg.Tags)
for _, name := range strings.Split(targetsStr, ",") { for _, name := range strings.Split(targetsStr, ",") {
params := []string{name}
if msg.Command != "TAGMSG" {
params = append(params, text)
}
if name == "$"+dc.srv.Config().Hostname || (name == "$*" && dc.network == nil) { if name == "$"+dc.srv.Config().Hostname || (name == "$*" && dc.network == nil) {
// "$" means a server mask follows. If it's the bouncer's // "$" means a server mask follows. If it's the bouncer's
// hostname, broadcast the message to all bouncer users. // hostname, broadcast the message to all bouncer users.
@ -2451,7 +2463,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Tags: broadcastTags, Tags: broadcastTags,
Prefix: servicePrefix, Prefix: servicePrefix,
Command: msg.Command, Command: msg.Command,
Params: []string{name, text}, Params: params,
} }
dc.srv.forEachUser(func(u *user) { dc.srv.forEachUser(func(u *user) {
u.events <- eventBroadcast{broadcastMsg} u.events <- eventBroadcast{broadcastMsg}
@ -2464,12 +2476,12 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Tags: msg.Tags.Copy(), Tags: msg.Tags.Copy(),
Prefix: dc.prefix(), Prefix: dc.prefix(),
Command: msg.Command, Command: msg.Command,
Params: []string{name, text}, Params: params,
}) })
continue continue
} }
if msg.Command == "PRIVMSG" && casemapASCII(name) == serviceNickCM { if casemapASCII(name) == serviceNickCM {
if dc.caps.IsEnabled("echo-message") { if dc.caps.IsEnabled("echo-message") {
echoTags := tags.Copy() echoTags := tags.Copy()
echoTags["time"] = irc.TagValue(formatServerTime(time.Now())) echoTags["time"] = irc.TagValue(formatServerTime(time.Now()))
@ -2477,10 +2489,12 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Tags: echoTags, Tags: echoTags,
Prefix: dc.prefix(), Prefix: dc.prefix(),
Command: msg.Command, Command: msg.Command,
Params: []string{name, text}, Params: params,
}) })
} }
handleServicePRIVMSG(ctx, dc, text) if msg.Command == "PRIVMSG" {
handleServicePRIVMSG(ctx, dc, text)
}
continue continue
} }
@ -2497,12 +2511,23 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
if uc.isChannel(upstreamName) { if uc.isChannel(upstreamName) {
unmarshaledText = dc.unmarshalText(uc, text) unmarshaledText = dc.unmarshalText(uc, text)
} }
upstreamParams := []string{upstreamName}
if msg.Command != "TAGMSG" {
upstreamParams = append(upstreamParams, unmarshaledText)
}
uc.SendMessageLabeled(ctx, dc.id, &irc.Message{ uc.SendMessageLabeled(ctx, dc.id, &irc.Message{
Tags: tags, Tags: tags,
Command: msg.Command, Command: msg.Command,
Params: []string{upstreamName, unmarshaledText}, Params: upstreamParams,
}) })
echoParams := []string{upstreamName}
if msg.Command != "TAGMSG" {
echoParams = append(echoParams, text)
}
echoTags := tags.Copy() echoTags := tags.Copy()
echoTags["time"] = irc.TagValue(formatServerTime(time.Now())) echoTags["time"] = irc.TagValue(formatServerTime(time.Now()))
if uc.account != "" { if uc.account != "" {
@ -2512,58 +2537,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Tags: echoTags, Tags: echoTags,
Prefix: &irc.Prefix{Name: uc.nick}, Prefix: &irc.Prefix{Name: uc.nick},
Command: msg.Command, Command: msg.Command,
Params: []string{upstreamName, text}, Params: echoParams,
}
uc.produce(upstreamName, echoMsg, dc)
uc.updateChannelAutoDetach(upstreamName)
}
case "TAGMSG":
var targetsStr string
if err := parseMessageParams(msg, &targetsStr); err != nil {
return err
}
tags := copyClientTags(msg.Tags)
for _, name := range strings.Split(targetsStr, ",") {
if dc.network == nil && casemapASCII(name) == dc.nickCM {
dc.SendMessage(&irc.Message{
Tags: msg.Tags.Copy(),
Prefix: dc.prefix(),
Command: "TAGMSG",
Params: []string{name},
})
continue
}
if casemapASCII(name) == serviceNickCM {
continue
}
uc, upstreamName, err := dc.unmarshalEntity(name)
if err != nil {
return err
}
if !uc.caps.IsEnabled("message-tags") {
continue
}
uc.SendMessageLabeled(ctx, dc.id, &irc.Message{
Tags: tags,
Command: "TAGMSG",
Params: []string{upstreamName},
})
echoTags := tags.Copy()
echoTags["time"] = irc.TagValue(formatServerTime(time.Now()))
if uc.account != "" {
echoTags["account"] = irc.TagValue(uc.account)
}
echoMsg := &irc.Message{
Tags: echoTags,
Prefix: &irc.Prefix{Name: uc.nick},
Command: "TAGMSG",
Params: []string{upstreamName},
} }
uc.produce(upstreamName, echoMsg, dc) uc.produce(upstreamName, echoMsg, dc)