From 60af8ee491d1f713b8a2d347dcad0c0dfb458d15 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Thu, 1 Jun 2023 06:28:02 -0400 Subject: [PATCH] clean up force-trailing logic --- irc/client.go | 30 +++++++++++++++--------------- irc/message_cache.go | 6 ++---- irc/utils/types.go | 8 ++++++++ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/irc/client.go b/irc/client.go index feca599b..1f74dee9 100644 --- a/irc/client.go +++ b/irc/client.go @@ -1425,27 +1425,27 @@ func composeMultilineBatch(batchID, fromNickMask, fromAccount string, isBot bool } var ( - // these are all the output commands that MUST have their last param be a trailing. - // this is needed because dumb clients like to treat trailing params separately from the - // other params in messages. - commandsThatMustUseTrailing = map[string]bool{ - "PRIVMSG": true, - "NOTICE": true, - - RPL_WHOISCHANNELS: true, - RPL_USERHOST: true, - + // in practice, many clients require that the final parameter be a trailing + // (prefixed with `:`) even when this is not syntactically necessary. + // by default, force the following commands to use a trailing: + commandsThatMustUseTrailing = utils.SetLiteral( + "PRIVMSG", + "NOTICE", + RPL_WHOISCHANNELS, + RPL_USERHOST, // mirc's handling of RPL_NAMREPLY is broken: // https://forums.mirc.com/ubbthreads.php/topics/266939/re-nick-list - RPL_NAMREPLY: true, - } + RPL_NAMREPLY, + ) ) +func forceTrailing(config *Config, command string) bool { + return config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing.Has(command) +} + // SendRawMessage sends a raw message to the client. func (session *Session) SendRawMessage(message ircmsg.Message, blocking bool) error { - // use dumb hack to force the last param to be a trailing param if required - config := session.client.server.Config() - if config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[message.Command] { + if forceTrailing(session.client.server.Config(), message.Command) { message.ForceTrailing() } diff --git a/irc/message_cache.go b/irc/message_cache.go index cde8b68d..2d731823 100644 --- a/irc/message_cache.go +++ b/irc/message_cache.go @@ -79,8 +79,7 @@ func (m *MessageCache) Initialize(server *Server, serverTime time.Time, msgid st m.params = params var msg ircmsg.Message - config := server.Config() - if config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[command] { + if forceTrailing(server.Config(), command) { msg.ForceTrailing() } msg.Source = nickmask @@ -111,8 +110,7 @@ func (m *MessageCache) InitializeSplitMessage(server *Server, nickmask, accountN m.target = target m.splitMessage = message - config := server.Config() - forceTrailing := config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[command] + forceTrailing := forceTrailing(server.Config(), command) if message.Is512() { isTagmsg := command == "TAGMSG" diff --git a/irc/utils/types.go b/irc/utils/types.go index ca1e4f7a..8c2ca4eb 100644 --- a/irc/utils/types.go +++ b/irc/utils/types.go @@ -20,6 +20,14 @@ func (s HashSet[T]) Remove(elem T) { delete(s, elem) } +func SetLiteral[T comparable](elems ...T) HashSet[T] { + result := make(HashSet[T], len(elems)) + for _, elem := range elems { + result.Add(elem) + } + return result +} + func CopyMap[K comparable, V any](input map[K]V) (result map[K]V) { result = make(map[K]V, len(input)) for key, value := range input {