3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-14 16:09:32 +01:00

Enhancements to CS PURGE

1. Consolidate PURGE and UNPURGE into subcommands
2. Add PURGE LIST
3. PURGE ADD now requires a confirmation code

Fixes #1294
This commit is contained in:
Shivaram Lingamneni 2020-12-15 04:00:44 -05:00
parent 4d5815ab2e
commit fd71b79bb8
3 changed files with 76 additions and 19 deletions

View File

@ -4,6 +4,7 @@
package irc package irc
import ( import (
"sort"
"sync" "sync"
"github.com/oragono/oragono/irc/utils" "github.com/oragono/oragono/irc/utils"
@ -405,3 +406,14 @@ func (cm *ChannelManager) Unpurge(chname string) (err error) {
} }
return nil return nil
} }
func (cm *ChannelManager) ListPurged() (result []string) {
cm.RLock()
result = make([]string, 0, len(cm.purgedChannels))
for c := range cm.purgedChannels {
result = append(result, c)
}
cm.RUnlock()
sort.Strings(result)
return
}

View File

@ -114,28 +114,19 @@ To cancel a pending transfer, transfer the channel to yourself.`,
}, },
"purge": { "purge": {
handler: csPurgeHandler, handler: csPurgeHandler,
help: `Syntax: $bPURGE #channel [reason]$b help: `Syntax: $bPURGE <ADD | DEL | LIST> #channel [code] [reason]$b
PURGE blacklists a channel from the server, making it impossible to join PURGE ADD blacklists a channel from the server, making it impossible to join
or otherwise interact with the channel. If the channel currently has members, or otherwise interact with the channel. If the channel currently has members,
they will be kicked from it. PURGE may also be applied preemptively to they will be kicked from it. PURGE may also be applied preemptively to
channels that do not currently have members.`, channels that do not currently have members. A purge can be undone with
PURGE DEL. To list purged channels, use PURGE LIST.`,
helpShort: `$bPURGE$b blacklists a channel from the server.`, helpShort: `$bPURGE$b blacklists a channel from the server.`,
capabs: []string{"chanreg"}, capabs: []string{"chanreg"},
minParams: 1, minParams: 1,
maxParams: 2, maxParams: 3,
unsplitFinalParam: true, unsplitFinalParam: true,
}, },
"unpurge": {
handler: csUnpurgeHandler,
help: `Syntax: $bUNPURGE #channel$b
UNPURGE removes any blacklisting of a channel that was previously
set using PURGE.`,
helpShort: `$bUNPURGE$b undoes a previous PURGE command.`,
capabs: []string{"chanreg"},
minParams: 1,
},
"list": { "list": {
handler: csListHandler, handler: csListHandler,
help: `Syntax: $bLIST [regex]$b help: `Syntax: $bLIST [regex]$b
@ -587,19 +578,53 @@ func csPurgeHandler(service *ircService, server *Server, client *Client, command
return // should be impossible because you need oper capabs for this return // should be impossible because you need oper capabs for this
} }
switch strings.ToLower(params[0]) {
case "add":
csPurgeAddHandler(service, client, params[1:], oper.Name, rb)
case "del", "remove":
csPurgeDelHandler(service, client, params[1:], oper.Name, rb)
case "list":
csPurgeListHandler(service, client, rb)
default:
service.Notice(rb, client.t("Invalid parameters"))
}
}
func csPurgeAddHandler(service *ircService, client *Client, params []string, operName string, rb *ResponseBuffer) {
if len(params) == 0 {
service.Notice(rb, client.t("Invalid parameters"))
return
}
chname := params[0] chname := params[0]
params = params[1:]
channel := client.server.channels.Get(chname) // possibly nil
var ctime time.Time
if channel != nil {
chname = channel.Name()
ctime = channel.Ctime()
}
code := utils.ConfirmationCode(chname, ctime)
if len(params) == 0 || params[0] != code {
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: you are about to empty this channel and remove it from the server.$b")))
service.Notice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/CS PURGE ADD %s %s", chname, code)))
return
}
params = params[1:]
var reason string var reason string
if 1 < len(params) { if 1 < len(params) {
reason = params[1] reason = params[1]
} }
purgeRecord := ChannelPurgeRecord{ purgeRecord := ChannelPurgeRecord{
Oper: oper.Name, Oper: operName,
PurgedAt: time.Now().UTC(), PurgedAt: time.Now().UTC(),
Reason: reason, Reason: reason,
} }
switch server.channels.Purge(chname, purgeRecord) { switch client.server.channels.Purge(chname, purgeRecord) {
case nil: case nil:
channel := server.channels.Get(chname)
if channel != nil { // channel need not exist to be purged if channel != nil { // channel need not exist to be purged
for _, target := range channel.Members() { for _, target := range channel.Members() {
channel.Kick(client, target, "Cleared by ChanServ", rb, true) channel.Kick(client, target, "Cleared by ChanServ", rb, true)
@ -613,9 +638,14 @@ func csPurgeHandler(service *ircService, server *Server, client *Client, command
} }
} }
func csUnpurgeHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { func csPurgeDelHandler(service *ircService, client *Client, params []string, operName string, rb *ResponseBuffer) {
if len(params) == 0 {
service.Notice(rb, client.t("Invalid parameters"))
return
}
chname := params[0] chname := params[0]
switch server.channels.Unpurge(chname) { switch client.server.channels.Unpurge(chname) {
case nil: case nil:
service.Notice(rb, fmt.Sprintf(client.t("Successfully unpurged channel %s from the server"), chname)) service.Notice(rb, fmt.Sprintf(client.t("Successfully unpurged channel %s from the server"), chname))
case errNoSuchChannel: case errNoSuchChannel:
@ -625,6 +655,14 @@ func csUnpurgeHandler(service *ircService, server *Server, client *Client, comma
} }
} }
func csPurgeListHandler(service *ircService, client *Client, rb *ResponseBuffer) {
l := client.server.channels.ListPurged()
service.Notice(rb, fmt.Sprintf(client.t("There are %d purged channel(s)."), len(l)))
for i, c := range l {
service.Notice(rb, fmt.Sprintf("%d: %s", i+1, c))
}
}
func csListHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { func csListHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
if !client.HasRoleCapabs("chanreg") { if !client.HasRoleCapabs("chanreg") {
service.Notice(rb, client.t("Insufficient privileges")) service.Notice(rb, client.t("Insufficient privileges"))

View File

@ -523,3 +523,10 @@ func (channel *Channel) setForward(forward string) {
channel.forward = forward channel.forward = forward
channel.stateMutex.Unlock() channel.stateMutex.Unlock()
} }
func (channel *Channel) Ctime() (ctime time.Time) {
channel.stateMutex.RLock()
ctime = channel.createdTime
channel.stateMutex.RUnlock()
return
}