diff --git a/bridge/irc_listener.go b/bridge/irc_listener.go index 1875a73..983b2ec 100644 --- a/bridge/irc_listener.go +++ b/bridge/irc_listener.go @@ -13,11 +13,12 @@ type ircListener struct { bridge *Bridge joinQuitCallbacks map[string]int + relayNickTrackID int } func newIRCListener(dib *Bridge, webIRCPass string) *ircListener { irccon := irc.IRC(dib.Config.IRCListenerName, "discord") - listener := &ircListener{irccon, dib, nil} + listener := &ircListener{irccon, dib, nil, 0} dib.SetupIRCConnection(irccon, "discord.", "fd75:f5f5:226f::") listener.SetDebugMode(dib.Config.Debug) @@ -39,6 +40,8 @@ func newIRCListener(dib *Bridge, webIRCPass string) *ircListener { listener.JoinChannels() }) + listener.AddCallback("NICK", listener.nickTrackNick) + // Note that this might override SetupNickTrack! listener.OnJoinQuitSettingChange() @@ -54,6 +57,51 @@ func (i *ircListener) nickTrackNick(event *irc.Event) { } } +func userOnChannelFix(user string, channel irc.Channel) bool { + if _, ok := channel.Users[user]; ok { + return true + } + + // work around nicks being prefixed with mode characters for some reason + for _, c := range "!$~&@%+" { + if _, ok := channel.Users[string(c)+user]; ok { + return true + } + } + + return false +} + +func (i *ircListener) OnNickRelayToDiscord(event *irc.Event) { + newNick := event.Message() + message := i.bridge.ircManager.formatDiscordMessage(event.Code, event, newNick, "") + + // if the message is empty... + if message == "" { + return // do nothing, Discord doesn't like empty messages anyway + } + + msg := IRCMessage{ + Username: "", + Message: message, + } + + for _, m := range i.bridge.mappings { + channel := m.IRCChannel + channelObj, ok := i.Connection.Channels[channel] + if !ok { + continue + } + + if !userOnChannelFix(newNick, channelObj) { + continue + } + + msg.IRCChannel = channel + i.bridge.discordMessagesChan <- msg + } +} + // From irc_nicktrack.go. func (i *ircListener) nickTrackQuit(e *irc.Event) { for k := range i.Connection.Channels { @@ -64,8 +112,11 @@ func (i *ircListener) nickTrackQuit(e *irc.Event) { func (i *ircListener) OnJoinQuitSettingChange() { // Clear Nicktrack QUIT callback as it races with this i.ClearCallback("QUIT") - i.ClearCallback("NICK") - i.AddCallback("NICK", i.nickTrackNick) + + if i.relayNickTrackID != 0 { + i.RemoveCallback("NICK", i.relayNickTrackID) + i.relayNickTrackID = 0 + } // If remove callbacks... if !i.bridge.Config.ShowJoinQuit { @@ -78,6 +129,8 @@ func (i *ircListener) OnJoinQuitSettingChange() { return } + i.relayNickTrackID = i.AddCallback("NICK", i.OnNickRelayToDiscord) + callbacks := []string{"JOIN", "PART", "QUIT", "KICK"} cbs := make(map[string]int, len(callbacks)) for _, cb := range callbacks { diff --git a/main.go b/main.go index 258db47..e1a9931 100644 --- a/main.go +++ b/main.go @@ -290,6 +290,7 @@ func setupDiscordFormat(discordFormat map[string]string) (map[string]string, err "part": "_${NICK} left (${IDENT}@${HOST}) - ${CONTENT}_", "quit": "_${NICK} quit (${IDENT}@${HOST}) - Quit: ${CONTENT}_", "kick": "_${TARGET} was kicked by ${NICK} - ${CONTENT}_", + "nick": "_${NICK} changed nick to ${CONTENT}_", } for ev, format := range discordFormatDefaults {