mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
commit
3db6c9472b
@ -187,6 +187,10 @@ func (am *AccountManager) EnforcementStatus(nick string) (account string, method
|
||||
defer am.RUnlock()
|
||||
|
||||
account = am.nickToAccount[cfnick]
|
||||
if account == "" {
|
||||
method = NickReservationNone
|
||||
return
|
||||
}
|
||||
method = am.accountToMethod[account]
|
||||
// if they don't have a custom setting, or customization is disabled, use the default
|
||||
if method == NickReservationOptional || !config.Accounts.NickReservation.AllowCustomEnforcement {
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
"github.com/goshuirc/irc-go/ircfmt"
|
||||
"github.com/oragono/oragono/irc/modes"
|
||||
"github.com/oragono/oragono/irc/sno"
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
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:
|
||||
%s`
|
||||
|
||||
func chanregEnabled(server *Server) bool {
|
||||
return server.ChannelRegistrationEnabled()
|
||||
func chanregEnabled(config *Config) bool {
|
||||
return config.Channels.Registration.Enabled
|
||||
}
|
||||
|
||||
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.`,
|
||||
authRequired: true,
|
||||
enabled: chanregEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"register": {
|
||||
handler: csRegisterHandler,
|
||||
@ -52,6 +52,7 @@ remembered.`,
|
||||
helpShort: `$bREGISTER$b lets you own a given channel.`,
|
||||
authRequired: true,
|
||||
enabled: chanregEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"unregister": {
|
||||
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.`,
|
||||
helpShort: `$bUNREGISTER$b deletes a channel registration.`,
|
||||
enabled: chanregEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"drop": {
|
||||
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.`,
|
||||
helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`,
|
||||
enabled: chanregEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -86,8 +89,8 @@ func csNotice(rb *ResponseBuffer, text string) {
|
||||
rb.Add(nil, "ChanServ", "NOTICE", rb.target.Nick(), text)
|
||||
}
|
||||
|
||||
func csAmodeHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
channelName, modeChange := utils.ExtractParam(params)
|
||||
func csAmodeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
channelName := params[0]
|
||||
|
||||
channel := server.channels.Get(channelName)
|
||||
if channel == nil {
|
||||
@ -98,7 +101,7 @@ func csAmodeHandler(server *Server, client *Client, command, params string, rb *
|
||||
return
|
||||
}
|
||||
|
||||
modeChanges, unknown := modes.ParseChannelModeChanges(strings.Fields(modeChange)...)
|
||||
modeChanges, unknown := modes.ParseChannelModeChanges(params[1:]...)
|
||||
var change modes.ModeChange
|
||||
if len(modeChanges) > 1 || len(unknown) > 0 {
|
||||
csNotice(rb, client.t("Invalid mode change"))
|
||||
@ -159,27 +162,13 @@ func csAmodeHandler(server *Server, client *Client, command, params string, rb *
|
||||
}
|
||||
}
|
||||
|
||||
func csOpHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
channelName, clientToOp := utils.ExtractParam(params)
|
||||
|
||||
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)
|
||||
func csOpHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
channelInfo := server.channels.Get(params[0])
|
||||
if channelInfo == nil {
|
||||
csNotice(rb, client.t("Channel does not exist"))
|
||||
return
|
||||
}
|
||||
channelName := channelInfo.Name()
|
||||
|
||||
clientAccount := client.Account()
|
||||
if clientAccount == "" || clientAccount != channelInfo.Founder() {
|
||||
@ -188,10 +177,9 @@ func csOpHandler(server *Server, client *Client, command, params string, rb *Res
|
||||
}
|
||||
|
||||
var target *Client
|
||||
if clientToOp != "" {
|
||||
casefoldedNickname, err := CasefoldName(clientToOp)
|
||||
target = server.clients.Get(casefoldedNickname)
|
||||
if err != nil || target == nil {
|
||||
if len(params) > 1 {
|
||||
target = server.clients.Get(params[1])
|
||||
if target == nil {
|
||||
csNotice(rb, client.t("Could not find given client"))
|
||||
return
|
||||
}
|
||||
@ -216,16 +204,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))
|
||||
|
||||
server.logger.Info("chanserv", fmt.Sprintf("Client %s op'd [%s] in channel %s", client.nick, clientToOp, 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, clientToOp, channelName))
|
||||
tnick := target.Nick()
|
||||
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) {
|
||||
channelName := strings.TrimSpace(params)
|
||||
if channelName == "" {
|
||||
csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b")))
|
||||
return
|
||||
}
|
||||
func csRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
channelName := params[0]
|
||||
|
||||
channelKey, err := CasefoldChannel(channelName)
|
||||
if err != nil {
|
||||
@ -251,7 +236,7 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
|
||||
|
||||
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))
|
||||
|
||||
// give them founder privs
|
||||
@ -266,8 +251,13 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
|
||||
}
|
||||
}
|
||||
|
||||
func csUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
channelName, verificationCode := utils.ExtractParam(params)
|
||||
func csUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
channelName := params[0]
|
||||
var verificationCode string
|
||||
if len(params) > 1 {
|
||||
verificationCode = params[1]
|
||||
}
|
||||
|
||||
channelKey, err := CasefoldChannel(channelName)
|
||||
if channelKey == "" || err != nil {
|
||||
csNotice(rb, client.t("Channel name is not valid"))
|
||||
|
@ -129,7 +129,7 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error {
|
||||
if currentNewEntry != nil && currentNewEntry != client {
|
||||
return errNicknameInUse
|
||||
}
|
||||
if method == NickReservationStrict && reservedAccount != client.Account() {
|
||||
if method == NickReservationStrict && reservedAccount != "" && reservedAccount != client.Account() {
|
||||
return errNicknameReserved
|
||||
}
|
||||
clients.removeInternal(client)
|
||||
|
@ -7,10 +7,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
const hostservHelp = `HostServ lets you manage your vhost (i.e., the string displayed
|
||||
@ -29,13 +26,12 @@ var (
|
||||
defaultValidVhostRegex = regexp.MustCompile(`^[0-9A-Za-z.\-_/]+$`)
|
||||
)
|
||||
|
||||
func hostservEnabled(server *Server) bool {
|
||||
return server.AccountConfig().VHosts.Enabled
|
||||
func hostservEnabled(config *Config) bool {
|
||||
return config.Accounts.VHosts.Enabled
|
||||
}
|
||||
|
||||
func hostservRequestsEnabled(server *Server) bool {
|
||||
ac := server.AccountConfig()
|
||||
return ac.VHosts.Enabled && ac.VHosts.UserRequests.Enabled
|
||||
func hostservRequestsEnabled(config *Config) bool {
|
||||
return config.Accounts.VHosts.Enabled && config.Accounts.VHosts.UserRequests.Enabled
|
||||
}
|
||||
|
||||
var (
|
||||
@ -67,16 +63,16 @@ then be approved by a server operator.`,
|
||||
helpShort: `$bREQUEST$b requests a new vhost, pending operator approval.`,
|
||||
authRequired: true,
|
||||
enabled: hostservRequestsEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"status": {
|
||||
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
|
||||
request for a new one.`,
|
||||
helpShort: `$bSTATUS$b shows your vhost and request status.`,
|
||||
authRequired: true,
|
||||
enabled: hostservEnabled,
|
||||
request for a new one. A server operator can view someone else's status.`,
|
||||
helpShort: `$bSTATUS$b shows your vhost and request status.`,
|
||||
enabled: hostservEnabled,
|
||||
},
|
||||
"set": {
|
||||
handler: hsSetHandler,
|
||||
@ -86,6 +82,7 @@ SET sets a user's vhost, bypassing the request system.`,
|
||||
helpShort: `$bSET$b sets a user's vhost.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 2,
|
||||
},
|
||||
"del": {
|
||||
handler: hsSetHandler,
|
||||
@ -95,6 +92,7 @@ DEL deletes a user's vhost.`,
|
||||
helpShort: `$bDEL$b deletes a user's vhost.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"waiting": {
|
||||
handler: hsWaitingHandler,
|
||||
@ -114,6 +112,7 @@ APPROVE approves a user's vhost request.`,
|
||||
helpShort: `$bAPPROVE$b approves a user's vhost request.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"reject": {
|
||||
handler: hsRejectHandler,
|
||||
@ -124,6 +123,8 @@ for the rejection.`,
|
||||
helpShort: `$bREJECT$b rejects a user's vhost request.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
maxParams: 2,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -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
|
||||
if command == "on" {
|
||||
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) {
|
||||
vhost, _ := utils.ExtractParam(params)
|
||||
func hsRequestHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
vhost := params[0]
|
||||
if validateVhost(server, vhost, false) != nil {
|
||||
hsNotice(rb, client.t("Invalid vhost"))
|
||||
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) {
|
||||
accountName := client.Account()
|
||||
func hsStatusHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
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)
|
||||
if err != nil {
|
||||
server.logger.Warning("internal", "error loading account info", accountName, err.Error())
|
||||
hsNotice(rb, client.t("An error occurred"))
|
||||
if err != errAccountDoesNotExist {
|
||||
server.logger.Warning("internal", "error loading account info", accountName, err.Error())
|
||||
}
|
||||
hsNotice(rb, client.t("No such account"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -232,23 +245,18 @@ func validateVhost(server *Server, vhost string, oper bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func hsSetHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
var user, vhost string
|
||||
user, params = utils.ExtractParam(params)
|
||||
if user == "" {
|
||||
hsNotice(rb, client.t("A user is required"))
|
||||
return
|
||||
}
|
||||
func hsSetHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
user := params[0]
|
||||
var vhost string
|
||||
|
||||
if command == "set" {
|
||||
vhost, _ = utils.ExtractParam(params)
|
||||
vhost = params[1]
|
||||
if validateVhost(server, vhost, true) != nil {
|
||||
hsNotice(rb, client.t("Invalid vhost"))
|
||||
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)
|
||||
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)
|
||||
hsNotice(rb, fmt.Sprintf(client.t("There are %d pending requests for vhosts (%d displayed)"), total, len(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) {
|
||||
user, _ := utils.ExtractParam(params)
|
||||
if user == "" {
|
||||
hsNotice(rb, client.t("A user is required"))
|
||||
return
|
||||
}
|
||||
func hsApproveHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
user := params[0]
|
||||
|
||||
vhostInfo, err := server.accounts.VHostApprove(user)
|
||||
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) {
|
||||
user, params := utils.ExtractParam(params)
|
||||
if user == "" {
|
||||
hsNotice(rb, client.t("A user is required"))
|
||||
return
|
||||
func hsRejectHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
var reason string
|
||||
user := params[0]
|
||||
if len(params) > 1 {
|
||||
reason = params[1]
|
||||
}
|
||||
reason := strings.TrimSpace(params)
|
||||
|
||||
vhostInfo, err := server.accounts.VHostReject(user, reason)
|
||||
if err != nil {
|
||||
|
@ -15,9 +15,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// anything added here MUST be casefolded:
|
||||
restrictedNicknames = map[string]bool{
|
||||
"=scene=": true, // used for rp commands
|
||||
"HistServ": true, // TODO(slingamn) this should become a real service
|
||||
"histserv": true, // TODO(slingamn) this should become a real service
|
||||
}
|
||||
)
|
||||
|
||||
|
127
irc/nickserv.go
127
irc/nickserv.go
@ -8,25 +8,22 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircfmt"
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
// "enabled" callbacks for specific nickserv commands
|
||||
func servCmdRequiresAccreg(server *Server) bool {
|
||||
return server.AccountConfig().Registration.Enabled
|
||||
func servCmdRequiresAccreg(config *Config) bool {
|
||||
return config.Accounts.Registration.Enabled
|
||||
}
|
||||
|
||||
func servCmdRequiresAuthEnabled(server *Server) bool {
|
||||
return server.AccountConfig().AuthenticationEnabled
|
||||
func servCmdRequiresAuthEnabled(config *Config) bool {
|
||||
return config.Accounts.AuthenticationEnabled
|
||||
}
|
||||
|
||||
func nsGroupEnabled(server *Server) bool {
|
||||
conf := server.Config()
|
||||
return conf.Accounts.AuthenticationEnabled && conf.Accounts.NickReservation.Enabled
|
||||
func nsGroupEnabled(config *Config) bool {
|
||||
return config.Accounts.AuthenticationEnabled && config.Accounts.NickReservation.Enabled
|
||||
}
|
||||
|
||||
func nsEnforceEnabled(server *Server) bool {
|
||||
config := server.Config()
|
||||
func nsEnforceEnabled(config *Config) bool {
|
||||
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.`,
|
||||
helpShort: `$bGHOST$b reclaims your nickname.`,
|
||||
authRequired: true,
|
||||
minParams: 1,
|
||||
},
|
||||
"group": {
|
||||
handler: nsGroupHandler,
|
||||
@ -84,7 +82,6 @@ users from changing to it (or forcing them to rename).`,
|
||||
enabled: nsGroupEnabled,
|
||||
authRequired: true,
|
||||
},
|
||||
|
||||
"identify": {
|
||||
handler: nsIdentifyHandler,
|
||||
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
|
||||
certfp (your client certificate) if a password is not given.`,
|
||||
helpShort: `$bIDENTIFY$b lets you login to your account.`,
|
||||
minParams: 1,
|
||||
},
|
||||
"info": {
|
||||
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).`,
|
||||
helpShort: `$bREGISTER$b lets you register a user account.`,
|
||||
enabled: servCmdRequiresAccreg,
|
||||
minParams: 2,
|
||||
},
|
||||
"sadrop": {
|
||||
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.`,
|
||||
capabs: []string{"accreg"},
|
||||
enabled: servCmdRequiresAccreg,
|
||||
minParams: 1,
|
||||
},
|
||||
"unregister": {
|
||||
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
|
||||
a code will display the necessary code.`,
|
||||
helpShort: `$bUNREGISTER$b lets you delete your user account.`,
|
||||
enabled: servCmdRequiresAccreg,
|
||||
minParams: 1,
|
||||
},
|
||||
"verify": {
|
||||
handler: nsVerifyHandler,
|
||||
@ -141,6 +143,7 @@ VERIFY lets you complete an account registration, if the server requires email
|
||||
or other verification.`,
|
||||
helpShort: `$bVERIFY$b lets you complete account registration.`,
|
||||
enabled: servCmdRequiresAccreg,
|
||||
minParams: 2,
|
||||
},
|
||||
"passwd": {
|
||||
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.`,
|
||||
helpShort: `$bPASSWD$b lets you change your password.`,
|
||||
enabled: servCmdRequiresAuthEnabled,
|
||||
minParams: 2,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -162,9 +166,14 @@ func nsNotice(rb *ResponseBuffer, text string) {
|
||||
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"
|
||||
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)
|
||||
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"))
|
||||
} else if err == errAccountCantDropPrimaryNick {
|
||||
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 {
|
||||
nsNotice(rb, client.t("Could not ungroup nick"))
|
||||
}
|
||||
}
|
||||
|
||||
func nsGhostHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
nick, _ := utils.ExtractParam(params)
|
||||
func nsGhostHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
nick := params[0]
|
||||
|
||||
ghost := server.clients.Get(nick)
|
||||
if ghost == nil {
|
||||
@ -207,7 +214,7 @@ func nsGhostHandler(server *Server, client *Client, command, params string, rb *
|
||||
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()
|
||||
err := server.accounts.SetNickReserved(client, nick, false, true)
|
||||
if err == nil {
|
||||
@ -230,13 +237,17 @@ func nsLoginThrottleCheck(client *Client, rb *ResponseBuffer) (success bool) {
|
||||
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
|
||||
|
||||
username, passphrase := utils.ExtractParam(params)
|
||||
username := params[0]
|
||||
var passphrase string
|
||||
if len(params) > 1 {
|
||||
passphrase = params[1]
|
||||
}
|
||||
|
||||
// try passphrase
|
||||
if username != "" && passphrase != "" {
|
||||
if passphrase != "" {
|
||||
if !nsLoginThrottleCheck(client, rb) {
|
||||
return
|
||||
}
|
||||
@ -257,18 +268,23 @@ func nsIdentifyHandler(server *Server, client *Client, command, params string, r
|
||||
}
|
||||
}
|
||||
|
||||
func nsInfoHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||
nick, _ := utils.ExtractParam(params)
|
||||
|
||||
if nick == "" {
|
||||
nick = client.Nick()
|
||||
}
|
||||
|
||||
accountName := nick
|
||||
if server.AccountConfig().NickReservation.Enabled {
|
||||
accountName = server.accounts.NickToAccount(nick)
|
||||
func nsInfoHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
var accountName string
|
||||
if len(params) > 0 {
|
||||
nick := params[0]
|
||||
if server.AccountConfig().NickReservation.Enabled {
|
||||
accountName = server.accounts.NickToAccount(nick)
|
||||
if accountName == "" {
|
||||
nsNotice(rb, client.t("That nickname is not registered"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
accountName = nick
|
||||
}
|
||||
} else {
|
||||
accountName = client.Account()
|
||||
if accountName == "" {
|
||||
nsNotice(rb, client.t("That nickname is not registered"))
|
||||
nsNotice(rb, client.t("You're not logged into an account"))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -276,6 +292,7 @@ func nsInfoHandler(server *Server, client *Client, command, params string, rb *R
|
||||
account, err := server.accounts.LoadAccount(accountName)
|
||||
if err != nil || !account.Verified {
|
||||
nsNotice(rb, client.t("Account does not exist"))
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
username, afterUsername := utils.ExtractParam(params)
|
||||
email, passphrase := utils.ExtractParam(afterUsername)
|
||||
username, email := params[0], params[1]
|
||||
var passphrase string
|
||||
if len(params) > 0 {
|
||||
passphrase = params[2]
|
||||
}
|
||||
|
||||
if !server.AccountConfig().Registration.Enabled {
|
||||
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) {
|
||||
username, verificationCode := utils.ExtractParam(params)
|
||||
|
||||
if !server.AccountConfig().Registration.Enabled {
|
||||
nsNotice(rb, client.t("Account registration has been disabled"))
|
||||
return
|
||||
func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
username := params[0]
|
||||
var verificationCode string
|
||||
if len(params) > 1 {
|
||||
verificationCode = params[1]
|
||||
}
|
||||
|
||||
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) {
|
||||
username, code := utils.ExtractParam(params)
|
||||
|
||||
func nsVerifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
username, code := params[0], params[1]
|
||||
err := server.accounts.Verify(client, username, code)
|
||||
|
||||
var errorMessage string
|
||||
@ -435,7 +453,7 @@ func nsVerifyHandler(server *Server, client *Client, command, params string, rb
|
||||
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 newPassword string
|
||||
var errorMessage string
|
||||
@ -445,27 +463,26 @@ func nsPasswdHandler(server *Server, client *Client, command, params string, rb
|
||||
return
|
||||
}
|
||||
|
||||
fields := strings.Fields(params)
|
||||
switch len(fields) {
|
||||
switch len(params) {
|
||||
case 2:
|
||||
if !hasPrivs {
|
||||
errorMessage = "Insufficient privileges"
|
||||
} else {
|
||||
target, newPassword = fields[0], fields[1]
|
||||
target, newPassword = params[0], params[1]
|
||||
}
|
||||
case 3:
|
||||
target = client.Account()
|
||||
if target == "" {
|
||||
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"
|
||||
} else {
|
||||
// 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 {
|
||||
errorMessage = "Password incorrect"
|
||||
} else {
|
||||
newPassword = fields[1]
|
||||
newPassword = params[1]
|
||||
}
|
||||
}
|
||||
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) {
|
||||
arg := strings.TrimSpace(params)
|
||||
|
||||
if arg == "" {
|
||||
func nsEnforceHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
if len(params) == 0 {
|
||||
status := server.accounts.getStoredEnforcementStatus(client.Account())
|
||||
nsNotice(rb, fmt.Sprintf(client.t("Your current nickname enforcement is: %s"), status))
|
||||
} else {
|
||||
method, err := nickReservationFromString(arg)
|
||||
method, err := nickReservationFromString(params[0])
|
||||
if err != nil {
|
||||
nsNotice(rb, client.t("Invalid parameters"))
|
||||
return
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/goshuirc/irc-go/ircfmt"
|
||||
"github.com/goshuirc/irc-go/ircmsg"
|
||||
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
@ -28,11 +27,13 @@ type ircService struct {
|
||||
type serviceCommand struct {
|
||||
aliasOf string // marks this command as an alias of another
|
||||
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
|
||||
helpShort string
|
||||
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
|
||||
maxParams int // split into at most n params, with last param containing remaining unsplit text
|
||||
}
|
||||
|
||||
// looks up a command in the table of command definitions for a service, resolving aliases
|
||||
@ -90,7 +91,7 @@ HELP returns information on the given command.`,
|
||||
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 {
|
||||
service, ok := oragonoServicesByCommandAlias[msg.Command]
|
||||
if !ok {
|
||||
@ -98,28 +99,60 @@ func serviceCmdHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb
|
||||
return false
|
||||
}
|
||||
|
||||
fakePrivmsg := strings.Join(msg.Params, " ")
|
||||
servicePrivmsgHandler(service, server, client, fakePrivmsg, rb)
|
||||
if len(msg.Params) == 0 {
|
||||
return false
|
||||
}
|
||||
commandName := strings.ToLower(msg.Params[0])
|
||||
params := msg.Params[1:]
|
||||
cmd := lookupServiceCommand(service.Commands, commandName)
|
||||
// for a maxParams command, join all final parameters together if necessary
|
||||
if cmd != nil && cmd.maxParams != 0 && cmd.maxParams < len(params) {
|
||||
newParams := make([]string, cmd.maxParams)
|
||||
copy(newParams, params[:cmd.maxParams-1])
|
||||
newParams[cmd.maxParams-1] = strings.Join(params[cmd.maxParams-1:], " ")
|
||||
params = newParams
|
||||
}
|
||||
serviceRunCommand(service, server, client, cmd, commandName, params, rb)
|
||||
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) {
|
||||
commandName, params := utils.ExtractParam(message)
|
||||
commandName = strings.ToLower(commandName)
|
||||
params := strings.Fields(message)
|
||||
if len(params) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// look up the service command to see how to parse it
|
||||
commandName := strings.ToLower(params[0])
|
||||
cmd := lookupServiceCommand(service.Commands, commandName)
|
||||
// reparse if needed
|
||||
if cmd != nil && cmd.maxParams != 0 {
|
||||
params = utils.FieldsN(message, cmd.maxParams+1)[1:]
|
||||
} else {
|
||||
params = params[1:]
|
||||
}
|
||||
serviceRunCommand(service, server, client, cmd, commandName, params, rb)
|
||||
}
|
||||
|
||||
// actually execute a service command
|
||||
func serviceRunCommand(service *ircService, server *Server, client *Client, cmd *serviceCommand, commandName string, params []string, rb *ResponseBuffer) {
|
||||
nick := rb.target.Nick()
|
||||
sendNotice := func(notice string) {
|
||||
rb.Add(nil, service.Name, "NOTICE", nick, notice)
|
||||
}
|
||||
|
||||
cmd := lookupServiceCommand(service.Commands, commandName)
|
||||
if cmd == nil {
|
||||
sendNotice(fmt.Sprintf("%s /%s HELP", client.t("Unknown command. To see available commands, run"), service.ShortName))
|
||||
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"))
|
||||
return
|
||||
}
|
||||
@ -143,15 +176,16 @@ func servicePrivmsgHandler(service *ircService, server *Server, client *Client,
|
||||
}
|
||||
|
||||
// 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()
|
||||
config := server.Config()
|
||||
sendNotice := func(notice string) {
|
||||
rb.Add(nil, service.Name, "NOTICE", nick, notice)
|
||||
}
|
||||
|
||||
sendNotice(ircfmt.Unescape(fmt.Sprintf("*** $b%s HELP$b ***", service.Name)))
|
||||
|
||||
if params == "" {
|
||||
if len(params) == 0 {
|
||||
// show general help
|
||||
var shownHelpLines sort.StringSlice
|
||||
var disabledCommands bool
|
||||
@ -163,7 +197,7 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
|
||||
if commandInfo.aliasOf != "" {
|
||||
continue // don't show help lines for aliases
|
||||
}
|
||||
if commandInfo.enabled != nil && !commandInfo.enabled(server) {
|
||||
if commandInfo.enabled != nil && !commandInfo.enabled(config) {
|
||||
disabledCommands = true
|
||||
continue
|
||||
}
|
||||
@ -187,7 +221,7 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
|
||||
sendNotice(line)
|
||||
}
|
||||
} else {
|
||||
commandName := strings.ToLower(strings.TrimSpace(params))
|
||||
commandName := strings.ToLower(params[0])
|
||||
commandInfo := lookupServiceCommand(service.Commands, commandName)
|
||||
if commandInfo == nil {
|
||||
sendNotice(client.t(fmt.Sprintf("Unknown command. To see available commands, run /%s HELP", service.ShortName)))
|
||||
|
@ -3,19 +3,6 @@
|
||||
|
||||
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,
|
||||
// each argument separated by delim and each string bounded by maxLength.
|
||||
func ArgsToStrings(maxLength int, arguments []string, delim string) []string {
|
||||
|
52
irc/utils/fieldsn.go
Normal file
52
irc/utils/fieldsn.go
Normal file
@ -0,0 +1,52 @@
|
||||
package utils
|
||||
|
||||
// Copyright (c) 2014 Kevin Wallace <kevin@pentabarf.net>
|
||||
// Found here: https://github.com/kevinwallace/fieldsn
|
||||
// Released under the MIT license
|
||||
// XXX this implementation treats negative n as "return nil",
|
||||
// unlike stdlib SplitN and friends, which treat it as "no limit"
|
||||
|
||||
// Original source code below:
|
||||
|
||||
// Package fieldsn implements FieldsN and FieldsFuncN,
|
||||
// which are conspicuously missing from the strings package.
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// FieldsN is like strings.Fields, but returns at most n fields,
|
||||
// and the nth field includes any whitespace at the end of the string.
|
||||
func FieldsN(s string, n int) []string {
|
||||
return FieldsFuncN(s, unicode.IsSpace, n)
|
||||
}
|
||||
|
||||
// FieldsFuncN is like strings.FieldsFunc, but returns at most n fields,
|
||||
// and the nth field includes any runes at the end of the string normally excluded by f.
|
||||
func FieldsFuncN(s string, f func(rune) bool, n int) []string {
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := make([]string, 0, n)
|
||||
na := 0
|
||||
fieldStart := -1
|
||||
for i, rune := range s {
|
||||
if f(rune) {
|
||||
if fieldStart >= 0 {
|
||||
a = append(a, s[fieldStart:i])
|
||||
na++
|
||||
fieldStart = -1
|
||||
}
|
||||
} else if fieldStart == -1 {
|
||||
fieldStart = i
|
||||
if na+1 == n {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if fieldStart >= 0 {
|
||||
a = append(a, s[fieldStart:])
|
||||
}
|
||||
return a
|
||||
}
|
Loading…
Reference in New Issue
Block a user