diff --git a/bridge/discord.go b/bridge/discord.go index 6bd89f8..069750e 100644 --- a/bridge/discord.go +++ b/bridge/discord.go @@ -247,6 +247,7 @@ func (d *discordBot) handleMemberUpdate(m *discordgo.Member) { d.bridge.updateUserChan <- DiscordUser{ ID: m.User.ID, + Username: m.User.Username, Discriminator: m.User.Discriminator, Nick: GetMemberNick(m), Bot: m.User.Bot, diff --git a/bridge/irc_connection.go b/bridge/irc_connection.go index 495cb6a..a112604 100644 --- a/bridge/irc_connection.go +++ b/bridge/irc_connection.go @@ -12,10 +12,8 @@ import ( type ircConnection struct { innerCon *irc.Connection - userID string - discriminator string - originalNick string - nick string + discord DiscordUser + nick string messages chan IRCMessage @@ -38,24 +36,20 @@ func (i *ircConnection) OnWelcome(e *irc.Event) { } func (i *ircConnection) JoinChannels() { - channels := i.manager.RequestChannels(i.userID) + channels := i.manager.RequestChannels(i.discord.ID) i.innerCon.SendRaw("JOIN " + strings.Join(channels, ",")) } -func (i *ircConnection) UpdateDetails(discriminator, nick string) { +func (i *ircConnection) UpdateDetails(discord DiscordUser) { // if their details haven't changed, don't do anything - if (i.originalNick == nick) && (i.discriminator == discriminator) { + if (i.discord.Nick == discord.Nick) && (i.discord.Discriminator == discord.Discriminator) { return } - i.originalNick = nick + i.discord = discord + i.nick = i.manager.generateNickname(i.discord) - nick = i.manager.generateNickname(discriminator, nick) - - i.discriminator = discriminator - i.nick = nick - - go i.innerCon.Nick(nick) + go i.innerCon.Nick(i.nick) } func (i *ircConnection) OnPrivateMessage(e *irc.Event) { @@ -64,7 +58,7 @@ func (i *ircConnection) OnPrivateMessage(e *irc.Event) { if e.Message() == "help" { i.innerCon.Privmsg(e.Nick, "help, who") } else if e.Message() == "who" { - i.innerCon.Privmsgf(e.Nick, "I am: %s#%s with ID %s", i.originalNick, i.discriminator, i.userID) + i.innerCon.Privmsgf(e.Nick, "I am: %s#%s with ID %s", i.discord.Nick, i.discord.Discriminator, i.discord.ID) } else { i.innerCon.Privmsg(e.Nick, "Private messaging Discord users is not supported, but I support commands! Type 'help'.") } diff --git a/bridge/irc_manager.go b/bridge/irc_manager.go index 9d0e0fa..7140f11 100644 --- a/bridge/irc_manager.go +++ b/bridge/irc_manager.go @@ -2,6 +2,7 @@ package bridge import ( "fmt" + "math" "time" "github.com/qaisjp/go-discord-irc/ircnick" @@ -25,7 +26,7 @@ func NewIRCManager(bridge *Bridge) *IRCManager { } func (m *IRCManager) CloseConnection(i *ircConnection) { - delete(m.ircConnections, i.userID) + delete(m.ircConnections, i.discord.ID) close(i.messages) i.innerCon.Quit() } @@ -52,7 +53,7 @@ func (m *IRCManager) HandleUser(user DiscordUser) { // from `online` to `dnd` (online related states) // In UpdateDetails we handle nickname changes so it is // OK to call the below potentially redundant function - con.UpdateDetails(user.Discriminator, user.Nick) + con.UpdateDetails(user) return } @@ -61,10 +62,10 @@ func (m *IRCManager) HandleUser(user DiscordUser) { return } - nick := m.generateNickname(user.Discriminator, user.Nick) + nick := m.generateNickname(user) innerCon := irc.IRC(nick, "discord") - // innerCon.Debug = true + innerCon.Debug = m.bridge.Config.Debug var ip string { @@ -89,9 +90,8 @@ func (m *IRCManager) HandleUser(user DiscordUser) { con := &ircConnection{ innerCon: innerCon, - userID: user.ID, - discriminator: user.Discriminator, - nick: user.Nick, + discord: user, + nick: nick, messages: make(chan IRCMessage), @@ -115,11 +115,37 @@ func (m *IRCManager) HandleUser(user DiscordUser) { return } -func (m *IRCManager) generateNickname(_ string, nick string) string { - // First clean it - nick = ircnick.NickClean(nick) +func (m *IRCManager) generateNickname(discord DiscordUser) string { + username := discord.Username + discriminator := discord.Discriminator + nick := discord.Nick - return nick + m.bridge.Config.Suffix + // https://github.com/lp0/charybdis/blob/9ced2a7932dddd069636fe6fe8e9faa6db904703/ircd/client.c#L854-L884 + if nick[0] == '-' { + nick = "_" + nick + } + if ircnick.IsDigit(nick[0]) { + nick = "_" + nick + } + + newNick := []byte(nick) + + // Replace bad characters with underscores + for i, c := range []byte(nick) { + if !ircnick.IsNickChar(c) || ircnick.IsFakeNickChar(c) { + newNick[i] = '_' + } + } + + suffix := m.bridge.Config.Suffix + nick = string(newNick) + suffix + + if len(nick) > 30 { + length := int(math.Min(float64(len(username)), float64(30-len(discriminator)-len(suffix)))) + return username[:length] + discriminator + suffix + } + + return nick } func (m *IRCManager) SendMessage(channel string, msg *DiscordMessage) { diff --git a/bridge/structs.go b/bridge/structs.go index b5d3664..3ced0d1 100644 --- a/bridge/structs.go +++ b/bridge/structs.go @@ -22,7 +22,8 @@ type IRCMessage struct { // DiscordUser is information that IRC needs to know about a user type DiscordUser struct { ID string // globally unique id - Discriminator string // locally unique ID + Username string + Discriminator string Nick string // still non-unique Bot bool // are they a bot? Online bool diff --git a/ircnick/clean.go b/ircnick/clean.go deleted file mode 100644 index c4c8c5f..0000000 --- a/ircnick/clean.go +++ /dev/null @@ -1,25 +0,0 @@ -package ircnick - -// NickClean replaces invalid characters with an underscore -func NickClean(nick string) string { - // https://github.com/lp0/charybdis/blob/9ced2a7932dddd069636fe6fe8e9faa6db904703/ircd/client.c#L854-L884 - if nick[0] == '-' { - nick = "_" + nick - } - if IsDigit(nick[0]) { - nick = "_" + nick - } - - newNick := []byte(nick) - - // Replace bad characters with underscores - for i, c := range []byte(nick) { - if !IsNickChar(c) || IsFakeNickChar(c) { - newNick[i] = '_' - } else { - // newNick[i] = c - } - } - - return string(newNick) -}