diff --git a/TODO.txt b/TODO.txt index 139365a..1b69493 100644 --- a/TODO.txt +++ b/TODO.txt @@ -7,8 +7,6 @@ WISHLIST - automatic markdown bold/italic formatting -- client version sync (CTCP VERSION) - - support changing nick (via reconnecting) - support USERHOST (used by androirc) diff --git a/server.go b/server.go index 7ac0fae..994d7ec 100644 --- a/server.go +++ b/server.go @@ -51,6 +51,8 @@ type Server struct { verbose bool autojoin bool + + sentCtcpVersion bool } func NewServer(name string, upstream libnmdc.HubAddress, conn net.Conn) *Server { @@ -244,6 +246,12 @@ func (s *Server) upstreamWorker() { } else { // nick!username@userhost, but for us all three of those are always identical s.reply(rplMsg, hubEvent.Nick+"!"+hubEvent.Nick+"@"+hubEvent.Nick, BLESSED_CHANNEL, reformatIncomingMessageBody(hubEvent.Message)) + + if !s.sentCtcpVersion { + // Abuse this first username in order to also send a CTCP version request + s.reply(rplMsg, hubEvent.Nick+"!"+hubEvent.Nick+"@"+hubEvent.Nick, BLESSED_CHANNEL, "\x01VERSION\x01") + s.sentCtcpVersion = true + } } case libnmdc.EVENT_SYSTEM_MESSAGE_FROM_CONN, libnmdc.EVENT_SYSTEM_MESSAGE_FROM_HUB: @@ -346,10 +354,6 @@ func (s *Server) handleCommand(command string, args []string) { s.handleCommand("JOIN", []string{BLESSED_CHANNEL}) } - // Send a CTCP VERSION request to the client. If the IRC client can - // supply a client version string, we can replace our tag with it, - // but that's optional - default: s.handleRegisteredCommand(command, args) } @@ -413,6 +417,24 @@ func (s *Server) handleRegisteredCommand(command string, args []string) { } } +func (s *Server) SetClientSoftwareVersion(ver string) { + // "HexChat 2.12.1 [x64] / Microsoft Windows 10 Pro (x64) [Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz (3.60GHz)]" + // A bit long and unwieldy. Heuristic: stop after the first word containing digits + + parts := regexp.MustCompilePOSIX("^([^0-9]*[0-9]+[^ ]*) ").FindStringSubmatch(ver) + + if len(parts) > 0 { + ver = strings.TrimRight(parts[0], " ") + } + + s.verbosef("Replacing client tag with '%s'...", ver) + + s.upstreamLauncher.Self.ClientTag = ver + s.upstream.Hco.Self.ClientTag = ver + + s.upstream.SayInfo() +} + func (s *Server) handleJoinedCommand(command string, args []string) { if s.clientState != CSJoined { @@ -446,6 +468,14 @@ func (s *Server) handleJoinedCommand(command string, args []string) { message := strings.Join(args[1:], " ")[1:] // strip leading colon + if strings.HasPrefix(message, "\x01VERSION ") { + // Not a real message - a reply to our internal request. Change the user's tag to match the actual client software + versionString := message[9:] + versionString = versionString[:len(versionString)-1] + s.SetClientSoftwareVersion(versionString) + return + } + if strings.HasPrefix(message, "\x01ACTION ") { message = "/me " + message[8:] message = message[:len(message)-1] // trailing \x01