3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-26 22:09:24 +01:00
ergo/irc/commands.go

367 lines
7.5 KiB
Go
Raw Normal View History

// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
2017-03-27 14:15:02 +02:00
// Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package irc
import (
"github.com/goshuirc/irc-go/ircmsg"
"github.com/oragono/oragono/irc/modes"
)
2012-12-09 21:51:50 +01:00
2016-06-19 04:53:52 +02:00
// Command represents a command accepted from a client.
type Command struct {
handler func(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool
oper bool
usablePreReg bool
leaveClientIdle bool // if true, leaves the client active time alone
2019-12-23 21:26:37 +01:00
allowedInBatch bool // allowed in client-to-server batches
minParams int
capabs []string
}
2016-06-19 04:53:52 +02:00
// Run runs this command with the given client/message.
func (cmd *Command) Run(server *Server, client *Client, session *Session, msg ircmsg.IrcMessage) (exiting bool) {
rb := NewResponseBuffer(session)
2018-01-30 05:20:12 +01:00
rb.Label = GetLabel(msg)
exiting = func() bool {
defer rb.Send(true)
if !client.registered && !cmd.usablePreReg {
rb.Add(nil, server.name, ERR_NOTREGISTERED, "*", client.t("You need to register before you can use that command"))
return false
}
if cmd.oper && !client.HasMode(modes.Operator) {
rb.Add(nil, server.name, ERR_NOPRIVILEGES, client.Nick(), client.t("Permission Denied - You're not an IRC operator"))
return false
}
if len(cmd.capabs) > 0 && !client.HasRoleCapabs(cmd.capabs...) {
rb.Add(nil, server.name, ERR_NOPRIVILEGES, client.Nick(), client.t("Permission Denied"))
return false
}
if len(msg.Params) < cmd.minParams {
rb.Add(nil, server.name, ERR_NEEDMOREPARAMS, client.Nick(), msg.Command, rb.target.t("Not enough parameters"))
return false
}
2019-12-23 21:26:37 +01:00
if session.batch.label != "" && !cmd.allowedInBatch {
rb.Add(nil, server.name, "FAIL", "BATCH", "MULTILINE_INVALID", client.t("Command not allowed during a multiline batch"))
2020-03-27 15:40:19 +01:00
session.EndMultilineBatch("")
2019-12-23 21:26:37 +01:00
return false
}
return cmd.handler(server, client, msg, rb)
}()
2020-02-25 19:26:49 +01:00
// after each command, see if we can send registration to the client
if !exiting && !client.registered {
exiting = server.tryRegister(client, session)
}
// most servers do this only for PING/PONG, but we'll do it for any command:
if client.registered {
// touch even if `exiting`, so we record the time of a QUIT accurately
session.idletimer.Touch()
}
// TODO: eliminate idletimer entirely in favor of this measurement
if client.registered {
client.Touch(!cmd.leaveClientIdle, session)
}
return exiting
}
2020-05-08 11:44:40 +02:00
// fake handler for unknown commands (see #994: this ensures the response tags are correct)
var unknownCommand = Command{
handler: unknownCommandHandler,
usablePreReg: true,
}
// Commands holds all commands executable by a client connected to us.
var Commands map[string]Command
func init() {
Commands = map[string]Command{
"AMBIANCE": {
handler: sceneHandler,
minParams: 2,
},
"AUTHENTICATE": {
handler: authenticateHandler,
usablePreReg: true,
minParams: 1,
},
"AWAY": {
handler: awayHandler,
minParams: 0,
},
2019-12-23 21:26:37 +01:00
"BATCH": {
handler: batchHandler,
minParams: 1,
allowedInBatch: true,
},
2019-05-22 03:40:25 +02:00
"BRB": {
handler: brbHandler,
minParams: 0,
},
"CAP": {
handler: capHandler,
usablePreReg: true,
minParams: 1,
},
"CHATHISTORY": {
handler: chathistoryHandler,
minParams: 4,
},
"DEBUG": {
handler: debugHandler,
minParams: 1,
oper: true,
},
2020-02-21 12:10:35 +01:00
"DEOPER": {
handler: deoperHandler,
minParams: 0,
oper: true,
},
"DLINE": {
handler: dlineHandler,
minParams: 1,
oper: true,
},
2020-04-15 10:14:17 +02:00
"EXTJWT": {
handler: extjwtHandler,
minParams: 1,
},
"HELP": {
handler: helpHandler,
minParams: 0,
},
"HELPOP": {
handler: helpHandler,
minParams: 0,
},
"HISTORY": {
handler: historyHandler,
minParams: 1,
},
"INFO": {
handler: infoHandler,
},
"INVITE": {
handler: inviteHandler,
minParams: 2,
},
"ISON": {
handler: isonHandler,
minParams: 1,
leaveClientIdle: true,
},
"JOIN": {
handler: joinHandler,
minParams: 1,
},
"KICK": {
handler: kickHandler,
minParams: 2,
},
"KILL": {
handler: killHandler,
minParams: 1,
oper: true,
2020-03-18 10:42:52 +01:00
capabs: []string{"local_kill"}, //TODO(dan): when we have S2S, this will be checked in the command handler itself
},
"KLINE": {
handler: klineHandler,
minParams: 1,
oper: true,
},
"LANGUAGE": {
handler: languageHandler,
usablePreReg: true,
minParams: 1,
},
"LIST": {
handler: listHandler,
minParams: 0,
},
"LUSERS": {
handler: lusersHandler,
minParams: 0,
},
"MODE": {
handler: modeHandler,
minParams: 1,
},
"MONITOR": {
handler: monitorHandler,
minParams: 1,
},
"MOTD": {
handler: motdHandler,
minParams: 0,
},
"NAMES": {
handler: namesHandler,
minParams: 0,
},
"NICK": {
handler: nickHandler,
usablePreReg: true,
minParams: 1,
},
"NOTICE": {
2019-12-23 21:26:37 +01:00
handler: messageHandler,
minParams: 2,
allowedInBatch: true,
},
"NPC": {
handler: npcHandler,
minParams: 3,
},
"NPCA": {
handler: npcaHandler,
minParams: 3,
},
"OPER": {
handler: operHandler,
2019-12-18 21:44:06 +01:00
minParams: 1,
},
"PART": {
handler: partHandler,
minParams: 1,
},
"PASS": {
handler: passHandler,
usablePreReg: true,
minParams: 1,
},
"PING": {
handler: pingHandler,
usablePreReg: true,
minParams: 1,
leaveClientIdle: true,
},
"PONG": {
handler: pongHandler,
usablePreReg: true,
minParams: 1,
leaveClientIdle: true,
},
"PRIVMSG": {
2019-12-23 21:26:37 +01:00
handler: messageHandler,
minParams: 2,
allowedInBatch: true,
},
"RENAME": {
handler: renameHandler,
minParams: 2,
},
"RESUME": {
handler: resumeHandler,
usablePreReg: true,
minParams: 1,
},
"SAJOIN": {
handler: sajoinHandler,
minParams: 1,
capabs: []string{"sajoin"},
},
"SANICK": {
handler: sanickHandler,
minParams: 2,
oper: true,
},
"SAMODE": {
handler: modeHandler,
minParams: 1,
capabs: []string{"samode"},
},
"SCENE": {
handler: sceneHandler,
minParams: 2,
},
2019-02-13 14:22:16 +01:00
"SETNAME": {
handler: setnameHandler,
minParams: 1,
},
2020-06-02 15:57:51 +02:00
"SUMMON": {
handler: summonHandler,
},
"TAGMSG": {
2019-03-19 08:35:49 +01:00
handler: messageHandler,
minParams: 1,
},
"QUIT": {
handler: quitHandler,
usablePreReg: true,
minParams: 0,
},
"REHASH": {
handler: rehashHandler,
minParams: 0,
oper: true,
2020-03-18 10:42:52 +01:00
capabs: []string{"rehash"},
},
"TIME": {
handler: timeHandler,
minParams: 0,
},
"TOPIC": {
handler: topicHandler,
minParams: 1,
},
"UNDLINE": {
handler: unDLineHandler,
minParams: 1,
oper: true,
},
"UNKLINE": {
handler: unKLineHandler,
minParams: 1,
oper: true,
},
"USER": {
handler: userHandler,
usablePreReg: true,
minParams: 4,
},
"USERHOST": {
handler: userhostHandler,
minParams: 1,
},
2020-06-02 15:57:51 +02:00
"USERS": {
handler: usersHandler,
},
"VERSION": {
handler: versionHandler,
minParams: 0,
},
"WEBIRC": {
handler: webircHandler,
usablePreReg: true,
minParams: 4,
},
"WHO": {
handler: whoHandler,
minParams: 1,
leaveClientIdle: true,
},
"WHOIS": {
handler: whoisHandler,
minParams: 1,
},
"WHOWAS": {
handler: whowasHandler,
minParams: 1,
},
2019-05-21 01:08:57 +02:00
"ZNC": {
handler: zncHandler,
minParams: 1,
},
}
2018-04-19 08:48:19 +02:00
initializeServices()
}