diff --git a/irc/modes/modes.go b/irc/modes/modes.go index 9e311298..ae2d9224 100644 --- a/irc/modes/modes.go +++ b/irc/modes/modes.go @@ -6,6 +6,7 @@ package modes import ( + "sort" "strings" "github.com/oragono/oragono/irc/utils" @@ -418,3 +419,27 @@ func (set *ModeSet) HighestChannelUserMode() (result Mode) { } return } + +type ByCodepoint Modes + +func (a ByCodepoint) Len() int { return len(a) } +func (a ByCodepoint) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByCodepoint) Less(i, j int) bool { return a[i] < a[j] } + +func RplMyInfo() (param1, param2, param3 string) { + userModes := make(Modes, len(SupportedUserModes)) + copy(userModes, SupportedUserModes) + sort.Sort(ByCodepoint(userModes)) + + channelModes := make(Modes, len(SupportedChannelModes)+len(ChannelUserModes)) + copy(channelModes, SupportedChannelModes) + copy(channelModes[len(SupportedChannelModes):], ChannelUserModes) + sort.Sort(ByCodepoint(channelModes)) + + // XXX enumerate these by hand, i can't see any way to DRY this + channelParametrizedModes := Modes{BanMask, ExceptMask, InviteMask, Key, UserLimit} + channelParametrizedModes = append(channelParametrizedModes, ChannelUserModes...) + sort.Sort(ByCodepoint(channelParametrizedModes)) + + return userModes.String(), channelModes.String(), channelParametrizedModes.String() +} diff --git a/irc/server.go b/irc/server.go index dfeb118a..d20ebd35 100644 --- a/irc/server.go +++ b/irc/server.go @@ -36,10 +36,8 @@ var ( // common error line to sub values into errorMsg = "ERROR :%s\r\n" - // supportedUserModesString acts as a cache for when we introduce users - supportedUserModesString = modes.SupportedUserModes.String() - // supportedChannelModesString acts as a cache for when we introduce users - supportedChannelModesString = modes.SupportedChannelModes.String() + // three final parameters of 004 RPL_MYINFO, enumerating our supported modes + rplMyInfo1, rplMyInfo2, rplMyInfo3 = modes.RplMyInfo() // whitelist of caps to serve on the STS-only listener. In particular, // never advertise SASL, to discourage people from sending their passwords: @@ -297,8 +295,7 @@ func (server *Server) playRegistrationBurst(session *Session) { session.Send(nil, server.name, RPL_WELCOME, d.nick, fmt.Sprintf(c.t("Welcome to the Internet Relay Network %s"), d.nick)) session.Send(nil, server.name, RPL_YOURHOST, d.nick, fmt.Sprintf(c.t("Your host is %[1]s, running version %[2]s"), server.name, Ver)) session.Send(nil, server.name, RPL_CREATED, d.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123))) - //TODO(dan): Look at adding last optional [] parameter - session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString) + session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, rplMyInfo1, rplMyInfo2, rplMyInfo3) if c.isSTSOnly { for _, line := range server.Config().Server.STS.bannerLines {