refactor services code

This commit is contained in:
Shivaram Lingamneni 2019-01-03 22:32:07 -05:00
parent ea970f94a0
commit b80df0885f
5 changed files with 172 additions and 164 deletions

View File

@ -15,7 +15,6 @@ import (
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
"github.com/oragono/oragono/irc/modes" "github.com/oragono/oragono/irc/modes"
"github.com/oragono/oragono/irc/sno" "github.com/oragono/oragono/irc/sno"
"github.com/oragono/oragono/irc/utils"
) )
const chanservHelp = `ChanServ lets you register and manage channels. const chanservHelp = `ChanServ lets you register and manage channels.
@ -26,8 +25,8 @@ To see in-depth help for a specific ChanServ command, try:
Here are the commands you can use: Here are the commands you can use:
%s` %s`
func chanregEnabled(server *Server) bool { func chanregEnabled(config *Config) bool {
return server.ChannelRegistrationEnabled() return config.Channels.Registration.Enabled
} }
var ( var (
@ -41,6 +40,7 @@ this command if you're the founder of the channel.`,
helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`, helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`,
authRequired: true, authRequired: true,
enabled: chanregEnabled, enabled: chanregEnabled,
minParams: 1,
}, },
"register": { "register": {
handler: csRegisterHandler, handler: csRegisterHandler,
@ -52,6 +52,7 @@ remembered.`,
helpShort: `$bREGISTER$b lets you own a given channel.`, helpShort: `$bREGISTER$b lets you own a given channel.`,
authRequired: true, authRequired: true,
enabled: chanregEnabled, enabled: chanregEnabled,
minParams: 1,
}, },
"unregister": { "unregister": {
handler: csUnregisterHandler, handler: csUnregisterHandler,
@ -62,6 +63,7 @@ To prevent accidental unregistrations, a verification code is required;
invoking the command without a code will display the necessary code.`, invoking the command without a code will display the necessary code.`,
helpShort: `$bUNREGISTER$b deletes a channel registration.`, helpShort: `$bUNREGISTER$b deletes a channel registration.`,
enabled: chanregEnabled, enabled: chanregEnabled,
minParams: 1,
}, },
"drop": { "drop": {
aliasOf: "unregister", aliasOf: "unregister",
@ -77,6 +79,7 @@ accounts and modes, use $bAMODE #channel$b. Note that users are always
referenced by their registered account names, not their nicknames.`, referenced by their registered account names, not their nicknames.`,
helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`, helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`,
enabled: chanregEnabled, enabled: chanregEnabled,
minParams: 1,
}, },
} }
) )
@ -86,8 +89,9 @@ func csNotice(rb *ResponseBuffer, text string) {
rb.Add(nil, "ChanServ", "NOTICE", rb.target.Nick(), text) rb.Add(nil, "ChanServ", "NOTICE", rb.target.Nick(), text)
} }
func csAmodeHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func csAmodeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
channelName, modeChange := utils.ExtractParam(params) channelName := params[0]
modeChange := strings.Join(params[1:], " ")
channel := server.channels.Get(channelName) channel := server.channels.Get(channelName)
if channel == nil { if channel == nil {
@ -159,27 +163,13 @@ func csAmodeHandler(server *Server, client *Client, command, params string, rb *
} }
} }
func csOpHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func csOpHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
channelName, clientToOp := utils.ExtractParam(params) channelInfo := server.channels.Get(params[0])
if channelName == "" {
csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bOP #channel [nickname]$b")))
return
}
clientToOp = strings.TrimSpace(clientToOp)
channelKey, err := CasefoldChannel(channelName)
if err != nil {
csNotice(rb, client.t("Channel name is not valid"))
return
}
channelInfo := server.channels.Get(channelKey)
if channelInfo == nil { if channelInfo == nil {
csNotice(rb, client.t("Channel does not exist")) csNotice(rb, client.t("Channel does not exist"))
return return
} }
channelName := channelInfo.Name()
clientAccount := client.Account() clientAccount := client.Account()
if clientAccount == "" || clientAccount != channelInfo.Founder() { if clientAccount == "" || clientAccount != channelInfo.Founder() {
@ -188,10 +178,9 @@ func csOpHandler(server *Server, client *Client, command, params string, rb *Res
} }
var target *Client var target *Client
if clientToOp != "" { if len(params) > 1 {
casefoldedNickname, err := CasefoldName(clientToOp) target = server.clients.Get(params[1])
target = server.clients.Get(casefoldedNickname) if target == nil {
if err != nil || target == nil {
csNotice(rb, client.t("Could not find given client")) csNotice(rb, client.t("Could not find given client"))
return return
} }
@ -216,16 +205,13 @@ func csOpHandler(server *Server, client *Client, command, params string, rb *Res
csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName)) csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName))
server.logger.Info("chanserv", fmt.Sprintf("Client %s op'd [%s] in channel %s", client.nick, clientToOp, channelName)) tnick := target.Nick()
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, clientToOp, 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))
} }
func csRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func csRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
channelName := strings.TrimSpace(params) channelName := params[0]
if channelName == "" {
csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b")))
return
}
channelKey, err := CasefoldChannel(channelName) channelKey, err := CasefoldChannel(channelName)
if err != nil { if err != nil {
@ -251,7 +237,7 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
csNotice(rb, fmt.Sprintf(client.t("Channel %s successfully registered"), channelName)) csNotice(rb, fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
server.logger.Info("chanserv", 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))
// give them founder privs // give them founder privs
@ -266,8 +252,13 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
} }
} }
func csUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func csUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
channelName, verificationCode := utils.ExtractParam(params) channelName := params[0]
var verificationCode string
if len(params) > 1 {
verificationCode = params[1]
}
channelKey, err := CasefoldChannel(channelName) channelKey, err := CasefoldChannel(channelName)
if channelKey == "" || err != nil { if channelKey == "" || err != nil {
csNotice(rb, client.t("Channel name is not valid")) csNotice(rb, client.t("Channel name is not valid"))

View File

@ -9,8 +9,6 @@ import (
"regexp" "regexp"
"strings" "strings"
"time" "time"
"github.com/oragono/oragono/irc/utils"
) )
const hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed const hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
@ -29,13 +27,12 @@ var (
defaultValidVhostRegex = regexp.MustCompile(`^[0-9A-Za-z.\-_/]+$`) defaultValidVhostRegex = regexp.MustCompile(`^[0-9A-Za-z.\-_/]+$`)
) )
func hostservEnabled(server *Server) bool { func hostservEnabled(config *Config) bool {
return server.AccountConfig().VHosts.Enabled return config.Accounts.VHosts.Enabled
} }
func hostservRequestsEnabled(server *Server) bool { func hostservRequestsEnabled(config *Config) bool {
ac := server.AccountConfig() return config.Accounts.VHosts.Enabled && config.Accounts.VHosts.UserRequests.Enabled
return ac.VHosts.Enabled && ac.VHosts.UserRequests.Enabled
} }
var ( var (
@ -67,15 +64,15 @@ then be approved by a server operator.`,
helpShort: `$bREQUEST$b requests a new vhost, pending operator approval.`, helpShort: `$bREQUEST$b requests a new vhost, pending operator approval.`,
authRequired: true, authRequired: true,
enabled: hostservRequestsEnabled, enabled: hostservRequestsEnabled,
minParams: 1,
}, },
"status": { "status": {
handler: hsStatusHandler, handler: hsStatusHandler,
help: `Syntax: $bSTATUS$b help: `Syntax: $bSTATUS [user]$b
STATUS displays your current vhost, if any, and the status of your most recent STATUS displays your current vhost, if any, and the status of your most recent
request for a new one.`, request for a new one. A server operator can view someone else's status.`,
helpShort: `$bSTATUS$b shows your vhost and request status.`, helpShort: `$bSTATUS$b shows your vhost and request status.`,
authRequired: true,
enabled: hostservEnabled, enabled: hostservEnabled,
}, },
"set": { "set": {
@ -86,6 +83,7 @@ SET sets a user's vhost, bypassing the request system.`,
helpShort: `$bSET$b sets a user's vhost.`, helpShort: `$bSET$b sets a user's vhost.`,
capabs: []string{"vhosts"}, capabs: []string{"vhosts"},
enabled: hostservEnabled, enabled: hostservEnabled,
minParams: 2,
}, },
"del": { "del": {
handler: hsSetHandler, handler: hsSetHandler,
@ -95,6 +93,7 @@ DEL deletes a user's vhost.`,
helpShort: `$bDEL$b deletes a user's vhost.`, helpShort: `$bDEL$b deletes a user's vhost.`,
capabs: []string{"vhosts"}, capabs: []string{"vhosts"},
enabled: hostservEnabled, enabled: hostservEnabled,
minParams: 1,
}, },
"waiting": { "waiting": {
handler: hsWaitingHandler, handler: hsWaitingHandler,
@ -114,6 +113,7 @@ APPROVE approves a user's vhost request.`,
helpShort: `$bAPPROVE$b approves a user's vhost request.`, helpShort: `$bAPPROVE$b approves a user's vhost request.`,
capabs: []string{"vhosts"}, capabs: []string{"vhosts"},
enabled: hostservEnabled, enabled: hostservEnabled,
minParams: 1,
}, },
"reject": { "reject": {
handler: hsRejectHandler, handler: hsRejectHandler,
@ -124,6 +124,7 @@ for the rejection.`,
helpShort: `$bREJECT$b rejects a user's vhost request.`, helpShort: `$bREJECT$b rejects a user's vhost request.`,
capabs: []string{"vhosts"}, capabs: []string{"vhosts"},
enabled: hostservEnabled, enabled: hostservEnabled,
minParams: 1,
}, },
} }
) )
@ -146,7 +147,7 @@ func hsNotifyChannel(server *Server, message string) {
} }
} }
func hsOnOffHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { 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
@ -162,8 +163,8 @@ func hsOnOffHandler(server *Server, client *Client, command, params string, rb *
} }
} }
func hsRequestHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsRequestHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
vhost, _ := utils.ExtractParam(params) vhost := params[0]
if validateVhost(server, vhost, false) != nil { if validateVhost(server, vhost, false) != nil {
hsNotice(rb, client.t("Invalid vhost")) hsNotice(rb, client.t("Invalid vhost"))
return return
@ -195,12 +196,24 @@ func hsRequestHandler(server *Server, client *Client, command, params string, rb
} }
} }
func hsStatusHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsStatusHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
accountName := client.Account() var accountName string
if len(params) > 0 {
if !client.HasRoleCapabs("vhosts") {
hsNotice(rb, client.t("Command restricted"))
return
}
accountName = params[0]
} else {
accountName = client.Account()
}
account, err := server.accounts.LoadAccount(accountName) account, err := server.accounts.LoadAccount(accountName)
if err != nil { if err != nil {
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("An error occurred")) }
hsNotice(rb, client.t("No such account"))
return return
} }
@ -232,23 +245,18 @@ func validateVhost(server *Server, vhost string, oper bool) error {
return nil return nil
} }
func hsSetHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsSetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
var user, vhost string user := params[0]
user, params = utils.ExtractParam(params) var vhost string
if user == "" {
hsNotice(rb, client.t("A user is required"))
return
}
if command == "set" { if command == "set" {
vhost, _ = utils.ExtractParam(params) vhost = params[1]
if validateVhost(server, vhost, true) != nil { if validateVhost(server, vhost, true) != nil {
hsNotice(rb, client.t("Invalid vhost")) hsNotice(rb, client.t("Invalid vhost"))
return return
} }
} else if command != "del" {
server.logger.Warning("internal", "invalid hostserv set command", command)
return
} }
// else: command == "del", vhost == ""
_, err := server.accounts.VHostSet(user, vhost) _, err := server.accounts.VHostSet(user, vhost)
if err != nil { if err != nil {
@ -260,7 +268,7 @@ func hsSetHandler(server *Server, client *Client, command, params string, rb *Re
} }
} }
func hsWaitingHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsWaitingHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
requests, total := server.accounts.VHostListRequests(10) requests, total := server.accounts.VHostListRequests(10)
hsNotice(rb, fmt.Sprintf(client.t("There are %d pending requests for vhosts (%d displayed)"), total, len(requests))) hsNotice(rb, fmt.Sprintf(client.t("There are %d pending requests for vhosts (%d displayed)"), total, len(requests)))
for i, request := range requests { for i, request := range requests {
@ -268,12 +276,8 @@ func hsWaitingHandler(server *Server, client *Client, command, params string, rb
} }
} }
func hsApproveHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsApproveHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
user, _ := utils.ExtractParam(params) user := params[0]
if user == "" {
hsNotice(rb, client.t("A user is required"))
return
}
vhostInfo, err := server.accounts.VHostApprove(user) vhostInfo, err := server.accounts.VHostApprove(user)
if err != nil { if err != nil {
@ -288,13 +292,12 @@ func hsApproveHandler(server *Server, client *Client, command, params string, rb
} }
} }
func hsRejectHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func hsRejectHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
user, params := utils.ExtractParam(params) var reason string
if user == "" { user := params[0]
hsNotice(rb, client.t("A user is required")) if len(params) > 1 {
return reason = strings.Join(params[1:], " ")
} }
reason := strings.TrimSpace(params)
vhostInfo, err := server.accounts.VHostReject(user, reason) vhostInfo, err := server.accounts.VHostReject(user, reason)
if err != nil { if err != nil {

View File

@ -8,25 +8,22 @@ import (
"strings" "strings"
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
"github.com/oragono/oragono/irc/utils"
) )
// "enabled" callbacks for specific nickserv commands // "enabled" callbacks for specific nickserv commands
func servCmdRequiresAccreg(server *Server) bool { func servCmdRequiresAccreg(config *Config) bool {
return server.AccountConfig().Registration.Enabled return config.Accounts.Registration.Enabled
} }
func servCmdRequiresAuthEnabled(server *Server) bool { func servCmdRequiresAuthEnabled(config *Config) bool {
return server.AccountConfig().AuthenticationEnabled return config.Accounts.AuthenticationEnabled
} }
func nsGroupEnabled(server *Server) bool { func nsGroupEnabled(config *Config) bool {
conf := server.Config() return config.Accounts.AuthenticationEnabled && config.Accounts.NickReservation.Enabled
return conf.Accounts.AuthenticationEnabled && conf.Accounts.NickReservation.Enabled
} }
func nsEnforceEnabled(server *Server) bool { func nsEnforceEnabled(config *Config) bool {
config := server.Config()
return config.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.AllowCustomEnforcement return config.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.AllowCustomEnforcement
} }
@ -73,6 +70,7 @@ GHOST disconnects the given user from the network if they're logged in with the
same user account, letting you reclaim your nickname.`, same user account, letting you reclaim your nickname.`,
helpShort: `$bGHOST$b reclaims your nickname.`, helpShort: `$bGHOST$b reclaims your nickname.`,
authRequired: true, authRequired: true,
minParams: 1,
}, },
"group": { "group": {
handler: nsGroupHandler, handler: nsGroupHandler,
@ -84,7 +82,6 @@ users from changing to it (or forcing them to rename).`,
enabled: nsGroupEnabled, enabled: nsGroupEnabled,
authRequired: true, authRequired: true,
}, },
"identify": { "identify": {
handler: nsIdentifyHandler, handler: nsIdentifyHandler,
help: `Syntax: $bIDENTIFY <username> [password]$b help: `Syntax: $bIDENTIFY <username> [password]$b
@ -92,6 +89,7 @@ users from changing to it (or forcing them to rename).`,
IDENTIFY lets you login to the given username using either password auth, or IDENTIFY lets you login to the given username using either password auth, or
certfp (your client certificate) if a password is not given.`, certfp (your client certificate) if a password is not given.`,
helpShort: `$bIDENTIFY$b lets you login to your account.`, helpShort: `$bIDENTIFY$b lets you login to your account.`,
minParams: 1,
}, },
"info": { "info": {
handler: nsInfoHandler, handler: nsInfoHandler,
@ -113,6 +111,7 @@ If the password is left out, your account will be registered to your TLS client
certificate (and you will need to use that certificate to login in future).`, certificate (and you will need to use that certificate to login in future).`,
helpShort: `$bREGISTER$b lets you register a user account.`, helpShort: `$bREGISTER$b lets you register a user account.`,
enabled: servCmdRequiresAccreg, enabled: servCmdRequiresAccreg,
minParams: 2,
}, },
"sadrop": { "sadrop": {
handler: nsDropHandler, handler: nsDropHandler,
@ -122,6 +121,7 @@ SADROP forcibly de-links the given nickname from the attached user account.`,
helpShort: `$bSADROP$b forcibly de-links the given nickname from its user account.`, helpShort: `$bSADROP$b forcibly de-links the given nickname from its user account.`,
capabs: []string{"accreg"}, capabs: []string{"accreg"},
enabled: servCmdRequiresAccreg, enabled: servCmdRequiresAccreg,
minParams: 1,
}, },
"unregister": { "unregister": {
handler: nsUnregisterHandler, handler: nsUnregisterHandler,
@ -132,6 +132,8 @@ IRC operator with the correct permissions). To prevent accidental
unregistrations, a verification code is required; invoking the command without unregistrations, a verification code is required; invoking the command without
a code will display the necessary code.`, a code will display the necessary code.`,
helpShort: `$bUNREGISTER$b lets you delete your user account.`, helpShort: `$bUNREGISTER$b lets you delete your user account.`,
enabled: servCmdRequiresAccreg,
minParams: 1,
}, },
"verify": { "verify": {
handler: nsVerifyHandler, handler: nsVerifyHandler,
@ -141,6 +143,7 @@ VERIFY lets you complete an account registration, if the server requires email
or other verification.`, or other verification.`,
helpShort: `$bVERIFY$b lets you complete account registration.`, helpShort: `$bVERIFY$b lets you complete account registration.`,
enabled: servCmdRequiresAccreg, enabled: servCmdRequiresAccreg,
minParams: 2,
}, },
"passwd": { "passwd": {
handler: nsPasswdHandler, handler: nsPasswdHandler,
@ -153,6 +156,7 @@ with the correct permissions, you can use PASSWD to reset someone else's
password by supplying their username and then the desired password.`, password by supplying their username and then the desired password.`,
helpShort: `$bPASSWD$b lets you change your password.`, helpShort: `$bPASSWD$b lets you change your password.`,
enabled: servCmdRequiresAuthEnabled, enabled: servCmdRequiresAuthEnabled,
minParams: 2,
}, },
} }
) )
@ -162,9 +166,14 @@ func nsNotice(rb *ResponseBuffer, text string) {
rb.Add(nil, "NickServ", "NOTICE", rb.target.Nick(), text) rb.Add(nil, "NickServ", "NOTICE", rb.target.Nick(), text)
} }
func nsDropHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsDropHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
sadrop := command == "sadrop" sadrop := command == "sadrop"
nick, _ := utils.ExtractParam(params) var nick string
if len(params) > 0 {
nick = params[0]
} else {
nick = client.NickCasefolded()
}
err := server.accounts.SetNickReserved(client, nick, sadrop, false) err := server.accounts.SetNickReserved(client, nick, sadrop, false)
if err == nil { if err == nil {
@ -173,15 +182,13 @@ func nsDropHandler(server *Server, client *Client, command, params string, rb *R
nsNotice(rb, client.t("You're not logged into an account")) nsNotice(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)")) nsNotice(rb, client.t("You can't ungroup your primary nickname (try unregistering your account instead)"))
} else if err == errNicknameReserved {
nsNotice(rb, client.t("That nickname is already reserved by someone else"))
} else { } else {
nsNotice(rb, client.t("Could not ungroup nick")) nsNotice(rb, client.t("Could not ungroup nick"))
} }
} }
func nsGhostHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsGhostHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
nick, _ := utils.ExtractParam(params) nick := params[0]
ghost := server.clients.Get(nick) ghost := server.clients.Get(nick)
if ghost == nil { if ghost == nil {
@ -207,7 +214,7 @@ func nsGhostHandler(server *Server, client *Client, command, params string, rb *
ghost.destroy(false) ghost.destroy(false)
} }
func nsGroupHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsGroupHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
nick := client.NickCasefolded() nick := client.NickCasefolded()
err := server.accounts.SetNickReserved(client, nick, false, true) err := server.accounts.SetNickReserved(client, nick, false, true)
if err == nil { if err == nil {
@ -230,13 +237,17 @@ func nsLoginThrottleCheck(client *Client, rb *ResponseBuffer) (success bool) {
return true return true
} }
func nsIdentifyHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsIdentifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
loginSuccessful := false loginSuccessful := false
username, passphrase := utils.ExtractParam(params) username := params[0]
var passphrase string
if len(params) > 1 {
passphrase = params[1]
}
// try passphrase // try passphrase
if username != "" && passphrase != "" { if passphrase != "" {
if !nsLoginThrottleCheck(client, rb) { if !nsLoginThrottleCheck(client, rb) {
return return
} }
@ -257,25 +268,31 @@ func nsIdentifyHandler(server *Server, client *Client, command, params string, r
} }
} }
func nsInfoHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsInfoHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
nick, _ := utils.ExtractParam(params) var accountName string
if len(params) > 0 {
if nick == "" { nick := params[0]
nick = client.Nick()
}
accountName := nick
if server.AccountConfig().NickReservation.Enabled { if server.AccountConfig().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")) nsNotice(rb, client.t("That nickname is not registered"))
return return
} }
} else {
accountName = nick
}
} else {
accountName = client.Account()
if accountName == "" {
nsNotice(rb, client.t("You're not logged into an account"))
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")) nsNotice(rb, client.t("Account does not exist"))
return
} }
nsNotice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name)) nsNotice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name))
@ -287,10 +304,13 @@ func nsInfoHandler(server *Server, client *Client, command, params string, rb *R
} }
} }
func nsRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
// get params // get params
username, afterUsername := utils.ExtractParam(params) username, email := params[0], params[1]
email, passphrase := utils.ExtractParam(afterUsername) var passphrase string
if len(params) > 0 {
passphrase = params[2]
}
if !server.AccountConfig().Registration.Enabled { if !server.AccountConfig().Registration.Enabled {
nsNotice(rb, client.t("Account registration has been disabled")) nsNotice(rb, client.t("Account registration has been disabled"))
@ -366,12 +386,11 @@ func nsRegisterHandler(server *Server, client *Client, command, params string, r
} }
} }
func nsUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
username, verificationCode := utils.ExtractParam(params) username := params[0]
var verificationCode string
if !server.AccountConfig().Registration.Enabled { if len(params) > 1 {
nsNotice(rb, client.t("Account registration has been disabled")) verificationCode = params[1]
return
} }
if username == "" { if username == "" {
@ -415,9 +434,8 @@ func nsUnregisterHandler(server *Server, client *Client, command, params string,
} }
} }
func nsVerifyHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsVerifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
username, code := utils.ExtractParam(params) username, code := params[0], params[1]
err := server.accounts.Verify(client, username, code) err := server.accounts.Verify(client, username, code)
var errorMessage string var errorMessage string
@ -435,7 +453,7 @@ func nsVerifyHandler(server *Server, client *Client, command, params string, rb
sendSuccessfulRegResponse(client, rb, true) sendSuccessfulRegResponse(client, rb, true)
} }
func nsPasswdHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsPasswdHandler(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
@ -445,27 +463,26 @@ func nsPasswdHandler(server *Server, client *Client, command, params string, rb
return return
} }
fields := strings.Fields(params) switch len(params) {
switch len(fields) {
case 2: case 2:
if !hasPrivs { if !hasPrivs {
errorMessage = "Insufficient privileges" errorMessage = "Insufficient privileges"
} else { } else {
target, newPassword = fields[0], fields[1] target, newPassword = params[0], params[1]
} }
case 3: case 3:
target = client.Account() target = client.Account()
if target == "" { if target == "" {
errorMessage = "You're not logged into an account" errorMessage = "You're not logged into an account"
} else if fields[1] != fields[2] { } else if params[1] != params[2] {
errorMessage = "Passwords do not match" errorMessage = "Passwords do not match"
} else { } else {
// check that they correctly supplied the preexisting password // check that they correctly supplied the preexisting password
_, err := server.accounts.checkPassphrase(target, fields[0]) _, err := server.accounts.checkPassphrase(target, params[0])
if err != nil { if err != nil {
errorMessage = "Password incorrect" errorMessage = "Password incorrect"
} else { } else {
newPassword = fields[1] newPassword = params[1]
} }
} }
default: default:
@ -486,14 +503,12 @@ func nsPasswdHandler(server *Server, client *Client, command, params string, rb
} }
} }
func nsEnforceHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func nsEnforceHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
arg := strings.TrimSpace(params) if len(params) == 0 {
if arg == "" {
status := server.accounts.getStoredEnforcementStatus(client.Account()) status := server.accounts.getStoredEnforcementStatus(client.Account())
nsNotice(rb, fmt.Sprintf(client.t("Your current nickname enforcement is: %s"), status)) nsNotice(rb, fmt.Sprintf(client.t("Your current nickname enforcement is: %s"), status))
} else { } else {
method, err := nickReservationFromString(arg) method, err := nickReservationFromString(params[0])
if err != nil { if err != nil {
nsNotice(rb, client.t("Invalid parameters")) nsNotice(rb, client.t("Invalid parameters"))
return return

View File

@ -11,8 +11,6 @@ import (
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
"github.com/goshuirc/irc-go/ircmsg" "github.com/goshuirc/irc-go/ircmsg"
"github.com/oragono/oragono/irc/utils"
) )
// defines an IRC service, e.g., NICKSERV // defines an IRC service, e.g., NICKSERV
@ -28,11 +26,12 @@ 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, params string, rb *ResponseBuffer) handler func(server *Server, client *Client, command string, params []string, rb *ResponseBuffer)
help string help string
helpShort string helpShort string
authRequired bool authRequired bool
enabled func(*Server) bool // is this command enabled in the server config? enabled func(*Config) bool // is this command enabled in the server config?
minParams int
} }
// looks up a command in the table of command definitions for a service, resolving aliases // looks up a command in the table of command definitions for a service, resolving aliases
@ -90,7 +89,7 @@ HELP returns information on the given command.`,
helpShort: `$bHELP$b shows in-depth information about commands.`, helpShort: `$bHELP$b shows in-depth information about commands.`,
} }
// this handles IRC commands like `/NICKSERV INFO`, translating into `/MSG NICKSERV INFO` // generic handler for IRC commands like `/NICKSERV INFO`
func serviceCmdHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func serviceCmdHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
service, ok := oragonoServicesByCommandAlias[msg.Command] service, ok := oragonoServicesByCommandAlias[msg.Command]
if !ok { if !ok {
@ -98,15 +97,22 @@ func serviceCmdHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb
return false return false
} }
fakePrivmsg := strings.Join(msg.Params, " ") serviceRunCommand(service, server, client, msg.Params, rb)
servicePrivmsgHandler(service, server, client, fakePrivmsg, rb)
return false return false
} }
// generic handler for service PRIVMSG // generic handler for service PRIVMSG, like `/msg NickServ INFO`
func servicePrivmsgHandler(service *ircService, server *Server, client *Client, message string, rb *ResponseBuffer) { func servicePrivmsgHandler(service *ircService, server *Server, client *Client, message string, rb *ResponseBuffer) {
commandName, params := utils.ExtractParam(message) serviceRunCommand(service, server, client, strings.Fields(message), rb)
commandName = strings.ToLower(commandName) }
// actually execute a service command
func serviceRunCommand(service *ircService, server *Server, client *Client, params []string, rb *ResponseBuffer) {
if len(params) == 0 {
return
}
commandName := strings.ToLower(params[0])
params = params[1:]
nick := rb.target.Nick() nick := rb.target.Nick()
sendNotice := func(notice string) { sendNotice := func(notice string) {
@ -119,7 +125,12 @@ func servicePrivmsgHandler(service *ircService, server *Server, client *Client,
return return
} }
if cmd.enabled != nil && !cmd.enabled(server) { if len(params) < cmd.minParams {
sendNotice(fmt.Sprintf(client.t("Invalid parameters. For usage, do /msg %s HELP %s"), service.Name, strings.ToUpper(commandName)))
return
}
if cmd.enabled != nil && !cmd.enabled(server.Config()) {
sendNotice(client.t("This command has been disabled by the server administrators")) sendNotice(client.t("This command has been disabled by the server administrators"))
return return
} }
@ -143,15 +154,16 @@ func servicePrivmsgHandler(service *ircService, server *Server, client *Client,
} }
// generic handler that displays help for service commands // generic handler that displays help for service commands
func serviceHelpHandler(service *ircService, server *Server, client *Client, params string, rb *ResponseBuffer) { func serviceHelpHandler(service *ircService, server *Server, client *Client, params []string, rb *ResponseBuffer) {
nick := rb.target.Nick() nick := rb.target.Nick()
config := server.Config()
sendNotice := func(notice string) { sendNotice := func(notice string) {
rb.Add(nil, service.Name, "NOTICE", nick, notice) rb.Add(nil, service.Name, "NOTICE", nick, notice)
} }
sendNotice(ircfmt.Unescape(fmt.Sprintf("*** $b%s HELP$b ***", service.Name))) sendNotice(ircfmt.Unescape(fmt.Sprintf("*** $b%s HELP$b ***", service.Name)))
if params == "" { if len(params) == 0 {
// show general help // show general help
var shownHelpLines sort.StringSlice var shownHelpLines sort.StringSlice
var disabledCommands bool var disabledCommands bool
@ -163,7 +175,7 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
if commandInfo.aliasOf != "" { if commandInfo.aliasOf != "" {
continue // don't show help lines for aliases continue // don't show help lines for aliases
} }
if commandInfo.enabled != nil && !commandInfo.enabled(server) { if commandInfo.enabled != nil && !commandInfo.enabled(config) {
disabledCommands = true disabledCommands = true
continue continue
} }
@ -187,7 +199,7 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
sendNotice(line) sendNotice(line)
} }
} else { } else {
commandName := strings.ToLower(strings.TrimSpace(params)) commandName := strings.ToLower(params[0])
commandInfo := lookupServiceCommand(service.Commands, commandName) commandInfo := lookupServiceCommand(service.Commands, commandName)
if commandInfo == nil { if commandInfo == nil {
sendNotice(client.t(fmt.Sprintf("Unknown command. To see available commands, run /%s HELP", service.ShortName))) sendNotice(client.t(fmt.Sprintf("Unknown command. To see available commands, run /%s HELP", service.ShortName)))

View File

@ -3,19 +3,6 @@
package utils package utils
import "strings"
// ExtractParam extracts a parameter from the given string, returning the param and the rest of the string.
func ExtractParam(line string) (string, string) {
rawParams := strings.SplitN(strings.TrimSpace(line), " ", 2)
param0 := rawParams[0]
var param1 string
if 1 < len(rawParams) {
param1 = strings.TrimSpace(rawParams[1])
}
return param0, param1
}
// ArgsToStrings takes the arguments and splits them into a series of strings, // ArgsToStrings takes the arguments and splits them into a series of strings,
// each argument separated by delim and each string bounded by maxLength. // each argument separated by delim and each string bounded by maxLength.
func ArgsToStrings(maxLength int, arguments []string, delim string) []string { func ArgsToStrings(maxLength int, arguments []string, delim string) []string {