mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-11 06:29:29 +01:00
commit
34fc8aa3c8
@ -335,7 +335,11 @@ server:
|
|||||||
# oragono will write files to disk under certain circumstances, e.g.,
|
# oragono will write files to disk under certain circumstances, e.g.,
|
||||||
# CPU profiling or data export. by default, these files will be written
|
# CPU profiling or data export. by default, these files will be written
|
||||||
# to the working directory. set this to customize:
|
# to the working directory. set this to customize:
|
||||||
# output-path: "/home/oragono/out"
|
#output-path: "/home/oragono/out"
|
||||||
|
|
||||||
|
# the hostname used by "services", e.g., NickServ, defaults to "localhost",
|
||||||
|
# e.g., `NickServ!NickServ@localhost`. uncomment this to override:
|
||||||
|
#override-services-hostname: "example.network"
|
||||||
|
|
||||||
# account options
|
# account options
|
||||||
accounts:
|
accounts:
|
||||||
|
@ -1037,7 +1037,7 @@ func (channel *Channel) replayHistoryForResume(session *Session, after time.Time
|
|||||||
}
|
}
|
||||||
if !complete && !session.resumeDetails.HistoryIncomplete {
|
if !complete && !session.resumeDetails.HistoryIncomplete {
|
||||||
// warn here if we didn't warn already
|
// warn here if we didn't warn already
|
||||||
rb.Add(nil, histServMask, "NOTICE", channel.Name(), session.client.t("Some additional message history may have been lost"))
|
rb.Add(nil, histservService.prefix, "NOTICE", channel.Name(), session.client.t("Some additional message history may have been lost"))
|
||||||
}
|
}
|
||||||
rb.Send(true)
|
rb.Send(true)
|
||||||
}
|
}
|
||||||
@ -1099,7 +1099,7 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
|||||||
} else {
|
} else {
|
||||||
message = fmt.Sprintf(client.t("%[1]s [account: %[2]s] joined the channel"), nick, item.AccountName)
|
message = fmt.Sprintf(client.t("%[1]s [account: %[2]s] joined the channel"), nick, item.AccountName)
|
||||||
}
|
}
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Part:
|
case history.Part:
|
||||||
if eventPlayback {
|
if eventPlayback {
|
||||||
@ -1109,14 +1109,14 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
|||||||
continue // #474
|
continue // #474
|
||||||
}
|
}
|
||||||
message := fmt.Sprintf(client.t("%[1]s left the channel (%[2]s)"), nick, item.Message.Message)
|
message := fmt.Sprintf(client.t("%[1]s left the channel (%[2]s)"), nick, item.Message.Message)
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Kick:
|
case history.Kick:
|
||||||
if eventPlayback {
|
if eventPlayback {
|
||||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "KICK", chname, item.Params[0], item.Message.Message)
|
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "KICK", chname, item.Params[0], item.Message.Message)
|
||||||
} else {
|
} else {
|
||||||
message := fmt.Sprintf(client.t("%[1]s kicked %[2]s (%[3]s)"), nick, item.Params[0], item.Message.Message)
|
message := fmt.Sprintf(client.t("%[1]s kicked %[2]s (%[3]s)"), nick, item.Params[0], item.Message.Message)
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Quit:
|
case history.Quit:
|
||||||
if eventPlayback {
|
if eventPlayback {
|
||||||
@ -1126,21 +1126,21 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
|||||||
continue // #474
|
continue // #474
|
||||||
}
|
}
|
||||||
message := fmt.Sprintf(client.t("%[1]s quit (%[2]s)"), nick, item.Message.Message)
|
message := fmt.Sprintf(client.t("%[1]s quit (%[2]s)"), nick, item.Message.Message)
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Nick:
|
case history.Nick:
|
||||||
if eventPlayback {
|
if eventPlayback {
|
||||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "NICK", item.Params[0])
|
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "NICK", item.Params[0])
|
||||||
} else {
|
} else {
|
||||||
message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0])
|
message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0])
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Topic:
|
case history.Topic:
|
||||||
if eventPlayback {
|
if eventPlayback {
|
||||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "TOPIC", chname, item.Message.Message)
|
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "TOPIC", chname, item.Message.Message)
|
||||||
} else {
|
} else {
|
||||||
message := fmt.Sprintf(client.t("%[1]s set the channel topic to: %[2]s"), nick, item.Message.Message)
|
message := fmt.Sprintf(client.t("%[1]s set the channel topic to: %[2]s"), nick, item.Message.Message)
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
case history.Mode:
|
case history.Mode:
|
||||||
params := make([]string, len(item.Message.Split)+1)
|
params := make([]string, len(item.Message.Split)+1)
|
||||||
@ -1152,7 +1152,7 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
|||||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "MODE", params...)
|
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "MODE", params...)
|
||||||
} else {
|
} else {
|
||||||
message := fmt.Sprintf(client.t("%[1]s set channel modes: %[2]s"), nick, strings.Join(params[1:], " "))
|
message := fmt.Sprintf(client.t("%[1]s set channel modes: %[2]s"), nick, strings.Join(params[1:], " "))
|
||||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histservService.prefix, "*", nil, "PRIVMSG", chname, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
220
irc/chanserv.go
220
irc/chanserv.go
@ -17,7 +17,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const chanservHelp = `ChanServ lets you register and manage channels.`
|
const chanservHelp = `ChanServ lets you register and manage channels.`
|
||||||
const chanservMask = "ChanServ!ChanServ@localhost"
|
|
||||||
|
|
||||||
func chanregEnabled(config *Config) bool {
|
func chanregEnabled(config *Config) bool {
|
||||||
return config.Channels.Registration.Enabled
|
return config.Channels.Registration.Enabled
|
||||||
@ -188,27 +187,22 @@ SET modifies a channel's settings. The following settings are available:`,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// csNotice sends the client a notice from ChanServ
|
func csAmodeHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
func csNotice(rb *ResponseBuffer, text string) {
|
|
||||||
rb.Add(nil, chanservMask, "NOTICE", rb.target.Nick(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func csAmodeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
|
||||||
channelName := params[0]
|
channelName := params[0]
|
||||||
|
|
||||||
channel := server.channels.Get(channelName)
|
channel := server.channels.Get(channelName)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
} else if channel.Founder() == "" {
|
} else if channel.Founder() == "" {
|
||||||
csNotice(rb, client.t("Channel is not registered"))
|
service.Notice(rb, client.t("Channel is not registered"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
modeChanges, unknown := modes.ParseChannelModeChanges(params[1:]...)
|
modeChanges, unknown := modes.ParseChannelModeChanges(params[1:]...)
|
||||||
var change modes.ModeChange
|
var change modes.ModeChange
|
||||||
if len(modeChanges) > 1 || len(unknown) > 0 {
|
if len(modeChanges) > 1 || len(unknown) > 0 {
|
||||||
csNotice(rb, client.t("Invalid mode change"))
|
service.Notice(rb, client.t("Invalid mode change"))
|
||||||
return
|
return
|
||||||
} else if len(modeChanges) == 1 {
|
} else if len(modeChanges) == 1 {
|
||||||
change = modeChanges[0]
|
change = modeChanges[0]
|
||||||
@ -233,17 +227,17 @@ func csAmodeHandler(server *Server, client *Client, command string, params []str
|
|||||||
accountIsValid = (change.Arg != "")
|
accountIsValid = (change.Arg != "")
|
||||||
}
|
}
|
||||||
if !accountIsValid {
|
if !accountIsValid {
|
||||||
csNotice(rb, client.t("Account does not exist"))
|
service.Notice(rb, client.t("Account does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
affectedModes, err := channel.ProcessAccountToUmodeChange(client, change)
|
affectedModes, err := channel.ProcessAccountToUmodeChange(client, change)
|
||||||
|
|
||||||
if err == errInsufficientPrivs {
|
if err == errInsufficientPrivs {
|
||||||
csNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
csNotice(rb, client.t("Internal error"))
|
service.Notice(rb, client.t("Internal error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,13 +247,13 @@ func csAmodeHandler(server *Server, client *Client, command string, params []str
|
|||||||
sort.Slice(affectedModes, func(i, j int) bool {
|
sort.Slice(affectedModes, func(i, j int) bool {
|
||||||
return umodeGreaterThan(affectedModes[i].Mode, affectedModes[j].Mode)
|
return umodeGreaterThan(affectedModes[i].Mode, affectedModes[j].Mode)
|
||||||
})
|
})
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %[1]s has %[2]d persistent modes set"), channelName, len(affectedModes)))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %[1]s has %[2]d persistent modes set"), channelName, len(affectedModes)))
|
||||||
for _, modeChange := range affectedModes {
|
for _, modeChange := range affectedModes {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Account %[1]s receives mode +%[2]s"), modeChange.Arg, string(modeChange.Mode)))
|
service.Notice(rb, fmt.Sprintf(client.t("Account %[1]s receives mode +%[2]s"), modeChange.Arg, string(modeChange.Mode)))
|
||||||
}
|
}
|
||||||
case modes.Add, modes.Remove:
|
case modes.Add, modes.Remove:
|
||||||
if len(affectedModes) > 0 {
|
if len(affectedModes) > 0 {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Successfully set persistent mode %[1]s on %[2]s"), strings.Join([]string{string(change.Op), string(change.Mode)}, ""), change.Arg))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully set persistent mode %[1]s on %[2]s"), strings.Join([]string{string(change.Op), string(change.Mode)}, ""), change.Arg))
|
||||||
// #729: apply change to current membership
|
// #729: apply change to current membership
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
if member.Account() == change.Arg {
|
if member.Account() == change.Arg {
|
||||||
@ -270,22 +264,22 @@ func csAmodeHandler(server *Server, client *Client, command string, params []str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
csNotice(rb, client.t("No changes were made"))
|
service.Notice(rb, client.t("No changes were made"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func csOpHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csOpHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
channelInfo := server.channels.Get(params[0])
|
channelInfo := server.channels.Get(params[0])
|
||||||
if channelInfo == nil {
|
if channelInfo == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
channelName := channelInfo.Name()
|
channelName := channelInfo.Name()
|
||||||
|
|
||||||
clientAccount := client.Account()
|
clientAccount := client.Account()
|
||||||
if clientAccount == "" || clientAccount != channelInfo.Founder() {
|
if clientAccount == "" || clientAccount != channelInfo.Founder() {
|
||||||
csNotice(rb, client.t("Only the channel founder can do this"))
|
service.Notice(rb, client.t("Only the channel founder can do this"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +287,7 @@ func csOpHandler(server *Server, client *Client, command string, params []string
|
|||||||
if len(params) > 1 {
|
if len(params) > 1 {
|
||||||
target = server.clients.Get(params[1])
|
target = server.clients.Get(params[1])
|
||||||
if target == nil {
|
if target == nil {
|
||||||
csNotice(rb, client.t("Could not find given client"))
|
service.Notice(rb, client.t("Could not find given client"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -315,21 +309,21 @@ func csOpHandler(server *Server, client *Client, command string, params []string
|
|||||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, server.name, "*", "", rb)
|
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, server.name, "*", "", rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
csNotice(rb, client.t("Successfully granted operator privileges"))
|
service.Notice(rb, client.t("Successfully granted operator privileges"))
|
||||||
|
|
||||||
tnick := target.Nick()
|
tnick := target.Nick()
|
||||||
server.logger.Info("services", fmt.Sprintf("Client %s op'd [%s] in channel %s", client.Nick(), tnick, channelName))
|
server.logger.Info("services", fmt.Sprintf("Client %s op'd [%s] in channel %s", client.Nick(), tnick, channelName))
|
||||||
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] CS OP'd $c[grey][$r%s$c[grey]] in channel $c[grey][$r%s$c[grey]]"), client.NickMaskString(), tnick, channelName))
|
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] CS OP'd $c[grey][$r%s$c[grey]] in channel $c[grey][$r%s$c[grey]]"), client.NickMaskString(), tnick, channelName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func csDeopHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csDeopHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
channel := server.channels.Get(params[0])
|
channel := server.channels.Get(params[0])
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channel.hasClient(client) {
|
if !channel.hasClient(client) {
|
||||||
csNotice(rb, client.t("You're not on that channel"))
|
service.Notice(rb, client.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +331,7 @@ func csDeopHandler(server *Server, client *Client, command string, params []stri
|
|||||||
if len(params) > 1 {
|
if len(params) > 1 {
|
||||||
target = server.clients.Get(params[1])
|
target = server.clients.Get(params[1])
|
||||||
if target == nil {
|
if target == nil {
|
||||||
csNotice(rb, client.t("Could not find given client"))
|
service.Notice(rb, client.t("Could not find given client"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -346,7 +340,7 @@ func csDeopHandler(server *Server, client *Client, command string, params []stri
|
|||||||
|
|
||||||
present, cumodes := channel.ClientStatus(target)
|
present, cumodes := channel.ClientStatus(target)
|
||||||
if !present || len(cumodes) == 0 {
|
if !present || len(cumodes) == 0 {
|
||||||
csNotice(rb, client.t("Target has no privileges to remove"))
|
service.Notice(rb, client.t("Target has no privileges to remove"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,38 +364,38 @@ func csDeopHandler(server *Server, client *Client, command string, params []stri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
csNotice(rb, client.t("Successfully removed operator privileges"))
|
service.Notice(rb, client.t("Successfully removed operator privileges"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func csRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csRegisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if server.Config().Channels.Registration.OperatorOnly && !client.HasRoleCapabs("chanreg") {
|
if server.Config().Channels.Registration.OperatorOnly && !client.HasRoleCapabs("chanreg") {
|
||||||
csNotice(rb, client.t("Channel registration is restricted to server operators"))
|
service.Notice(rb, client.t("Channel registration is restricted to server operators"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
channelName := params[0]
|
channelName := params[0]
|
||||||
channelInfo := server.channels.Get(channelName)
|
channelInfo := server.channels.Get(channelName)
|
||||||
if channelInfo == nil {
|
if channelInfo == nil {
|
||||||
csNotice(rb, client.t("No such channel"))
|
service.Notice(rb, client.t("No such channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channelInfo.ClientIsAtLeast(client, modes.ChannelOperator) {
|
if !channelInfo.ClientIsAtLeast(client, modes.ChannelOperator) {
|
||||||
csNotice(rb, client.t("You must be an oper on the channel to register it"))
|
service.Notice(rb, client.t("You must be an oper on the channel to register it"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
account := client.Account()
|
account := client.Account()
|
||||||
if !checkChanLimit(client, rb) {
|
if !checkChanLimit(service, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// this provides the synchronization that allows exactly one registration of the channel:
|
// this provides the synchronization that allows exactly one registration of the channel:
|
||||||
err := server.channels.SetRegistered(channelName, account)
|
err := server.channels.SetRegistered(channelName, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
csNotice(rb, err.Error())
|
service.Notice(rb, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
|
||||||
|
|
||||||
server.logger.Info("services", fmt.Sprintf("Client %s registered channel %s", client.Nick(), channelName))
|
server.logger.Info("services", fmt.Sprintf("Client %s registered channel %s", client.Nick(), channelName))
|
||||||
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Channel registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), channelName, client.nickMaskString))
|
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Channel registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), channelName, client.nickMaskString))
|
||||||
@ -415,38 +409,38 @@ func csRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
},
|
},
|
||||||
rb)
|
rb)
|
||||||
if applied {
|
if applied {
|
||||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, "*", "", rb)
|
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, service.prefix, "*", "", rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether a client has already registered too many channels
|
// check whether a client has already registered too many channels
|
||||||
func checkChanLimit(client *Client, rb *ResponseBuffer) (ok bool) {
|
func checkChanLimit(service *ircService, client *Client, rb *ResponseBuffer) (ok bool) {
|
||||||
account := client.Account()
|
account := client.Account()
|
||||||
channelsAlreadyRegistered := client.server.accounts.ChannelsForAccount(account)
|
channelsAlreadyRegistered := client.server.accounts.ChannelsForAccount(account)
|
||||||
ok = len(channelsAlreadyRegistered) < client.server.Config().Channels.Registration.MaxChannelsPerAccount || client.HasRoleCapabs("chanreg")
|
ok = len(channelsAlreadyRegistered) < client.server.Config().Channels.Registration.MaxChannelsPerAccount || client.HasRoleCapabs("chanreg")
|
||||||
if !ok {
|
if !ok {
|
||||||
csNotice(rb, client.t("You have already registered the maximum number of channels; try dropping some with /CS UNREGISTER"))
|
service.Notice(rb, client.t("You have already registered the maximum number of channels; try dropping some with /CS UNREGISTER"))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func csPrivsCheck(channel RegisteredChannel, client *Client, rb *ResponseBuffer) (success bool) {
|
func csPrivsCheck(service *ircService, channel RegisteredChannel, client *Client, rb *ResponseBuffer) (success bool) {
|
||||||
founder := channel.Founder
|
founder := channel.Founder
|
||||||
if founder == "" {
|
if founder == "" {
|
||||||
csNotice(rb, client.t("That channel is not registered"))
|
service.Notice(rb, client.t("That channel is not registered"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if client.HasRoleCapabs("chanreg") {
|
if client.HasRoleCapabs("chanreg") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if founder != client.Account() {
|
if founder != client.Account() {
|
||||||
csNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func csUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csUnregisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
channelName := params[0]
|
channelName := params[0]
|
||||||
var verificationCode string
|
var verificationCode string
|
||||||
if len(params) > 1 {
|
if len(params) > 1 {
|
||||||
@ -455,41 +449,41 @@ func csUnregisterHandler(server *Server, client *Client, command string, params
|
|||||||
|
|
||||||
channel := server.channels.Get(channelName)
|
channel := server.channels.Get(channelName)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("No such channel"))
|
service.Notice(rb, client.t("No such channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info := channel.ExportRegistration(0)
|
info := channel.ExportRegistration(0)
|
||||||
channelKey := info.NameCasefolded
|
channelKey := info.NameCasefolded
|
||||||
if !csPrivsCheck(info, client, rb) {
|
if !csPrivsCheck(service, info, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCode := utils.ConfirmationCode(info.Name, info.RegisteredAt)
|
expectedCode := utils.ConfirmationCode(info.Name, info.RegisteredAt)
|
||||||
if expectedCode != verificationCode {
|
if expectedCode != verificationCode {
|
||||||
csNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this channel will remove all stored channel attributes.$b")))
|
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this channel will remove all stored channel attributes.$b")))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/CS UNREGISTER %s %s", channelKey, expectedCode)))
|
service.Notice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/CS UNREGISTER %s %s", channelKey, expectedCode)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server.channels.SetUnregistered(channelKey, info.Founder)
|
server.channels.SetUnregistered(channelKey, info.Founder)
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
func csClearHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csClearHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
channel := server.channels.Get(params[0])
|
channel := server.channels.Get(params[0])
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !csPrivsCheck(channel.ExportRegistration(0), client, rb) {
|
if !csPrivsCheck(service, channel.ExportRegistration(0), client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(params[1]) {
|
switch strings.ToLower(params[1]) {
|
||||||
case "access":
|
case "access":
|
||||||
channel.resetAccess()
|
channel.resetAccess()
|
||||||
csNotice(rb, client.t("Successfully reset channel access"))
|
service.Notice(rb, client.t("Successfully reset channel access"))
|
||||||
case "users":
|
case "users":
|
||||||
for _, target := range channel.Members() {
|
for _, target := range channel.Members() {
|
||||||
if target != client {
|
if target != client {
|
||||||
@ -497,20 +491,20 @@ func csClearHandler(server *Server, client *Client, command string, params []str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
csNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func csTransferHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csTransferHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if strings.ToLower(params[0]) == "accept" {
|
if strings.ToLower(params[0]) == "accept" {
|
||||||
processTransferAccept(client, params[1], rb)
|
processTransferAccept(service, client, params[1], rb)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
chname := params[0]
|
chname := params[0]
|
||||||
channel := server.channels.Get(chname)
|
channel := server.channels.Get(chname)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
regInfo := channel.ExportRegistration(0)
|
regInfo := channel.ExportRegistration(0)
|
||||||
@ -519,21 +513,21 @@ func csTransferHandler(server *Server, client *Client, command string, params []
|
|||||||
isFounder := account != "" && account == regInfo.Founder
|
isFounder := account != "" && account == regInfo.Founder
|
||||||
hasPrivs := client.HasRoleCapabs("chanreg")
|
hasPrivs := client.HasRoleCapabs("chanreg")
|
||||||
if !(isFounder || hasPrivs) {
|
if !(isFounder || hasPrivs) {
|
||||||
csNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := params[1]
|
target := params[1]
|
||||||
targetAccount, err := server.accounts.LoadAccount(params[1])
|
targetAccount, err := server.accounts.LoadAccount(params[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
csNotice(rb, client.t("Account does not exist"))
|
service.Notice(rb, client.t("Account does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if targetAccount.NameCasefolded != account {
|
if targetAccount.NameCasefolded != account {
|
||||||
expectedCode := utils.ConfirmationCode(regInfo.Name, regInfo.RegisteredAt)
|
expectedCode := utils.ConfirmationCode(regInfo.Name, regInfo.RegisteredAt)
|
||||||
codeValidated := 2 < len(params) && params[2] == expectedCode
|
codeValidated := 2 < len(params) && params[2] == expectedCode
|
||||||
if !codeValidated {
|
if !codeValidated {
|
||||||
csNotice(rb, ircfmt.Unescape(client.t("$bWarning: you are about to transfer control of your channel to another user.$b")))
|
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: you are about to transfer control of your channel to another user.$b")))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("To confirm your channel transfer, type: /CS TRANSFER %[1]s %[2]s %[3]s"), chname, target, expectedCode))
|
service.Notice(rb, fmt.Sprintf(client.t("To confirm your channel transfer, type: /CS TRANSFER %[1]s %[2]s %[3]s"), chname, target, expectedCode))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,19 +535,19 @@ func csTransferHandler(server *Server, client *Client, command string, params []
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
switch status {
|
switch status {
|
||||||
case channelTransferComplete:
|
case channelTransferComplete:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Successfully transferred channel %[1]s to account %[2]s"), chname, target))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully transferred channel %[1]s to account %[2]s"), chname, target))
|
||||||
case channelTransferPending:
|
case channelTransferPending:
|
||||||
sendTransferPendingNotice(server, target, chname)
|
sendTransferPendingNotice(service, server, target, chname)
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Transfer of channel %[1]s to account %[2]s succeeded, pending acceptance"), chname, target))
|
service.Notice(rb, fmt.Sprintf(client.t("Transfer of channel %[1]s to account %[2]s succeeded, pending acceptance"), chname, target))
|
||||||
case channelTransferCancelled:
|
case channelTransferCancelled:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Cancelled pending transfer of channel %s"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Cancelled pending transfer of channel %s"), chname))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
csNotice(rb, client.t("Could not transfer channel"))
|
service.Notice(rb, client.t("Could not transfer channel"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTransferPendingNotice(server *Server, account, chname string) {
|
func sendTransferPendingNotice(service *ircService, server *Server, account, chname string) {
|
||||||
clients := server.accounts.AccountToClients(account)
|
clients := server.accounts.AccountToClients(account)
|
||||||
if len(clients) == 0 {
|
if len(clients) == 0 {
|
||||||
return
|
return
|
||||||
@ -565,29 +559,29 @@ func sendTransferPendingNotice(server *Server, account, chname string) {
|
|||||||
break // prefer the login where the nick is the account
|
break // prefer the login where the nick is the account
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.Send(nil, chanservMask, "NOTICE", client.Nick(), fmt.Sprintf(client.t("You have been offered ownership of channel %[1]s. To accept, /CS TRANSFER ACCEPT %[1]s"), chname))
|
client.Send(nil, service.prefix, "NOTICE", client.Nick(), fmt.Sprintf(client.t("You have been offered ownership of channel %[1]s. To accept, /CS TRANSFER ACCEPT %[1]s"), chname))
|
||||||
}
|
}
|
||||||
|
|
||||||
func processTransferAccept(client *Client, chname string, rb *ResponseBuffer) {
|
func processTransferAccept(service *ircService, client *Client, chname string, rb *ResponseBuffer) {
|
||||||
channel := client.server.channels.Get(chname)
|
channel := client.server.channels.Get(chname)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("Channel does not exist"))
|
service.Notice(rb, client.t("Channel does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !checkChanLimit(client, rb) {
|
if !checkChanLimit(service, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch channel.AcceptTransfer(client) {
|
switch channel.AcceptTransfer(client) {
|
||||||
case nil:
|
case nil:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Successfully accepted ownership of channel %s"), channel.Name()))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully accepted ownership of channel %s"), channel.Name()))
|
||||||
case errChannelTransferNotOffered:
|
case errChannelTransferNotOffered:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("You weren't offered ownership of channel %s"), channel.Name()))
|
service.Notice(rb, fmt.Sprintf(client.t("You weren't offered ownership of channel %s"), channel.Name()))
|
||||||
default:
|
default:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Could not accept ownership of channel %s"), channel.Name()))
|
service.Notice(rb, fmt.Sprintf(client.t("Could not accept ownership of channel %s"), channel.Name()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func csPurgeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csPurgeHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
oper := client.Oper()
|
oper := client.Oper()
|
||||||
if oper == nil {
|
if oper == nil {
|
||||||
return // should be impossible because you need oper capabs for this
|
return // should be impossible because you need oper capabs for this
|
||||||
@ -611,29 +605,29 @@ func csPurgeHandler(server *Server, client *Client, command string, params []str
|
|||||||
channel.Kick(client, target, "Cleared by ChanServ", rb, true)
|
channel.Kick(client, target, "Cleared by ChanServ", rb, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Successfully purged channel %s from the server"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully purged channel %s from the server"), chname))
|
||||||
case errInvalidChannelName:
|
case errInvalidChannelName:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Can't purge invalid channel %s"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Can't purge invalid channel %s"), chname))
|
||||||
default:
|
default:
|
||||||
csNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func csUnpurgeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csUnpurgeHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
chname := params[0]
|
chname := params[0]
|
||||||
switch server.channels.Unpurge(chname) {
|
switch server.channels.Unpurge(chname) {
|
||||||
case nil:
|
case nil:
|
||||||
csNotice(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:
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s wasn't previously purged from the server"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s wasn't previously purged from the server"), chname))
|
||||||
default:
|
default:
|
||||||
csNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func csListHandler(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") {
|
||||||
csNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,27 +636,27 @@ func csListHandler(server *Server, client *Client, command string, params []stri
|
|||||||
var err error
|
var err error
|
||||||
searchRegex, err = regexp.Compile(params[0])
|
searchRegex, err = regexp.Compile(params[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
csNotice(rb, client.t("Invalid regex"))
|
service.Notice(rb, client.t("Invalid regex"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
csNotice(rb, ircfmt.Unescape(client.t("*** $bChanServ LIST$b ***")))
|
service.Notice(rb, ircfmt.Unescape(client.t("*** $bChanServ LIST$b ***")))
|
||||||
|
|
||||||
channels := server.channelRegistry.AllChannels()
|
channels := server.channelRegistry.AllChannels()
|
||||||
for _, channel := range channels {
|
for _, channel := range channels {
|
||||||
if searchRegex == nil || searchRegex.MatchString(channel) {
|
if searchRegex == nil || searchRegex.MatchString(channel) {
|
||||||
csNotice(rb, fmt.Sprintf(" %s", channel))
|
service.Notice(rb, fmt.Sprintf(" %s", channel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
csNotice(rb, ircfmt.Unescape(client.t("*** $bEnd of ChanServ LIST$b ***")))
|
service.Notice(rb, ircfmt.Unescape(client.t("*** $bEnd of ChanServ LIST$b ***")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func csInfoHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csInfoHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
chname, err := CasefoldChannel(params[0])
|
chname, err := CasefoldChannel(params[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
csNotice(rb, client.t("Invalid channel name"))
|
service.Notice(rb, client.t("Invalid channel name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,16 +664,16 @@ func csInfoHandler(server *Server, client *Client, command string, params []stri
|
|||||||
if client.HasRoleCapabs("chanreg") {
|
if client.HasRoleCapabs("chanreg") {
|
||||||
purgeRecord, err := server.channelRegistry.LoadPurgeRecord(chname)
|
purgeRecord, err := server.channelRegistry.LoadPurgeRecord(chname)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s was purged by the server operators and cannot be used"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s was purged by the server operators and cannot be used"), chname))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Purged by operator: %s"), purgeRecord.Oper))
|
service.Notice(rb, fmt.Sprintf(client.t("Purged by operator: %s"), purgeRecord.Oper))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Purged at: %s"), purgeRecord.PurgedAt.Format(time.RFC1123)))
|
service.Notice(rb, fmt.Sprintf(client.t("Purged at: %s"), purgeRecord.PurgedAt.Format(time.RFC1123)))
|
||||||
if purgeRecord.Reason != "" {
|
if purgeRecord.Reason != "" {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Purge reason: %s"), purgeRecord.Reason))
|
service.Notice(rb, fmt.Sprintf(client.t("Purge reason: %s"), purgeRecord.Reason))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if server.channels.IsPurged(chname) {
|
if server.channels.IsPurged(chname) {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s was purged by the server operators and cannot be used"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s was purged by the server operators and cannot be used"), chname))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,59 +684,59 @@ func csInfoHandler(server *Server, client *Client, command string, params []stri
|
|||||||
} else {
|
} else {
|
||||||
chinfo, err = server.channelRegistry.LoadChannel(chname)
|
chinfo, err = server.channelRegistry.LoadChannel(chname)
|
||||||
if err != nil && !(err == errNoSuchChannel || err == errFeatureDisabled) {
|
if err != nil && !(err == errNoSuchChannel || err == errFeatureDisabled) {
|
||||||
csNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// channel exists but is unregistered, or doesn't exist:
|
// channel exists but is unregistered, or doesn't exist:
|
||||||
if chinfo.Founder == "" {
|
if chinfo.Founder == "" {
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s is not registered"), chname))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s is not registered"), chname))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Channel %s is registered"), chinfo.Name))
|
service.Notice(rb, fmt.Sprintf(client.t("Channel %s is registered"), chinfo.Name))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Founder: %s"), chinfo.Founder))
|
service.Notice(rb, fmt.Sprintf(client.t("Founder: %s"), chinfo.Founder))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Registered at: %s"), chinfo.RegisteredAt.Format(time.RFC1123)))
|
service.Notice(rb, fmt.Sprintf(client.t("Registered at: %s"), chinfo.RegisteredAt.Format(time.RFC1123)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func displayChannelSetting(settingName string, settings ChannelSettings, client *Client, rb *ResponseBuffer) {
|
func displayChannelSetting(service *ircService, settingName string, settings ChannelSettings, client *Client, rb *ResponseBuffer) {
|
||||||
config := client.server.Config()
|
config := client.server.Config()
|
||||||
|
|
||||||
switch strings.ToLower(settingName) {
|
switch strings.ToLower(settingName) {
|
||||||
case "history":
|
case "history":
|
||||||
effectiveValue := historyEnabled(config.History.Persistent.RegisteredChannels, settings.History)
|
effectiveValue := historyEnabled(config.History.Persistent.RegisteredChannels, settings.History)
|
||||||
csNotice(rb, fmt.Sprintf(client.t("The stored channel history setting is: %s"), historyStatusToString(settings.History)))
|
service.Notice(rb, fmt.Sprintf(client.t("The stored channel history setting is: %s"), historyStatusToString(settings.History)))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("Given current server settings, the channel history setting is: %s"), historyStatusToString(effectiveValue)))
|
service.Notice(rb, fmt.Sprintf(client.t("Given current server settings, the channel history setting is: %s"), historyStatusToString(effectiveValue)))
|
||||||
default:
|
default:
|
||||||
csNotice(rb, client.t("Invalid params"))
|
service.Notice(rb, client.t("Invalid params"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func csGetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csGetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
chname, setting := params[0], params[1]
|
chname, setting := params[0], params[1]
|
||||||
channel := server.channels.Get(chname)
|
channel := server.channels.Get(chname)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("No such channel"))
|
service.Notice(rb, client.t("No such channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info := channel.ExportRegistration(IncludeSettings)
|
info := channel.ExportRegistration(IncludeSettings)
|
||||||
if !csPrivsCheck(info, client, rb) {
|
if !csPrivsCheck(service, info, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
displayChannelSetting(setting, info.Settings, client, rb)
|
displayChannelSetting(service, setting, info.Settings, client, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func csSetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func csSetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
chname, setting, value := params[0], params[1], params[2]
|
chname, setting, value := params[0], params[1], params[2]
|
||||||
channel := server.channels.Get(chname)
|
channel := server.channels.Get(chname)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
csNotice(rb, client.t("No such channel"))
|
service.Notice(rb, client.t("No such channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info := channel.ExportRegistration(IncludeSettings)
|
info := channel.ExportRegistration(IncludeSettings)
|
||||||
settings := info.Settings
|
settings := info.Settings
|
||||||
if !csPrivsCheck(info, client, rb) {
|
if !csPrivsCheck(service, info, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,12 +754,12 @@ func csSetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
csNotice(rb, client.t("Successfully changed the channel settings"))
|
service.Notice(rb, client.t("Successfully changed the channel settings"))
|
||||||
displayChannelSetting(setting, settings, client, rb)
|
displayChannelSetting(service, setting, settings, client, rb)
|
||||||
case errInvalidParams:
|
case errInvalidParams:
|
||||||
csNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
default:
|
default:
|
||||||
server.logger.Error("internal", "CS SET error:", err.Error())
|
server.logger.Error("internal", "CS SET error:", err.Error())
|
||||||
csNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,17 +526,18 @@ type Config struct {
|
|||||||
forceTrailing bool
|
forceTrailing bool
|
||||||
SendUnprefixedSasl bool `yaml:"send-unprefixed-sasl"`
|
SendUnprefixedSasl bool `yaml:"send-unprefixed-sasl"`
|
||||||
}
|
}
|
||||||
isupport isupport.List
|
isupport isupport.List
|
||||||
IPLimits connection_limits.LimiterConfig `yaml:"ip-limits"`
|
IPLimits connection_limits.LimiterConfig `yaml:"ip-limits"`
|
||||||
Cloaks cloaks.CloakConfig `yaml:"ip-cloaking"`
|
Cloaks cloaks.CloakConfig `yaml:"ip-cloaking"`
|
||||||
SecureNetDefs []string `yaml:"secure-nets"`
|
SecureNetDefs []string `yaml:"secure-nets"`
|
||||||
secureNets []net.IPNet
|
secureNets []net.IPNet
|
||||||
supportedCaps *caps.Set
|
supportedCaps *caps.Set
|
||||||
capValues caps.Values
|
capValues caps.Values
|
||||||
Casemapping Casemapping
|
Casemapping Casemapping
|
||||||
EnforceUtf8 bool `yaml:"enforce-utf8"`
|
EnforceUtf8 bool `yaml:"enforce-utf8"`
|
||||||
OutputPath string `yaml:"output-path"`
|
OutputPath string `yaml:"output-path"`
|
||||||
IPCheckScript ScriptConfig `yaml:"ip-check-script"`
|
IPCheckScript ScriptConfig `yaml:"ip-check-script"`
|
||||||
|
OverrideServicesHostname string `yaml:"override-services-hostname"`
|
||||||
}
|
}
|
||||||
|
|
||||||
Roleplay struct {
|
Roleplay struct {
|
||||||
|
@ -77,23 +77,23 @@ func registrationErrorToMessage(err error) (message string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helper function to dispatch messages when a client successfully registers
|
// helper function to dispatch messages when a client successfully registers
|
||||||
func sendSuccessfulRegResponse(client *Client, rb *ResponseBuffer, forNS bool) {
|
func sendSuccessfulRegResponse(service *ircService, client *Client, rb *ResponseBuffer) {
|
||||||
details := client.Details()
|
details := client.Details()
|
||||||
if forNS {
|
if service != nil {
|
||||||
nsNotice(rb, client.t("Account created"))
|
service.Notice(rb, client.t("Account created"))
|
||||||
} else {
|
} else {
|
||||||
rb.Add(nil, client.server.name, RPL_REG_SUCCESS, details.nick, details.accountName, client.t("Account created"))
|
rb.Add(nil, client.server.name, RPL_REG_SUCCESS, details.nick, details.accountName, client.t("Account created"))
|
||||||
}
|
}
|
||||||
client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] registered account $c[grey][$r%s$c[grey]] from IP %s"), details.nickMask, details.accountName, rb.session.IP().String()))
|
client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] registered account $c[grey][$r%s$c[grey]] from IP %s"), details.nickMask, details.accountName, rb.session.IP().String()))
|
||||||
sendSuccessfulAccountAuth(client, rb, forNS, false)
|
sendSuccessfulAccountAuth(service, client, rb, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendSuccessfulAccountAuth means that an account auth attempt completed successfully, and is used to dispatch messages.
|
// sendSuccessfulAccountAuth means that an account auth attempt completed successfully, and is used to dispatch messages.
|
||||||
func sendSuccessfulAccountAuth(client *Client, rb *ResponseBuffer, forNS, forSASL bool) {
|
func sendSuccessfulAccountAuth(service *ircService, client *Client, rb *ResponseBuffer, forSASL bool) {
|
||||||
details := client.Details()
|
details := client.Details()
|
||||||
|
|
||||||
if forNS {
|
if service != nil {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("You're now logged in as %s"), details.accountName))
|
service.Notice(rb, fmt.Sprintf(client.t("You're now logged in as %s"), details.accountName))
|
||||||
} else {
|
} else {
|
||||||
//TODO(dan): some servers send this numeric even for NickServ logins iirc? to confirm and maybe do too
|
//TODO(dan): some servers send this numeric even for NickServ logins iirc? to confirm and maybe do too
|
||||||
rb.Add(nil, client.server.name, RPL_LOGGEDIN, details.nick, details.nickMask, details.accountName, fmt.Sprintf(client.t("You are now logged in as %s"), details.accountName))
|
rb.Add(nil, client.server.name, RPL_LOGGEDIN, details.nick, details.nickMask, details.accountName, fmt.Sprintf(client.t("You are now logged in as %s"), details.accountName))
|
||||||
@ -253,11 +253,11 @@ func authPlainHandler(server *Server, client *Client, mechanism string, value []
|
|||||||
msg := authErrorToMessage(server, err)
|
msg := authErrorToMessage(server, err)
|
||||||
rb.Add(nil, server.name, ERR_SASLFAIL, client.Nick(), fmt.Sprintf("%s: %s", client.t("SASL authentication failed"), client.t(msg)))
|
rb.Add(nil, server.name, ERR_SASLFAIL, client.Nick(), fmt.Sprintf("%s: %s", client.t("SASL authentication failed"), client.t(msg)))
|
||||||
return false
|
return false
|
||||||
} else if !fixupNickEqualsAccount(client, rb, server.Config()) {
|
} else if !fixupNickEqualsAccount(client, rb, server.Config(), "") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSuccessfulAccountAuth(client, rb, false, true)
|
sendSuccessfulAccountAuth(nil, client, rb, true)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,11 +311,11 @@ func authExternalHandler(server *Server, client *Client, mechanism string, value
|
|||||||
msg := authErrorToMessage(server, err)
|
msg := authErrorToMessage(server, err)
|
||||||
rb.Add(nil, server.name, ERR_SASLFAIL, client.nick, fmt.Sprintf("%s: %s", client.t("SASL authentication failed"), client.t(msg)))
|
rb.Add(nil, server.name, ERR_SASLFAIL, client.nick, fmt.Sprintf("%s: %s", client.t("SASL authentication failed"), client.t(msg)))
|
||||||
return false
|
return false
|
||||||
} else if !fixupNickEqualsAccount(client, rb, server.Config()) {
|
} else if !fixupNickEqualsAccount(client, rb, server.Config(), "") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSuccessfulAccountAuth(client, rb, false, true)
|
sendSuccessfulAccountAuth(nil, client, rb, true)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,7 +1525,7 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
config := server.Config()
|
config := server.Config()
|
||||||
if time.Since(client.ctime) < config.Channels.ListDelay && client.Account() == "" && !client.HasMode(modes.Operator) {
|
if time.Since(client.ctime) < config.Channels.ListDelay && client.Account() == "" && !client.HasMode(modes.Operator) {
|
||||||
remaining := time.Until(client.ctime.Add(config.Channels.ListDelay))
|
remaining := time.Until(client.ctime.Add(config.Channels.ListDelay))
|
||||||
csNotice(rb, fmt.Sprintf(client.t("This server requires that you wait %v after connecting before you can use /LIST. You have %v left."), config.Channels.ListDelay, remaining))
|
rb.Notice(fmt.Sprintf(client.t("This server requires that you wait %v after connecting before you can use /LIST. You have %v left."), config.Channels.ListDelay, remaining))
|
||||||
rb.Add(nil, server.name, RPL_LISTEND, client.Nick(), client.t("End of LIST"))
|
rb.Add(nil, server.name, RPL_LISTEND, client.Nick(), client.t("End of LIST"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -2355,7 +2355,7 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
}
|
}
|
||||||
err := server.accounts.AuthenticateByPassphrase(client, account, accountPass)
|
err := server.accounts.AuthenticateByPassphrase(client, account, accountPass)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
sendSuccessfulAccountAuth(client, rb, false, true)
|
sendSuccessfulAccountAuth(nil, client, rb, true)
|
||||||
// login-via-pass-command entails that we do not need to check
|
// login-via-pass-command entails that we do not need to check
|
||||||
// an actual server password (either no password or skip-server-password)
|
// an actual server password (either no password or skip-server-password)
|
||||||
rb.session.passStatus = serverPassSuccessful
|
rb.session.passStatus = serverPassSuccessful
|
||||||
@ -2446,13 +2446,13 @@ func registerHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
|
|||||||
err := server.accounts.Verify(client, accountName, "")
|
err := server.accounts.Verify(client, accountName, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if client.registered {
|
if client.registered {
|
||||||
if !fixupNickEqualsAccount(client, rb, config) {
|
if !fixupNickEqualsAccount(client, rb, config, "") {
|
||||||
err = errNickAccountMismatch
|
err = errNickAccountMismatch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rb.Add(nil, server.name, "REGISTER", "SUCCESS", accountName, client.t("Account successfully registered"))
|
rb.Add(nil, server.name, "REGISTER", "SUCCESS", accountName, client.t("Account successfully registered"))
|
||||||
sendSuccessfulRegResponse(client, rb, true)
|
sendSuccessfulRegResponse(nil, client, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2494,14 +2494,14 @@ func verifyHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
|
|||||||
accountName, verificationCode := msg.Params[0], msg.Params[1]
|
accountName, verificationCode := msg.Params[0], msg.Params[1]
|
||||||
err := server.accounts.Verify(client, accountName, verificationCode)
|
err := server.accounts.Verify(client, accountName, verificationCode)
|
||||||
if err == nil && client.registered {
|
if err == nil && client.registered {
|
||||||
if !fixupNickEqualsAccount(client, rb, config) {
|
if !fixupNickEqualsAccount(client, rb, config, "") {
|
||||||
err = errNickAccountMismatch
|
err = errNickAccountMismatch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
rb.Add(nil, server.name, "VERIFY", "SUCCESS", accountName, client.t("Account successfully registered"))
|
rb.Add(nil, server.name, "VERIFY", "SUCCESS", accountName, client.t("Account successfully registered"))
|
||||||
sendSuccessfulRegResponse(client, rb, true)
|
sendSuccessfulRegResponse(nil, client, rb)
|
||||||
case errAccountVerificationInvalidCode:
|
case errAccountVerificationInvalidCode:
|
||||||
rb.Add(nil, server.name, "FAIL", "VERIFY", "INVALID_CODE", client.t("Invalid verification code"))
|
rb.Add(nil, server.name, "FAIL", "VERIFY", "INVALID_CODE", client.t("Invalid verification code"))
|
||||||
default:
|
default:
|
||||||
@ -2873,7 +2873,7 @@ func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
username, password = username[:colonIndex], username[colonIndex+1:]
|
username, password = username[:colonIndex], username[colonIndex+1:]
|
||||||
err := server.accounts.AuthenticateByPassphrase(client, username, password)
|
err := server.accounts.AuthenticateByPassphrase(client, username, password)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
sendSuccessfulAccountAuth(client, rb, false, true)
|
sendSuccessfulAccountAuth(nil, client, rb, true)
|
||||||
} else {
|
} else {
|
||||||
// this is wrong, but send something for debugging that will show up in a raw transcript
|
// this is wrong, but send something for debugging that will show up in a raw transcript
|
||||||
rb.Add(nil, server.name, ERR_SASLFAIL, client.Nick(), client.t("SASL authentication failed"))
|
rb.Add(nil, server.name, ERR_SASLFAIL, client.Nick(), client.t("SASL authentication failed"))
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
histservHelp = `HistServ provides commands related to history.`
|
histservHelp = `HistServ provides commands related to history.`
|
||||||
histServMask = "HistServ!HistServ@localhost"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func histservEnabled(config *Config) bool {
|
func histservEnabled(config *Config) bool {
|
||||||
@ -83,24 +82,19 @@ CHATHISTORY.`,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// histNotice sends the client a notice from HistServ
|
func histservForgetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
func histNotice(rb *ResponseBuffer, text string) {
|
|
||||||
rb.Add(nil, histServMask, "NOTICE", rb.target.Nick(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func histservForgetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
|
||||||
accountName := server.accounts.AccountToAccountName(params[0])
|
accountName := server.accounts.AccountToAccountName(params[0])
|
||||||
if accountName == "" {
|
if accountName == "" {
|
||||||
histNotice(rb, client.t("Could not look up account name, proceeding anyway"))
|
service.Notice(rb, client.t("Could not look up account name, proceeding anyway"))
|
||||||
accountName = params[0]
|
accountName = params[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
server.ForgetHistory(accountName)
|
server.ForgetHistory(accountName)
|
||||||
|
|
||||||
histNotice(rb, fmt.Sprintf(client.t("Enqueued account %s for message deletion"), accountName))
|
service.Notice(rb, fmt.Sprintf(client.t("Enqueued account %s for message deletion"), accountName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func histservDeleteHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func histservDeleteHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var target, msgid string
|
var target, msgid string
|
||||||
if len(params) == 1 {
|
if len(params) == 1 {
|
||||||
msgid = params[0]
|
msgid = params[0]
|
||||||
@ -113,27 +107,27 @@ func histservDeleteHandler(server *Server, client *Client, command string, param
|
|||||||
if !hasPrivs {
|
if !hasPrivs {
|
||||||
accountName = client.AccountName()
|
accountName = client.AccountName()
|
||||||
if !(server.Config().History.Retention.AllowIndividualDelete && accountName != "*") {
|
if !(server.Config().History.Retention.AllowIndividualDelete && accountName != "*") {
|
||||||
histNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.DeleteMessage(target, msgid, accountName)
|
err := server.DeleteMessage(target, msgid, accountName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
histNotice(rb, client.t("Successfully deleted message"))
|
service.Notice(rb, client.t("Successfully deleted message"))
|
||||||
} else {
|
} else {
|
||||||
if hasPrivs {
|
if hasPrivs {
|
||||||
histNotice(rb, fmt.Sprintf(client.t("Error deleting message: %v"), err))
|
service.Notice(rb, fmt.Sprintf(client.t("Error deleting message: %v"), err))
|
||||||
} else {
|
} else {
|
||||||
histNotice(rb, client.t("Could not delete message"))
|
service.Notice(rb, client.t("Could not delete message"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func histservExportHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func histservExportHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
cfAccount, err := CasefoldName(params[0])
|
cfAccount, err := CasefoldName(params[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
histNotice(rb, client.t("Invalid account name"))
|
service.Notice(rb, client.t("Invalid account name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,15 +137,15 @@ func histservExportHandler(server *Server, client *Client, command string, param
|
|||||||
pathname := config.getOutputPath(filename)
|
pathname := config.getOutputPath(filename)
|
||||||
outfile, err := os.Create(pathname)
|
outfile, err := os.Create(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
histNotice(rb, fmt.Sprintf(client.t("Error opening export file: %v"), err))
|
service.Notice(rb, fmt.Sprintf(client.t("Error opening export file: %v"), err))
|
||||||
} else {
|
} else {
|
||||||
histNotice(rb, fmt.Sprintf(client.t("Started exporting data for account %[1]s to file %[2]s"), cfAccount, filename))
|
service.Notice(rb, fmt.Sprintf(client.t("Started exporting data for account %[1]s to file %[2]s"), cfAccount, filename))
|
||||||
}
|
}
|
||||||
|
|
||||||
go histservExportAndNotify(server, cfAccount, outfile, filename, client.Nick())
|
go histservExportAndNotify(service, server, cfAccount, outfile, filename, client.Nick())
|
||||||
}
|
}
|
||||||
|
|
||||||
func histservExportAndNotify(server *Server, cfAccount string, outfile *os.File, filename, alertNick string) {
|
func histservExportAndNotify(service *ircService, server *Server, cfAccount string, outfile *os.File, filename, alertNick string) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
server.logger.Error("history",
|
server.logger.Error("history",
|
||||||
@ -167,19 +161,19 @@ func histservExportAndNotify(server *Server, cfAccount string, outfile *os.File,
|
|||||||
|
|
||||||
client := server.clients.Get(alertNick)
|
client := server.clients.Get(alertNick)
|
||||||
if client != nil && client.HasRoleCapabs("history") {
|
if client != nil && client.HasRoleCapabs("history") {
|
||||||
client.Send(nil, histServMask, "NOTICE", client.Nick(), fmt.Sprintf(client.t("Data export for %[1]s completed and written to %[2]s"), cfAccount, filename))
|
client.Send(nil, service.prefix, "NOTICE", client.Nick(), fmt.Sprintf(client.t("Data export for %[1]s completed and written to %[2]s"), cfAccount, filename))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func histservPlayHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func histservPlayHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
items, _, err := easySelectHistory(server, client, params)
|
items, _, err := easySelectHistory(server, client, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
histNotice(rb, client.t("Could not retrieve history"))
|
service.Notice(rb, client.t("Could not retrieve history"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
playMessage := func(timestamp time.Time, nick, message string) {
|
playMessage := func(timestamp time.Time, nick, message string) {
|
||||||
histNotice(rb, fmt.Sprintf("%s <%s> %s", timestamp.Format("15:04:05"), stripMaskFromNick(nick), message))
|
service.Notice(rb, fmt.Sprintf("%s <%s> %s", timestamp.Format("15:04:05"), stripMaskFromNick(nick), message))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
@ -196,7 +190,7 @@ func histservPlayHandler(server *Server, client *Client, command string, params
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
histNotice(rb, client.t("End of history playback"))
|
service.Notice(rb, client.t("End of history playback"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// handles parameter parsing and history queries for /HISTORY and /HISTSERV PLAY
|
// handles parameter parsing and history queries for /HISTORY and /HISTSERV PLAY
|
||||||
|
@ -16,7 +16,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
|
hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
|
||||||
in place of your client's hostname/IP).`
|
in place of your client's hostname/IP).`
|
||||||
hsNickMask = "HostServ!HostServ@localhost"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -95,12 +94,7 @@ display the necessary code.`,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// hsNotice sends the client a notice from HostServ
|
func hsOnOffHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
func hsNotice(rb *ResponseBuffer, text string) {
|
|
||||||
rb.Add(nil, hsNickMask, "NOTICE", rb.target.Nick(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hsOnOffHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
|
||||||
enable := false
|
enable := false
|
||||||
if command == "on" {
|
if command == "on" {
|
||||||
enable = true
|
enable = true
|
||||||
@ -108,28 +102,28 @@ func hsOnOffHandler(server *Server, client *Client, command string, params []str
|
|||||||
|
|
||||||
_, err := server.accounts.VHostSetEnabled(client, enable)
|
_, err := server.accounts.VHostSetEnabled(client, enable)
|
||||||
if err == errNoVhost {
|
if err == errNoVhost {
|
||||||
hsNotice(rb, client.t(err.Error()))
|
service.Notice(rb, client.t(err.Error()))
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
hsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
} else if enable {
|
} else if enable {
|
||||||
hsNotice(rb, client.t("Successfully enabled your vhost"))
|
service.Notice(rb, client.t("Successfully enabled your vhost"))
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, client.t("Successfully disabled your vhost"))
|
service.Notice(rb, client.t("Successfully disabled your vhost"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hsStatusHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func hsStatusHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var accountName string
|
var accountName string
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
if !client.HasRoleCapabs("vhosts") {
|
if !client.HasRoleCapabs("vhosts") {
|
||||||
hsNotice(rb, client.t("Command restricted"))
|
service.Notice(rb, client.t("Command restricted"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accountName = params[0]
|
accountName = params[0]
|
||||||
} else {
|
} else {
|
||||||
accountName = client.Account()
|
accountName = client.Account()
|
||||||
if accountName == "" {
|
if accountName == "" {
|
||||||
hsNotice(rb, client.t("You're not logged into an account"))
|
service.Notice(rb, client.t("You're not logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,17 +133,17 @@ func hsStatusHandler(server *Server, client *Client, command string, params []st
|
|||||||
if err != errAccountDoesNotExist {
|
if err != errAccountDoesNotExist {
|
||||||
server.logger.Warning("internal", "error loading account info", accountName, err.Error())
|
server.logger.Warning("internal", "error loading account info", accountName, err.Error())
|
||||||
}
|
}
|
||||||
hsNotice(rb, client.t("No such account"))
|
service.Notice(rb, client.t("No such account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if account.VHost.ApprovedVHost != "" {
|
if account.VHost.ApprovedVHost != "" {
|
||||||
hsNotice(rb, fmt.Sprintf(client.t("Account %[1]s has vhost: %[2]s"), accountName, account.VHost.ApprovedVHost))
|
service.Notice(rb, fmt.Sprintf(client.t("Account %[1]s has vhost: %[2]s"), accountName, account.VHost.ApprovedVHost))
|
||||||
if !account.VHost.Enabled {
|
if !account.VHost.Enabled {
|
||||||
hsNotice(rb, client.t("This vhost is currently disabled, but can be enabled with /HS ON"))
|
service.Notice(rb, client.t("This vhost is currently disabled, but can be enabled with /HS ON"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, fmt.Sprintf(client.t("Account %s has no vhost"), accountName))
|
service.Notice(rb, fmt.Sprintf(client.t("Account %s has no vhost"), accountName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,14 +158,14 @@ func validateVhost(server *Server, vhost string, oper bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hsSetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func hsSetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
user := params[0]
|
user := params[0]
|
||||||
var vhost string
|
var vhost string
|
||||||
|
|
||||||
if command == "set" {
|
if command == "set" {
|
||||||
vhost = params[1]
|
vhost = params[1]
|
||||||
if validateVhost(server, vhost, true) != nil {
|
if validateVhost(server, vhost, true) != nil {
|
||||||
hsNotice(rb, client.t("Invalid vhost"))
|
service.Notice(rb, client.t("Invalid vhost"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,22 +173,22 @@ func hsSetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
|
|
||||||
_, err := server.accounts.VHostSet(user, vhost)
|
_, err := server.accounts.VHostSet(user, vhost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
hsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
} else if vhost != "" {
|
} else if vhost != "" {
|
||||||
hsNotice(rb, client.t("Successfully set vhost"))
|
service.Notice(rb, client.t("Successfully set vhost"))
|
||||||
} else {
|
} else {
|
||||||
hsNotice(rb, client.t("Successfully cleared vhost"))
|
service.Notice(rb, client.t("Successfully cleared vhost"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hsSetCloakSecretHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func hsSetCloakSecretHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
secret := params[0]
|
secret := params[0]
|
||||||
expectedCode := utils.ConfirmationCode(secret, server.ctime)
|
expectedCode := utils.ConfirmationCode(secret, server.ctime)
|
||||||
if len(params) == 1 || params[1] != expectedCode {
|
if len(params) == 1 || params[1] != expectedCode {
|
||||||
hsNotice(rb, ircfmt.Unescape(client.t("$bWarning: changing the cloak secret will invalidate stored ban/invite/exception lists.$b")))
|
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: changing the cloak secret will invalidate stored ban/invite/exception lists.$b")))
|
||||||
hsNotice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/HS SETCLOAKSECRET %s %s", secret, expectedCode)))
|
service.Notice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/HS SETCLOAKSECRET %s %s", secret, expectedCode)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
StoreCloakSecret(server.store, secret)
|
StoreCloakSecret(server.store, secret)
|
||||||
hsNotice(rb, client.t("Rotated the cloak secret; you must rehash or restart the server for it to take effect"))
|
service.Notice(rb, client.t("Rotated the cloak secret; you must rehash or restart the server for it to take effect"))
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ func (server *Server) RandomlyRename(client *Client) {
|
|||||||
// so we need to re-NICK automatically on every login event (IDENTIFY,
|
// so we need to re-NICK automatically on every login event (IDENTIFY,
|
||||||
// VERIFY, and a REGISTER that auto-verifies). if we can't get the nick
|
// VERIFY, and a REGISTER that auto-verifies). if we can't get the nick
|
||||||
// then we log them out (they will be able to reattach with SASL)
|
// then we log them out (they will be able to reattach with SASL)
|
||||||
func fixupNickEqualsAccount(client *Client, rb *ResponseBuffer, config *Config) (success bool) {
|
func fixupNickEqualsAccount(client *Client, rb *ResponseBuffer, config *Config, source string) (success bool) {
|
||||||
if !config.Accounts.NickReservation.ForceNickEqualsAccount {
|
if !config.Accounts.NickReservation.ForceNickEqualsAccount {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -161,7 +161,10 @@ func fixupNickEqualsAccount(client *Client, rb *ResponseBuffer, config *Config)
|
|||||||
err := performNickChange(client.server, client, client, rb.session, client.AccountName(), rb)
|
err := performNickChange(client.server, client, client, rb.session, client.AccountName(), rb)
|
||||||
if err != nil && err != errNoop {
|
if err != nil && err != errNoop {
|
||||||
client.server.accounts.Logout(client)
|
client.server.accounts.Logout(client)
|
||||||
nsNotice(rb, client.t("A client is already using that account; try logging out and logging back in with SASL"))
|
if source == "" {
|
||||||
|
source = client.server.name
|
||||||
|
}
|
||||||
|
rb.Add(nil, source, "NOTICE", client.t("A client is already using that account; try logging out and logging back in with SASL"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
379
irc/nickserv.go
379
irc/nickserv.go
@ -36,10 +36,6 @@ func servCmdRequiresBouncerEnabled(config *Config) bool {
|
|||||||
return config.Accounts.Multiclient.Enabled
|
return config.Accounts.Multiclient.Enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
nsPrefix = "NickServ!NickServ@localhost"
|
|
||||||
)
|
|
||||||
|
|
||||||
const nickservHelp = `NickServ lets you register, log in to, and manage an account.`
|
const nickservHelp = `NickServ lets you register, log in to, and manage an account.`
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -361,14 +357,7 @@ Currently, you can only change the canonical casefolding of an account
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// nsNotice sends the client a notice from NickServ
|
func nsGetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
func nsNotice(rb *ResponseBuffer, text string) {
|
|
||||||
// XXX i can't figure out how to use OragonoServices[servicename].prefix here
|
|
||||||
// without creating a compile-time initialization loop
|
|
||||||
rb.Add(nil, nsPrefix, "NOTICE", rb.target.Nick(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func nsGetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
|
||||||
var account string
|
var account string
|
||||||
if command == "saget" {
|
if command == "saget" {
|
||||||
account = params[0]
|
account = params[0]
|
||||||
@ -379,101 +368,101 @@ func nsGetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
|
|
||||||
accountData, err := server.accounts.LoadAccount(account)
|
accountData, err := server.accounts.LoadAccount(account)
|
||||||
if err == errAccountDoesNotExist {
|
if err == errAccountDoesNotExist {
|
||||||
nsNotice(rb, client.t("No such account"))
|
service.Notice(rb, client.t("No such account"))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
nsNotice(rb, client.t("Error loading account data"))
|
service.Notice(rb, client.t("Error loading account data"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
displaySetting(params[0], accountData.Settings, client, rb)
|
displaySetting(service, params[0], accountData.Settings, client, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func displaySetting(settingName string, settings AccountSettings, client *Client, rb *ResponseBuffer) {
|
func displaySetting(service *ircService, settingName string, settings AccountSettings, client *Client, rb *ResponseBuffer) {
|
||||||
config := client.server.Config()
|
config := client.server.Config()
|
||||||
switch strings.ToLower(settingName) {
|
switch strings.ToLower(settingName) {
|
||||||
case "enforce":
|
case "enforce":
|
||||||
storedValue := settings.NickEnforcement
|
storedValue := settings.NickEnforcement
|
||||||
serializedStoredValue := nickReservationToString(storedValue)
|
serializedStoredValue := nickReservationToString(storedValue)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Your stored nickname enforcement setting is: %s"), serializedStoredValue))
|
service.Notice(rb, fmt.Sprintf(client.t("Your stored nickname enforcement setting is: %s"), serializedStoredValue))
|
||||||
serializedActualValue := nickReservationToString(configuredEnforcementMethod(config, storedValue))
|
serializedActualValue := nickReservationToString(configuredEnforcementMethod(config, storedValue))
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Given current server settings, your nickname is enforced with: %s"), serializedActualValue))
|
service.Notice(rb, fmt.Sprintf(client.t("Given current server settings, your nickname is enforced with: %s"), serializedActualValue))
|
||||||
case "autoreplay-lines":
|
case "autoreplay-lines":
|
||||||
if settings.AutoreplayLines == nil {
|
if settings.AutoreplayLines == nil {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("You will receive the server default of %d lines of autoreplayed history"), config.History.AutoreplayOnJoin))
|
service.Notice(rb, fmt.Sprintf(client.t("You will receive the server default of %d lines of autoreplayed history"), config.History.AutoreplayOnJoin))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("You will receive %d lines of autoreplayed history"), *settings.AutoreplayLines))
|
service.Notice(rb, fmt.Sprintf(client.t("You will receive %d lines of autoreplayed history"), *settings.AutoreplayLines))
|
||||||
}
|
}
|
||||||
case "replay-joins":
|
case "replay-joins":
|
||||||
switch settings.ReplayJoins {
|
switch settings.ReplayJoins {
|
||||||
case ReplayJoinsCommandsOnly:
|
case ReplayJoinsCommandsOnly:
|
||||||
nsNotice(rb, client.t("You will see JOINs and PARTs in /HISTORY output, but not in autoreplay"))
|
service.Notice(rb, client.t("You will see JOINs and PARTs in /HISTORY output, but not in autoreplay"))
|
||||||
case ReplayJoinsAlways:
|
case ReplayJoinsAlways:
|
||||||
nsNotice(rb, client.t("You will see JOINs and PARTs in /HISTORY output and in autoreplay"))
|
service.Notice(rb, client.t("You will see JOINs and PARTs in /HISTORY output and in autoreplay"))
|
||||||
case ReplayJoinsNever:
|
case ReplayJoinsNever:
|
||||||
nsNotice(rb, client.t("You will not see JOINs and PARTs in /HISTORY output or in autoreplay"))
|
service.Notice(rb, client.t("You will not see JOINs and PARTs in /HISTORY output or in autoreplay"))
|
||||||
}
|
}
|
||||||
case "multiclient":
|
case "multiclient":
|
||||||
if !config.Accounts.Multiclient.Enabled {
|
if !config.Accounts.Multiclient.Enabled {
|
||||||
nsNotice(rb, client.t("This feature has been disabled by the server administrators"))
|
service.Notice(rb, client.t("This feature has been disabled by the server administrators"))
|
||||||
} else {
|
} else {
|
||||||
switch settings.AllowBouncer {
|
switch settings.AllowBouncer {
|
||||||
case MulticlientAllowedServerDefault:
|
case MulticlientAllowedServerDefault:
|
||||||
if config.Accounts.Multiclient.AllowedByDefault {
|
if config.Accounts.Multiclient.AllowedByDefault {
|
||||||
nsNotice(rb, client.t("Multiclient functionality is currently enabled for your account, but you can opt out"))
|
service.Notice(rb, client.t("Multiclient functionality is currently enabled for your account, but you can opt out"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Multiclient functionality is currently disabled for your account, but you can opt in"))
|
service.Notice(rb, client.t("Multiclient functionality is currently disabled for your account, but you can opt in"))
|
||||||
}
|
}
|
||||||
case MulticlientDisallowedByUser:
|
case MulticlientDisallowedByUser:
|
||||||
nsNotice(rb, client.t("Multiclient functionality is currently disabled for your account"))
|
service.Notice(rb, client.t("Multiclient functionality is currently disabled for your account"))
|
||||||
case MulticlientAllowedByUser:
|
case MulticlientAllowedByUser:
|
||||||
nsNotice(rb, client.t("Multiclient functionality is currently enabled for your account"))
|
service.Notice(rb, client.t("Multiclient functionality is currently enabled for your account"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "always-on":
|
case "always-on":
|
||||||
stored := settings.AlwaysOn
|
stored := settings.AlwaysOn
|
||||||
actual := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, stored)
|
actual := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, stored)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Your stored always-on setting is: %s"), persistentStatusToString(stored)))
|
service.Notice(rb, fmt.Sprintf(client.t("Your stored always-on setting is: %s"), persistentStatusToString(stored)))
|
||||||
if actual {
|
if actual {
|
||||||
nsNotice(rb, client.t("Given current server settings, your client is always-on"))
|
service.Notice(rb, client.t("Given current server settings, your client is always-on"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Given current server settings, your client is not always-on"))
|
service.Notice(rb, client.t("Given current server settings, your client is not always-on"))
|
||||||
}
|
}
|
||||||
case "autoreplay-missed":
|
case "autoreplay-missed":
|
||||||
stored := settings.AutoreplayMissed
|
stored := settings.AutoreplayMissed
|
||||||
if stored {
|
if stored {
|
||||||
alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
|
alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
|
||||||
if alwaysOn {
|
if alwaysOn {
|
||||||
nsNotice(rb, client.t("Autoreplay of missed messages is enabled"))
|
service.Notice(rb, client.t("Autoreplay of missed messages is enabled"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("You have enabled autoreplay of missed messages, but you can't receive them because your client isn't set to always-on"))
|
service.Notice(rb, client.t("You have enabled autoreplay of missed messages, but you can't receive them because your client isn't set to always-on"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Your account is not configured to receive autoreplayed missed messages"))
|
service.Notice(rb, client.t("Your account is not configured to receive autoreplayed missed messages"))
|
||||||
}
|
}
|
||||||
case "auto-away":
|
case "auto-away":
|
||||||
stored := settings.AutoAway
|
stored := settings.AutoAway
|
||||||
alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
|
alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
|
||||||
actual := persistenceEnabled(config.Accounts.Multiclient.AutoAway, settings.AutoAway)
|
actual := persistenceEnabled(config.Accounts.Multiclient.AutoAway, settings.AutoAway)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Your stored auto-away setting is: %s"), persistentStatusToString(stored)))
|
service.Notice(rb, fmt.Sprintf(client.t("Your stored auto-away setting is: %s"), persistentStatusToString(stored)))
|
||||||
if actual && alwaysOn {
|
if actual && alwaysOn {
|
||||||
nsNotice(rb, client.t("Given current server settings, auto-away is enabled for your client"))
|
service.Notice(rb, client.t("Given current server settings, auto-away is enabled for your client"))
|
||||||
} else if actual && !alwaysOn {
|
} else if actual && !alwaysOn {
|
||||||
nsNotice(rb, client.t("Because your client is not always-on, auto-away is disabled"))
|
service.Notice(rb, client.t("Because your client is not always-on, auto-away is disabled"))
|
||||||
} else if !actual {
|
} else if !actual {
|
||||||
nsNotice(rb, client.t("Given current server settings, auto-away is disabled for your client"))
|
service.Notice(rb, client.t("Given current server settings, auto-away is disabled for your client"))
|
||||||
}
|
}
|
||||||
case "dm-history":
|
case "dm-history":
|
||||||
effectiveValue := historyEnabled(config.History.Persistent.DirectMessages, settings.DMHistory)
|
effectiveValue := historyEnabled(config.History.Persistent.DirectMessages, settings.DMHistory)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Your stored direct message history setting is: %s"), historyStatusToString(settings.DMHistory)))
|
service.Notice(rb, fmt.Sprintf(client.t("Your stored direct message history setting is: %s"), historyStatusToString(settings.DMHistory)))
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Given current server settings, your direct message history setting is: %s"), historyStatusToString(effectiveValue)))
|
service.Notice(rb, fmt.Sprintf(client.t("Given current server settings, your direct message history setting is: %s"), historyStatusToString(effectiveValue)))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("No such setting"))
|
service.Notice(rb, client.t("No such setting"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsSetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSetHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var account string
|
var account string
|
||||||
if command == "saset" {
|
if command == "saset" {
|
||||||
account = params[0]
|
account = params[0]
|
||||||
@ -487,7 +476,7 @@ func nsSetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
var err error
|
var err error
|
||||||
switch strings.ToLower(params[0]) {
|
switch strings.ToLower(params[0]) {
|
||||||
case "pass", "password":
|
case "pass", "password":
|
||||||
nsNotice(rb, client.t("To change a password, use the PASSWD command. For details, /msg NickServ HELP PASSWD"))
|
service.Notice(rb, client.t("To change a password, use the PASSWD command. For details, /msg NickServ HELP PASSWD"))
|
||||||
return
|
return
|
||||||
case "enforce":
|
case "enforce":
|
||||||
var method NickEnforcementMethod
|
var method NickEnforcementMethod
|
||||||
@ -612,19 +601,19 @@ func nsSetHandler(server *Server, client *Client, command string, params []strin
|
|||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
nsNotice(rb, client.t("Successfully changed your account settings"))
|
service.Notice(rb, client.t("Successfully changed your account settings"))
|
||||||
displaySetting(params[0], finalSettings, client, rb)
|
displaySetting(service, params[0], finalSettings, client, rb)
|
||||||
case errInvalidParams, errAccountDoesNotExist, errFeatureDisabled, errAccountUnverified, errAccountUpdateFailed:
|
case errInvalidParams, errAccountDoesNotExist, errFeatureDisabled, errAccountUnverified, errAccountUpdateFailed:
|
||||||
nsNotice(rb, client.t(err.Error()))
|
service.Notice(rb, client.t(err.Error()))
|
||||||
case errNickAccountMismatch:
|
case errNickAccountMismatch:
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Your nickname must match your account name %s exactly to modify this setting. Try changing it with /NICK, or logging out and back in with the correct nickname."), client.AccountName()))
|
service.Notice(rb, fmt.Sprintf(client.t("Your nickname must match your account name %s exactly to modify this setting. Try changing it with /NICK, or logging out and back in with the correct nickname."), client.AccountName()))
|
||||||
default:
|
default:
|
||||||
// unknown error
|
// unknown error
|
||||||
nsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsDropHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsDropHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
sadrop := command == "sadrop"
|
sadrop := command == "sadrop"
|
||||||
var nick string
|
var nick string
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
@ -635,28 +624,28 @@ func nsDropHandler(server *Server, client *Client, command string, params []stri
|
|||||||
|
|
||||||
err := server.accounts.SetNickReserved(client, nick, sadrop, false)
|
err := server.accounts.SetNickReserved(client, nick, sadrop, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully ungrouped nick %s with your account"), nick))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully ungrouped nick %s with your account"), nick))
|
||||||
} else if err == errAccountNotLoggedIn {
|
} else if err == errAccountNotLoggedIn {
|
||||||
nsNotice(rb, client.t("You're not logged into an account"))
|
service.Notice(rb, client.t("You're not logged into an account"))
|
||||||
} else if err == errAccountCantDropPrimaryNick {
|
} else if err == errAccountCantDropPrimaryNick {
|
||||||
nsNotice(rb, client.t("You can't ungroup your primary nickname (try unregistering your account instead)"))
|
service.Notice(rb, client.t("You can't ungroup your primary nickname (try unregistering your account instead)"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Could not ungroup nick"))
|
service.Notice(rb, client.t("Could not ungroup nick"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsGhostHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsGhostHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
nick := params[0]
|
nick := params[0]
|
||||||
|
|
||||||
ghost := server.clients.Get(nick)
|
ghost := server.clients.Get(nick)
|
||||||
if ghost == nil {
|
if ghost == nil {
|
||||||
nsNotice(rb, client.t("No such nick"))
|
service.Notice(rb, client.t("No such nick"))
|
||||||
return
|
return
|
||||||
} else if ghost == client {
|
} else if ghost == client {
|
||||||
nsNotice(rb, client.t("You can't GHOST yourself (try /QUIT instead)"))
|
service.Notice(rb, client.t("You can't GHOST yourself (try /QUIT instead)"))
|
||||||
return
|
return
|
||||||
} else if ghost.AlwaysOn() {
|
} else if ghost.AlwaysOn() {
|
||||||
nsNotice(rb, client.t("You can't GHOST an always-on client"))
|
service.Notice(rb, client.t("You can't GHOST an always-on client"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +656,7 @@ func nsGhostHandler(server *Server, client *Client, command string, params []str
|
|||||||
authorized = (server.accounts.NickToAccount(nick) == account) || (ghost.Account() == account)
|
authorized = (server.accounts.NickToAccount(nick) == account) || (ghost.Account() == account)
|
||||||
}
|
}
|
||||||
if !authorized {
|
if !authorized {
|
||||||
nsNotice(rb, client.t("You don't own that nick"))
|
service.Notice(rb, client.t("You don't own that nick"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,31 +664,31 @@ func nsGhostHandler(server *Server, client *Client, command string, params []str
|
|||||||
ghost.destroy(nil)
|
ghost.destroy(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsGroupHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsGroupHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
nick := client.Nick()
|
nick := client.Nick()
|
||||||
err := server.accounts.SetNickReserved(client, nick, false, true)
|
err := server.accounts.SetNickReserved(client, nick, false, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully grouped nick %s with your account"), nick))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully grouped nick %s with your account"), nick))
|
||||||
} else if err == errAccountTooManyNicks {
|
} else if err == errAccountTooManyNicks {
|
||||||
nsNotice(rb, client.t("You have too many nicks reserved already (you can remove some with /NS DROP)"))
|
service.Notice(rb, client.t("You have too many nicks reserved already (you can remove some with /NS DROP)"))
|
||||||
} else if err == errNicknameReserved {
|
} else if err == errNicknameReserved {
|
||||||
nsNotice(rb, client.t("That nickname is already reserved by someone else"))
|
service.Notice(rb, client.t("That nickname is already reserved by someone else"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Error reserving nickname"))
|
service.Notice(rb, client.t("Error reserving nickname"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsLoginThrottleCheck(client *Client, rb *ResponseBuffer) (success bool) {
|
func nsLoginThrottleCheck(service *ircService, client *Client, rb *ResponseBuffer) (success bool) {
|
||||||
throttled, remainingTime := client.checkLoginThrottle()
|
throttled, remainingTime := client.checkLoginThrottle()
|
||||||
if throttled {
|
if throttled {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Please wait at least %v and try again"), remainingTime))
|
service.Notice(rb, fmt.Sprintf(client.t("Please wait at least %v and try again"), remainingTime))
|
||||||
}
|
}
|
||||||
return !throttled
|
return !throttled
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsIdentifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsIdentifyHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if client.LoggedIntoAccount() {
|
if client.LoggedIntoAccount() {
|
||||||
nsNotice(rb, client.t("You're already logged into an account"))
|
service.Notice(rb, client.t("You're already logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,7 +724,7 @@ func nsIdentifyHandler(server *Server, client *Client, command string, params []
|
|||||||
|
|
||||||
nickFixupFailed := false
|
nickFixupFailed := false
|
||||||
if loginSuccessful {
|
if loginSuccessful {
|
||||||
if !fixupNickEqualsAccount(client, rb, server.Config()) {
|
if !fixupNickEqualsAccount(client, rb, server.Config(), service.prefix) {
|
||||||
loginSuccessful = false
|
loginSuccessful = false
|
||||||
// fixupNickEqualsAccount sends its own error message, don't send another
|
// fixupNickEqualsAccount sends its own error message, don't send another
|
||||||
nickFixupFailed = true
|
nickFixupFailed = true
|
||||||
@ -743,15 +732,15 @@ func nsIdentifyHandler(server *Server, client *Client, command string, params []
|
|||||||
}
|
}
|
||||||
|
|
||||||
if loginSuccessful {
|
if loginSuccessful {
|
||||||
sendSuccessfulAccountAuth(client, rb, true, true)
|
sendSuccessfulAccountAuth(service, client, rb, true)
|
||||||
} else if !nickFixupFailed {
|
} else if !nickFixupFailed {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Authentication failed: %s"), authErrorToMessage(server, err)))
|
service.Notice(rb, fmt.Sprintf(client.t("Authentication failed: %s"), authErrorToMessage(server, err)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsListHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsListHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if !client.HasRoleCapabs("accreg") {
|
if !client.HasRoleCapabs("accreg") {
|
||||||
nsNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,26 +749,26 @@ func nsListHandler(server *Server, client *Client, command string, params []stri
|
|||||||
var err error
|
var err error
|
||||||
searchRegex, err = regexp.Compile(params[0])
|
searchRegex, err = regexp.Compile(params[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nsNotice(rb, client.t("Invalid regex"))
|
service.Notice(rb, client.t("Invalid regex"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsNotice(rb, ircfmt.Unescape(client.t("*** $bNickServ LIST$b ***")))
|
service.Notice(rb, ircfmt.Unescape(client.t("*** $bNickServ LIST$b ***")))
|
||||||
|
|
||||||
nicks := server.accounts.AllNicks()
|
nicks := server.accounts.AllNicks()
|
||||||
for _, nick := range nicks {
|
for _, nick := range nicks {
|
||||||
if searchRegex == nil || searchRegex.MatchString(nick) {
|
if searchRegex == nil || searchRegex.MatchString(nick) {
|
||||||
nsNotice(rb, fmt.Sprintf(" %s", nick))
|
service.Notice(rb, fmt.Sprintf(" %s", nick))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsNotice(rb, ircfmt.Unescape(client.t("*** $bEnd of NickServ LIST$b ***")))
|
service.Notice(rb, ircfmt.Unescape(client.t("*** $bEnd of NickServ LIST$b ***")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsInfoHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsInfoHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if !server.Config().Accounts.AuthenticationEnabled && !client.HasRoleCapabs("accreg") {
|
if !server.Config().Accounts.AuthenticationEnabled && !client.HasRoleCapabs("accreg") {
|
||||||
nsNotice(rb, client.t("This command has been disabled by the server administrators"))
|
service.Notice(rb, client.t("This command has been disabled by the server administrators"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +778,7 @@ func nsInfoHandler(server *Server, client *Client, command string, params []stri
|
|||||||
if server.Config().Accounts.NickReservation.Enabled {
|
if server.Config().Accounts.NickReservation.Enabled {
|
||||||
accountName = server.accounts.NickToAccount(nick)
|
accountName = server.accounts.NickToAccount(nick)
|
||||||
if accountName == "" {
|
if accountName == "" {
|
||||||
nsNotice(rb, client.t("That nickname is not registered"))
|
service.Notice(rb, client.t("That nickname is not registered"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -798,33 +787,33 @@ func nsInfoHandler(server *Server, client *Client, command string, params []stri
|
|||||||
} else {
|
} else {
|
||||||
accountName = client.Account()
|
accountName = client.Account()
|
||||||
if accountName == "" {
|
if accountName == "" {
|
||||||
nsNotice(rb, client.t("You're not logged into an account"))
|
service.Notice(rb, client.t("You're not logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
account, err := server.accounts.LoadAccount(accountName)
|
account, err := server.accounts.LoadAccount(accountName)
|
||||||
if err != nil || !account.Verified {
|
if err != nil || !account.Verified {
|
||||||
nsNotice(rb, client.t("Account does not exist"))
|
service.Notice(rb, client.t("Account does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name))
|
service.Notice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name))
|
||||||
registeredAt := account.RegisteredAt.Format(time.RFC1123)
|
registeredAt := account.RegisteredAt.Format(time.RFC1123)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Registered at: %s"), registeredAt))
|
service.Notice(rb, fmt.Sprintf(client.t("Registered at: %s"), registeredAt))
|
||||||
// TODO nicer formatting for this
|
// TODO nicer formatting for this
|
||||||
for _, nick := range account.AdditionalNicks {
|
for _, nick := range account.AdditionalNicks {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Additional grouped nick: %s"), nick))
|
service.Notice(rb, fmt.Sprintf(client.t("Additional grouped nick: %s"), nick))
|
||||||
}
|
}
|
||||||
for _, channel := range server.accounts.ChannelsForAccount(accountName) {
|
for _, channel := range server.accounts.ChannelsForAccount(accountName) {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Registered channel: %s"), channel))
|
service.Notice(rb, fmt.Sprintf(client.t("Registered channel: %s"), channel))
|
||||||
}
|
}
|
||||||
if account.Suspended != nil {
|
if account.Suspended != nil {
|
||||||
nsNotice(rb, suspensionToString(client, *account.Suspended))
|
service.Notice(rb, suspensionToString(client, *account.Suspended))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsRegisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
details := client.Details()
|
details := client.Details()
|
||||||
passphrase := params[0]
|
passphrase := params[0]
|
||||||
var email string
|
var email string
|
||||||
@ -835,7 +824,7 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
certfp := rb.session.certfp
|
certfp := rb.session.certfp
|
||||||
if passphrase == "*" {
|
if passphrase == "*" {
|
||||||
if certfp == "" {
|
if certfp == "" {
|
||||||
nsNotice(rb, client.t("You must be connected with TLS and a client certificate to do this"))
|
service.Notice(rb, client.t("You must be connected with TLS and a client certificate to do this"))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
passphrase = ""
|
passphrase = ""
|
||||||
@ -845,12 +834,12 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
if passphrase != "" {
|
if passphrase != "" {
|
||||||
cfPassphrase, err := Casefold(passphrase)
|
cfPassphrase, err := Casefold(passphrase)
|
||||||
if err == nil && cfPassphrase == details.nickCasefolded {
|
if err == nil && cfPassphrase == details.nickCasefolded {
|
||||||
nsNotice(rb, client.t("Usage: REGISTER <passphrase> [email]")) // #1179
|
service.Notice(rb, client.t("Usage: REGISTER <passphrase> [email]")) // #1179
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !nsLoginThrottleCheck(client, rb) {
|
if !nsLoginThrottleCheck(service, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,7 +848,7 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
if config.Accounts.NickReservation.ForceGuestFormat {
|
if config.Accounts.NickReservation.ForceGuestFormat {
|
||||||
matches := config.Accounts.NickReservation.guestRegexp.FindStringSubmatch(account)
|
matches := config.Accounts.NickReservation.guestRegexp.FindStringSubmatch(account)
|
||||||
if matches == nil || len(matches) < 2 {
|
if matches == nil || len(matches) < 2 {
|
||||||
nsNotice(rb, client.t("Erroneous nickname"))
|
service.Notice(rb, client.t("Erroneous nickname"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
account = matches[1]
|
account = matches[1]
|
||||||
@ -867,7 +856,7 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
|
|
||||||
callbackNamespace, callbackValue, validationErr := parseCallback(email, config)
|
callbackNamespace, callbackValue, validationErr := parseCallback(email, config)
|
||||||
if validationErr != nil {
|
if validationErr != nil {
|
||||||
nsNotice(rb, client.t("Registration requires a valid e-mail address"))
|
service.Notice(rb, client.t("Registration requires a valid e-mail address"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,22 +864,22 @@ func nsRegisterHandler(server *Server, client *Client, command string, params []
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
if callbackNamespace == "*" {
|
if callbackNamespace == "*" {
|
||||||
err = server.accounts.Verify(client, account, "")
|
err = server.accounts.Verify(client, account, "")
|
||||||
if err == nil && fixupNickEqualsAccount(client, rb, config) {
|
if err == nil && fixupNickEqualsAccount(client, rb, config, service.prefix) {
|
||||||
sendSuccessfulRegResponse(client, rb, true)
|
sendSuccessfulRegResponse(service, client, rb)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
messageTemplate := client.t("Account created, pending verification; verification code has been sent to %s")
|
messageTemplate := client.t("Account created, pending verification; verification code has been sent to %s")
|
||||||
message := fmt.Sprintf(messageTemplate, callbackValue)
|
message := fmt.Sprintf(messageTemplate, callbackValue)
|
||||||
nsNotice(rb, message)
|
service.Notice(rb, message)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// details could not be stored and relevant numerics have been dispatched, abort
|
// details could not be stored and relevant numerics have been dispatched, abort
|
||||||
message := registrationErrorToMessage(err)
|
message := registrationErrorToMessage(err)
|
||||||
nsNotice(rb, client.t(message))
|
service.Notice(rb, client.t(message))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsSaregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSaregisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var account, passphrase string
|
var account, passphrase string
|
||||||
account = params[0]
|
account = params[0]
|
||||||
if 1 < len(params) && params[1] != "*" {
|
if 1 < len(params) && params[1] != "*" {
|
||||||
@ -908,14 +897,14 @@ func nsSaregisterHandler(server *Server, client *Client, command string, params
|
|||||||
server.logger.Error("services", "unknown error from saregister", err.Error())
|
server.logger.Error("services", "unknown error from saregister", err.Error())
|
||||||
errMsg = client.t("Could not register")
|
errMsg = client.t("Could not register")
|
||||||
}
|
}
|
||||||
nsNotice(rb, errMsg)
|
service.Notice(rb, errMsg)
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully registered account %s"), account))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully registered account %s"), account))
|
||||||
server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Operator $c[grey][$r%s$c[grey]] registered account $c[grey][$r%s$c[grey]] with SAREGISTER"), client.Oper().Name, account))
|
server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Operator $c[grey][$r%s$c[grey]] registered account $c[grey][$r%s$c[grey]] with SAREGISTER"), client.Oper().Name, account))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsUnregisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
erase := command == "erase"
|
erase := command == "erase"
|
||||||
|
|
||||||
username := params[0]
|
username := params[0]
|
||||||
@ -925,7 +914,7 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
|
|||||||
}
|
}
|
||||||
|
|
||||||
if username == "" {
|
if username == "" {
|
||||||
nsNotice(rb, client.t("You must specify an account"))
|
service.Notice(rb, client.t("You must specify an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,10 +928,10 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
|
|||||||
} else {
|
} else {
|
||||||
account, err := server.accounts.LoadAccount(username)
|
account, err := server.accounts.LoadAccount(username)
|
||||||
if err == errAccountDoesNotExist {
|
if err == errAccountDoesNotExist {
|
||||||
nsNotice(rb, client.t("Invalid account name"))
|
service.Notice(rb, client.t("Invalid account name"))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
nsNotice(rb, client.t("Internal error"))
|
service.Notice(rb, client.t("Internal error"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accountName = account.Name
|
accountName = account.Name
|
||||||
@ -950,34 +939,34 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !(accountName == client.AccountName() || client.HasRoleCapabs("accreg")) {
|
if !(accountName == client.AccountName() || client.HasRoleCapabs("accreg")) {
|
||||||
nsNotice(rb, client.t("Insufficient oper privs"))
|
service.Notice(rb, client.t("Insufficient oper privs"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCode := utils.ConfirmationCode(accountName, registeredAt)
|
expectedCode := utils.ConfirmationCode(accountName, registeredAt)
|
||||||
if expectedCode != verificationCode {
|
if expectedCode != verificationCode {
|
||||||
if erase {
|
if erase {
|
||||||
nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: erasing this account will allow it to be re-registered; consider UNREGISTER instead.$b")))
|
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: erasing this account will allow it to be re-registered; consider UNREGISTER instead.$b")))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
|
service.Notice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
|
||||||
}
|
}
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/NS %s %s %s", strings.ToUpper(command), accountName, expectedCode)))
|
service.Notice(rb, fmt.Sprintf(client.t("To confirm, run this command: %s"), fmt.Sprintf("/NS %s %s %s", strings.ToUpper(command), accountName, expectedCode)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.accounts.Unregister(accountName, erase)
|
err := server.accounts.Unregister(accountName, erase)
|
||||||
if err == errAccountDoesNotExist {
|
if err == errAccountDoesNotExist {
|
||||||
nsNotice(rb, client.t(err.Error()))
|
service.Notice(rb, client.t(err.Error()))
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
nsNotice(rb, client.t("Error while unregistering account"))
|
service.Notice(rb, client.t("Error while unregistering account"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), accountName))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), accountName))
|
||||||
server.logger.Info("accounts", "client", client.Nick(), "unregistered account", accountName)
|
server.logger.Info("accounts", "client", client.Nick(), "unregistered account", accountName)
|
||||||
client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] unregistered account $c[grey][$r%s$c[grey]]"), client.NickMaskString(), accountName))
|
client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] unregistered account $c[grey][$r%s$c[grey]]"), client.NickMaskString(), accountName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsVerifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsVerifyHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
username, code := params[0], params[1]
|
username, code := params[0], params[1]
|
||||||
err := server.accounts.Verify(client, username, code)
|
err := server.accounts.Verify(client, username, code)
|
||||||
|
|
||||||
@ -992,16 +981,16 @@ func nsVerifyHandler(server *Server, client *Client, command string, params []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errorMessage != "" {
|
if errorMessage != "" {
|
||||||
nsNotice(rb, client.t(errorMessage))
|
service.Notice(rb, client.t(errorMessage))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if fixupNickEqualsAccount(client, rb, server.Config()) {
|
if fixupNickEqualsAccount(client, rb, server.Config(), service.prefix) {
|
||||||
sendSuccessfulRegResponse(client, rb, true)
|
sendSuccessfulRegResponse(service, client, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsPasswdHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsPasswdHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var target string
|
var target string
|
||||||
var newPassword string
|
var newPassword string
|
||||||
var errorMessage string
|
var errorMessage string
|
||||||
@ -1025,7 +1014,7 @@ func nsPasswdHandler(server *Server, client *Client, command string, params []st
|
|||||||
} else if params[1] != params[2] {
|
} else if params[1] != params[2] {
|
||||||
errorMessage = `Passwords do not match`
|
errorMessage = `Passwords do not match`
|
||||||
} else {
|
} else {
|
||||||
if !nsLoginThrottleCheck(client, rb) {
|
if !nsLoginThrottleCheck(service, client, rb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accountData, err := server.accounts.LoadAccount(target)
|
accountData, err := server.accounts.LoadAccount(target)
|
||||||
@ -1048,37 +1037,37 @@ func nsPasswdHandler(server *Server, client *Client, command string, params []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errorMessage != "" {
|
if errorMessage != "" {
|
||||||
nsNotice(rb, client.t(errorMessage))
|
service.Notice(rb, client.t(errorMessage))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.accounts.setPassword(target, newPassword, hasPrivs)
|
err := server.accounts.setPassword(target, newPassword, hasPrivs)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
nsNotice(rb, client.t("Password changed"))
|
service.Notice(rb, client.t("Password changed"))
|
||||||
case errEmptyCredentials:
|
case errEmptyCredentials:
|
||||||
nsNotice(rb, client.t("You can't delete your password unless you add a certificate fingerprint"))
|
service.Notice(rb, client.t("You can't delete your password unless you add a certificate fingerprint"))
|
||||||
case errCredsExternallyManaged:
|
case errCredsExternallyManaged:
|
||||||
nsNotice(rb, client.t("Your account credentials are managed externally and cannot be changed here"))
|
service.Notice(rb, client.t("Your account credentials are managed externally and cannot be changed here"))
|
||||||
case errCASFailed:
|
case errCASFailed:
|
||||||
nsNotice(rb, client.t("Try again later"))
|
service.Notice(rb, client.t("Try again later"))
|
||||||
default:
|
default:
|
||||||
server.logger.Error("internal", "could not upgrade user password:", err.Error())
|
server.logger.Error("internal", "could not upgrade user password:", err.Error())
|
||||||
nsNotice(rb, client.t("Password could not be changed due to server error"))
|
service.Notice(rb, client.t("Password could not be changed due to server error"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsEnforceHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsEnforceHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
newParams := []string{"enforce"}
|
newParams := []string{"enforce"}
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
nsGetHandler(server, client, "get", newParams, rb)
|
nsGetHandler(service, server, client, "get", newParams, rb)
|
||||||
} else {
|
} else {
|
||||||
newParams = append(newParams, params[0])
|
newParams = append(newParams, params[0])
|
||||||
nsSetHandler(server, client, "set", newParams, rb)
|
nsSetHandler(service, server, client, "set", newParams, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsClientsHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsClientsHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
var verb string
|
var verb string
|
||||||
|
|
||||||
if command == "sessions" {
|
if command == "sessions" {
|
||||||
@ -1091,56 +1080,56 @@ func nsClientsHandler(server *Server, client *Client, command string, params []s
|
|||||||
|
|
||||||
switch verb {
|
switch verb {
|
||||||
case "list":
|
case "list":
|
||||||
nsClientsListHandler(server, client, params, rb)
|
nsClientsListHandler(service, server, client, params, rb)
|
||||||
case "logout":
|
case "logout":
|
||||||
nsClientsLogoutHandler(server, client, params, rb)
|
nsClientsLogoutHandler(service, server, client, params, rb)
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsClientsListHandler(server *Server, client *Client, params []string, rb *ResponseBuffer) {
|
func nsClientsListHandler(service *ircService, server *Server, client *Client, params []string, rb *ResponseBuffer) {
|
||||||
target := client
|
target := client
|
||||||
hasPrivs := client.HasRoleCapabs("local_ban")
|
hasPrivs := client.HasRoleCapabs("local_ban")
|
||||||
if 0 < len(params) {
|
if 0 < len(params) {
|
||||||
target = server.clients.Get(params[0])
|
target = server.clients.Get(params[0])
|
||||||
if target == nil {
|
if target == nil {
|
||||||
nsNotice(rb, client.t("No such nick"))
|
service.Notice(rb, client.t("No such nick"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if target != client && !hasPrivs {
|
if target != client && !hasPrivs {
|
||||||
nsNotice(rb, client.t("Command restricted"))
|
service.Notice(rb, client.t("Command restricted"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionData, currentIndex := target.AllSessionData(rb.session, hasPrivs)
|
sessionData, currentIndex := target.AllSessionData(rb.session, hasPrivs)
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Nickname %[1]s has %[2]d attached clients(s)"), target.Nick(), len(sessionData)))
|
service.Notice(rb, fmt.Sprintf(client.t("Nickname %[1]s has %[2]d attached clients(s)"), target.Nick(), len(sessionData)))
|
||||||
for i, session := range sessionData {
|
for i, session := range sessionData {
|
||||||
if currentIndex == i {
|
if currentIndex == i {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Client %d (currently attached client):"), session.sessionID))
|
service.Notice(rb, fmt.Sprintf(client.t("Client %d (currently attached client):"), session.sessionID))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Client %d:"), session.sessionID))
|
service.Notice(rb, fmt.Sprintf(client.t("Client %d:"), session.sessionID))
|
||||||
}
|
}
|
||||||
if session.deviceID != "" {
|
if session.deviceID != "" {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Device ID: %s"), session.deviceID))
|
service.Notice(rb, fmt.Sprintf(client.t("Device ID: %s"), session.deviceID))
|
||||||
}
|
}
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("IP address: %s"), session.ip.String()))
|
service.Notice(rb, fmt.Sprintf(client.t("IP address: %s"), session.ip.String()))
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Hostname: %s"), session.hostname))
|
service.Notice(rb, fmt.Sprintf(client.t("Hostname: %s"), session.hostname))
|
||||||
if hasPrivs {
|
if hasPrivs {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Connection: %s"), session.connInfo))
|
service.Notice(rb, fmt.Sprintf(client.t("Connection: %s"), session.connInfo))
|
||||||
}
|
}
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Created at: %s"), session.ctime.Format(time.RFC1123)))
|
service.Notice(rb, fmt.Sprintf(client.t("Created at: %s"), session.ctime.Format(time.RFC1123)))
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.Format(time.RFC1123)))
|
service.Notice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.Format(time.RFC1123)))
|
||||||
if session.certfp != "" {
|
if session.certfp != "" {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Certfp: %s"), session.certfp))
|
service.Notice(rb, fmt.Sprintf(client.t("Certfp: %s"), session.certfp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsClientsLogoutHandler(server *Server, client *Client, params []string, rb *ResponseBuffer) {
|
func nsClientsLogoutHandler(service *ircService, server *Server, client *Client, params []string, rb *ResponseBuffer) {
|
||||||
if len(params) < 1 {
|
if len(params) < 1 {
|
||||||
nsNotice(rb, client.t("Missing client ID to logout (or \"all\")"))
|
service.Notice(rb, client.t("Missing client ID to logout (or \"all\")"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,14 +1138,14 @@ func nsClientsLogoutHandler(server *Server, client *Client, params []string, rb
|
|||||||
// CLIENTS LOGOUT [nickname] [client ID]
|
// CLIENTS LOGOUT [nickname] [client ID]
|
||||||
target = server.clients.Get(params[0])
|
target = server.clients.Get(params[0])
|
||||||
if target == nil {
|
if target == nil {
|
||||||
nsNotice(rb, client.t("No such nick"))
|
service.Notice(rb, client.t("No such nick"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// User must have "local_kill" privileges to logout other user sessions.
|
// User must have "local_kill" privileges to logout other user sessions.
|
||||||
if target != client {
|
if target != client {
|
||||||
oper := client.Oper()
|
oper := client.Oper()
|
||||||
if oper == nil || !oper.Class.Capabilities.Has("local_kill") {
|
if oper == nil || !oper.Class.Capabilities.Has("local_kill") {
|
||||||
nsNotice(rb, client.t("Insufficient oper privs"))
|
service.Notice(rb, client.t("Insufficient oper privs"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1167,7 +1156,7 @@ func nsClientsLogoutHandler(server *Server, client *Client, params []string, rb
|
|||||||
if strings.ToLower(params[0]) != "all" {
|
if strings.ToLower(params[0]) != "all" {
|
||||||
sessionID, err := strconv.ParseInt(params[0], 10, 64)
|
sessionID, err := strconv.ParseInt(params[0], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nsNotice(rb, client.t("Client ID to logout should be an integer (or \"all\")"))
|
service.Notice(rb, client.t("Client ID to logout should be an integer (or \"all\")"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Find the client ID that the user requested to logout.
|
// Find the client ID that the user requested to logout.
|
||||||
@ -1178,7 +1167,7 @@ func nsClientsLogoutHandler(server *Server, client *Client, params []string, rb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sessionToDestroy == nil {
|
if sessionToDestroy == nil {
|
||||||
nsNotice(rb, client.t("Specified client ID does not exist"))
|
service.Notice(rb, client.t("Specified client ID does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1186,14 +1175,14 @@ func nsClientsLogoutHandler(server *Server, client *Client, params []string, rb
|
|||||||
target.destroy(sessionToDestroy)
|
target.destroy(sessionToDestroy)
|
||||||
if (sessionToDestroy != nil && rb.session != sessionToDestroy) || client != target {
|
if (sessionToDestroy != nil && rb.session != sessionToDestroy) || client != target {
|
||||||
if sessionToDestroy != nil {
|
if sessionToDestroy != nil {
|
||||||
nsNotice(rb, client.t("Successfully logged out session"))
|
service.Notice(rb, client.t("Successfully logged out session"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Successfully logged out all sessions"))
|
service.Notice(rb, client.t("Successfully logged out all sessions"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsCertHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsCertHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
verb := strings.ToLower(params[0])
|
verb := strings.ToLower(params[0])
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
var target, certfp string
|
var target, certfp string
|
||||||
@ -1211,22 +1200,22 @@ func nsCertHandler(server *Server, client *Client, command string, params []stri
|
|||||||
} else if len(params) == 0 && verb == "add" && rb.session.certfp != "" {
|
} else if len(params) == 0 && verb == "add" && rb.session.certfp != "" {
|
||||||
certfp = rb.session.certfp // #1059
|
certfp = rb.session.certfp // #1059
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPrivs := client.HasRoleCapabs("accreg")
|
hasPrivs := client.HasRoleCapabs("accreg")
|
||||||
if target != "" && !hasPrivs {
|
if target != "" && !hasPrivs {
|
||||||
nsNotice(rb, client.t("Insufficient privileges"))
|
service.Notice(rb, client.t("Insufficient privileges"))
|
||||||
return
|
return
|
||||||
} else if target == "" {
|
} else if target == "" {
|
||||||
target = client.Account()
|
target = client.Account()
|
||||||
if target == "" {
|
if target == "" {
|
||||||
nsNotice(rb, client.t("You're not logged into an account"))
|
service.Notice(rb, client.t("You're not logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1236,16 +1225,16 @@ func nsCertHandler(server *Server, client *Client, command string, params []stri
|
|||||||
case "list":
|
case "list":
|
||||||
accountData, err := server.accounts.LoadAccount(target)
|
accountData, err := server.accounts.LoadAccount(target)
|
||||||
if err == errAccountDoesNotExist {
|
if err == errAccountDoesNotExist {
|
||||||
nsNotice(rb, client.t("Account does not exist"))
|
service.Notice(rb, client.t("Account does not exist"))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
nsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
certfps := accountData.Credentials.Certfps
|
certfps := accountData.Credentials.Certfps
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("There are %[1]d certificate fingerprint(s) authorized for account %[2]s."), len(certfps), accountData.Name))
|
service.Notice(rb, fmt.Sprintf(client.t("There are %[1]d certificate fingerprint(s) authorized for account %[2]s."), len(certfps), accountData.Name))
|
||||||
for i, certfp := range certfps {
|
for i, certfp := range certfps {
|
||||||
nsNotice(rb, fmt.Sprintf("%d: %s", i+1, certfp))
|
service.Notice(rb, fmt.Sprintf("%d: %s", i+1, certfp))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case "add":
|
case "add":
|
||||||
@ -1257,54 +1246,54 @@ func nsCertHandler(server *Server, client *Client, command string, params []stri
|
|||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
if verb == "add" {
|
if verb == "add" {
|
||||||
nsNotice(rb, client.t("Certificate fingerprint successfully added"))
|
service.Notice(rb, client.t("Certificate fingerprint successfully added"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Certificate fingerprint successfully removed"))
|
service.Notice(rb, client.t("Certificate fingerprint successfully removed"))
|
||||||
}
|
}
|
||||||
case errNoop:
|
case errNoop:
|
||||||
if verb == "add" {
|
if verb == "add" {
|
||||||
nsNotice(rb, client.t("That certificate fingerprint was already authorized"))
|
service.Notice(rb, client.t("That certificate fingerprint was already authorized"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Certificate fingerprint not found"))
|
service.Notice(rb, client.t("Certificate fingerprint not found"))
|
||||||
}
|
}
|
||||||
case errAccountDoesNotExist:
|
case errAccountDoesNotExist:
|
||||||
nsNotice(rb, client.t("Account does not exist"))
|
service.Notice(rb, client.t("Account does not exist"))
|
||||||
case errLimitExceeded:
|
case errLimitExceeded:
|
||||||
nsNotice(rb, client.t("You already have too many certificate fingerprints"))
|
service.Notice(rb, client.t("You already have too many certificate fingerprints"))
|
||||||
case utils.ErrInvalidCertfp:
|
case utils.ErrInvalidCertfp:
|
||||||
nsNotice(rb, client.t("Invalid certificate fingerprint"))
|
service.Notice(rb, client.t("Invalid certificate fingerprint"))
|
||||||
case errCertfpAlreadyExists:
|
case errCertfpAlreadyExists:
|
||||||
nsNotice(rb, client.t("That certificate fingerprint is already associated with another account"))
|
service.Notice(rb, client.t("That certificate fingerprint is already associated with another account"))
|
||||||
case errEmptyCredentials:
|
case errEmptyCredentials:
|
||||||
nsNotice(rb, client.t("You can't remove all your certificate fingerprints unless you add a password"))
|
service.Notice(rb, client.t("You can't remove all your certificate fingerprints unless you add a password"))
|
||||||
case errCredsExternallyManaged:
|
case errCredsExternallyManaged:
|
||||||
nsNotice(rb, client.t("Your account credentials are managed externally and cannot be changed here"))
|
service.Notice(rb, client.t("Your account credentials are managed externally and cannot be changed here"))
|
||||||
case errCASFailed:
|
case errCASFailed:
|
||||||
nsNotice(rb, client.t("Try again later"))
|
service.Notice(rb, client.t("Try again later"))
|
||||||
default:
|
default:
|
||||||
server.logger.Error("internal", "could not modify certificates:", err.Error())
|
server.logger.Error("internal", "could not modify certificates:", err.Error())
|
||||||
nsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsSuspendHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSuspendHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
subCmd := strings.ToLower(params[0])
|
subCmd := strings.ToLower(params[0])
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
switch subCmd {
|
switch subCmd {
|
||||||
case "add":
|
case "add":
|
||||||
nsSuspendAddHandler(server, client, command, params, rb)
|
nsSuspendAddHandler(service, server, client, command, params, rb)
|
||||||
case "del", "delete", "remove":
|
case "del", "delete", "remove":
|
||||||
nsSuspendRemoveHandler(server, client, command, params, rb)
|
nsSuspendRemoveHandler(service, server, client, command, params, rb)
|
||||||
case "list":
|
case "list":
|
||||||
nsSuspendListHandler(server, client, command, params, rb)
|
nsSuspendListHandler(service, server, client, command, params, rb)
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsSuspendAddHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSuspendAddHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,7 +1305,7 @@ func nsSuspendAddHandler(server *Server, client *Client, command string, params
|
|||||||
var err error
|
var err error
|
||||||
cDuration, err := custime.ParseDuration(params[1])
|
cDuration, err := custime.ParseDuration(params[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nsNotice(rb, client.t("Invalid time duration for NS SUSPEND"))
|
service.Notice(rb, client.t("Invalid time duration for NS SUSPEND"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
duration = time.Duration(cDuration)
|
duration = time.Duration(cDuration)
|
||||||
@ -1333,30 +1322,30 @@ func nsSuspendAddHandler(server *Server, client *Client, command string, params
|
|||||||
err := server.accounts.Suspend(account, duration, name, reason)
|
err := server.accounts.Suspend(account, duration, name, reason)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully suspended account %s"), account))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully suspended account %s"), account))
|
||||||
case errAccountDoesNotExist:
|
case errAccountDoesNotExist:
|
||||||
nsNotice(rb, client.t("No such account"))
|
service.Notice(rb, client.t("No such account"))
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsSuspendRemoveHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSuspendRemoveHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
nsNotice(rb, client.t("Invalid parameters"))
|
service.Notice(rb, client.t("Invalid parameters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.accounts.Unsuspend(params[0])
|
err := server.accounts.Unsuspend(params[0])
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully un-suspended account %s"), params[0]))
|
service.Notice(rb, fmt.Sprintf(client.t("Successfully un-suspended account %s"), params[0]))
|
||||||
case errAccountDoesNotExist:
|
case errAccountDoesNotExist:
|
||||||
nsNotice(rb, client.t("No such account"))
|
service.Notice(rb, client.t("No such account"))
|
||||||
case errNoop:
|
case errNoop:
|
||||||
nsNotice(rb, client.t("Account was not suspended"))
|
service.Notice(rb, client.t("Account was not suspended"))
|
||||||
default:
|
default:
|
||||||
nsNotice(rb, client.t("An error occurred"))
|
service.Notice(rb, client.t("An error occurred"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,12 +1356,12 @@ func (a ByCreationTime) Len() int { return len(a) }
|
|||||||
func (a ByCreationTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a ByCreationTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a ByCreationTime) Less(i, j int) bool { return a[i].TimeCreated.After(a[j].TimeCreated) }
|
func (a ByCreationTime) Less(i, j int) bool { return a[i].TimeCreated.After(a[j].TimeCreated) }
|
||||||
|
|
||||||
func nsSuspendListHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsSuspendListHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
suspensions := server.accounts.ListSuspended()
|
suspensions := server.accounts.ListSuspended()
|
||||||
sort.Sort(ByCreationTime(suspensions))
|
sort.Sort(ByCreationTime(suspensions))
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("There are %d active suspensions."), len(suspensions)))
|
service.Notice(rb, fmt.Sprintf(client.t("There are %d active suspensions."), len(suspensions)))
|
||||||
for _, suspension := range suspensions {
|
for _, suspension := range suspensions {
|
||||||
nsNotice(rb, suspensionToString(client, suspension))
|
service.Notice(rb, suspensionToString(client, suspension))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,21 +1378,21 @@ func suspensionToString(client *Client, suspension AccountSuspension) (result st
|
|||||||
return fmt.Sprintf(client.t("Account %[1]s suspended at %[2]s. Duration: %[3]s. %[4]s"), suspension.AccountName, ts, duration, reason)
|
return fmt.Sprintf(client.t("Account %[1]s suspended at %[2]s. Duration: %[3]s. %[4]s"), suspension.AccountName, ts, duration, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsRenameHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
func nsRenameHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||||
oldName, newName := params[0], params[1]
|
oldName, newName := params[0], params[1]
|
||||||
err := server.accounts.Rename(oldName, newName)
|
err := server.accounts.Rename(oldName, newName)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Couldn't rename account: %s"), client.t(err.Error())))
|
service.Notice(rb, fmt.Sprintf(client.t("Couldn't rename account: %s"), client.t(err.Error())))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nsNotice(rb, client.t("Successfully renamed account"))
|
service.Notice(rb, client.t("Successfully renamed account"))
|
||||||
if server.Config().Accounts.NickReservation.ForceNickEqualsAccount {
|
if server.Config().Accounts.NickReservation.ForceNickEqualsAccount {
|
||||||
if curClient := server.clients.Get(oldName); curClient != nil {
|
if curClient := server.clients.Get(oldName); curClient != nil {
|
||||||
renameErr := performNickChange(client.server, client, curClient, nil, newName, rb)
|
renameErr := performNickChange(client.server, client, curClient, nil, newName, rb)
|
||||||
if renameErr != nil && renameErr != errNoop {
|
if renameErr != nil && renameErr != errNoop {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Warning: could not rename affected client: %v"), err))
|
service.Notice(rb, fmt.Sprintf(client.t("Warning: could not rename affected client: %v"), err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,6 +530,8 @@ func (server *Server) applyConfig(config *Config) (err error) {
|
|||||||
} else if oldConfig.Server.IPCheckScript.MaxConcurrency != config.Server.IPCheckScript.MaxConcurrency ||
|
} else if oldConfig.Server.IPCheckScript.MaxConcurrency != config.Server.IPCheckScript.MaxConcurrency ||
|
||||||
oldConfig.Accounts.AuthScript.MaxConcurrency != config.Accounts.AuthScript.MaxConcurrency {
|
oldConfig.Accounts.AuthScript.MaxConcurrency != config.Accounts.AuthScript.MaxConcurrency {
|
||||||
return fmt.Errorf("Cannot change max-concurrency for scripts after launching the server, rehash aborted")
|
return fmt.Errorf("Cannot change max-concurrency for scripts after launching the server, rehash aborted")
|
||||||
|
} else if oldConfig.Server.OverrideServicesHostname != config.Server.OverrideServicesHostname {
|
||||||
|
return fmt.Errorf("Cannot change override-services-hostname after launching the server, rehash aborted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,6 +565,10 @@ func (server *Server) applyConfig(config *Config) (err error) {
|
|||||||
if maxAuthConc != 0 {
|
if maxAuthConc != 0 {
|
||||||
server.semaphores.AuthScript.Initialize(maxAuthConc)
|
server.semaphores.AuthScript.Initialize(maxAuthConc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := overrideServicePrefixes(config.Server.OverrideServicesHostname); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldConfig != nil {
|
if oldConfig != nil {
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
type ircService struct {
|
type ircService struct {
|
||||||
Name string
|
Name string
|
||||||
ShortName string
|
ShortName string
|
||||||
prefix string
|
prefix string // NUH source of messages from this service
|
||||||
CommandAliases []string
|
CommandAliases []string
|
||||||
Commands map[string]*serviceCommand
|
Commands map[string]*serviceCommand
|
||||||
HelpBanner string
|
HelpBanner string
|
||||||
@ -30,7 +30,7 @@ type ircService struct {
|
|||||||
type serviceCommand struct {
|
type serviceCommand struct {
|
||||||
aliasOf string // marks this command as an alias of another
|
aliasOf string // marks this command as an alias of another
|
||||||
capabs []string // oper capabs the given user has to have to access this command
|
capabs []string // oper capabs the given user has to have to access this command
|
||||||
handler func(server *Server, client *Client, command string, params []string, rb *ResponseBuffer)
|
handler func(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer)
|
||||||
help string
|
help string
|
||||||
helpStrings []string
|
helpStrings []string
|
||||||
helpShort string
|
helpShort string
|
||||||
@ -60,36 +60,47 @@ func lookupServiceCommand(commands map[string]*serviceCommand, command string) *
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// all services, by lowercase name
|
var (
|
||||||
var OragonoServices = map[string]*ircService{
|
nickservService = &ircService{
|
||||||
"nickserv": {
|
|
||||||
Name: "NickServ",
|
Name: "NickServ",
|
||||||
ShortName: "NS",
|
ShortName: "NS",
|
||||||
CommandAliases: []string{"NICKSERV", "NS"},
|
CommandAliases: []string{"NICKSERV", "NS"},
|
||||||
Commands: nickservCommands,
|
Commands: nickservCommands,
|
||||||
HelpBanner: nickservHelp,
|
HelpBanner: nickservHelp,
|
||||||
},
|
}
|
||||||
"chanserv": {
|
chanservService = &ircService{
|
||||||
Name: "ChanServ",
|
Name: "ChanServ",
|
||||||
ShortName: "CS",
|
ShortName: "CS",
|
||||||
CommandAliases: []string{"CHANSERV", "CS"},
|
CommandAliases: []string{"CHANSERV", "CS"},
|
||||||
Commands: chanservCommands,
|
Commands: chanservCommands,
|
||||||
HelpBanner: chanservHelp,
|
HelpBanner: chanservHelp,
|
||||||
},
|
}
|
||||||
"hostserv": {
|
hostservService = &ircService{
|
||||||
Name: "HostServ",
|
Name: "HostServ",
|
||||||
ShortName: "HS",
|
ShortName: "HS",
|
||||||
CommandAliases: []string{"HOSTSERV", "HS"},
|
CommandAliases: []string{"HOSTSERV", "HS"},
|
||||||
Commands: hostservCommands,
|
Commands: hostservCommands,
|
||||||
HelpBanner: hostservHelp,
|
HelpBanner: hostservHelp,
|
||||||
},
|
}
|
||||||
"histserv": {
|
histservService = &ircService{
|
||||||
Name: "HistServ",
|
Name: "HistServ",
|
||||||
ShortName: "HISTSERV",
|
ShortName: "HISTSERV",
|
||||||
CommandAliases: []string{"HISTSERV"},
|
CommandAliases: []string{"HISTSERV"},
|
||||||
Commands: histservCommands,
|
Commands: histservCommands,
|
||||||
HelpBanner: histservHelp,
|
HelpBanner: histservHelp,
|
||||||
},
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// all services, by lowercase name
|
||||||
|
var OragonoServices = map[string]*ircService{
|
||||||
|
"nickserv": nickservService,
|
||||||
|
"chanserv": chanservService,
|
||||||
|
"hostserv": hostservService,
|
||||||
|
"histserv": histservService,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *ircService) Notice(rb *ResponseBuffer, text string) {
|
||||||
|
rb.Add(nil, service.prefix, "NOTICE", rb.target.Nick(), text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// all service commands at the protocol level, by uppercase command name
|
// all service commands at the protocol level, by uppercase command name
|
||||||
@ -212,7 +223,7 @@ func serviceRunCommand(service *ircService, server *Server, client *Client, cmd
|
|||||||
if commandName == "help" {
|
if commandName == "help" {
|
||||||
serviceHelpHandler(service, server, client, params, rb)
|
serviceHelpHandler(service, server, client, params, rb)
|
||||||
} else {
|
} else {
|
||||||
cmd.handler(server, client, commandName, params, rb)
|
cmd.handler(service, server, client, commandName, params, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +316,19 @@ func makeServiceHelpTextGenerator(cmd string, banner string) func(*Client) strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func overrideServicePrefixes(hostname string) error {
|
||||||
|
if hostname == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !utils.IsHostname(hostname) {
|
||||||
|
return fmt.Errorf("`%s` is an invalid services hostname", hostname)
|
||||||
|
}
|
||||||
|
for _, serv := range OragonoServices {
|
||||||
|
serv.prefix = fmt.Sprintf("%s!%s@%s", serv.Name, serv.Name, hostname)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func initializeServices() {
|
func initializeServices() {
|
||||||
// this modifies the global Commands map,
|
// this modifies the global Commands map,
|
||||||
// so it must be called from irc/commands.go's init()
|
// so it must be called from irc/commands.go's init()
|
||||||
|
@ -307,7 +307,11 @@ server:
|
|||||||
# oragono will write files to disk under certain circumstances, e.g.,
|
# oragono will write files to disk under certain circumstances, e.g.,
|
||||||
# CPU profiling or data export. by default, these files will be written
|
# CPU profiling or data export. by default, these files will be written
|
||||||
# to the working directory. set this to customize:
|
# to the working directory. set this to customize:
|
||||||
# output-path: "/home/oragono/out"
|
#output-path: "/home/oragono/out"
|
||||||
|
|
||||||
|
# the hostname used by "services", e.g., NickServ, defaults to "localhost",
|
||||||
|
# e.g., `NickServ!NickServ@localhost`. uncomment this to override:
|
||||||
|
#override-services-hostname: "example.network"
|
||||||
|
|
||||||
# account options
|
# account options
|
||||||
accounts:
|
accounts:
|
||||||
|
Loading…
Reference in New Issue
Block a user