irc: add support for stateless bridging via draft/relaymsg
As discussed at https://github.com/42wim/matterbridge/issues/667#issuecomment-634214165
This commit is contained in:
@@ -205,27 +205,57 @@ 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
|
if (b.i.HasCapability("overdrivenetworks.com/relaymsg") || b.i.HasCapability("draft/relaymsg")) &&
|
||||||
username = fmt.Sprintf("\x03%02d%s\x0F", colorCode, msg.Username)
|
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)
|
||||||
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)
|
||||||
|
}
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,18 +293,19 @@ func (b *Birc) getClient() (*girc.Client, error) {
|
|||||||
b.Log.Debugf("setting pingdelay to %s", pingDelay)
|
b.Log.Debugf("setting pingdelay to %s", pingDelay)
|
||||||
|
|
||||||
i := girc.New(girc.Config{
|
i := girc.New(girc.Config{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPass: b.GetString("Password"),
|
ServerPass: b.GetString("Password"),
|
||||||
Port: port,
|
Port: port,
|
||||||
Nick: b.GetString("Nick"),
|
Nick: b.GetString("Nick"),
|
||||||
User: user,
|
User: user,
|
||||||
Name: b.GetString("Nick"),
|
Name: b.GetString("Nick"),
|
||||||
SSL: b.GetBool("UseTLS"),
|
SSL: b.GetBool("UseTLS"),
|
||||||
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 +342,10 @@ 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("relaymsg"); ok && relayedNick == b.Nick {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user