Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Commit

Permalink
Add ChannelData to Cmd (#41)
Browse files Browse the repository at this point in the history
This stores a bit more info than just the channel name; in addition you get the protocol (irc, slack, telegram), server host, and whether the channel is a private chat or a public channel.
  • Loading branch information
doenietzomoeilijk authored and fabioxgn committed Feb 21, 2017
1 parent 88f9e21 commit e614e12
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 72 deletions.
11 changes: 6 additions & 5 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,19 @@ func (b *Bot) startPeriodicCommands() {
}

// MessageReceived must be called by the protocol upon receiving a message
func (b *Bot) MessageReceived(channel string, text string, sender *User) {
func (b *Bot) MessageReceived(channel *ChannelData, text string, sender *User) {
command, err := parse(text, channel, sender)
if err != nil {
b.handlers.Response(channel, err.Error(), sender)
b.handlers.Response(channel.Channel, err.Error(), sender)
return
}

if command == nil {
b.executePassiveCommands(&PassiveCmd{
Raw: text,
Channel: channel,
User: sender,
Raw: text,
Channel: channel.Channel,
ChannelData: channel,
User: sender,
})
return
}
Expand Down
42 changes: 25 additions & 17 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,35 @@ import (

// Cmd holds the parsed user's input for easier handling of commands
type Cmd struct {
Raw string // Raw is full string passed to the command
Channel string // Channel where the command was called
User *User // User who sent the message
Message string // Full string without the prefix
Command string // Command is the first argument passed to the bot
RawArgs string // Raw arguments after the command
Args []string // Arguments as array
Raw string // Raw is full string passed to the command
Channel string // Channel where the command was called
ChannelData *ChannelData // More info about the channel, including network
User *User // User who sent the message
Message string // Full string without the prefix
Command string // Command is the first argument passed to the bot
RawArgs string // Raw arguments after the command
Args []string // Arguments as array
}

// ChannelData holds the improved channel info, which includes protocol and server
type ChannelData struct {
Protocol string // What protocol the message was sent on (irc, slack, telegram)
Server string // The server hostname the message was sent on
Channel string // The channel name the message appeared in
IsPrivate bool // Whether the channel is a group or private chat
}

// URI gives back an URI-fied string containing protocol, server and channel.
func (c *ChannelData) URI() string {
return fmt.Sprintf("%s://%s/%s", c.Protocol, c.Server, c.Channel)
}

// PassiveCmd holds the information which will be passed to passive commands when receiving a message
type PassiveCmd struct {
Raw string // Raw message sent to the channel
Channel string // Channel which the message was sent to
User *User // User who sent this message
Raw string // Raw message sent to the channel
Channel string // Channel which the message was sent to
ChannelData *ChannelData // Channel and network info
User *User // User who sent this message
}

// PeriodicConfig holds a cron specification for periodically notifying the configured channels
Expand All @@ -47,13 +62,6 @@ type customCommand struct {
ExampleArgs string
}

type incomingMessage struct {
Channel string
Text string
User *User
BotCurrentNick string
}

// CmdResult is the result message of V2 commands
type CmdResult struct {
Channel string // The channel where the bot should send the message
Expand Down
30 changes: 15 additions & 15 deletions cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ func TestDisabledCommands(t *testing.T) {
})

b.Disable([]string{"cmd"})
b.MessageReceived("#go-bot", "!cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "user"})
if len(replies) != 0 {
t.Fatal("Should not execute disabled active commands")
}

b.Disable([]string{"passive"})
b.MessageReceived("#go-bot", "regular message", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "regular message", &User{Nick: "user"})

if len(replies) != 0 {
t.Fatal("Should not execute disabled passive commands")
Expand All @@ -124,15 +124,15 @@ func TestMessageReceived(t *testing.T) {

Convey("When the command is not registered", func() {
Convey("It should not post to the channel", func() {
b.MessageReceived("#go-bot", "!not_a_cmd", &User{})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!not_a_cmd", &User{})

So(replies, ShouldBeEmpty)
})
})

Convey("When the command arguments are invalid", func() {
Convey("It should reply with an error message", func() {
b.MessageReceived("#go-bot", "!cmd \"invalid arg", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd \"invalid arg", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldHaveLength, 1)
Expand All @@ -148,7 +148,7 @@ func TestMessageReceived(t *testing.T) {
return "", cmdError
})

b.MessageReceived("#go-bot", "!cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble,
Expand All @@ -169,21 +169,21 @@ func TestMessageReceived(t *testing.T) {
})

Convey("If it is called in the channel, reply on the channel", func() {
b.MessageReceived("#go-bot", "!cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble, []string{expectedMsg})
})

Convey("If it is a private message, reply to the user", func() {
user = &User{Nick: "go-bot"}
b.MessageReceived("go-bot", "!cmd", &User{Nick: "sender-nick"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "sender-nick"})
So(user.Nick, ShouldEqual, "sender-nick")
})

Convey("When the command is help", func() {
Convey("Display the available commands in the channel", func() {
b.MessageReceived("#go-bot", "!help", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!help", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble, []string{
Expand All @@ -193,7 +193,7 @@ func TestMessageReceived(t *testing.T) {
})

Convey("If the command exists send a message to the channel", func() {
b.MessageReceived("#go-bot", "!help cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!help cmd", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble, []string{
Expand All @@ -203,7 +203,7 @@ func TestMessageReceived(t *testing.T) {
})

Convey("If the command does not exists, display the generic help", func() {
b.MessageReceived("#go-bot", "!help not_a_command", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!help not_a_command", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble, []string{
Expand All @@ -213,7 +213,7 @@ func TestMessageReceived(t *testing.T) {
})

Convey("if the help arguments are invalid, reply with an error", func() {
b.MessageReceived("#go-bot", "!help cmd \"invalid arg", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!help cmd \"invalid arg", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldHaveLength, 1)
Expand All @@ -231,7 +231,7 @@ func TestMessageReceived(t *testing.T) {
Message: "message"}, nil
})

b.MessageReceived("#go-bot", "!cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "user"})

So(channel, ShouldEqual, "#channel")
So(replies, ShouldResemble, []string{"message"})
Expand All @@ -244,7 +244,7 @@ func TestMessageReceived(t *testing.T) {
Message: "message"}, nil
})

b.MessageReceived("#go-bot", "!cmd", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "!cmd", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(replies, ShouldResemble, []string{"message"})
Expand All @@ -269,7 +269,7 @@ func TestMessageReceived(t *testing.T) {
RegisterPassiveCommand("errored", errored)

Convey("If it is called in the channel, reply on the channel", func() {
b.MessageReceived("#go-bot", "test", &User{Nick: "user"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "test", &User{Nick: "user"})

So(channel, ShouldEqual, "#go-bot")
So(len(replies), ShouldEqual, 2)
Expand All @@ -279,7 +279,7 @@ func TestMessageReceived(t *testing.T) {

Convey("If it is a private message, reply to the user", func() {
user = &User{Nick: "go-bot"}
b.MessageReceived("go-bot", "test", &User{Nick: "sender-nick"})
b.MessageReceived(&ChannelData{Channel: "#go-bot"}, "test", &User{Nick: "sender-nick"})

So(user.Nick, ShouldEqual, "sender-nick")
So(len(replies), ShouldEqual, 2)
Expand Down
2 changes: 1 addition & 1 deletion help.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const (
)

func (b *Bot) help(c *Cmd) {
cmd, _ := parse(CmdPrefix+c.RawArgs, c.Channel, c.User)
cmd, _ := parse(CmdPrefix+c.RawArgs, c.ChannelData, c.User)
if cmd == nil {
b.showAvailabeCommands(c.Channel, c.User)
return
Expand Down
15 changes: 11 additions & 4 deletions irc/irc.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@ func responseHandler(target string, message string, sender *bot.User) {
}

func onPRIVMSG(e *ircevent.Event) {
b.MessageReceived(e.Arguments[0], e.Message(), &bot.User{
ID: e.Host,
Nick: e.Nick,
RealName: e.User})
b.MessageReceived(
&bot.ChannelData{
Protocol: "irc",
Server: ircConn.Server,
Channel: e.Arguments[0],
IsPrivate: e.Arguments[0] == ircConn.GetNick()},
e.Message(),
&bot.User{
ID: e.Host,
Nick: e.Nick,
RealName: e.User})
}

func getServerName(server string) string {
Expand Down
5 changes: 3 additions & 2 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ var (
re = regexp.MustCompile("\\s+") // Matches one or more spaces
)

func parse(s string, channel string, user *User) (*Cmd, error) {
func parse(s string, channel *ChannelData, user *User) (*Cmd, error) {
c := &Cmd{Raw: s}
s = strings.TrimSpace(s)

if !strings.HasPrefix(s, CmdPrefix) {
return nil, nil
}

c.Channel = strings.TrimSpace(channel)
c.Channel = strings.TrimSpace(channel.Channel)
c.ChannelData = channel
c.User = user

// Trim the prefix and extra spaces
Expand Down
47 changes: 25 additions & 22 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"testing"
)

func TestPaser(t *testing.T) {
channel := "#go-bot"
func TestParser(t *testing.T) {
channel := &ChannelData{Channel: "#go-bot"}
user := &User{Nick: "user123"}
cmdWithoutArgs := CmdPrefix + "cmd"
cmdWithArgs := CmdPrefix + "cmd arg1 arg2 "
Expand All @@ -20,29 +20,32 @@ func TestPaser(t *testing.T) {
{"!", nil},
{"regular message", nil},
{cmdWithoutArgs, &Cmd{
Raw: cmdWithoutArgs,
Command: "cmd",
Channel: channel,
User: user,
Message: "cmd",
Raw: cmdWithoutArgs,
Command: "cmd",
Channel: channel.Channel,
ChannelData: channel,
User: user,
Message: "cmd",
}},
{cmdWithArgs, &Cmd{
Raw: cmdWithArgs,
Command: "cmd",
Channel: channel,
User: user,
Message: "cmd arg1 arg2",
RawArgs: "arg1 arg2",
Args: []string{"arg1", "arg2"},
Raw: cmdWithArgs,
Command: "cmd",
Channel: channel.Channel,
ChannelData: channel,
User: user,
Message: "cmd arg1 arg2",
RawArgs: "arg1 arg2",
Args: []string{"arg1", "arg2"},
}},
{cmdWithQuotes, &Cmd{
Raw: cmdWithQuotes,
Command: "cmd",
Channel: channel,
User: user,
Message: "cmd \"arg1 arg2\"",
RawArgs: "\"arg1 arg2\"",
Args: []string{"arg1 arg2"},
Raw: cmdWithQuotes,
Command: "cmd",
Channel: channel.Channel,
ChannelData: channel,
User: user,
Message: "cmd \"arg1 arg2\"",
RawArgs: "\"arg1 arg2\"",
Args: []string{"arg1 arg2"},
}},
}

Expand All @@ -55,7 +58,7 @@ func TestPaser(t *testing.T) {
}

func TestInvalidArguments(t *testing.T) {
cmd, err := parse("!cmd Invalid \"arg", "#go-bot", &User{Nick: "user123"})
cmd, err := parse("!cmd Invalid \"arg", &ChannelData{Channel: "#go-bot"}, &User{Nick: "user123"})
if err == nil {
t.Error("Expected error, got nil")
}
Expand Down
Loading

0 comments on commit e614e12

Please sign in to comment.