YOLO: DEAL WITH IT

Refactored a bunch of junk.
This commit is contained in:
Chris Sexton 2016-04-01 10:20:03 -04:00
parent 58bd45b41c
commit e449a82001
28 changed files with 302 additions and 217 deletions

View File

@ -9,10 +9,12 @@ import (
"net/http" "net/http"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/mattn/go-sqlite3" "github.com/mattn/go-sqlite3"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/msglog"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
) )
@ -24,9 +26,9 @@ type bot struct {
pluginOrdering []string pluginOrdering []string
// Users holds information about all of our friends // Users holds information about all of our friends
users []User users []user.User
// Represents the bot // Represents the bot
me User me user.User
config *config.Config config *config.Config
@ -39,8 +41,8 @@ type bot struct {
db *sqlx.DB db *sqlx.DB
dbVersion int64 dbVersion int64
logIn chan Message logIn chan msg.Message
logOut chan Messages logOut chan msg.Messages
version string version string
@ -48,51 +50,6 @@ type bot struct {
httpEndPoints map[string]string httpEndPoints map[string]string
} }
// Log provides a slice of messages in order
type Log Messages
type Messages []Message
type Logger struct {
in <-chan Message
out chan<- Messages
entries Messages
}
func NewLogger(in chan Message, out chan Messages) *Logger {
return &Logger{in, out, make(Messages, 0)}
}
func RunNewLogger(in chan Message, out chan Messages) {
logger := NewLogger(in, out)
go logger.Run()
}
func (l *Logger) sendEntries() {
l.out <- l.entries
}
func (l *Logger) Run() {
var msg Message
for {
select {
case msg = <-l.in:
l.entries = append(l.entries, msg)
case l.out <- l.entries:
go l.sendEntries()
}
}
}
type Message struct {
User *User
Channel, Body string
Raw string
Command bool
Action bool
Time time.Time
Host string
}
type Variable struct { type Variable struct {
Variable, Value string Variable, Value string
} }
@ -116,13 +73,13 @@ func New(config *config.Config, connector Connector) Bot {
log.Fatal(err) log.Fatal(err)
} }
logIn := make(chan Message) logIn := make(chan msg.Message)
logOut := make(chan Messages) logOut := make(chan msg.Messages)
RunNewLogger(logIn, logOut) msglog.RunNew(logIn, logOut)
users := []User{ users := []user.User{
User{ user.User{
Name: config.Nick, Name: config.Nick,
}, },
} }
@ -220,8 +177,8 @@ func (b *bot) AddHandler(name string, h Handler) {
} }
} }
func (b *bot) Who(channel string) []User { func (b *bot) Who(channel string) []user.User {
out := []User{} out := []user.User{}
for _, u := range b.users { for _, u := range b.users {
if u.Name != b.Config().Nick { if u.Name != b.Config().Nick {
out = append(out, u) out = append(out, u)
@ -299,3 +256,40 @@ func IsCmd(c *config.Config, message string) (bool, string) {
return iscmd, message return iscmd, message
} }
func (b *bot) CheckAdmin(nick string) bool {
for _, u := range b.Config().Admins {
if nick == u {
return true
}
}
return false
}
var users = map[string]*user.User{}
func (b *bot) GetUser(nick string) *user.User {
if _, ok := users[nick]; !ok {
users[nick] = &user.User{
Name: nick,
Admin: b.checkAdmin(nick),
}
}
return users[nick]
}
func (b *bot) NewUser(nick string) *user.User {
return &user.User{
Name: nick,
Admin: b.checkAdmin(nick),
}
}
func (b *bot) checkAdmin(nick string) bool {
for _, u := range b.Config().Admins {
if nick == u {
return true
}
}
return false
}

View File

@ -12,10 +12,12 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/velour/catbase/bot/msg"
) )
// Handles incomming PRIVMSG requests // Handles incomming PRIVMSG requests
func (b *bot) MsgReceived(msg Message) { func (b *bot) MsgReceived(msg msg.Message) {
log.Println("Received message: ", msg) log.Println("Received message: ", msg)
// msg := b.buildMessage(client, inMsg) // msg := b.buildMessage(client, inMsg)
@ -40,7 +42,7 @@ RET:
} }
// Handle incoming events // Handle incoming events
func (b *bot) EventReceived(msg Message) { func (b *bot) EventReceived(msg msg.Message) {
log.Println("Received event: ", msg) log.Println("Received event: ", msg)
//msg := b.buildMessage(conn, inMsg) //msg := b.buildMessage(conn, inMsg)
for _, name := range b.pluginOrdering { for _, name := range b.pluginOrdering {
@ -88,10 +90,10 @@ func (b *bot) checkHelp(channel string, parts []string) {
} }
} }
func (b *bot) LastMessage(channel string) (Message, error) { func (b *bot) LastMessage(channel string) (msg.Message, error) {
log := <-b.logOut log := <-b.logOut
if len(log) == 0 { if len(log) == 0 {
return Message{}, errors.New("No messages found.") return msg.Message{}, errors.New("No messages found.")
} }
for i := len(log) - 1; i >= 0; i-- { for i := len(log) - 1; i >= 0; i-- {
msg := log[i] msg := log[i]
@ -99,11 +101,11 @@ func (b *bot) LastMessage(channel string) (Message, error) {
return msg, nil return msg, nil
} }
} }
return Message{}, errors.New("No messages found.") return msg.Message{}, errors.New("No messages found.")
} }
// Take an input string and mutate it based on $vars in the string // Take an input string and mutate it based on $vars in the string
func (b *bot) Filter(message Message, input string) string { func (b *bot) Filter(message msg.Message, input string) string {
rand.Seed(time.Now().Unix()) rand.Seed(time.Now().Unix())
if strings.Contains(input, "$NICK") { if strings.Contains(input, "$NICK") {
@ -194,7 +196,7 @@ func (b *bot) Help(channel string, parts []string) {
// Send our own musings to the plugins // Send our own musings to the plugins
func (b *bot) selfSaid(channel, message string, action bool) { func (b *bot) selfSaid(channel, message string, action bool) {
msg := Message{ msg := msg.Message{
User: &b.me, // hack User: &b.me, // hack
Channel: channel, Channel: channel,
Body: message, Body: message,

View File

@ -4,6 +4,8 @@ package bot
import ( import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
) )
@ -11,19 +13,20 @@ type Bot interface {
Config() *config.Config Config() *config.Config
DBVersion() int64 DBVersion() int64
DB() *sqlx.DB DB() *sqlx.DB
Who(string) []User Who(string) []user.User
AddHandler(string, Handler) AddHandler(string, Handler)
SendMessage(string, string) SendMessage(string, string)
SendAction(string, string) SendAction(string, string)
MsgReceived(Message) MsgReceived(msg.Message)
EventReceived(Message) EventReceived(msg.Message)
Filter(Message, string) string Filter(msg.Message, string) string
LastMessage(string) (Message, error) LastMessage(string) (msg.Message, error)
CheckAdmin(string) bool
} }
type Connector interface { type Connector interface {
RegisterEventReceived(func(message Message)) RegisterEventReceived(func(message msg.Message))
RegisterMessageReceived(func(message Message)) RegisterMessageReceived(func(message msg.Message))
SendMessage(channel, message string) SendMessage(channel, message string)
SendAction(channel, message string) SendAction(channel, message string)
@ -32,9 +35,9 @@ type Connector interface {
// Interface used for compatibility with the Plugin interface // Interface used for compatibility with the Plugin interface
type Handler interface { type Handler interface {
Message(message Message) bool Message(message msg.Message) bool
Event(kind string, message Message) bool Event(kind string, message msg.Message) bool
BotMessage(message Message) bool BotMessage(message msg.Message) bool
Help(channel string, parts []string) Help(channel string, parts []string)
RegisterWeb() *string RegisterWeb() *string
} }

View File

@ -7,6 +7,8 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
) )
@ -21,7 +23,7 @@ type MockBot struct {
func (mb *MockBot) Config() *config.Config { return &config.Config{} } func (mb *MockBot) Config() *config.Config { return &config.Config{} }
func (mb *MockBot) DBVersion() int64 { return 1 } func (mb *MockBot) DBVersion() int64 { return 1 }
func (mb *MockBot) DB() *sqlx.DB { return mb.db } func (mb *MockBot) DB() *sqlx.DB { return mb.db }
func (mb *MockBot) Who(string) []User { return []User{} } func (mb *MockBot) Who(string) []user.User { return []user.User{} }
func (mb *MockBot) AddHandler(name string, f Handler) {} func (mb *MockBot) AddHandler(name string, f Handler) {}
func (mb *MockBot) SendMessage(ch string, msg string) { func (mb *MockBot) SendMessage(ch string, msg string) {
mb.Messages = append(mb.Messages, msg) mb.Messages = append(mb.Messages, msg)
@ -29,10 +31,11 @@ func (mb *MockBot) SendMessage(ch string, msg string) {
func (mb *MockBot) SendAction(ch string, msg string) { func (mb *MockBot) SendAction(ch string, msg string) {
mb.Actions = append(mb.Actions, msg) mb.Actions = append(mb.Actions, msg)
} }
func (mb *MockBot) MsgReceived(msg Message) {} func (mb *MockBot) MsgReceived(msg msg.Message) {}
func (mb *MockBot) EventReceived(msg Message) {} func (mb *MockBot) EventReceived(msg msg.Message) {}
func (mb *MockBot) Filter(msg Message, s string) string { return "" } func (mb *MockBot) Filter(msg msg.Message, s string) string { return "" }
func (mb *MockBot) LastMessage(ch string) (Message, error) { return Message{}, nil } func (mb *MockBot) LastMessage(ch string) (msg.Message, error) { return msg.Message{}, nil }
func (mb *MockBot) CheckAdmin(nick string) bool { return false }
func NewMockBot() *MockBot { func NewMockBot() *MockBot {
db, err := sqlx.Open("sqlite3_custom", ":memory:") db, err := sqlx.Open("sqlite3_custom", ":memory:")

22
bot/msg/message.go Normal file
View File

@ -0,0 +1,22 @@
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package msg
import (
"time"
"github.com/velour/catbase/bot/user"
)
type Log Messages
type Messages []Message
type Message struct {
User *user.User
Channel, Body string
Raw string
Command bool
Action bool
Time time.Time
Host string
}

36
bot/msglog/msglog.go Normal file
View File

@ -0,0 +1,36 @@
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package msglog
import "github.com/velour/catbase/bot/msg"
type MsgLogger struct {
in <-chan msg.Message
out chan<- msg.Messages
entries msg.Messages
}
func New(in chan msg.Message, out chan msg.Messages) *MsgLogger {
return &MsgLogger{in, out, make(msg.Messages, 0)}
}
func RunNew(in chan msg.Message, out chan msg.Messages) {
logger := New(in, out)
go logger.Run()
}
func (l *MsgLogger) sendEntries() {
l.out <- l.entries
}
func (l *MsgLogger) Run() {
var msg msg.Message
for {
select {
case msg = <-l.in:
l.entries = append(l.entries, msg)
case l.out <- l.entries:
go l.sendEntries()
}
}
}

28
bot/msglog/msglog_test.go Normal file
View File

@ -0,0 +1,28 @@
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package msglog
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot/msg"
)
func TestNew(t *testing.T) {
in := make(chan msg.Message)
out := make(chan msg.Messages)
logger := New(in, out)
assert.NotNil(t, logger)
}
func TestRunNew(t *testing.T) {
in := make(chan msg.Message)
out := make(chan msg.Messages)
RunNew(in, out)
in <- msg.Message{}
msg := <-out
assert.Empty(t, out)
assert.NotNil(t, msg)
}

20
bot/user/users.go Normal file
View File

@ -0,0 +1,20 @@
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package user
// User type stores user history. This is a vehicle that will follow the user for the active
// session
type User struct {
// Current nickname known
Name string
// LastSeen DateTime
// Alternative nicknames seen
Alts []string
Parent string
Admin bool
//bot *bot
}

View File

@ -1,48 +0,0 @@
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package bot
// User type stores user history. This is a vehicle that will follow the user for the active
// session
type User struct {
// Current nickname known
Name string
// LastSeen DateTime
// Alternative nicknames seen
Alts []string
Parent string
Admin bool
//bot *bot
}
var users = map[string]*User{}
func (b *bot) GetUser(nick string) *User {
if _, ok := users[nick]; !ok {
users[nick] = &User{
Name: nick,
Admin: b.checkAdmin(nick),
}
}
return users[nick]
}
func (b *bot) NewUser(nick string) *User {
return &User{
Name: nick,
Admin: b.checkAdmin(nick),
}
}
func (b *bot) checkAdmin(nick string) bool {
for _, u := range b.Config().Admins {
if nick == u {
return true
}
}
return false
}

View File

@ -10,6 +10,8 @@ import (
"time" "time"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
"github.com/velour/velour/irc" "github.com/velour/velour/irc"
) )
@ -39,8 +41,8 @@ type Irc struct {
config *config.Config config *config.Config
quit chan bool quit chan bool
eventReceived func(bot.Message) eventReceived func(msg.Message)
messageReceived func(bot.Message) messageReceived func(msg.Message)
} }
func New(c *config.Config) *Irc { func New(c *config.Config) *Irc {
@ -50,11 +52,11 @@ func New(c *config.Config) *Irc {
return &i return &i
} }
func (i *Irc) RegisterEventReceived(f func(bot.Message)) { func (i *Irc) RegisterEventReceived(f func(msg.Message)) {
i.eventReceived = f i.eventReceived = f
} }
func (i *Irc) RegisterMessageReceived(f func(bot.Message)) { func (i *Irc) RegisterMessageReceived(f func(msg.Message)) {
i.messageReceived = f i.messageReceived = f
} }
@ -229,9 +231,9 @@ func (i *Irc) handleMsg(msg irc.Msg) {
} }
// Builds our internal message type out of a Conn & Line from irc // Builds our internal message type out of a Conn & Line from irc
func (i *Irc) buildMessage(inMsg irc.Msg) bot.Message { func (i *Irc) buildMessage(inMsg irc.Msg) msg.Message {
// Check for the user // Check for the user
user := bot.User{ u := user.User{
Name: inMsg.Origin, Name: inMsg.Origin,
} }
@ -259,8 +261,8 @@ func (i *Irc) buildMessage(inMsg irc.Msg) bot.Message {
iscmd, filteredMessage = bot.IsCmd(i.config, message) iscmd, filteredMessage = bot.IsCmd(i.config, message)
} }
msg := bot.Message{ msg := msg.Message{
User: &user, User: &u,
Channel: channel, Channel: channel,
Body: filteredMessage, Body: filteredMessage,
Raw: message, Raw: message,

View File

@ -12,6 +12,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
// This is a admin plugin to serve as an example and quick copy/paste for new plugins. // This is a admin plugin to serve as an example and quick copy/paste for new plugins.
@ -34,7 +35,7 @@ func New(bot bot.Bot) *AdminPlugin {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *AdminPlugin) Message(message bot.Message) bool { func (p *AdminPlugin) Message(message msg.Message) bool {
// This bot does not reply to anything // This bot does not reply to anything
if !message.User.Admin { if !message.User.Admin {
@ -54,7 +55,7 @@ func (p *AdminPlugin) Message(message bot.Message) bool {
return false return false
} }
func (p *AdminPlugin) handleVariables(message bot.Message) bool { func (p *AdminPlugin) handleVariables(message msg.Message) bool {
parts := strings.SplitN(message.Body, "=", 2) parts := strings.SplitN(message.Body, "=", 2)
if len(parts) != 2 { if len(parts) != 2 {
return false return false
@ -98,12 +99,12 @@ func (p *AdminPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *AdminPlugin) Event(kind string, message bot.Message) bool { func (p *AdminPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *AdminPlugin) BotMessage(message bot.Message) bool { func (p *AdminPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -16,6 +16,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/plugins/counter" "github.com/velour/catbase/plugins/counter"
) )
@ -61,7 +62,7 @@ func New(bot bot.Bot) *BeersPlugin {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *BeersPlugin) Message(message bot.Message) bool { func (p *BeersPlugin) Message(message msg.Message) bool {
parts := strings.Fields(message.Body) parts := strings.Fields(message.Body)
if len(parts) == 0 { if len(parts) == 0 {
@ -203,7 +204,7 @@ func (p *BeersPlugin) Message(message bot.Message) bool {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *BeersPlugin) Event(kind string, message bot.Message) bool { func (p *BeersPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
@ -429,7 +430,7 @@ func (p *BeersPlugin) untappdLoop(channel string) {
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *BeersPlugin) BotMessage(message bot.Message) bool { func (p *BeersPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -8,16 +8,18 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/plugins/counter" "github.com/velour/catbase/plugins/counter"
) )
func makeMessage(payload string) bot.Message { func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
return bot.Message{ return msg.Message{
User: &bot.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test", Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,

View File

@ -10,6 +10,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
// This is a counter plugin to count arbitrary things. // This is a counter plugin to count arbitrary things.
@ -123,7 +124,7 @@ func New(bot bot.Bot) *CounterPlugin {
// This function returns true if the plugin responds in a meaningful way to the // This function returns true if the plugin responds in a meaningful way to the
// users message. Otherwise, the function returns false and the bot continues // users message. Otherwise, the function returns false and the bot continues
// execution of other plugins. // execution of other plugins.
func (p *CounterPlugin) Message(message bot.Message) bool { func (p *CounterPlugin) Message(message msg.Message) bool {
// This bot does not reply to anything // This bot does not reply to anything
nick := message.User.Name nick := message.User.Name
channel := message.Channel channel := message.Channel
@ -280,12 +281,12 @@ func (p *CounterPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *CounterPlugin) Event(kind string, message bot.Message) bool { func (p *CounterPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *CounterPlugin) BotMessage(message bot.Message) bool { func (p *CounterPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -9,15 +9,17 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
) )
func makeMessage(payload string) bot.Message { func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
return bot.Message{ return msg.Message{
User: &bot.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test", Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
import ( import (
@ -37,7 +38,7 @@ func rollDie(sides int) int {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *DicePlugin) Message(message bot.Message) bool { func (p *DicePlugin) Message(message msg.Message) bool {
channel := message.Channel channel := message.Channel
parts := strings.Fields(message.Body) parts := strings.Fields(message.Body)
@ -86,12 +87,12 @@ func (p *DicePlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *DicePlugin) Event(kind string, message bot.Message) bool { func (p *DicePlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *DicePlugin) BotMessage(message bot.Message) bool { func (p *DicePlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -8,15 +8,17 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
) )
func makeMessage(payload string) bot.Message { func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
return bot.Message{ return msg.Message{
User: &bot.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test", Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,

View File

@ -7,6 +7,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
import ( import (
@ -123,7 +124,7 @@ func New(bot bot.Bot) *DowntimePlugin {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *DowntimePlugin) Message(message bot.Message) bool { func (p *DowntimePlugin) Message(message msg.Message) bool {
// If it's a command and the payload is idle <nick>, give it. Log everything. // If it's a command and the payload is idle <nick>, give it. Log everything.
parts := strings.Fields(strings.ToLower(message.Body)) parts := strings.Fields(strings.ToLower(message.Body))
@ -202,7 +203,7 @@ func (p *DowntimePlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *DowntimePlugin) Event(kind string, message bot.Message) bool { func (p *DowntimePlugin) Event(kind string, message msg.Message) bool {
log.Println(kind, "\t", message) log.Println(kind, "\t", message)
if kind != "PART" && message.User.Name != p.Bot.Config().Nick { if kind != "PART" && message.User.Name != p.Bot.Config().Nick {
// user joined, let's nail them for it // user joined, let's nail them for it
@ -222,7 +223,7 @@ func (p *DowntimePlugin) Event(kind string, message bot.Message) bool {
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *DowntimePlugin) BotMessage(message bot.Message) bool { func (p *DowntimePlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
// The factoid plugin provides a learning system to the bot so that it can // The factoid plugin provides a learning system to the bot so that it can
@ -238,7 +239,7 @@ func New(botInst bot.Bot) *FactoidPlugin {
// Some random time to start up // Some random time to start up
time.Sleep(time.Duration(15) * time.Second) time.Sleep(time.Duration(15) * time.Second)
if ok, fact := p.findTrigger(p.Bot.Config().StartupFact); ok { if ok, fact := p.findTrigger(p.Bot.Config().StartupFact); ok {
p.sayFact(bot.Message{ p.sayFact(msg.Message{
Channel: ch, Channel: ch,
Body: "speed test", // BUG: This is defined in the config too Body: "speed test", // BUG: This is defined in the config too
Command: true, Command: true,
@ -272,7 +273,7 @@ func findAction(message string) string {
// learnFact assumes we have a learning situation and inserts a new fact // learnFact assumes we have a learning situation and inserts a new fact
// into the database // into the database
func (p *FactoidPlugin) learnFact(message bot.Message, fact, verb, tidbit string) bool { func (p *FactoidPlugin) learnFact(message msg.Message, fact, verb, tidbit string) bool {
verb = strings.ToLower(verb) verb = strings.ToLower(verb)
var count sql.NullInt64 var count sql.NullInt64
@ -319,7 +320,7 @@ func (p *FactoidPlugin) findTrigger(fact string) (bool, *factoid) {
// sayFact spits out a fact to the channel and updates the fact in the database // sayFact spits out a fact to the channel and updates the fact in the database
// with new time and count information // with new time and count information
func (p *FactoidPlugin) sayFact(message bot.Message, fact factoid) { func (p *FactoidPlugin) sayFact(message msg.Message, fact factoid) {
msg := p.Bot.Filter(message, fact.Tidbit) msg := p.Bot.Filter(message, fact.Tidbit)
full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s", full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s",
fact.Fact, fact.Verb, fact.Tidbit, fact.Fact, fact.Verb, fact.Tidbit,
@ -353,7 +354,7 @@ func (p *FactoidPlugin) sayFact(message bot.Message, fact factoid) {
// trigger checks the message for its fitness to be a factoid and then hauls // trigger checks the message for its fitness to be a factoid and then hauls
// the message off to sayFact for processing if it is in fact a trigger // the message off to sayFact for processing if it is in fact a trigger
func (p *FactoidPlugin) trigger(message bot.Message) bool { func (p *FactoidPlugin) trigger(message msg.Message) bool {
if len(message.Body) > 4 || message.Command || message.Body == "..." { if len(message.Body) > 4 || message.Command || message.Body == "..." {
if ok, fact := p.findTrigger(message.Body); ok { if ok, fact := p.findTrigger(message.Body); ok {
p.sayFact(message, *fact) p.sayFact(message, *fact)
@ -371,7 +372,7 @@ func (p *FactoidPlugin) trigger(message bot.Message) bool {
} }
// tellThemWhatThatWas is a hilarious name for a function. // tellThemWhatThatWas is a hilarious name for a function.
func (p *FactoidPlugin) tellThemWhatThatWas(message bot.Message) bool { func (p *FactoidPlugin) tellThemWhatThatWas(message msg.Message) bool {
fact := p.LastFact fact := p.LastFact
var msg string var msg string
if fact == nil { if fact == nil {
@ -384,7 +385,7 @@ func (p *FactoidPlugin) tellThemWhatThatWas(message bot.Message) bool {
return true return true
} }
func (p *FactoidPlugin) learnAction(message bot.Message, action string) bool { func (p *FactoidPlugin) learnAction(message msg.Message, action string) bool {
body := message.Body body := message.Body
parts := strings.SplitN(body, action, 2) parts := strings.SplitN(body, action, 2)
@ -430,7 +431,7 @@ func changeOperator(body string) string {
// If the user requesting forget is either the owner of the last learned fact or // If the user requesting forget is either the owner of the last learned fact or
// an admin, it may be deleted // an admin, it may be deleted
func (p *FactoidPlugin) forgetLastFact(message bot.Message) bool { func (p *FactoidPlugin) forgetLastFact(message msg.Message) bool {
if p.LastFact == nil { if p.LastFact == nil {
p.Bot.SendMessage(message.Channel, "I refuse.") p.Bot.SendMessage(message.Channel, "I refuse.")
return true return true
@ -452,7 +453,7 @@ func (p *FactoidPlugin) forgetLastFact(message bot.Message) bool {
} }
// Allow users to change facts with a simple regexp // Allow users to change facts with a simple regexp
func (p *FactoidPlugin) changeFact(message bot.Message) bool { func (p *FactoidPlugin) changeFact(message msg.Message) bool {
oper := changeOperator(message.Body) oper := changeOperator(message.Body)
parts := strings.SplitN(message.Body, oper, 2) parts := strings.SplitN(message.Body, oper, 2)
userexp := strings.TrimSpace(parts[1]) userexp := strings.TrimSpace(parts[1])
@ -530,7 +531,7 @@ func (p *FactoidPlugin) changeFact(message bot.Message) bool {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *FactoidPlugin) Message(message bot.Message) bool { func (p *FactoidPlugin) Message(message msg.Message) bool {
if strings.ToLower(message.Body) == "what was that?" { if strings.ToLower(message.Body) == "what was that?" {
return p.tellThemWhatThatWas(message) return p.tellThemWhatThatWas(message)
} }
@ -580,7 +581,7 @@ func (p *FactoidPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *FactoidPlugin) Event(kind string, message bot.Message) bool { func (p *FactoidPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
@ -620,7 +621,7 @@ func (p *FactoidPlugin) factTimer(channel string) {
users := p.Bot.Who(channel) users := p.Bot.Who(channel)
// we need to fabricate a message so that bot.Filter can operate // we need to fabricate a message so that bot.Filter can operate
message := bot.Message{ message := msg.Message{
User: &users[rand.Intn(len(users))], User: &users[rand.Intn(len(users))],
Channel: channel, Channel: channel,
} }
@ -631,7 +632,7 @@ func (p *FactoidPlugin) factTimer(channel string) {
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *FactoidPlugin) BotMessage(message bot.Message) bool { func (p *FactoidPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
// This is a skeleton plugin to serve as an example and quick copy/paste for new // This is a skeleton plugin to serve as an example and quick copy/paste for new
@ -18,7 +19,7 @@ import (
type RememberPlugin struct { type RememberPlugin struct {
Bot bot.Bot Bot bot.Bot
Log map[string][]bot.Message Log map[string][]msg.Message
db *sqlx.DB db *sqlx.DB
} }
@ -26,7 +27,7 @@ type RememberPlugin struct {
func NewRemember(b bot.Bot) *RememberPlugin { func NewRemember(b bot.Bot) *RememberPlugin {
p := RememberPlugin{ p := RememberPlugin{
Bot: b, Bot: b,
Log: make(map[string][]bot.Message), Log: make(map[string][]msg.Message),
db: b.DB(), db: b.DB(),
} }
return &p return &p
@ -36,7 +37,7 @@ func NewRemember(b bot.Bot) *RememberPlugin {
// This function returns true if the plugin responds in a meaningful way to the // This function returns true if the plugin responds in a meaningful way to the
// users message. Otherwise, the function returns false and the bot continues // users message. Otherwise, the function returns false and the bot continues
// execution of other plugins. // execution of other plugins.
func (p *RememberPlugin) Message(message bot.Message) bool { func (p *RememberPlugin) Message(message msg.Message) bool {
if strings.ToLower(message.Body) == "quote" && message.Command { if strings.ToLower(message.Body) == "quote" && message.Command {
q := p.randQuote() q := p.randQuote()
@ -177,12 +178,12 @@ func (p *RememberPlugin) quoteTimer(channel string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *RememberPlugin) Event(kind string, message bot.Message) bool { func (p *RememberPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Record what the bot says in the log // Record what the bot says in the log
func (p *RememberPlugin) BotMessage(message bot.Message) bool { func (p *RememberPlugin) BotMessage(message msg.Message) bool {
p.Log[message.Channel] = append(p.Log[message.Channel], message) p.Log[message.Channel] = append(p.Log[message.Channel], message)
return false return false
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
// This is a first plugin to serve as an example and quick copy/paste for new plugins. // This is a first plugin to serve as an example and quick copy/paste for new plugins.
@ -124,7 +125,7 @@ func isToday(t time.Time) bool {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *FirstPlugin) Message(message bot.Message) bool { func (p *FirstPlugin) Message(message msg.Message) bool {
// This bot does not reply to anything // This bot does not reply to anything
if p.First == nil && p.allowed(message) { if p.First == nil && p.allowed(message) {
@ -150,7 +151,7 @@ func (p *FirstPlugin) Message(message bot.Message) bool {
return false return false
} }
func (p *FirstPlugin) allowed(message bot.Message) bool { func (p *FirstPlugin) allowed(message msg.Message) bool {
for _, msg := range p.Bot.Config().Bad.Msgs { for _, msg := range p.Bot.Config().Bad.Msgs {
match, err := regexp.MatchString(msg, strings.ToLower(message.Body)) match, err := regexp.MatchString(msg, strings.ToLower(message.Body))
if err != nil { if err != nil {
@ -176,7 +177,7 @@ func (p *FirstPlugin) allowed(message bot.Message) bool {
return true return true
} }
func (p *FirstPlugin) recordFirst(message bot.Message) { func (p *FirstPlugin) recordFirst(message msg.Message) {
log.Println("Recording first: ", message.User.Name, ":", message.Body) log.Println("Recording first: ", message.User.Name, ":", message.Body)
p.First = &FirstEntry{ p.First = &FirstEntry{
day: midnight(time.Now()), day: midnight(time.Now()),
@ -192,7 +193,7 @@ func (p *FirstPlugin) recordFirst(message bot.Message) {
p.announceFirst(message) p.announceFirst(message)
} }
func (p *FirstPlugin) announceFirst(message bot.Message) { func (p *FirstPlugin) announceFirst(message msg.Message) {
c := message.Channel c := message.Channel
if p.First != nil { if p.First != nil {
p.Bot.SendMessage(c, fmt.Sprintf("%s had first at %s with the message: \"%s\"", p.Bot.SendMessage(c, fmt.Sprintf("%s had first at %s with the message: \"%s\"",
@ -213,12 +214,12 @@ func (p *FirstPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *FirstPlugin) Event(kind string, message bot.Message) bool { func (p *FirstPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *FirstPlugin) BotMessage(message bot.Message) bool { func (p *FirstPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/jamescun/leftpad" "github.com/jamescun/leftpad"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
type LeftpadPlugin struct { type LeftpadPlugin struct {
@ -27,7 +28,7 @@ type leftpadResp struct {
Str string Str string
} }
func (p *LeftpadPlugin) Message(message bot.Message) bool { func (p *LeftpadPlugin) Message(message msg.Message) bool {
if !message.Command { if !message.Command {
return false return false
} }
@ -51,11 +52,11 @@ func (p *LeftpadPlugin) Message(message bot.Message) bool {
return false return false
} }
func (p *LeftpadPlugin) Event(e string, message bot.Message) bool { func (p *LeftpadPlugin) Event(e string, message msg.Message) bool {
return false return false
} }
func (p *LeftpadPlugin) BotMessage(message bot.Message) bool { func (p *LeftpadPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -8,16 +8,18 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/plugins/counter" "github.com/velour/catbase/plugins/counter"
) )
func makeMessage(payload string) bot.Message { func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
return bot.Message{ return msg.Message{
User: &bot.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test", Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,

View File

@ -2,13 +2,13 @@
package plugins package plugins
import "github.com/velour/catbase/bot" import "github.com/velour/catbase/bot/msg"
// Plugin interface defines the methods needed to accept a plugin // Plugin interface defines the methods needed to accept a plugin
type Plugin interface { type Plugin interface {
Message(message bot.Message) bool Message(message msg.Message) bool
Event(kind string, message bot.Message) bool Event(kind string, message msg.Message) bool
BotMessage(message bot.Message) bool BotMessage(message msg.Message) bool
LoadData() LoadData()
Help() Help()
RegisterWeb() RegisterWeb()

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
var goatse []string = []string{ var goatse []string = []string{
@ -54,7 +55,7 @@ func New(bot bot.Bot) *TalkerPlugin {
} }
} }
func (p *TalkerPlugin) Message(message bot.Message) bool { func (p *TalkerPlugin) Message(message msg.Message) bool {
channel := message.Channel channel := message.Channel
body := message.Body body := message.Body
lowermessage := strings.ToLower(body) lowermessage := strings.ToLower(body)
@ -97,7 +98,7 @@ func (p *TalkerPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *TalkerPlugin) Event(kind string, message bot.Message) bool { func (p *TalkerPlugin) Event(kind string, message msg.Message) bool {
if kind == "JOIN" && strings.ToLower(message.User.Name) != strings.ToLower(p.Bot.Config().Nick) { if kind == "JOIN" && strings.ToLower(message.User.Name) != strings.ToLower(p.Bot.Config().Nick) {
if len(p.sayings) == 0 { if len(p.sayings) == 0 {
return false return false
@ -110,7 +111,7 @@ func (p *TalkerPlugin) Event(kind string, message bot.Message) bool {
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *TalkerPlugin) BotMessage(message bot.Message) bool { func (p *TalkerPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -8,15 +8,17 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
) )
func makeMessage(payload string) bot.Message { func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
return bot.Message{ return msg.Message{
User: &bot.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test", Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
) )
type YourPlugin struct { type YourPlugin struct {
@ -26,7 +27,7 @@ func New(bot bot.Bot) *YourPlugin {
// Message responds to the bot hook on recieving messages. // Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message. // This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins. // Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *YourPlugin) Message(message bot.Message) bool { func (p *YourPlugin) Message(message msg.Message) bool {
lower := strings.ToLower(message.Body) lower := strings.ToLower(message.Body)
config := p.bot.Config().Your config := p.bot.Config().Your
if len(message.Body) > config.MaxLength { if len(message.Body) > config.MaxLength {
@ -61,12 +62,12 @@ func (p *YourPlugin) Help(channel string, parts []string) {
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *YourPlugin) Event(kind string, message bot.Message) bool { func (p *YourPlugin) Event(kind string, message msg.Message) bool {
return false return false
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *YourPlugin) BotMessage(message bot.Message) bool { func (p *YourPlugin) BotMessage(message msg.Message) bool {
return false return false
} }

View File

@ -15,6 +15,8 @@ import (
"sync/atomic" "sync/atomic"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
"github.com/velour/catbase/config" "github.com/velour/catbase/config"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
@ -28,8 +30,8 @@ type Slack struct {
users map[string]string users map[string]string
eventReceived func(bot.Message) eventReceived func(msg.Message)
messageReceived func(bot.Message) messageReceived func(msg.Message)
} }
var idCounter uint64 var idCounter uint64
@ -71,11 +73,11 @@ func New(c *config.Config) *Slack {
} }
} }
func (s *Slack) RegisterEventReceived(f func(bot.Message)) { func (s *Slack) RegisterEventReceived(f func(msg.Message)) {
s.eventReceived = f s.eventReceived = f
} }
func (s *Slack) RegisterMessageReceived(f func(bot.Message)) { func (s *Slack) RegisterMessageReceived(f func(msg.Message)) {
s.messageReceived = f s.messageReceived = f
} }
@ -134,10 +136,10 @@ func (s *Slack) Serve() {
} }
} }
// Convert a slackMessage to a bot.Message // Convert a slackMessage to a msg.Message
func (s *Slack) buildMessage(msg slackMessage) bot.Message { func (s *Slack) buildMessage(m slackMessage) msg.Message {
log.Printf("DEBUG: msg: %#v", msg) log.Printf("DEBUG: msg: %#v", m)
text := html.UnescapeString(msg.Text) text := html.UnescapeString(m.Text)
isCmd, text := bot.IsCmd(s.config, text) isCmd, text := bot.IsCmd(s.config, text)
@ -146,18 +148,18 @@ func (s *Slack) buildMessage(msg slackMessage) bot.Message {
text = text[3:] text = text[3:]
} }
user := s.getUser(msg.User) u := s.getUser(m.User)
return bot.Message{ return msg.Message{
User: &bot.User{ User: &user.User{
Name: user, Name: u,
}, },
Body: text, Body: text,
Raw: msg.Text, Raw: m.Text,
Channel: msg.Channel, Channel: m.Channel,
Command: isCmd, Command: isCmd,
Action: isAction, Action: isAction,
Host: string(msg.Id), Host: string(m.Id),
} }
} }