mirror of
https://github.com/shazow/ssh-chat.git
synced 2025-04-13 07:37:17 +03:00
CommandHandler func -> Command struct
This commit is contained in:
parent
6f7410c7a0
commit
fb7cd83821
175
chat/command.go
175
chat/command.go
@ -18,52 +18,59 @@ var ErrNoOwner = errors.New("command without owner")
|
||||
// of arguments.
|
||||
var ErrMissingArg = errors.New("missing argument")
|
||||
|
||||
// CommandHandler is the function signature for command handlers..
|
||||
type CommandHandler func(*Channel, CommandMsg) error
|
||||
// The error returned when a command is added without a prefix.
|
||||
var ErrMissingPrefix = errors.New("command missing prefix")
|
||||
|
||||
// Command is a definition of a handler for a command.
|
||||
type Command struct {
|
||||
Prefix string
|
||||
PrefixHelp string
|
||||
Help string
|
||||
Handler func(*Channel, CommandMsg) error
|
||||
}
|
||||
|
||||
// Commands is a registry of available commands.
|
||||
type Commands struct {
|
||||
handlers map[string]CommandHandler
|
||||
help map[string]string
|
||||
commands map[string]Command
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// NewCommands returns a new Commands registry.
|
||||
func NewCommands() *Commands {
|
||||
return &Commands{
|
||||
handlers: map[string]CommandHandler{},
|
||||
help: map[string]string{},
|
||||
commands: map[string]Command{},
|
||||
}
|
||||
}
|
||||
|
||||
// Add will register a command. If help string is empty, it will be hidden from
|
||||
// Help().
|
||||
func (c Commands) Add(command string, help string, handler CommandHandler) {
|
||||
func (c *Commands) Add(cmd Command) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.handlers[command] = handler
|
||||
|
||||
if help != "" {
|
||||
c.help[command] = help
|
||||
if cmd.Prefix == "" {
|
||||
return ErrMissingPrefix
|
||||
}
|
||||
|
||||
c.commands[cmd.Prefix] = cmd
|
||||
return nil
|
||||
}
|
||||
|
||||
// Alias will add another command for the same handler, won't get added to help.
|
||||
func (c Commands) Alias(command string, alias string) error {
|
||||
func (c *Commands) Alias(command string, alias string) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
handler, ok := c.handlers[command]
|
||||
cmd, ok := c.commands[command]
|
||||
if !ok {
|
||||
return ErrInvalidCommand
|
||||
}
|
||||
c.handlers[alias] = handler
|
||||
c.commands[alias] = cmd
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a command message.
|
||||
func (c Commands) Run(channel *Channel, msg CommandMsg) error {
|
||||
func (c *Commands) Run(channel *Channel, msg CommandMsg) error {
|
||||
if msg.From == nil {
|
||||
return ErrNoOwner
|
||||
}
|
||||
@ -71,22 +78,22 @@ func (c Commands) Run(channel *Channel, msg CommandMsg) error {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
handler, ok := c.handlers[msg.Command()]
|
||||
cmd, ok := c.commands[msg.Command()]
|
||||
if !ok {
|
||||
return ErrInvalidCommand
|
||||
}
|
||||
|
||||
return handler(channel, msg)
|
||||
return cmd.Handler(channel, msg)
|
||||
}
|
||||
|
||||
// Help will return collated help text as one string.
|
||||
func (c Commands) Help() string {
|
||||
func (c *Commands) Help() string {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
r := []string{}
|
||||
for cmd, line := range c.help {
|
||||
r = append(r, fmt.Sprintf("%s %s", cmd, line))
|
||||
for _, cmd := range c.commands {
|
||||
r = append(r, fmt.Sprintf("%s %s - %s", cmd.Prefix, cmd.PrefixHelp, cmd.Help))
|
||||
}
|
||||
sort.Strings(r)
|
||||
|
||||
@ -98,75 +105,99 @@ var defaultCmdHandlers *Commands
|
||||
func init() {
|
||||
c := NewCommands()
|
||||
|
||||
c.Add("/help", "", func(channel *Channel, msg CommandMsg) error {
|
||||
channel.Send(NewSystemMsg("Available commands:"+Newline+c.Help(), msg.From()))
|
||||
return nil
|
||||
c.Add(Command{
|
||||
Prefix: "/help",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
channel.Send(NewSystemMsg("Available commands:"+Newline+c.Help(), msg.From()))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
c.Add("/me", "", func(channel *Channel, msg CommandMsg) error {
|
||||
me := strings.TrimLeft(msg.body, "/me")
|
||||
if me == "" {
|
||||
me = " is at a loss for words."
|
||||
} else {
|
||||
me = me[1:]
|
||||
}
|
||||
c.Add(Command{
|
||||
Prefix: "/me",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
me := strings.TrimLeft(msg.body, "/me")
|
||||
if me == "" {
|
||||
me = " is at a loss for words."
|
||||
} else {
|
||||
me = me[1:]
|
||||
}
|
||||
|
||||
channel.Send(NewEmoteMsg(me, msg.From()))
|
||||
return nil
|
||||
channel.Send(NewEmoteMsg(me, msg.From()))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
c.Add("/exit", "- Exit the chat.", func(channel *Channel, msg CommandMsg) error {
|
||||
msg.From().Close()
|
||||
return nil
|
||||
c.Add(Command{
|
||||
Prefix: "/exit",
|
||||
Help: "Exit the chat.",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
msg.From().Close()
|
||||
return nil
|
||||
},
|
||||
})
|
||||
c.Alias("/exit", "/quit")
|
||||
|
||||
c.Add("/nick", "NAME - Rename yourself.", func(channel *Channel, msg CommandMsg) error {
|
||||
args := msg.Args()
|
||||
if len(args) != 1 {
|
||||
return ErrMissingArg
|
||||
}
|
||||
u := msg.From()
|
||||
oldName := u.Name()
|
||||
u.SetName(args[0])
|
||||
c.Add(Command{
|
||||
Prefix: "/nick",
|
||||
PrefixHelp: "NAME",
|
||||
Help: "Rename yourself.",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
args := msg.Args()
|
||||
if len(args) != 1 {
|
||||
return ErrMissingArg
|
||||
}
|
||||
u := msg.From()
|
||||
oldName := u.Name()
|
||||
u.SetName(args[0])
|
||||
|
||||
body := fmt.Sprintf("%s is now known as %s.", oldName, u.Name())
|
||||
channel.Send(NewAnnounceMsg(body))
|
||||
return nil
|
||||
body := fmt.Sprintf("%s is now known as %s.", oldName, u.Name())
|
||||
channel.Send(NewAnnounceMsg(body))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
c.Add("/names", "- List users who are connected.", func(channel *Channel, msg CommandMsg) error {
|
||||
// TODO: colorize
|
||||
names := channel.NamesPrefix("")
|
||||
body := fmt.Sprintf("%d connected: %s", len(names), strings.Join(names, ", "))
|
||||
channel.Send(NewSystemMsg(body, msg.From()))
|
||||
return nil
|
||||
c.Add(Command{
|
||||
Prefix: "/names",
|
||||
Help: "List users who are connected.",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
// TODO: colorize
|
||||
names := channel.NamesPrefix("")
|
||||
body := fmt.Sprintf("%d connected: %s", len(names), strings.Join(names, ", "))
|
||||
channel.Send(NewSystemMsg(body, msg.From()))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
c.Alias("/names", "/list")
|
||||
|
||||
c.Add("/theme", "[mono|colors] - Set your color theme.", func(channel *Channel, msg CommandMsg) error {
|
||||
user := msg.From()
|
||||
args := msg.Args()
|
||||
if len(args) == 0 {
|
||||
theme := "plain"
|
||||
if user.Config.Theme != nil {
|
||||
theme = user.Config.Theme.Id()
|
||||
}
|
||||
body := fmt.Sprintf("Current theme: %s", theme)
|
||||
channel.Send(NewSystemMsg(body, user))
|
||||
return nil
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
for _, t := range Themes {
|
||||
if t.Id() == id {
|
||||
user.Config.Theme = &t
|
||||
body := fmt.Sprintf("Set theme: %s", id)
|
||||
c.Add(Command{
|
||||
Prefix: "/theme",
|
||||
PrefixHelp: "[mono|colors]",
|
||||
Help: "Set your color theme.",
|
||||
Handler: func(channel *Channel, msg CommandMsg) error {
|
||||
user := msg.From()
|
||||
args := msg.Args()
|
||||
if len(args) == 0 {
|
||||
theme := "plain"
|
||||
if user.Config.Theme != nil {
|
||||
theme = user.Config.Theme.Id()
|
||||
}
|
||||
body := fmt.Sprintf("Current theme: %s", theme)
|
||||
channel.Send(NewSystemMsg(body, user))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("theme not found")
|
||||
|
||||
id := args[0]
|
||||
for _, t := range Themes {
|
||||
if t.Id() == id {
|
||||
user.Config.Theme = &t
|
||||
body := fmt.Sprintf("Set theme: %s", id)
|
||||
channel.Send(NewSystemMsg(body, user))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("theme not found")
|
||||
},
|
||||
})
|
||||
|
||||
defaultCmdHandlers = c
|
||||
|
Loading…
x
Reference in New Issue
Block a user