mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
refactor monitor and /oper implementations
This commit is contained in:
parent
5e9767c46d
commit
26686d7e86
@ -61,8 +61,6 @@ type Client struct {
|
||||
idleTimer *time.Timer
|
||||
isDestroyed bool
|
||||
isQuitting bool
|
||||
monitoring map[string]bool
|
||||
monitoringMutex sync.RWMutex
|
||||
nick string
|
||||
nickCasefolded string
|
||||
nickMaskCasefolded string
|
||||
@ -81,6 +79,7 @@ type Client struct {
|
||||
saslValue string
|
||||
server *Server
|
||||
socket *Socket
|
||||
stateMutex sync.RWMutex // generic protection for mutable state
|
||||
timerMutex sync.Mutex
|
||||
username string
|
||||
vhost string
|
||||
@ -101,7 +100,6 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
|
||||
channels: make(ChannelSet),
|
||||
ctime: now,
|
||||
flags: make(map[Mode]bool),
|
||||
monitoring: make(map[string]bool),
|
||||
server: server,
|
||||
socket: &socket,
|
||||
account: &NoAccount,
|
||||
@ -302,8 +300,8 @@ func (client *Client) Register() {
|
||||
client.registered = true
|
||||
client.Touch()
|
||||
|
||||
client.updateNickMask()
|
||||
client.alertMonitors()
|
||||
client.updateNickMask("")
|
||||
client.server.monitorManager.alertMonitors(client, true)
|
||||
}
|
||||
|
||||
// IdleTime returns how long this client's been idle.
|
||||
@ -393,19 +391,28 @@ func (client *Client) Friends(capabs ...caps.Capability) ClientSet {
|
||||
return friends
|
||||
}
|
||||
|
||||
// updateNick updates the casefolded nickname.
|
||||
func (client *Client) updateNick() {
|
||||
casefoldedName, err := CasefoldName(client.nick)
|
||||
// updateNick updates `nick` and `nickCasefolded`.
|
||||
func (client *Client) updateNick(nick string) {
|
||||
casefoldedName, err := CasefoldName(nick)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("ERROR: Nick [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nick))
|
||||
debug.PrintStack()
|
||||
}
|
||||
client.stateMutex.Lock()
|
||||
client.nick = nick
|
||||
client.nickCasefolded = casefoldedName
|
||||
client.stateMutex.Unlock()
|
||||
}
|
||||
|
||||
// updateNickMask updates the casefolded nickname and nickmask.
|
||||
func (client *Client) updateNickMask() {
|
||||
client.updateNick()
|
||||
func (client *Client) updateNickMask(nick string) {
|
||||
// on "", just regenerate the nickmask etc.
|
||||
// otherwise, update the actual nick
|
||||
if nick != "" {
|
||||
client.updateNick(nick)
|
||||
}
|
||||
|
||||
client.stateMutex.Lock()
|
||||
|
||||
if len(client.vhost) > 0 {
|
||||
client.hostname = client.vhost
|
||||
@ -413,14 +420,17 @@ func (client *Client) updateNickMask() {
|
||||
client.hostname = client.rawHostname
|
||||
}
|
||||
|
||||
client.nickMaskString = fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
|
||||
|
||||
nickMaskCasefolded, err := Casefold(client.nickMaskString)
|
||||
nickMaskString := fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
|
||||
nickMaskCasefolded, err := Casefold(nickMaskString)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("ERROR: Nickmask [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nickMaskString))
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
client.nickMaskString = nickMaskString
|
||||
client.nickMaskCasefolded = nickMaskCasefolded
|
||||
|
||||
client.stateMutex.Unlock()
|
||||
}
|
||||
|
||||
// AllNickmasks returns all the possible nickmasks for the client.
|
||||
@ -458,8 +468,7 @@ func (client *Client) SetNickname(nickname string) error {
|
||||
|
||||
err := client.server.clients.Add(client, nickname)
|
||||
if err == nil {
|
||||
client.nick = nickname
|
||||
client.updateNick()
|
||||
client.updateNick(nickname)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -472,8 +481,7 @@ func (client *Client) ChangeNickname(nickname string) error {
|
||||
client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s", client.nick, nickname))
|
||||
client.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), client.nick, nickname))
|
||||
client.server.whoWas.Append(client)
|
||||
client.nick = nickname
|
||||
client.updateNickMask()
|
||||
client.updateNickMask(nickname)
|
||||
for friend := range client.Friends() {
|
||||
friend.Send(nil, origNickMask, "NICK", nickname)
|
||||
}
|
||||
@ -530,21 +538,10 @@ func (client *Client) destroy() {
|
||||
client.server.connectionLimitsMutex.Unlock()
|
||||
}
|
||||
|
||||
// remove from opers list
|
||||
_, exists := client.server.currentOpers[client]
|
||||
if exists {
|
||||
delete(client.server.currentOpers, client)
|
||||
}
|
||||
|
||||
// alert monitors
|
||||
client.server.monitoringMutex.RLock()
|
||||
for _, mClient := range client.server.monitoring[client.nickCasefolded] {
|
||||
mClient.Send(nil, client.server.name, RPL_MONOFFLINE, mClient.nick, client.nick)
|
||||
}
|
||||
client.server.monitoringMutex.RUnlock()
|
||||
|
||||
// remove my monitors
|
||||
client.clearMonitorList()
|
||||
client.server.monitorManager.alertMonitors(client, false)
|
||||
// clean up monitor state
|
||||
client.server.monitorManager.clearMonitorList(client)
|
||||
|
||||
// clean up channels
|
||||
client.server.channelJoinPartMutex.Lock()
|
||||
|
@ -20,3 +20,21 @@ func (server *Server) getPassword() []byte {
|
||||
defer server.configurableStateMutex.RUnlock()
|
||||
return server.password
|
||||
}
|
||||
|
||||
func (client *Client) getNick() string {
|
||||
client.stateMutex.RLock()
|
||||
defer client.stateMutex.RUnlock()
|
||||
return client.nick
|
||||
}
|
||||
|
||||
func (client *Client) getNickMaskString() string {
|
||||
client.stateMutex.RLock()
|
||||
defer client.stateMutex.RUnlock()
|
||||
return client.nickMaskString
|
||||
}
|
||||
|
||||
func (client *Client) getNickCasefolded() string {
|
||||
client.stateMutex.RLock()
|
||||
defer client.stateMutex.RUnlock()
|
||||
return client.nickCasefolded
|
||||
}
|
||||
|
228
irc/monitor.go
228
irc/monitor.go
@ -4,50 +4,108 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
)
|
||||
|
||||
// alertMonitors alerts everyone monitoring us that we're online.
|
||||
func (client *Client) alertMonitors() {
|
||||
// get monitors
|
||||
client.server.monitoringMutex.RLock()
|
||||
monitors := client.server.monitoring[client.nickCasefolded]
|
||||
client.server.monitoringMutex.RUnlock()
|
||||
type MonitorManager struct {
|
||||
sync.RWMutex
|
||||
// client -> nicks it's watching
|
||||
watching map[*Client]map[string]bool
|
||||
// nick -> clients watching it
|
||||
watchedby map[string]map[*Client]bool
|
||||
// (all nicks must be normalized externally by casefolding)
|
||||
}
|
||||
|
||||
// alert monitors
|
||||
for _, mClient := range monitors {
|
||||
func NewMonitorManager() *MonitorManager {
|
||||
mm := MonitorManager{
|
||||
watching: make(map[*Client]map[string]bool),
|
||||
watchedby: make(map[string]map[*Client]bool),
|
||||
}
|
||||
return &mm
|
||||
}
|
||||
|
||||
var MonitorLimitExceeded = errors.New("Monitor limit exceeded")
|
||||
|
||||
// alertMonitors alerts everyone monitoring us that we're online.
|
||||
func (manager *MonitorManager) alertMonitors(client *Client, online bool) {
|
||||
cfnick := client.getNickCasefolded()
|
||||
nick := client.getNick()
|
||||
var watchers []*Client
|
||||
// safely copy the list of clients watching our nick
|
||||
manager.RLock()
|
||||
for client := range manager.watchedby[cfnick] {
|
||||
watchers = append(watchers, client)
|
||||
}
|
||||
manager.RUnlock()
|
||||
|
||||
command := RPL_MONOFFLINE
|
||||
if online {
|
||||
command = RPL_MONONLINE
|
||||
}
|
||||
|
||||
// asynchronously send all the notifications
|
||||
go func() {
|
||||
for _, mClient := range watchers {
|
||||
// don't have to notify ourselves
|
||||
if mClient != client {
|
||||
mClient.SendFromClient("", client, nil, RPL_MONONLINE, mClient.nick, client.nickMaskString)
|
||||
mClient.SendFromClient("", client, nil, command, mClient.getNick(), nick)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// clearMonitorList clears our MONITOR list.
|
||||
func (client *Client) clearMonitorList() {
|
||||
// lockin' everything
|
||||
client.monitoringMutex.Lock()
|
||||
defer client.monitoringMutex.Unlock()
|
||||
client.server.monitoringMutex.Lock()
|
||||
defer client.server.monitoringMutex.Unlock()
|
||||
func (manager *MonitorManager) clearMonitorList(client *Client) {
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
|
||||
for name := range client.monitoring {
|
||||
// just removes current client from the list
|
||||
orig := client.server.monitoring[name]
|
||||
var index int
|
||||
for i, cli := range orig {
|
||||
if cli == client {
|
||||
index = i
|
||||
break
|
||||
for nick, _ := range manager.watching[client] {
|
||||
delete(manager.watchedby[nick], client)
|
||||
}
|
||||
}
|
||||
client.server.monitoring[name] = append(orig[:index], orig[index+1:]...)
|
||||
delete(manager.watching, client)
|
||||
}
|
||||
|
||||
client.monitoring = make(map[string]bool)
|
||||
func (manager *MonitorManager) addMonitor(client *Client, nick string, limit int) error {
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
|
||||
if manager.watching[client] == nil {
|
||||
manager.watching[client] = make(map[string]bool)
|
||||
}
|
||||
if manager.watchedby[nick] == nil {
|
||||
manager.watchedby[nick] = make(map[*Client]bool)
|
||||
}
|
||||
|
||||
if len(manager.watching[client]) >= limit {
|
||||
return MonitorLimitExceeded
|
||||
}
|
||||
|
||||
manager.watching[client][nick] = true
|
||||
manager.watchedby[nick][client] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *MonitorManager) removeMonitor(client *Client, nick string) error {
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
// deleting from nil maps is fine
|
||||
delete(manager.watching[client], nick)
|
||||
delete(manager.watchedby[nick], client)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *MonitorManager) listMonitors(client *Client) (nicks []string) {
|
||||
manager.RLock()
|
||||
defer manager.RUnlock()
|
||||
for nick := range manager.watching[client] {
|
||||
nicks = append(nicks, nick)
|
||||
}
|
||||
return nicks
|
||||
}
|
||||
|
||||
var (
|
||||
@ -64,7 +122,7 @@ func monitorHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
||||
handler, exists := metadataSubcommands[strings.ToLower(msg.Params[0])]
|
||||
|
||||
if !exists {
|
||||
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "MONITOR", msg.Params[0], "Unknown subcommand")
|
||||
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.getNick(), "MONITOR", msg.Params[0], "Unknown subcommand")
|
||||
return false
|
||||
}
|
||||
|
||||
@ -73,49 +131,17 @@ func monitorHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
||||
|
||||
func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
if len(msg.Params) < 2 {
|
||||
client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, "Not enough parameters")
|
||||
client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.getNick(), msg.Command, "Not enough parameters")
|
||||
return false
|
||||
}
|
||||
|
||||
targets := strings.Split(msg.Params[1], ",")
|
||||
for len(targets) > 0 {
|
||||
// check name length
|
||||
if len(targets[0]) < 1 {
|
||||
targets = targets[1:]
|
||||
continue
|
||||
}
|
||||
|
||||
// remove target
|
||||
casefoldedTarget, err := CasefoldName(targets[0])
|
||||
for _, target := range targets {
|
||||
cfnick, err := CasefoldName(target)
|
||||
if err != nil {
|
||||
// skip silently I guess
|
||||
targets = targets[1:]
|
||||
continue
|
||||
}
|
||||
|
||||
client.monitoringMutex.Lock()
|
||||
client.server.monitoringMutex.Lock()
|
||||
|
||||
if client.monitoring[casefoldedTarget] {
|
||||
// just removes current client from the list
|
||||
orig := server.monitoring[casefoldedTarget]
|
||||
var index int
|
||||
for i, cli := range orig {
|
||||
if cli == client {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
server.monitoring[casefoldedTarget] = append(orig[:index], orig[index+1:]...)
|
||||
|
||||
delete(client.monitoring, casefoldedTarget)
|
||||
}
|
||||
|
||||
client.monitoringMutex.Unlock()
|
||||
client.server.monitoringMutex.Unlock()
|
||||
|
||||
// remove first element of targets list
|
||||
targets = targets[1:]
|
||||
server.monitorManager.removeMonitor(client, cfnick)
|
||||
}
|
||||
|
||||
return false
|
||||
@ -123,88 +149,68 @@ func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
|
||||
|
||||
func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
if len(msg.Params) < 2 {
|
||||
client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, "Not enough parameters")
|
||||
client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.getNick(), msg.Command, "Not enough parameters")
|
||||
return false
|
||||
}
|
||||
|
||||
var online []string
|
||||
var offline []string
|
||||
|
||||
targets := strings.Split(msg.Params[1], ",")
|
||||
for len(targets) > 0 {
|
||||
// check name length
|
||||
if len(targets[0]) < 1 || len(targets[0]) > server.limits.NickLen {
|
||||
targets = targets[1:]
|
||||
continue
|
||||
}
|
||||
limit := server.getLimits().MonitorEntries
|
||||
|
||||
// check the monitor list length
|
||||
if len(client.monitoring) >= server.limits.MonitorEntries {
|
||||
client.Send(nil, server.name, ERR_MONLISTFULL, client.nick, strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ","))
|
||||
break
|
||||
targets := strings.Split(msg.Params[1], ",")
|
||||
for _, target := range targets {
|
||||
// check name length
|
||||
if len(target) < 1 || len(targets) > server.limits.NickLen {
|
||||
continue
|
||||
}
|
||||
|
||||
// add target
|
||||
casefoldedTarget, err := CasefoldName(targets[0])
|
||||
if err != nil {
|
||||
// skip silently I guess
|
||||
targets = targets[1:]
|
||||
continue
|
||||
}
|
||||
|
||||
client.monitoringMutex.Lock()
|
||||
client.server.monitoringMutex.Lock()
|
||||
|
||||
if !client.monitoring[casefoldedTarget] {
|
||||
client.monitoring[casefoldedTarget] = true
|
||||
|
||||
orig := server.monitoring[casefoldedTarget]
|
||||
server.monitoring[casefoldedTarget] = append(orig, client)
|
||||
err = server.monitorManager.addMonitor(client, casefoldedTarget, limit)
|
||||
if err == MonitorLimitExceeded {
|
||||
client.Send(nil, server.name, ERR_MONLISTFULL, client.getNick(), strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ","))
|
||||
break
|
||||
} else if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
client.monitoringMutex.Unlock()
|
||||
client.server.monitoringMutex.Unlock()
|
||||
|
||||
// add to online / offline lists
|
||||
target := server.clients.Get(casefoldedTarget)
|
||||
if target == nil {
|
||||
if target := server.clients.Get(casefoldedTarget); target == nil {
|
||||
offline = append(offline, targets[0])
|
||||
} else {
|
||||
online = append(online, target.nickMaskString)
|
||||
online = append(online, target.getNick())
|
||||
}
|
||||
|
||||
// remove first element of targets list
|
||||
targets = targets[1:]
|
||||
}
|
||||
|
||||
if len(online) > 0 {
|
||||
client.Send(nil, server.name, RPL_MONONLINE, client.nick, strings.Join(online, ","))
|
||||
client.Send(nil, server.name, RPL_MONONLINE, client.getNick(), strings.Join(online, ","))
|
||||
}
|
||||
if len(offline) > 0 {
|
||||
client.Send(nil, server.name, RPL_MONOFFLINE, client.nick, strings.Join(offline, ","))
|
||||
client.Send(nil, server.name, RPL_MONOFFLINE, client.getNick(), strings.Join(offline, ","))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func monitorClearHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
client.clearMonitorList()
|
||||
|
||||
server.monitorManager.clearMonitorList(client)
|
||||
return false
|
||||
}
|
||||
|
||||
func monitorListHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
var monitorList []string
|
||||
client.monitoringMutex.RLock()
|
||||
for name := range client.monitoring {
|
||||
monitorList = append(monitorList, name)
|
||||
}
|
||||
client.monitoringMutex.RUnlock()
|
||||
monitorList := server.monitorManager.listMonitors(client)
|
||||
|
||||
for _, line := range argsToStrings(maxLastArgLength, monitorList, ",") {
|
||||
client.Send(nil, server.name, RPL_MONLIST, client.nick, line)
|
||||
client.Send(nil, server.name, RPL_MONLIST, client.getNick(), line)
|
||||
}
|
||||
|
||||
client.Send(nil, server.name, RPL_ENDOFMONLIST, "End of MONITOR list")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -212,27 +218,25 @@ func monitorStatusHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
|
||||
var online []string
|
||||
var offline []string
|
||||
|
||||
client.monitoringMutex.RLock()
|
||||
monitoring := client.monitoring
|
||||
client.monitoringMutex.RUnlock()
|
||||
monitorList := server.monitorManager.listMonitors(client)
|
||||
|
||||
for name := range monitoring {
|
||||
for _, name := range monitorList {
|
||||
target := server.clients.Get(name)
|
||||
if target == nil {
|
||||
offline = append(offline, name)
|
||||
} else {
|
||||
online = append(online, target.nickMaskString)
|
||||
online = append(online, target.getNick())
|
||||
}
|
||||
}
|
||||
|
||||
if len(online) > 0 {
|
||||
for _, line := range argsToStrings(maxLastArgLength, online, ",") {
|
||||
client.Send(nil, server.name, RPL_MONONLINE, client.nick, line)
|
||||
client.Send(nil, server.name, RPL_MONONLINE, client.getNick(), line)
|
||||
}
|
||||
}
|
||||
if len(offline) > 0 {
|
||||
for _, line := range argsToStrings(maxLastArgLength, offline, ",") {
|
||||
client.Send(nil, server.name, RPL_MONOFFLINE, client.nick, line)
|
||||
client.Send(nil, server.name, RPL_MONOFFLINE, client.getNick(), line)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
return false
|
||||
}
|
||||
if client.registered {
|
||||
client.alertMonitors()
|
||||
client.server.monitorManager.alertMonitors(client, true)
|
||||
}
|
||||
server.tryRegister(client)
|
||||
return false
|
||||
|
@ -94,7 +94,6 @@ type Server struct {
|
||||
connectionThrottle *ConnectionThrottle
|
||||
connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
|
||||
ctime time.Time
|
||||
currentOpers map[*Client]bool
|
||||
defaultChannelModes Modes
|
||||
dlines *DLineManager
|
||||
isupport *ISupportList
|
||||
@ -103,8 +102,7 @@ type Server struct {
|
||||
listeners map[string]*ListenerWrapper
|
||||
logger *logger.Manager
|
||||
MaxSendQBytes uint64
|
||||
monitoring map[string][]*Client
|
||||
monitoringMutex sync.RWMutex
|
||||
monitorManager *MonitorManager
|
||||
motdLines []string
|
||||
name string
|
||||
nameCasefolded string
|
||||
@ -155,10 +153,9 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
|
||||
channels: *NewChannelNameMap(),
|
||||
clients: NewClientLookupSet(),
|
||||
commands: make(chan Command),
|
||||
currentOpers: make(map[*Client]bool),
|
||||
listeners: make(map[string]*ListenerWrapper),
|
||||
logger: logger,
|
||||
monitoring: make(map[string][]*Client),
|
||||
monitorManager: NewMonitorManager(),
|
||||
newConns: make(chan clientConn),
|
||||
registeredChannels: make(map[string]*RegisteredChannel),
|
||||
rehashSignal: make(chan os.Signal, 1),
|
||||
@ -1143,36 +1140,36 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||
client.Send(nil, server.name, ERR_UNKNOWNERROR, "OPER", "You're already opered-up!")
|
||||
return false
|
||||
}
|
||||
hash := server.operators[name].Pass
|
||||
server.configurableStateMutex.RLock()
|
||||
oper := server.operators[name]
|
||||
server.configurableStateMutex.RUnlock()
|
||||
|
||||
password := []byte(msg.Params[1])
|
||||
|
||||
err = ComparePassword(hash, password)
|
||||
|
||||
if (hash == nil) || (err != nil) {
|
||||
err = ComparePassword(oper.Pass, password)
|
||||
if (oper.Pass == nil) || (err != nil) {
|
||||
client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
|
||||
return true
|
||||
}
|
||||
|
||||
client.flags[Operator] = true
|
||||
client.operName = name
|
||||
client.class = server.operators[name].Class
|
||||
server.currentOpers[client] = true
|
||||
client.whoisLine = server.operators[name].WhoisLine
|
||||
client.class = oper.Class
|
||||
client.whoisLine = oper.WhoisLine
|
||||
|
||||
// push new vhost if one is set
|
||||
if len(server.operators[name].Vhost) > 0 {
|
||||
if len(oper.Vhost) > 0 {
|
||||
for fClient := range client.Friends(caps.ChgHost) {
|
||||
fClient.SendFromClient("", client, nil, "CHGHOST", client.username, server.operators[name].Vhost)
|
||||
fClient.SendFromClient("", client, nil, "CHGHOST", client.username, oper.Vhost)
|
||||
}
|
||||
// CHGHOST requires prefix nickmask to have original hostname, so do that before updating nickmask
|
||||
client.vhost = server.operators[name].Vhost
|
||||
client.updateNickMask()
|
||||
client.vhost = oper.Vhost
|
||||
client.updateNickMask("")
|
||||
}
|
||||
|
||||
// set new modes
|
||||
var applied ModeChanges
|
||||
if 0 < len(server.operators[name].Modes) {
|
||||
modeChanges, unknownChanges := ParseUserModeChanges(strings.Split(server.operators[name].Modes, " ")...)
|
||||
if 0 < len(oper.Modes) {
|
||||
modeChanges, unknownChanges := ParseUserModeChanges(strings.Split(oper.Modes, " ")...)
|
||||
applied = client.applyUserModeChanges(true, modeChanges)
|
||||
if 0 < len(unknownChanges) {
|
||||
var runes string
|
||||
@ -1257,12 +1254,8 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
|
||||
}
|
||||
for client := range server.currentOpers {
|
||||
_, exists := opers[client.operName]
|
||||
if !exists {
|
||||
return fmt.Errorf("Oper [%s] no longer exists (used by client [%s])", client.operName, client.nickMaskString)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support rehash of existing operator perms?
|
||||
|
||||
// sanity checks complete, start modifying server state
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user