2012-04-18 03:16:57 +02:00
|
|
|
package irc
|
|
|
|
|
2012-12-09 21:51:50 +01:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type Command interface {
|
2012-12-13 08:27:17 +01:00
|
|
|
Client() *Client
|
2012-12-15 23:34:20 +01:00
|
|
|
SetClient(*Client)
|
|
|
|
Handle(*Server)
|
2012-04-18 05:24:26 +02:00
|
|
|
}
|
|
|
|
|
2012-12-09 21:51:50 +01:00
|
|
|
var (
|
2012-12-15 23:34:20 +01:00
|
|
|
NotEnoughArgsError = errors.New("not enough arguments")
|
2012-12-09 21:51:50 +01:00
|
|
|
)
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type BaseCommand struct {
|
2012-12-13 08:27:17 +01:00
|
|
|
client *Client
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func (base *BaseCommand) Client() *Client {
|
|
|
|
return base.client
|
2012-12-13 08:27:17 +01:00
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func (base *BaseCommand) SetClient(c *Client) {
|
|
|
|
base.client = c
|
2012-12-13 08:27:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// unknown <command> [args...]
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type UnknownCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
command string
|
2012-12-12 07:34:22 +01:00
|
|
|
args []string
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewUnknownCommand(command string, args []string) Command {
|
|
|
|
return &UnknownCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
|
|
|
command: command,
|
|
|
|
args: args,
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func (m *UnknownCommand) Handle(s *Server) {
|
|
|
|
m.Client().replies <- ErrUnknownCommand(s, m.command)
|
2012-12-09 07:54:58 +01:00
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// PING <server1> [ <server2> ]
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type PingCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
server string
|
|
|
|
server2 string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewPingCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) < 1 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
msg := &PingCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
server: args[0],
|
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 1 {
|
|
|
|
msg.server2 = args[1]
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// PONG <server> [ <server2> ]
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type PongCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
server1 string
|
|
|
|
server2 string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewPongCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) < 1 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
message := &PongCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
|
|
|
server1: args[0],
|
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 1 {
|
|
|
|
message.server2 = args[1]
|
|
|
|
}
|
|
|
|
return message, nil
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:24:53 +01:00
|
|
|
// PASS <password>
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type PassCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-10 05:24:53 +01:00
|
|
|
password string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewPassCommand(args []string) (Command, error) {
|
2012-12-10 05:24:53 +01:00
|
|
|
if len(args) < 1 {
|
|
|
|
return nil, NotEnoughArgsError
|
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
return &PassCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
password: args[0],
|
2012-12-12 07:34:22 +01:00
|
|
|
}, nil
|
2012-12-10 05:24:53 +01:00
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// NICK <nickname>
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type NickCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
nickname string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewNickCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) != 1 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
return &NickCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
nickname: args[0],
|
|
|
|
}, nil
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// USER <user> <mode> <unused> <realname>
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type UserCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
user string
|
|
|
|
mode uint8
|
|
|
|
unused string
|
|
|
|
realname string
|
2012-04-18 03:16:57 +02:00
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewUserCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) != 4 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
msg := &UserCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
user: args[0],
|
|
|
|
unused: args[2],
|
|
|
|
realname: args[3],
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
|
|
|
mode, err := strconv.ParseUint(args[1], 10, 8)
|
|
|
|
if err == nil {
|
|
|
|
msg.mode = uint8(mode)
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
// QUIT [ <Quit Command> ]
|
2012-04-18 03:16:57 +02:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type QuitCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
message string
|
2012-04-18 03:16:57 +02:00
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewQuitCommand(args []string) (Command, error) {
|
|
|
|
msg := &QuitCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 0 {
|
|
|
|
msg.message = args[0]
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-10 05:24:53 +01:00
|
|
|
// JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type JoinCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
channels []string
|
|
|
|
keys []string
|
|
|
|
zero bool
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewJoinCommand(args []string) (Command, error) {
|
|
|
|
msg := &JoinCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 0 {
|
|
|
|
if args[0] == "0" {
|
|
|
|
msg.zero = true
|
|
|
|
} else {
|
|
|
|
msg.channels = strings.Split(args[0], ",")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(args) > 1 {
|
|
|
|
msg.keys = strings.Split(args[1], ",")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
// PART <channel> *( "," <channel> ) [ <Part Command> ]
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type PartCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
channels []string
|
|
|
|
message string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewPartCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) < 1 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
msg := &PartCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
channels: strings.Split(args[0], ","),
|
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 1 {
|
|
|
|
msg.message = args[1]
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// PRIVMSG <target> <message>
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type PrivMsgCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
target string
|
|
|
|
message string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewPrivMsgCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) < 2 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
return &PrivMsgCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
target: args[0],
|
|
|
|
message: args[1],
|
2012-12-09 21:51:50 +01:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func (m *PrivMsgCommand) TargetIsChannel() bool {
|
2012-12-09 07:54:58 +01:00
|
|
|
switch m.target[0] {
|
|
|
|
case '&', '#', '+', '!':
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2012-12-09 23:59:28 +01:00
|
|
|
// TOPIC [newtopic]
|
2012-12-09 07:54:58 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type TopicCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-09 07:54:58 +01:00
|
|
|
channel string
|
|
|
|
topic string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewTopicCommand(args []string) (Command, error) {
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) < 1 {
|
2012-12-10 05:24:53 +01:00
|
|
|
return nil, NotEnoughArgsError
|
2012-12-09 21:51:50 +01:00
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
msg := &TopicCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
channel: args[0],
|
|
|
|
}
|
2012-12-09 21:51:50 +01:00
|
|
|
if len(args) > 1 {
|
|
|
|
msg.topic = args[1]
|
|
|
|
}
|
|
|
|
return msg, nil
|
|
|
|
}
|
|
|
|
|
2012-12-13 08:27:17 +01:00
|
|
|
// LOGIN <nick> <password>
|
2012-12-10 05:24:53 +01:00
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
type LoginCommand struct {
|
|
|
|
*BaseCommand
|
2012-12-13 08:27:17 +01:00
|
|
|
nick string
|
2012-12-10 05:24:53 +01:00
|
|
|
password string
|
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
func NewLoginCommand(args []string) (Command, error) {
|
2012-12-10 05:24:53 +01:00
|
|
|
if len(args) < 2 {
|
|
|
|
return nil, NotEnoughArgsError
|
|
|
|
}
|
2012-12-15 23:34:20 +01:00
|
|
|
return &LoginCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
2012-12-13 08:27:17 +01:00
|
|
|
nick: args[0],
|
|
|
|
password: args[1],
|
2012-12-12 07:34:22 +01:00
|
|
|
}, nil
|
2012-12-10 05:24:53 +01:00
|
|
|
}
|
|
|
|
|
2012-12-15 23:34:20 +01:00
|
|
|
// RESERVE <nick> <password>
|
|
|
|
|
|
|
|
type ReserveCommand struct {
|
|
|
|
*BaseCommand
|
|
|
|
nick string
|
|
|
|
password string
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewReserveCommand(args []string) (Command, error) {
|
|
|
|
if len(args) < 2 {
|
|
|
|
return nil, NotEnoughArgsError
|
|
|
|
}
|
|
|
|
return &ReserveCommand{
|
|
|
|
BaseCommand: &BaseCommand{},
|
|
|
|
nick: args[0],
|
|
|
|
password: args[1],
|
|
|
|
}, nil
|
2012-12-10 05:24:53 +01:00
|
|
|
}
|