@ -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 ( ) {
rate := time . Millisecond * time . Duration ( b . MessageDelay )
throttle := time . NewTicker ( rate )
for msg := range b . Local {
<- throttle . C
username := msg . Username
if b . GetBool ( "Colornicks" ) && len ( username ) > 1 {
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 )
}
// Optional support for the proposed RELAYMSG extension, described at
// https://github.com/jlu5/ircv3-specifications/blob/master/extensions/relaymsg.md
// nolint:nestif
if ( b . i . HasCapability ( "overdrivenetworks.com/relaymsg" ) || b . i . HasCapability ( "draft/relaymsg" ) ) &&
b . GetBool ( "UseRelayMsg" ) {
username = sanitizeNick ( username )
text := msg . Text
// Work around girc chomping leading commas on single word messages?
if strings . HasPrefix ( text , ":" ) && ! strings . ContainsRune ( text , ' ' ) {
text = ":" + text
}
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 )
if msg . Event == config . EventUserAction {
b . i . Cmd . SendRawf ( "RELAYMSG %s %s :\x01ACTION %s\x01" , msg . Channel , username , text ) //nolint:errcheck
} else {
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
PingDelay : pingDelay ,
// skip gIRC internal rate limiting, since we have our own throttling
AllowFlood : true ,
Debug : debug ,
AllowFlood : true ,
Debug : debug ,
SupportedCaps : map [ string ] [ ] string { "overdrivenetworks.com/relaymsg" : nil , "draft/relaymsg" : nil } ,
} )
return i , nil
}
@ -311,6 +343,15 @@ func (b *Birc) skipPrivMsg(event girc.Event) bool {
if event . Source . Name == b . Nick {
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
}