ircd/irc/commands.go

928 lines
17 KiB
Go
Raw Normal View History

// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
// Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package irc
2012-12-09 20:51:50 +00:00
import (
"errors"
2013-05-11 20:55:01 +00:00
"fmt"
"regexp"
2012-12-09 20:51:50 +00:00
"strconv"
"strings"
)
type Command interface {
Client() *Client
Code() StringCode
SetClient(*Client)
SetCode(StringCode)
}
type checkPasswordCommand interface {
LoadPassword(*Server)
CheckPassword()
}
2014-03-08 22:24:17 +00:00
type parseCommandFunc func([]string) (Command, error)
var (
2013-05-09 18:05:10 +00:00
NotEnoughArgsError = errors.New("not enough arguments")
ErrParseCommand = errors.New("failed to parse message")
2014-02-17 07:29:11 +00:00
parseCommandFuncs = map[StringCode]parseCommandFunc{
AWAY: ParseAwayCommand,
CAP: ParseCapCommand,
DEBUG: ParseDebugCommand,
INVITE: ParseInviteCommand,
ISON: ParseIsOnCommand,
JOIN: ParseJoinCommand,
KICK: ParseKickCommand,
KILL: ParseKillCommand,
LIST: ParseListCommand,
MODE: ParseModeCommand,
MOTD: ParseMOTDCommand,
NAMES: ParseNamesCommand,
NICK: ParseNickCommand,
NOTICE: ParseNoticeCommand,
ONICK: ParseOperNickCommand,
OPER: ParseOperCommand,
PART: ParsePartCommand,
PASS: ParsePassCommand,
PING: ParsePingCommand,
PONG: ParsePongCommand,
PRIVMSG: ParsePrivMsgCommand,
PROXY: ParseProxyCommand,
QUIT: ParseQuitCommand,
THEATER: ParseTheaterCommand, // nonstandard
TIME: ParseTimeCommand,
TOPIC: ParseTopicCommand,
USER: ParseUserCommand,
VERSION: ParseVersionCommand,
WHO: ParseWhoCommand,
WHOIS: ParseWhoisCommand,
WHOWAS: ParseWhoWasCommand,
}
commandMinimumArgs = map[StringCode]int{
AWAY: 0,
CAP: 1,
DEBUG: 1,
INVITE: 2,
ISON: 1,
JOIN: 1,
KICK: 2,
KILL: 2,
LIST: 0,
MODE: 1,
MOTD: 0,
NAMES: 0,
NICK: 1,
NOTICE: 2,
ONICK: 2,
OPER: 2,
PART: 1,
PASS: 1,
PING: 1,
PONG: 1,
PRIVMSG: 2,
PROXY: 5,
QUIT: 0,
THEATER: 1,
TIME: 0,
TOPIC: 1,
USER: 4,
VERSION: 0,
WHO: 0,
WHOIS: 1,
WHOWAS: 1,
}
)
2013-05-09 18:05:10 +00:00
type BaseCommand struct {
client *Client
2014-02-17 07:29:11 +00:00
code StringCode
2013-05-09 18:05:10 +00:00
}
func (command *BaseCommand) Client() *Client {
2013-05-11 20:55:01 +00:00
return command.client
2013-05-09 18:05:10 +00:00
}
func (command *BaseCommand) SetClient(client *Client) {
command.client = client
2013-05-09 18:05:10 +00:00
}
2014-02-17 07:29:11 +00:00
func (command *BaseCommand) Code() StringCode {
return command.code
2014-02-15 02:28:36 +00:00
}
2014-02-17 07:29:11 +00:00
func (command *BaseCommand) SetCode(code StringCode) {
command.code = code
2014-02-15 02:28:36 +00:00
}
type NeedMoreParamsCommand struct {
BaseCommand
code StringCode
}
func ParseNeedMoreParams(code StringCode) *NeedMoreParamsCommand {
return &NeedMoreParamsCommand{
code: code,
}
}
2014-03-08 22:24:17 +00:00
func ParseCommand(line string) (cmd Command, err error) {
2014-02-28 05:18:05 +00:00
code, args := ParseLine(line)
2014-02-17 07:29:11 +00:00
constructor := parseCommandFuncs[code]
minArgs := commandMinimumArgs[code]
if constructor == nil {
cmd = ParseUnknownCommand(args)
} else if len(args) < minArgs {
cmd = ParseNeedMoreParams(code)
2014-02-15 02:28:36 +00:00
} else {
cmd, err = constructor(args)
// if NotEnoughArgsError was returned in the command handler itself
if err == NotEnoughArgsError {
cmd = ParseNeedMoreParams(code)
err = nil
}
}
2014-02-15 02:28:36 +00:00
if cmd != nil {
2014-02-17 07:29:11 +00:00
cmd.SetCode(code)
2014-02-15 02:28:36 +00:00
}
return
}
var (
spacesExpr = regexp.MustCompile(` +`)
)
2014-02-28 05:18:05 +00:00
func splitArg(line string) (arg string, rest string) {
parts := spacesExpr.Split(line, 2)
if len(parts) > 0 {
arg = parts[0]
}
if len(parts) > 1 {
rest = parts[1]
}
return
}
func ParseLine(line string) (command StringCode, args []string) {
args = make([]string, 0)
if strings.HasPrefix(line, ":") {
_, line = splitArg(line)
2014-02-17 06:22:46 +00:00
}
2014-02-28 05:18:05 +00:00
arg, line := splitArg(line)
2014-03-09 20:45:36 +00:00
command = StringCode(NewName(strings.ToUpper(arg)))
2014-02-28 05:18:05 +00:00
for len(line) > 0 {
if strings.HasPrefix(line, ":") {
2014-03-09 20:45:36 +00:00
args = append(args, line[len(":"):])
2014-02-28 05:18:05 +00:00
break
}
arg, line = splitArg(line)
2014-03-09 20:45:36 +00:00
args = append(args, arg)
2014-02-28 05:18:05 +00:00
}
return
}
// <command> [args...]
type UnknownCommand struct {
BaseCommand
2014-02-15 02:28:36 +00:00
args []string
}
func ParseUnknownCommand(args []string) *UnknownCommand {
return &UnknownCommand{
2014-02-15 02:28:36 +00:00
args: args,
}
}
2012-12-09 20:51:50 +00:00
2012-12-13 07:27:17 +00:00
// PING <server1> [ <server2> ]
type PingCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
server Name
server2 Name
}
func ParsePingCommand(args []string) (Command, error) {
msg := &PingCommand{
2014-03-09 20:45:36 +00:00
server: NewName(args[0]),
2012-12-13 07:27:17 +00:00
}
2012-12-09 20:51:50 +00:00
if len(args) > 1 {
2014-03-09 20:45:36 +00:00
msg.server2 = NewName(args[1])
2012-12-09 20:51:50 +00:00
}
return msg, nil
}
2012-12-13 07:27:17 +00:00
// PONG <server> [ <server2> ]
type PongCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
server1 Name
server2 Name
}
func ParsePongCommand(args []string) (Command, error) {
message := &PongCommand{
2014-03-09 20:45:36 +00:00
server1: NewName(args[0]),
}
2012-12-09 20:51:50 +00:00
if len(args) > 1 {
2014-03-09 20:45:36 +00:00
message.server2 = NewName(args[1])
2012-12-09 20:51:50 +00:00
}
return message, nil
}
2012-12-10 04:24:53 +00:00
// PASS <password>
type PassCommand struct {
BaseCommand
hash []byte
password []byte
err error
2012-12-10 04:24:53 +00:00
}
func (cmd *PassCommand) LoadPassword(server *Server) {
cmd.hash = server.password
}
func (cmd *PassCommand) CheckPassword() {
if cmd.hash == nil {
return
}
cmd.err = ComparePassword(cmd.hash, cmd.password)
}
func ParsePassCommand(args []string) (Command, error) {
return &PassCommand{
password: []byte(args[0]),
}, nil
2012-12-10 04:24:53 +00:00
}
2012-12-13 07:27:17 +00:00
// NICK <nickname>
func ParseNickCommand(args []string) (Command, error) {
return &NickCommand{
2014-03-09 20:45:36 +00:00
nickname: NewName(args[0]),
2012-12-13 07:27:17 +00:00
}, nil
2012-12-09 20:51:50 +00:00
}
type UserCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
username Name
realname Text
}
func ParseUserCommand(args []string) (Command, error) {
return &UserCommand{
username: NewName(args[0]),
realname: NewText(args[3]),
}, nil
2012-12-09 20:51:50 +00:00
}
// QUIT [ <Quit Command> ]
type QuitCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
message Text
}
func NewQuitCommand(message Text) *QuitCommand {
cmd := &QuitCommand{
message: message,
}
cmd.code = QUIT
return cmd
2013-05-11 20:55:01 +00:00
}
func ParseQuitCommand(args []string) (Command, error) {
2013-06-03 05:07:50 +00:00
msg := &QuitCommand{}
2012-12-09 20:51:50 +00:00
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
msg.message = NewText(args[0])
2012-12-09 20:51:50 +00:00
}
return msg, nil
}
2012-12-10 04:24:53 +00:00
// JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
type JoinCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channels map[Name]Text
zero bool
}
func ParseJoinCommand(args []string) (Command, error) {
msg := &JoinCommand{
2014-03-09 20:45:36 +00:00
channels: make(map[Name]Text),
}
if args[0] == "0" {
msg.zero = true
return msg, nil
}
channels := strings.Split(args[0], ",")
keys := make([]string, len(channels))
if len(args) > 1 {
for i, key := range strings.Split(args[1], ",") {
2015-06-07 01:26:28 +00:00
if i >= len(channels) {
break
}
keys[i] = key
2012-12-09 20:51:50 +00:00
}
}
for i, channel := range channels {
2014-03-09 20:45:36 +00:00
msg.channels[NewName(channel)] = NewText(keys[i])
}
2012-12-09 20:51:50 +00:00
return msg, nil
}
// PART <channel> *( "," <channel> ) [ <Part Command> ]
type PartCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channels []Name
message Text
}
2014-03-09 20:45:36 +00:00
func (cmd *PartCommand) Message() Text {
2014-02-09 01:53:06 +00:00
if cmd.message == "" {
2014-03-09 20:45:36 +00:00
return cmd.Client().Nick().Text()
2014-02-09 01:53:06 +00:00
}
return cmd.message
}
func ParsePartCommand(args []string) (Command, error) {
msg := &PartCommand{
2014-03-09 20:45:36 +00:00
channels: NewNames(strings.Split(args[0], ",")),
2012-12-13 07:27:17 +00:00
}
2012-12-09 20:51:50 +00:00
if len(args) > 1 {
2014-03-09 20:45:36 +00:00
msg.message = NewText(args[1])
2012-12-09 20:51:50 +00:00
}
return msg, nil
}
2012-12-13 07:27:17 +00:00
// PRIVMSG <target> <message>
type PrivMsgCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
message Text
}
func ParsePrivMsgCommand(args []string) (Command, error) {
return &PrivMsgCommand{
2014-03-09 20:45:36 +00:00
target: NewName(args[0]),
message: NewText(args[1]),
2012-12-09 20:51:50 +00:00
}, nil
}
2012-12-09 22:59:28 +00:00
// TOPIC [newtopic]
type TopicCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channel Name
setTopic bool
2014-03-09 20:45:36 +00:00
topic Text
}
func ParseTopicCommand(args []string) (Command, error) {
msg := &TopicCommand{
2014-03-09 20:45:36 +00:00
channel: NewName(args[0]),
2012-12-13 07:27:17 +00:00
}
2012-12-09 20:51:50 +00:00
if len(args) > 1 {
msg.setTopic = true
2014-03-09 20:45:36 +00:00
msg.topic = NewText(args[1])
2012-12-09 20:51:50 +00:00
}
return msg, nil
}
type ModeChange struct {
mode UserMode
2014-02-09 06:42:14 +00:00
op ModeOp
}
func (change *ModeChange) String() string {
2014-02-09 06:42:14 +00:00
return fmt.Sprintf("%s%s", change.op, change.mode)
}
type ModeChanges []*ModeChange
func (changes ModeChanges) String() string {
if len(changes) == 0 {
return ""
}
op := changes[0].op
str := changes[0].op.String()
for _, change := range changes {
2016-04-14 08:41:58 +00:00
if change.op != op {
op = change.op
2016-04-14 08:41:58 +00:00
str += change.op.String()
}
2016-04-14 08:41:58 +00:00
str += change.mode.String()
}
return str
}
type ModeCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
nickname Name
2014-02-18 17:45:10 +00:00
changes ModeChanges
2012-12-10 04:24:53 +00:00
}
2016-04-14 08:41:58 +00:00
// MODE <nickname> ( "+" / "-" )? *( "+" / "-" / <mode character> )
func ParseUserModeCommand(nickname Name, args []string) (Command, error) {
2014-02-09 06:42:14 +00:00
cmd := &ModeCommand{
2014-03-09 20:45:36 +00:00
nickname: nickname,
2014-02-18 17:45:10 +00:00
changes: make(ModeChanges, 0),
2014-02-09 06:42:14 +00:00
}
// account for MODE command with no args to list things
if len(args) < 1 {
// don't do any further processing
return cmd, nil
}
2014-02-09 06:42:14 +00:00
modeArg := args[0]
op := ModeOp(modeArg[0])
if (op == Add) || (op == Remove) {
modeArg = modeArg[1:]
} else {
return nil, ErrParseCommand
}
for _, mode := range modeArg {
if mode == '-' || mode == '+' {
op = ModeOp(mode)
continue
2014-02-09 06:42:14 +00:00
}
cmd.changes = append(cmd.changes, &ModeChange{
mode: UserMode(mode),
op: op,
})
2014-02-09 06:42:14 +00:00
}
return cmd, nil
}
type ChannelModeChange struct {
mode ChannelMode
op ModeOp
arg string
}
2014-02-17 19:46:40 +00:00
func (change *ChannelModeChange) String() (str string) {
if (change.op == Add) || (change.op == Remove) {
str = change.op.String()
}
str += change.mode.String()
if change.arg != "" {
str += " " + change.arg
}
return
}
type ChannelModeChanges []*ChannelModeChange
2016-04-14 08:41:58 +00:00
func (changes ChannelModeChanges) String() string {
if len(changes) == 0 {
2016-04-14 08:41:58 +00:00
return ""
}
2016-04-14 08:41:58 +00:00
op := changes[0].op
str := changes[0].op.String()
for _, change := range changes {
2016-04-14 08:41:58 +00:00
if change.op != op {
op = change.op
str += change.op.String()
}
str += change.mode.String()
}
2016-04-14 08:41:58 +00:00
for _, change := range changes {
2014-02-17 19:46:40 +00:00
if change.arg == "" {
continue
}
str += " " + change.arg
}
2016-04-14 08:41:58 +00:00
return str
}
2014-02-09 02:14:39 +00:00
type ChannelModeCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channel Name
changes ChannelModeChanges
2014-02-09 02:14:39 +00:00
}
2016-04-14 08:41:58 +00:00
// MODE <channel> ( "+" / "-" )? *( "+" / "-" / <mode character> ) *<modeparams>
func ParseChannelModeCommand(channel Name, args []string) (Command, error) {
2014-02-09 02:14:39 +00:00
cmd := &ChannelModeCommand{
2014-03-09 20:45:36 +00:00
channel: channel,
changes: make(ChannelModeChanges, 0),
}
// account for MODE command with no args to list things
if len(args) < 1 {
// don't do any further processing
return cmd, nil
}
modeArg := args[0]
op := ModeOp(modeArg[0])
if (op == Add) || (op == Remove) {
modeArg = modeArg[1:]
} else {
return nil, ErrParseCommand
}
currentArgIndex := 1
for _, mode := range modeArg {
if mode == '-' || mode == '+' {
op = ModeOp(mode)
continue
}
change := &ChannelModeChange{
mode: ChannelMode(mode),
op: op,
}
switch change.mode {
// TODO(dan): separate this into the type A/B/C/D args and use those lists here
case Key, BanMask, ExceptMask, InviteMask, UserLimit,
ChannelOperator, ChannelFounder, ChannelAdmin, Halfop, Voice:
if len(args) > currentArgIndex {
change.arg = args[currentArgIndex]
currentArgIndex++
} else {
// silently skip this mode
2016-04-14 08:41:58 +00:00
continue
}
}
cmd.changes = append(cmd.changes, change)
2012-12-10 04:24:53 +00:00
}
2014-02-09 02:14:39 +00:00
return cmd, nil
}
func ParseModeCommand(args []string) (Command, error) {
2014-03-09 20:45:36 +00:00
name := NewName(args[0])
if name.IsChannel() {
return ParseChannelModeCommand(name, args[1:])
2014-02-09 02:14:39 +00:00
} else {
return ParseUserModeCommand(name, args[1:])
2014-02-09 02:14:39 +00:00
}
}
2014-02-09 01:43:59 +00:00
type WhoisCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
masks []Name
2014-02-09 01:43:59 +00:00
}
2014-02-09 02:49:52 +00:00
// WHOIS [ <target> ] <mask> *( "," <mask> )
func ParseWhoisCommand(args []string) (Command, error) {
2014-02-09 01:43:59 +00:00
var masks string
var target string
if len(args) > 1 {
target = args[0]
masks = args[1]
} else {
masks = args[0]
}
return &WhoisCommand{
2014-03-09 20:45:36 +00:00
target: NewName(target),
masks: NewNames(strings.Split(masks, ",")),
2014-02-09 01:43:59 +00:00
}, nil
}
2014-02-09 02:49:52 +00:00
type WhoCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
mask Name
2014-02-09 02:49:52 +00:00
operatorOnly bool
}
// WHO [ <mask> [ "o" ] ]
func ParseWhoCommand(args []string) (Command, error) {
2014-02-09 02:49:52 +00:00
cmd := &WhoCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.mask = NewName(args[0])
2014-02-09 02:49:52 +00:00
}
if (len(args) > 1) && (args[1] == "o") {
cmd.operatorOnly = true
}
return cmd, nil
}
2014-02-09 18:07:40 +00:00
type OperCommand struct {
PassCommand
2014-03-09 20:45:36 +00:00
name Name
2014-02-09 18:07:40 +00:00
}
func (msg *OperCommand) LoadPassword(server *Server) {
msg.hash = server.operators[msg.name]
}
2014-02-09 18:07:40 +00:00
// OPER <name> <password>
func ParseOperCommand(args []string) (Command, error) {
cmd := &OperCommand{
2014-03-09 20:45:36 +00:00
name: NewName(args[0]),
}
cmd.password = []byte(args[1])
return cmd, nil
2014-02-09 18:07:40 +00:00
}
2014-02-10 19:14:34 +00:00
type CapCommand struct {
BaseCommand
2014-03-02 20:54:48 +00:00
subCommand CapSubCommand
capabilities CapabilitySet
2014-02-10 19:14:34 +00:00
}
func ParseCapCommand(args []string) (Command, error) {
cmd := &CapCommand{
2014-03-02 20:54:48 +00:00
subCommand: CapSubCommand(strings.ToUpper(args[0])),
capabilities: make(CapabilitySet),
}
if len(args) > 1 {
strs := spacesExpr.Split(args[1], -1)
for _, str := range strs {
cmd.capabilities[Capability(str)] = true
}
}
return cmd, nil
2014-02-10 19:14:34 +00:00
}
2014-02-11 02:40:06 +00:00
// HAPROXY support
type ProxyCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
net Name
sourceIP Name
destIP Name
sourcePort Name
destPort Name
hostname Name // looked up in socket thread
2014-02-11 02:40:06 +00:00
}
func NewProxyCommand(hostname Name) *ProxyCommand {
cmd := &ProxyCommand{
hostname: hostname,
}
cmd.code = PROXY
return cmd
2014-02-11 02:40:06 +00:00
}
func ParseProxyCommand(args []string) (Command, error) {
2014-02-11 02:40:06 +00:00
return &ProxyCommand{
2014-03-09 20:45:36 +00:00
net: NewName(args[0]),
sourceIP: NewName(args[1]),
destIP: NewName(args[2]),
sourcePort: NewName(args[3]),
destPort: NewName(args[4]),
hostname: LookupHostname(NewName(args[1])),
2014-02-11 02:40:06 +00:00
}, nil
}
2014-02-11 23:44:58 +00:00
type AwayCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
text Text
2014-02-11 23:44:58 +00:00
}
func ParseAwayCommand(args []string) (Command, error) {
2014-02-11 23:44:58 +00:00
cmd := &AwayCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.text = NewText(args[0])
2014-02-11 23:44:58 +00:00
}
return cmd, nil
}
2014-02-11 23:58:54 +00:00
type IsOnCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
nicks []Name
2014-02-11 23:58:54 +00:00
}
func ParseIsOnCommand(args []string) (Command, error) {
2014-02-11 23:58:54 +00:00
return &IsOnCommand{
2014-03-09 20:45:36 +00:00
nicks: NewNames(args),
2014-02-11 23:58:54 +00:00
}, nil
}
2014-02-12 00:35:32 +00:00
type MOTDCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
2014-02-12 00:35:32 +00:00
}
func ParseMOTDCommand(args []string) (Command, error) {
2014-02-12 00:35:32 +00:00
cmd := &MOTDCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[0])
2014-02-12 00:35:32 +00:00
}
return cmd, nil
}
2014-02-12 01:11:59 +00:00
type NoticeCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
message Text
2014-02-12 01:11:59 +00:00
}
func ParseNoticeCommand(args []string) (Command, error) {
2014-02-12 01:11:59 +00:00
return &NoticeCommand{
2014-03-09 20:45:36 +00:00
target: NewName(args[0]),
message: NewText(args[1]),
2014-02-12 01:11:59 +00:00
}, nil
}
2014-02-17 07:29:11 +00:00
type KickCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
kicks map[Name]Name
comment Text
2014-02-17 07:29:11 +00:00
}
2014-03-09 20:45:36 +00:00
func (msg *KickCommand) Comment() Text {
2014-02-17 07:29:11 +00:00
if msg.comment == "" {
2014-03-09 20:45:36 +00:00
return msg.Client().Nick().Text()
2014-02-17 07:29:11 +00:00
}
return msg.comment
}
func ParseKickCommand(args []string) (Command, error) {
2014-03-09 20:45:36 +00:00
channels := NewNames(strings.Split(args[0], ","))
users := NewNames(strings.Split(args[1], ","))
2014-02-17 07:29:11 +00:00
if (len(channels) != len(users)) && (len(users) != 1) {
return nil, NotEnoughArgsError
}
cmd := &KickCommand{
2014-03-09 20:45:36 +00:00
kicks: make(map[Name]Name),
2014-02-17 07:29:11 +00:00
}
for index, channel := range channels {
if len(users) == 1 {
cmd.kicks[channel] = users[0]
} else {
cmd.kicks[channel] = users[index]
}
}
if len(args) > 2 {
2014-03-09 20:45:36 +00:00
cmd.comment = NewText(args[2])
2014-02-17 07:29:11 +00:00
}
return cmd, nil
}
2014-02-17 07:51:27 +00:00
type ListCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channels []Name
target Name
2014-02-17 07:51:27 +00:00
}
func ParseListCommand(args []string) (Command, error) {
2014-02-17 07:51:27 +00:00
cmd := &ListCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.channels = NewNames(strings.Split(args[0], ","))
2014-02-17 07:51:27 +00:00
}
if len(args) > 1 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[1])
2014-02-17 07:51:27 +00:00
}
return cmd, nil
}
2014-02-18 05:02:03 +00:00
type NamesCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
channels []Name
target Name
2014-02-18 05:02:03 +00:00
}
func ParseNamesCommand(args []string) (Command, error) {
2014-02-18 05:02:03 +00:00
cmd := &NamesCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.channels = NewNames(strings.Split(args[0], ","))
2014-02-18 05:02:03 +00:00
}
if len(args) > 1 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[1])
2014-02-18 05:02:03 +00:00
}
return cmd, nil
}
type DebugCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
subCommand Name
}
func ParseDebugCommand(args []string) (Command, error) {
return &DebugCommand{
2014-03-09 20:45:36 +00:00
subCommand: NewName(strings.ToUpper(args[0])),
}, nil
}
2014-02-25 06:04:11 +00:00
type VersionCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
2014-02-25 06:04:11 +00:00
}
func ParseVersionCommand(args []string) (Command, error) {
2014-02-25 06:04:11 +00:00
cmd := &VersionCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[0])
2014-02-25 06:04:11 +00:00
}
return cmd, nil
}
2014-02-25 15:28:09 +00:00
type InviteCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
nickname Name
channel Name
2014-02-25 15:28:09 +00:00
}
func ParseInviteCommand(args []string) (Command, error) {
2014-02-25 15:28:09 +00:00
return &InviteCommand{
2014-03-09 20:45:36 +00:00
nickname: NewName(args[0]),
channel: NewName(args[1]),
2014-02-25 15:28:09 +00:00
}, nil
}
2014-02-25 15:45:40 +00:00
func ParseTheaterCommand(args []string) (Command, error) {
if upperSubCmd := strings.ToUpper(args[0]); upperSubCmd == "IDENTIFY" && len(args) == 3 {
2014-03-13 08:55:46 +00:00
return &TheaterIdentifyCommand{
channel: NewName(args[1]),
PassCommand: PassCommand{password: []byte(args[2])},
}, nil
} else if upperSubCmd == "PRIVMSG" && len(args) == 4 {
return &TheaterPrivMsgCommand{
channel: NewName(args[1]),
asNick: NewName(args[2]),
message: NewText(args[3]),
}, nil
} else if upperSubCmd == "ACTION" && len(args) == 4 {
return &TheaterActionCommand{
channel: NewName(args[1]),
asNick: NewName(args[2]),
action: NewCTCPText(args[3]),
2014-03-13 08:55:46 +00:00
}, nil
} else {
return nil, ErrParseCommand
}
}
2014-02-25 15:45:40 +00:00
type TimeCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
target Name
2014-02-25 15:45:40 +00:00
}
func ParseTimeCommand(args []string) (Command, error) {
2014-02-25 15:45:40 +00:00
cmd := &TimeCommand{}
if len(args) > 0 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[0])
2014-02-25 15:45:40 +00:00
}
return cmd, nil
}
2014-02-25 17:10:16 +00:00
type KillCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
nickname Name
comment Text
2014-02-25 17:10:16 +00:00
}
func ParseKillCommand(args []string) (Command, error) {
2014-02-25 17:10:16 +00:00
return &KillCommand{
2014-03-09 20:45:36 +00:00
nickname: NewName(args[0]),
comment: NewText(args[1]),
2014-02-25 17:10:16 +00:00
}, nil
}
2014-03-06 20:14:21 +00:00
type WhoWasCommand struct {
BaseCommand
2014-03-09 20:45:36 +00:00
nicknames []Name
2014-03-06 20:14:21 +00:00
count int64
2014-03-09 20:45:36 +00:00
target Name
2014-03-06 20:14:21 +00:00
}
func ParseWhoWasCommand(args []string) (Command, error) {
2014-03-06 20:14:21 +00:00
cmd := &WhoWasCommand{
2014-03-09 20:45:36 +00:00
nicknames: NewNames(strings.Split(args[0], ",")),
2014-03-06 20:14:21 +00:00
}
if len(args) > 1 {
cmd.count, _ = strconv.ParseInt(args[1], 10, 64)
}
if len(args) > 2 {
2014-03-09 20:45:36 +00:00
cmd.target = NewName(args[2])
2014-03-06 20:14:21 +00:00
}
return cmd, nil
}
func ParseOperNickCommand(args []string) (Command, error) {
return &OperNickCommand{
target: NewName(args[0]),
nick: NewName(args[1]),
}, nil
}