mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
Add very initial ChanServ and NickServ virtual clients
As well, add channel registration and re-applying founder privs on the first client joining the channel. I'm going to re-architect our modes system to better acocunt for this sort of change.
This commit is contained in:
parent
439331cfb8
commit
b33b217fab
@ -16,15 +16,6 @@ import (
|
|||||||
"github.com/tidwall/buntdb"
|
"github.com/tidwall/buntdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
keyAccountExists = "account.exists %s"
|
|
||||||
keyAccountVerified = "account.verified %s"
|
|
||||||
keyAccountName = "account.name %s" // stores the 'preferred name' of the account, not casemapped
|
|
||||||
keyAccountRegTime = "account.registered.time %s"
|
|
||||||
keyAccountCredentials = "account.credentials %s"
|
|
||||||
keyCertToAccount = "account.creds.certfp %s"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errAccountCreation = errors.New("Account could not be created")
|
errAccountCreation = errors.New("Account could not be created")
|
||||||
errCertfpAlreadyExists = errors.New("An account already exists with your certificate")
|
errCertfpAlreadyExists = errors.New("An account already exists with your certificate")
|
@ -17,6 +17,15 @@ import (
|
|||||||
"github.com/tidwall/buntdb"
|
"github.com/tidwall/buntdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
keyAccountExists = "account.exists %s"
|
||||||
|
keyAccountVerified = "account.verified %s"
|
||||||
|
keyAccountName = "account.name %s" // stores the 'preferred name' of the account, not casemapped
|
||||||
|
keyAccountRegTime = "account.registered.time %s"
|
||||||
|
keyAccountCredentials = "account.credentials %s"
|
||||||
|
keyCertToAccount = "account.creds.certfp %s"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
|
// EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
|
||||||
// This can be moved to some other data structure/place if we need to load/unload mechs later.
|
// This can be moved to some other data structure/place if we need to load/unload mechs later.
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/DanielOaks/girc-go/ircmsg"
|
"github.com/DanielOaks/girc-go/ircmsg"
|
||||||
|
"github.com/tidwall/buntdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Channel struct {
|
type Channel struct {
|
||||||
@ -277,10 +278,27 @@ func (channel *Channel) Join(client *Client, key string) {
|
|||||||
client.channels.Add(channel)
|
client.channels.Add(channel)
|
||||||
channel.members.Add(client)
|
channel.members.Add(client)
|
||||||
if len(channel.members) == 1 {
|
if len(channel.members) == 1 {
|
||||||
channel.createdTime = time.Now()
|
client.server.registeredChannelsMutex.Lock()
|
||||||
// // we should only do this on registered channels
|
defer client.server.registeredChannelsMutex.Unlock()
|
||||||
// channel.members[client][ChannelFounder] = true
|
client.server.store.Update(func(tx *buntdb.Tx) error {
|
||||||
channel.members[client][ChannelOperator] = true
|
chanReg := client.server.loadChannelNoMutex(tx, channel.nameCasefolded)
|
||||||
|
|
||||||
|
if chanReg == nil {
|
||||||
|
channel.createdTime = time.Now()
|
||||||
|
channel.members[client][ChannelOperator] = true
|
||||||
|
} else {
|
||||||
|
// we should only do this on registered channels
|
||||||
|
if client.account != nil && client.account.Name == chanReg.Founder {
|
||||||
|
channel.members[client][ChannelFounder] = true
|
||||||
|
}
|
||||||
|
channel.topic = chanReg.Topic
|
||||||
|
channel.topicSetBy = chanReg.TopicSetBy
|
||||||
|
channel.topicSetTime = chanReg.TopicSetTime
|
||||||
|
channel.name = chanReg.Name
|
||||||
|
channel.createdTime = chanReg.RegisteredAt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.capabilities[ExtendedJoin] {
|
if client.capabilities[ExtendedJoin] {
|
||||||
|
90
irc/channelreg.go
Normal file
90
irc/channelreg.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
|
||||||
|
// released under the MIT license
|
||||||
|
|
||||||
|
package irc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tidwall/buntdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
keyChannelExists = "channel.exists %s"
|
||||||
|
keyChannelName = "channel.name %s" // stores the 'preferred name' of the channel, not casemapped
|
||||||
|
keyChannelRegTime = "channel.registered.time %s"
|
||||||
|
keyChannelFounder = "channel.founder %s"
|
||||||
|
keyChannelTopic = "channel.topic %s"
|
||||||
|
keyChannelTopicSetBy = "channel.topic.setby %s"
|
||||||
|
keyChannelTopicSetTime = "channel.topic.settime %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errChanExists = errors.New("Channel already exists")
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisteredChannel holds details about a given registered channel.
|
||||||
|
type RegisteredChannel struct {
|
||||||
|
// Name of the channel.
|
||||||
|
Name string
|
||||||
|
// RegisteredAt represents the time that the channel was registered.
|
||||||
|
RegisteredAt time.Time
|
||||||
|
// Founder indicates the founder of the channel.
|
||||||
|
Founder string
|
||||||
|
// Topic represents the channel topic.
|
||||||
|
Topic string
|
||||||
|
// TopicSetBy represents the host that set the topic.
|
||||||
|
TopicSetBy string
|
||||||
|
// TopicSetTime represents the time the topic was set.
|
||||||
|
TopicSetTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadChannelNoMutex loads a channel from the store.
|
||||||
|
func (server *Server) loadChannelNoMutex(tx *buntdb.Tx, channelKey string) *RegisteredChannel {
|
||||||
|
// return loaded chan if it already exists
|
||||||
|
if server.registeredChannels[channelKey] != nil {
|
||||||
|
return server.registeredChannels[channelKey]
|
||||||
|
}
|
||||||
|
_, err := tx.Get(fmt.Sprintf(keyChannelExists, channelKey))
|
||||||
|
if err == buntdb.ErrNotFound {
|
||||||
|
// chan does not already exist, return
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel exists, load it
|
||||||
|
name, _ := tx.Get(fmt.Sprintf(keyChannelName, channelKey))
|
||||||
|
regTime, _ := tx.Get(fmt.Sprintf(keyChannelRegTime, channelKey))
|
||||||
|
regTimeInt, _ := strconv.ParseInt(regTime, 10, 64)
|
||||||
|
founder, _ := tx.Get(fmt.Sprintf(keyChannelFounder, channelKey))
|
||||||
|
topic, _ := tx.Get(fmt.Sprintf(keyChannelTopic, channelKey))
|
||||||
|
topicSetBy, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetBy, channelKey))
|
||||||
|
topicSetTime, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetTime, channelKey))
|
||||||
|
topicSetTimeInt, _ := strconv.ParseInt(topicSetTime, 10, 64)
|
||||||
|
|
||||||
|
chanInfo := RegisteredChannel{
|
||||||
|
Name: name,
|
||||||
|
RegisteredAt: time.Unix(regTimeInt, 0),
|
||||||
|
Founder: founder,
|
||||||
|
Topic: topic,
|
||||||
|
TopicSetBy: topicSetBy,
|
||||||
|
TopicSetTime: time.Unix(topicSetTimeInt, 0),
|
||||||
|
}
|
||||||
|
server.registeredChannels[channelKey] = &chanInfo
|
||||||
|
|
||||||
|
return &chanInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveChannelNoMutex saves a channel to the store.
|
||||||
|
func (server *Server) saveChannelNoMutex(tx *buntdb.Tx, channelKey string, channelInfo RegisteredChannel) {
|
||||||
|
tx.Set(fmt.Sprintf(keyChannelExists, channelKey), "1", nil)
|
||||||
|
tx.Set(fmt.Sprintf(keyChannelName, channelKey), channelInfo.Name, nil)
|
||||||
|
tx.Set(fmt.Sprintf(keyChannelRegTime, channelKey), strconv.FormatInt(channelInfo.RegisteredAt.Unix(), 10), nil)
|
||||||
|
tx.Set(fmt.Sprintf(keyChannelFounder, channelKey), channelInfo.Founder, nil)
|
||||||
|
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)
|
||||||
|
server.registeredChannels[channelKey] = &channelInfo
|
||||||
|
}
|
119
irc/chanserv.go
Normal file
119
irc/chanserv.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
|
||||||
|
// released under the MIT license
|
||||||
|
|
||||||
|
package irc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/DanielOaks/girc-go/ircmsg"
|
||||||
|
"github.com/tidwall/buntdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// csHandler handles the /CS and /CHANSERV commands
|
||||||
|
func csHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||||
|
server.chanservReceivePrivmsg(client, strings.Join(msg.Params, " "))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) chanservReceiveNotice(client *Client, message string) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChanServNotice sends the client a notice from ChanServ.
|
||||||
|
func (client *Client) ChanServNotice(text string) {
|
||||||
|
client.Send(nil, fmt.Sprintf("ChanServ!services@%s", client.server.name), "NOTICE", client.nick, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) chanservReceivePrivmsg(client *Client, message string) {
|
||||||
|
var params []string
|
||||||
|
for _, p := range strings.Split(message, " ") {
|
||||||
|
if len(p) > 0 {
|
||||||
|
params = append(params, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(params) < 1 {
|
||||||
|
client.ChanServNotice("You need to run a command")
|
||||||
|
//TODO(dan): dump CS help here
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
command := strings.ToLower(params[0])
|
||||||
|
server.logger.Debug("chanserv", fmt.Sprintf("Client %s ran command %s", client.nick, command))
|
||||||
|
|
||||||
|
if command == "register" {
|
||||||
|
if len(params) < 2 {
|
||||||
|
client.ChanServNotice("Syntax: REGISTER <channel>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
server.registeredChannelsMutex.Lock()
|
||||||
|
defer server.registeredChannelsMutex.Unlock()
|
||||||
|
|
||||||
|
channelName := params[1]
|
||||||
|
channelKey, err := CasefoldChannel(channelName)
|
||||||
|
if err != nil {
|
||||||
|
client.ChanServNotice("Channel name is not valid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
channelInfo := server.channels.Get(channelKey)
|
||||||
|
if channelInfo == nil {
|
||||||
|
client.ChanServNotice("You must be an oper on the channel to register it")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !channelInfo.ClientIsAtLeast(client, ChannelOperator) {
|
||||||
|
client.ChanServNotice("You must be an oper on the channel to register it")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
server.store.Update(func(tx *buntdb.Tx) error {
|
||||||
|
currentChan := server.loadChannelNoMutex(tx, channelKey)
|
||||||
|
if currentChan != nil {
|
||||||
|
client.ChanServNotice("Channel is already registered")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
account := client.account
|
||||||
|
if account == nil {
|
||||||
|
client.ChanServNotice("You must be logged in to register a channel")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
chanRegInfo := RegisteredChannel{
|
||||||
|
Name: channelName,
|
||||||
|
RegisteredAt: time.Now(),
|
||||||
|
Founder: account.Name,
|
||||||
|
Topic: channelInfo.topic,
|
||||||
|
TopicSetBy: channelInfo.topicSetBy,
|
||||||
|
TopicSetTime: channelInfo.topicSetTime,
|
||||||
|
}
|
||||||
|
server.saveChannelNoMutex(tx, channelKey, chanRegInfo)
|
||||||
|
|
||||||
|
client.ChanServNotice(fmt.Sprintf("Channel %s successfully registered", channelName))
|
||||||
|
|
||||||
|
server.logger.Info("chanserv", fmt.Sprintf("Client %s registered channel %s", client.nick, channelName))
|
||||||
|
|
||||||
|
channelInfo.membersMutex.Lock()
|
||||||
|
defer channelInfo.membersMutex.Unlock()
|
||||||
|
|
||||||
|
// give them founder privs
|
||||||
|
change := channelInfo.applyModeMemberNoMutex(client, ChannelFounder, Add, client.nickCasefolded)
|
||||||
|
if change != nil {
|
||||||
|
//TODO(dan): we should change the name of String and make it return a slice here
|
||||||
|
//TODO(dan): unify this code with code in modes.go
|
||||||
|
args := append([]string{channelName}, strings.Split(change.String(), " ")...)
|
||||||
|
for member := range channelInfo.members {
|
||||||
|
member.Send(nil, fmt.Sprintf("ChanServ!services@%s", client.server.name), "MODE", args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
client.ChanServNotice("Sorry, I don't know that command")
|
||||||
|
}
|
||||||
|
}
|
@ -74,6 +74,14 @@ var Commands = map[string]Command{
|
|||||||
usablePreReg: true,
|
usablePreReg: true,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
},
|
},
|
||||||
|
"CHANSERV": {
|
||||||
|
handler: csHandler,
|
||||||
|
minParams: 1,
|
||||||
|
},
|
||||||
|
"CS": {
|
||||||
|
handler: csHandler,
|
||||||
|
minParams: 1,
|
||||||
|
},
|
||||||
"DEBUG": {
|
"DEBUG": {
|
||||||
handler: debugHandler,
|
handler: debugHandler,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
@ -143,6 +151,10 @@ var Commands = map[string]Command{
|
|||||||
usablePreReg: true,
|
usablePreReg: true,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
},
|
},
|
||||||
|
"NICKSERV": {
|
||||||
|
handler: nsHandler,
|
||||||
|
minParams: 1,
|
||||||
|
},
|
||||||
"NOTICE": {
|
"NOTICE": {
|
||||||
handler: noticeHandler,
|
handler: noticeHandler,
|
||||||
minParams: 2,
|
minParams: 2,
|
||||||
@ -155,6 +167,10 @@ var Commands = map[string]Command{
|
|||||||
handler: npcaHandler,
|
handler: npcaHandler,
|
||||||
minParams: 3,
|
minParams: 3,
|
||||||
},
|
},
|
||||||
|
"NS": {
|
||||||
|
handler: nsHandler,
|
||||||
|
minParams: 1,
|
||||||
|
},
|
||||||
"OPER": {
|
"OPER": {
|
||||||
handler: operHandler,
|
handler: operHandler,
|
||||||
minParams: 2,
|
minParams: 2,
|
||||||
|
20
irc/help.go
20
irc/help.go
@ -84,6 +84,16 @@ longer away.`,
|
|||||||
Used in capability negotiation. See the IRCv3 specs for more info:
|
Used in capability negotiation. See the IRCv3 specs for more info:
|
||||||
http://ircv3.net/specs/core/capability-negotiation-3.1.html
|
http://ircv3.net/specs/core/capability-negotiation-3.1.html
|
||||||
http://ircv3.net/specs/core/capability-negotiation-3.2.html`,
|
http://ircv3.net/specs/core/capability-negotiation-3.2.html`,
|
||||||
|
},
|
||||||
|
"chanserv": {
|
||||||
|
text: `CHANSERV <subcommand> [params]
|
||||||
|
|
||||||
|
ChanServ controls channel registrations.`,
|
||||||
|
},
|
||||||
|
"cs": {
|
||||||
|
text: `CS <subcommand> [params]
|
||||||
|
|
||||||
|
ChanServ controls channel registrations.`,
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
oper: true,
|
oper: true,
|
||||||
@ -239,6 +249,11 @@ view the channel membership prefixes supported by this server, see the help for
|
|||||||
text: `NICK <newnick>
|
text: `NICK <newnick>
|
||||||
|
|
||||||
Sets your nickname to the new given one.`,
|
Sets your nickname to the new given one.`,
|
||||||
|
},
|
||||||
|
"nickserv": {
|
||||||
|
text: `NICKSERV <subcommand> [params]
|
||||||
|
|
||||||
|
NickServ controls accounts and user registrations.`,
|
||||||
},
|
},
|
||||||
"notice": {
|
"notice": {
|
||||||
text: `NOTICE <target>{,<target>} <text to be sent>
|
text: `NOTICE <target>{,<target>} <text to be sent>
|
||||||
@ -258,6 +273,11 @@ Requires the roleplay mode (+E) to be set on the target.`,
|
|||||||
The NPC command is used to send an action to the target as the source.
|
The NPC command is used to send an action to the target as the source.
|
||||||
|
|
||||||
Requires the roleplay mode (+E) to be set on the target.`,
|
Requires the roleplay mode (+E) to be set on the target.`,
|
||||||
|
},
|
||||||
|
"ns": {
|
||||||
|
text: `NS <subcommand> [params]
|
||||||
|
|
||||||
|
NickServ controls accounts and user registrations.`,
|
||||||
},
|
},
|
||||||
"oper": {
|
"oper": {
|
||||||
text: `OPER <name> <password>
|
text: `OPER <name> <password>
|
||||||
|
@ -11,6 +11,14 @@ import (
|
|||||||
"github.com/DanielOaks/girc-go/ircmsg"
|
"github.com/DanielOaks/girc-go/ircmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
restrictedNicknames = map[string]bool{
|
||||||
|
"=scene=": true, // used for rp commands
|
||||||
|
"chanserv": true,
|
||||||
|
"nickserv": true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// NICK <nickname>
|
// NICK <nickname>
|
||||||
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||||
if !client.authorized {
|
if !client.authorized {
|
||||||
@ -26,7 +34,7 @@ func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil || len(nicknameRaw) > server.limits.NickLen || nickname == "=scene=" {
|
if err != nil || len(nicknameRaw) > server.limits.NickLen || restrictedNicknames[nickname] {
|
||||||
client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nicknameRaw, "Erroneous nickname")
|
client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nicknameRaw, "Erroneous nickname")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -70,7 +78,7 @@ func sanickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if oerr != nil || err != nil || len(strings.TrimSpace(msg.Params[1])) > server.limits.NickLen || nickname == "=scene=" {
|
if oerr != nil || err != nil || len(strings.TrimSpace(msg.Params[1])) > server.limits.NickLen || restrictedNicknames[nickname] {
|
||||||
client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, msg.Params[0], "Erroneous nickname")
|
client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, msg.Params[0], "Erroneous nickname")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
24
irc/nickserv.go
Normal file
24
irc/nickserv.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
|
||||||
|
// released under the MIT license
|
||||||
|
|
||||||
|
package irc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/DanielOaks/girc-go/ircmsg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// nsHandler handles the /NS and /NICKSERV commands
|
||||||
|
func nsHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||||
|
server.nickservReceivePrivmsg(client, strings.Join(msg.Params, " "))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) nickservReceiveNotice(client *Client, message string) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) nickservReceivePrivmsg(client *Client, message string) {
|
||||||
|
client.Notice("NickServ is not yet implemented, sorry!")
|
||||||
|
}
|
@ -114,6 +114,8 @@ type Server struct {
|
|||||||
operclasses map[string]OperClass
|
operclasses map[string]OperClass
|
||||||
password []byte
|
password []byte
|
||||||
passwords *PasswordManager
|
passwords *PasswordManager
|
||||||
|
registeredChannels map[string]*RegisteredChannel
|
||||||
|
registeredChannelsMutex sync.RWMutex
|
||||||
rehashMutex sync.Mutex
|
rehashMutex sync.Mutex
|
||||||
rehashSignal chan os.Signal
|
rehashSignal chan os.Signal
|
||||||
restAPI *RestAPIConfig
|
restAPI *RestAPIConfig
|
||||||
@ -185,9 +187,10 @@ func NewServer(configFilename string, config *Config, logger *logger.Manager) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
server := &Server{
|
server := &Server{
|
||||||
accounts: make(map[string]*ClientAccount),
|
|
||||||
accountAuthenticationEnabled: config.Accounts.AuthenticationEnabled,
|
accountAuthenticationEnabled: config.Accounts.AuthenticationEnabled,
|
||||||
|
accounts: make(map[string]*ClientAccount),
|
||||||
channels: make(ChannelNameMap),
|
channels: make(ChannelNameMap),
|
||||||
|
checkIdent: config.Server.CheckIdent,
|
||||||
clients: NewClientLookupSet(),
|
clients: NewClientLookupSet(),
|
||||||
commands: make(chan Command),
|
commands: make(chan Command),
|
||||||
configFilename: configFilename,
|
configFilename: configFilename,
|
||||||
@ -209,21 +212,21 @@ func NewServer(configFilename string, config *Config, logger *logger.Manager) (*
|
|||||||
Rest: config.Limits.LineLen.Rest,
|
Rest: config.Limits.LineLen.Rest,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listeners: make(map[string]ListenerInterface),
|
listeners: make(map[string]ListenerInterface),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
monitoring: make(map[string][]Client),
|
monitoring: make(map[string][]Client),
|
||||||
name: config.Server.Name,
|
name: config.Server.Name,
|
||||||
nameCasefolded: casefoldedName,
|
nameCasefolded: casefoldedName,
|
||||||
networkName: config.Network.Name,
|
networkName: config.Network.Name,
|
||||||
newConns: make(chan clientConn),
|
newConns: make(chan clientConn),
|
||||||
operclasses: *operClasses,
|
operators: opers,
|
||||||
operators: opers,
|
operclasses: *operClasses,
|
||||||
signals: make(chan os.Signal, len(ServerExitSignals)),
|
registeredChannels: make(map[string]*RegisteredChannel),
|
||||||
stsEnabled: config.Server.STS.Enabled,
|
rehashSignal: make(chan os.Signal, 1),
|
||||||
rehashSignal: make(chan os.Signal, 1),
|
restAPI: &config.Server.RestAPI,
|
||||||
restAPI: &config.Server.RestAPI,
|
signals: make(chan os.Signal, len(ServerExitSignals)),
|
||||||
whoWas: NewWhoWasList(config.Limits.WhowasEntries),
|
stsEnabled: config.Server.STS.Enabled,
|
||||||
checkIdent: config.Server.CheckIdent,
|
whoWas: NewWhoWasList(config.Limits.WhowasEntries),
|
||||||
}
|
}
|
||||||
|
|
||||||
// open data store
|
// open data store
|
||||||
@ -949,6 +952,13 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
|
|||||||
channel.SplitPrivMsg(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
|
channel.SplitPrivMsg(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
|
||||||
} else {
|
} else {
|
||||||
target, err = CasefoldName(targetString)
|
target, err = CasefoldName(targetString)
|
||||||
|
if target == "chanserv" {
|
||||||
|
server.chanservReceivePrivmsg(client, message)
|
||||||
|
continue
|
||||||
|
} else if target == "nickserv" {
|
||||||
|
server.nickservReceivePrivmsg(client, message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
user := server.clients.Get(target)
|
user := server.clients.Get(target)
|
||||||
if err != nil || user == nil {
|
if err != nil || user == nil {
|
||||||
if len(target) > 0 {
|
if len(target) > 0 {
|
||||||
@ -1593,6 +1603,13 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if target == "chanserv" {
|
||||||
|
server.chanservReceiveNotice(client, message)
|
||||||
|
continue
|
||||||
|
} else if target == "nickserv" {
|
||||||
|
server.nickservReceiveNotice(client, message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
user := server.clients.Get(target)
|
user := server.clients.Get(target)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user