mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-21 10:12:00 -08:00
Add support for stateless bridging via draft/relaymsg (irc) (#1339)
* irc: add support for stateless bridging via draft/relaymsg As discussed at https://github.com/42wim/matterbridge/issues/667#issuecomment-634214165 * irc: handle the draft/relaymsg tag in spoofed messages too * Apply suggestions from code review Co-authored-by: Wim <wim@42.be> * Run gofmt on irc.go * Document relaymsg in matterbridge.toml.sample Co-authored-by: Wim <wim@42.be>
This commit is contained in:
parent
58ea1e07d2
commit
a9f89dbc64
@ -205,27 +205,58 @@ func (b *Birc) doConnect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize nicks for RELAYMSG: replace IRC characters with special meanings with "-"
|
||||||
|
func sanitizeNick(nick string) string {
|
||||||
|
sanitize := func(r rune) rune {
|
||||||
|
if strings.ContainsRune("!+%@&#$:'\"?*,. ", r) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return strings.Map(sanitize, nick)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Birc) doSend() {
|
func (b *Birc) doSend() {
|
||||||
rate := time.Millisecond * time.Duration(b.MessageDelay)
|
rate := time.Millisecond * time.Duration(b.MessageDelay)
|
||||||
throttle := time.NewTicker(rate)
|
throttle := time.NewTicker(rate)
|
||||||
for msg := range b.Local {
|
for msg := range b.Local {
|
||||||
<-throttle.C
|
<-throttle.C
|
||||||
username := msg.Username
|
username := msg.Username
|
||||||
if b.GetBool("Colornicks") && len(username) > 1 {
|
// Optional support for the proposed RELAYMSG extension, described at
|
||||||
checksum := crc32.ChecksumIEEE([]byte(msg.Username))
|
// https://github.com/jlu5/ircv3-specifications/blob/master/extensions/relaymsg.md
|
||||||
colorCode := checksum%14 + 2 // quick fix - prevent white or black color codes
|
// nolint:nestif
|
||||||
username = fmt.Sprintf("\x03%02d%s\x0F", colorCode, msg.Username)
|
if (b.i.HasCapability("overdrivenetworks.com/relaymsg") || b.i.HasCapability("draft/relaymsg")) &&
|
||||||
}
|
b.GetBool("UseRelayMsg") {
|
||||||
|
username = sanitizeNick(username)
|
||||||
|
text := msg.Text
|
||||||
|
|
||||||
switch msg.Event {
|
// Work around girc chomping leading commas on single word messages?
|
||||||
case config.EventUserAction:
|
if strings.HasPrefix(text, ":") && !strings.ContainsRune(text, ' ') {
|
||||||
b.i.Cmd.Action(msg.Channel, username+msg.Text)
|
text = ":" + text
|
||||||
case config.EventNoticeIRC:
|
}
|
||||||
b.Log.Debugf("Sending notice to channel %s", msg.Channel)
|
|
||||||
b.i.Cmd.Notice(msg.Channel, username+msg.Text)
|
if msg.Event == config.EventUserAction {
|
||||||
default:
|
b.i.Cmd.SendRawf("RELAYMSG %s %s :\x01ACTION %s\x01", msg.Channel, username, text) //nolint:errcheck
|
||||||
b.Log.Debugf("Sending to channel %s", msg.Channel)
|
} else {
|
||||||
b.i.Cmd.Message(msg.Channel, username+msg.Text)
|
b.Log.Debugf("Sending RELAYMSG to channel %s: nick=%s", msg.Channel, username)
|
||||||
|
b.i.Cmd.SendRawf("RELAYMSG %s %s :%s", msg.Channel, username, text) //nolint:errcheck
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if b.GetBool("Colornicks") {
|
||||||
|
checksum := crc32.ChecksumIEEE([]byte(msg.Username))
|
||||||
|
colorCode := checksum%14 + 2 // quick fix - prevent white or black color codes
|
||||||
|
username = fmt.Sprintf("\x03%02d%s\x0F", colorCode, msg.Username)
|
||||||
|
}
|
||||||
|
switch msg.Event {
|
||||||
|
case config.EventUserAction:
|
||||||
|
b.i.Cmd.Action(msg.Channel, username+msg.Text)
|
||||||
|
case config.EventNoticeIRC:
|
||||||
|
b.Log.Debugf("Sending notice to channel %s", msg.Channel)
|
||||||
|
b.i.Cmd.Notice(msg.Channel, username+msg.Text)
|
||||||
|
default:
|
||||||
|
b.Log.Debugf("Sending to channel %s", msg.Channel)
|
||||||
|
b.i.Cmd.Message(msg.Channel, username+msg.Text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,8 +304,9 @@ func (b *Birc) getClient() (*girc.Client, error) {
|
|||||||
TLSConfig: &tls.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"), ServerName: server}, //nolint:gosec
|
TLSConfig: &tls.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"), ServerName: server}, //nolint:gosec
|
||||||
PingDelay: pingDelay,
|
PingDelay: pingDelay,
|
||||||
// skip gIRC internal rate limiting, since we have our own throttling
|
// skip gIRC internal rate limiting, since we have our own throttling
|
||||||
AllowFlood: true,
|
AllowFlood: true,
|
||||||
Debug: debug,
|
Debug: debug,
|
||||||
|
SupportedCaps: map[string][]string{"overdrivenetworks.com/relaymsg": nil, "draft/relaymsg": nil},
|
||||||
})
|
})
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
@ -311,6 +343,15 @@ func (b *Birc) skipPrivMsg(event girc.Event) bool {
|
|||||||
if event.Source.Name == b.Nick {
|
if event.Source.Name == b.Nick {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// don't forward messages we sent via RELAYMSG
|
||||||
|
if relayedNick, ok := event.Tags.Get("draft/relaymsg"); ok && relayedNick == b.Nick {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// This is the old name of the cap sent in spoofed messages; I've kept this in
|
||||||
|
// for compatibility reasons
|
||||||
|
if relayedNick, ok := event.Tags.Get("relaymsg"); ok && relayedNick == b.Nick {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +193,19 @@ ShowTopicChange=false
|
|||||||
#OPTIONAL (default 0)
|
#OPTIONAL (default 0)
|
||||||
JoinDelay=0
|
JoinDelay=0
|
||||||
|
|
||||||
|
#Use the optional RELAYMSG extension for username spoofing on IRC.
|
||||||
|
#This requires an IRCd that supports the draft/relaymsg specification: currently this includes
|
||||||
|
#Oragono 2.4.0+ and InspIRCd 3 with the m_relaymsg contrib module.
|
||||||
|
#See https://github.com/42wim/matterbridge/issues/667#issuecomment-634214165 for more details.
|
||||||
|
#Spoofed nicks will use the configured RemoteNickFormat, replacing reserved IRC characters
|
||||||
|
#(!+%@&#$:'"?*,.) with a hyphen (-).
|
||||||
|
#On most configurations, the RemoteNickFormat must include a separator character such as "/".
|
||||||
|
#You should make sure that the settings here match your IRCd.
|
||||||
|
#This option overrides ColorNicks.
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
UseRelayMsg=false
|
||||||
|
#RemoteNickFormat="{NICK}/{PROTOCOL}"
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#XMPP section
|
#XMPP section
|
||||||
###################################################################
|
###################################################################
|
||||||
|
Loading…
Reference in New Issue
Block a user