diff --git a/CHANGELOG.md b/CHANGELOG.md index eb4259ab..d6827690 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ New release of Oragono! ### Fixed * Fixed an account issue where clients could login to multiple accounts at once. * Fixed issues that prevented rehashing after the first rehash had gone through successfully. +* Fixed the inability to view channel ban, ban exception, and invite exception lists. ## [0.6.0] - 2017-01-19 diff --git a/irc/channel.go b/irc/channel.go index c9a1e545..b62fb5af 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -299,6 +299,15 @@ func (channel *Channel) Join(client *Client, key string) { channel.topicSetTime = chanReg.TopicSetTime channel.name = chanReg.Name channel.createdTime = chanReg.RegisteredAt + for _, mask := range chanReg.Banlist { + channel.lists[BanMask].Add(mask) + } + for _, mask := range chanReg.Exceptlist { + channel.lists[ExceptMask].Add(mask) + } + for _, mask := range chanReg.Invitelist { + channel.lists[InviteMask].Add(mask) + } } return nil }) @@ -587,13 +596,24 @@ func (channel *Channel) applyModeMemberNoMutex(client *Client, mode Mode, } func (channel *Channel) ShowMaskList(client *Client, mode Mode) { - //TODO(dan): WE NEED TO fiX this PROPERLY - log.Fatal("Implement ShowMaskList") - /* - for lmask := range channel.lists[mode].masks { - client.RplMaskList(mode, channel, lmask) - } - client.RplEndOfMaskList(mode, channel)*/ + // choose appropriate modes + var rpllist, rplendoflist string + if mode == BanMask { + rpllist = RPL_BANLIST + rplendoflist = RPL_ENDOFBANLIST + } else if mode == ExceptMask { + rpllist = RPL_EXCEPTLIST + rplendoflist = RPL_ENDOFEXCEPTLIST + } else if mode == InviteMask { + rpllist = RPL_INVITELIST + rplendoflist = RPL_ENDOFINVITELIST + } + + // send out responses + for mask := range channel.lists[mode].masks { + client.Send(nil, client.server.name, rpllist, client.nick, channel.name, mask) + } + client.Send(nil, client.server.name, rplendoflist, client.nick, channel.name, "End of list") } func (channel *Channel) applyModeMask(client *Client, mode Mode, op ModeOp, mask string) bool { diff --git a/irc/channelreg.go b/irc/channelreg.go index a004f4ef..15cb3ea5 100644 --- a/irc/channelreg.go +++ b/irc/channelreg.go @@ -9,6 +9,8 @@ import ( "strconv" "time" + "encoding/json" + "github.com/tidwall/buntdb" ) @@ -20,6 +22,9 @@ const ( keyChannelTopic = "channel.topic %s" keyChannelTopicSetBy = "channel.topic.setby %s" keyChannelTopicSetTime = "channel.topic.settime %s" + keyChannelBanlist = "channel.banlist %s" + keyChannelExceptlist = "channel.exceptlist %s" + keyChannelInvitelist = "channel.invitelist %s" ) var ( @@ -40,6 +45,12 @@ type RegisteredChannel struct { TopicSetBy string // TopicSetTime represents the time the topic was set. TopicSetTime time.Time + // Banlist represents the bans set on the channel. + Banlist []string + // Exceptlist represents the exceptions set on the channel. + Exceptlist []string + // Invitelist represents the invite exceptions set on the channel. + Invitelist []string } // loadChannelNoMutex loads a channel from the store. @@ -63,6 +74,16 @@ func (server *Server) loadChannelNoMutex(tx *buntdb.Tx, channelKey string) *Regi topicSetBy, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetBy, channelKey)) topicSetTime, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetTime, channelKey)) topicSetTimeInt, _ := strconv.ParseInt(topicSetTime, 10, 64) + banlistString, _ := tx.Get(fmt.Sprintf(keyChannelBanlist, channelKey)) + exceptlistString, _ := tx.Get(fmt.Sprintf(keyChannelExceptlist, channelKey)) + invitelistString, _ := tx.Get(fmt.Sprintf(keyChannelInvitelist, channelKey)) + + var banlist []string + _ = json.Unmarshal([]byte(banlistString), &banlist) + var exceptlist []string + _ = json.Unmarshal([]byte(exceptlistString), &exceptlist) + var invitelist []string + _ = json.Unmarshal([]byte(invitelistString), &invitelist) chanInfo := RegisteredChannel{ Name: name, @@ -71,6 +92,9 @@ func (server *Server) loadChannelNoMutex(tx *buntdb.Tx, channelKey string) *Regi Topic: topic, TopicSetBy: topicSetBy, TopicSetTime: time.Unix(topicSetTimeInt, 0), + Banlist: banlist, + Exceptlist: exceptlist, + Invitelist: invitelist, } server.registeredChannels[channelKey] = &chanInfo @@ -86,5 +110,13 @@ func (server *Server) saveChannelNoMutex(tx *buntdb.Tx, channelKey string, chann tx.Set(fmt.Sprintf(keyChannelTopic, channelKey), channelInfo.Topic, nil) tx.Set(fmt.Sprintf(keyChannelTopicSetBy, channelKey), channelInfo.TopicSetBy, nil) tx.Set(fmt.Sprintf(keyChannelTopicSetTime, channelKey), strconv.FormatInt(channelInfo.TopicSetTime.Unix(), 10), nil) + + banlistString, _ := json.Marshal(channelInfo.Banlist) + tx.Set(fmt.Sprintf(keyChannelBanlist, channelKey), string(banlistString), nil) + exceptlistString, _ := json.Marshal(channelInfo.Exceptlist) + tx.Set(fmt.Sprintf(keyChannelExceptlist, channelKey), string(exceptlistString), nil) + invitelistString, _ := json.Marshal(channelInfo.Invitelist) + tx.Set(fmt.Sprintf(keyChannelInvitelist, channelKey), string(invitelistString), nil) + server.registeredChannels[channelKey] = &channelInfo } diff --git a/irc/modes.go b/irc/modes.go index 53f001c0..8e2aba2e 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/DanielOaks/girc-go/ircmsg" + "github.com/tidwall/buntdb" ) // ModeOp is an operation performed with modes @@ -311,7 +312,7 @@ func ParseChannelModeChanges(params ...string) (ModeChanges, map[rune]bool) { changes := make(ModeChanges, 0) unknown := make(map[rune]bool) - if len(params) > 1 { + if 0 < len(params) { modeArg := params[0] op := ModeOp(modeArg[0]) if (op == Add) || (op == Remove) { @@ -553,6 +554,53 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { applied = ApplyChannelModeChanges(channel, client, msg.Command == "SAMODE", changes) } + // save changes to banlist/exceptlist/invexlist + var banlistUpdated, exceptlistUpdated, invexlistUpdated bool + for _, change := range applied { + if change.mode == BanMask { + banlistUpdated = true + } else if change.mode == ExceptMask { + exceptlistUpdated = true + } else if change.mode == InviteMask { + invexlistUpdated = true + } + } + + server.registeredChannelsMutex.Lock() + if 0 < len(applied) && server.registeredChannels[channel.nameCasefolded] != nil && (banlistUpdated || exceptlistUpdated || invexlistUpdated) { + server.store.Update(func(tx *buntdb.Tx) error { + chanInfo := server.loadChannelNoMutex(tx, channel.nameCasefolded) + + if banlistUpdated { + var banlist []string + for mask := range channel.lists[BanMask].masks { + banlist = append(banlist, mask) + } + chanInfo.Banlist = banlist + } + if exceptlistUpdated { + var exceptlist []string + for mask := range channel.lists[ExceptMask].masks { + exceptlist = append(exceptlist, mask) + } + chanInfo.Exceptlist = exceptlist + } + if invexlistUpdated { + var invitelist []string + for mask := range channel.lists[InviteMask].masks { + invitelist = append(invitelist, mask) + } + chanInfo.Invitelist = invitelist + } + + server.saveChannelNoMutex(tx, channel.nameCasefolded, *chanInfo) + + return nil + }) + } + server.registeredChannelsMutex.Unlock() + + // send out changes if len(applied) > 0 { //TODO(dan): we should change the name of String and make it return a slice here args := append([]string{channel.name}, strings.Split(applied.String(), " ")...)