catbase/bot/handlers.go

215 lines
5.1 KiB
Go
Raw Normal View History

2016-01-17 18:00:44 +00:00
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package bot
import (
"database/sql"
"errors"
"fmt"
"log"
"math/rand"
2013-03-04 15:43:23 +00:00
"regexp"
"strconv"
"strings"
"time"
)
// Handles incomming PRIVMSG requests
func (b *bot) MsgReceived(msg Message) {
2016-03-11 02:11:52 +00:00
log.Println("Received message: ", msg)
2016-03-10 18:37:07 +00:00
// msg := b.buildMessage(client, inMsg)
// do need to look up user and fix it
if strings.HasPrefix(msg.Body, "help ") && msg.Command {
parts := strings.Fields(strings.ToLower(msg.Body))
b.checkHelp(msg.Channel, parts)
goto RET
}
for _, name := range b.pluginOrdering {
p := b.plugins[name]
if p.Message(msg) {
break
}
}
RET:
b.logIn <- msg
return
}
// Handle incoming events
func (b *bot) EventReceived(msg Message) {
2016-03-11 02:11:52 +00:00
log.Println("Received event: ", msg)
2016-03-10 18:37:07 +00:00
//msg := b.buildMessage(conn, inMsg)
for _, name := range b.pluginOrdering {
p := b.plugins[name]
2016-03-10 18:37:07 +00:00
if p.Event(msg.Body, msg) { // TODO: could get rid of msg.Body
break
}
}
}
func (b *bot) SendMessage(channel, message string) {
b.conn.SendMessage(channel, message)
2016-03-10 18:37:07 +00:00
}
func (b *bot) SendAction(channel, message string) {
b.conn.SendAction(channel, message)
}
// Checks to see if the user is asking for help, returns true if so and handles the situation.
func (b *bot) checkHelp(channel string, parts []string) {
if len(parts) == 1 {
// just print out a list of help topics
2012-08-27 00:30:23 +00:00
topics := "Help topics: about variables"
for name, _ := range b.plugins {
topics = fmt.Sprintf("%s, %s", topics, name)
}
b.SendMessage(channel, topics)
} else {
// trigger the proper plugin's help response
if parts[1] == "about" {
b.Help(channel, parts)
return
}
2012-08-27 00:30:23 +00:00
if parts[1] == "variables" {
b.listVars(channel, parts)
return
}
plugin := b.plugins[parts[1]]
if plugin != nil {
plugin.Help(channel, parts)
} else {
msg := fmt.Sprintf("I'm sorry, I don't know what %s is!", parts[1])
b.SendMessage(channel, msg)
}
}
}
func (b *bot) LastMessage(channel string) (Message, error) {
log := <-b.logOut
if len(log) == 0 {
return Message{}, errors.New("No messages found.")
}
for i := len(log) - 1; i >= 0; i-- {
msg := log[i]
if strings.ToLower(msg.Channel) == strings.ToLower(channel) {
return msg, nil
2013-06-17 01:03:43 +00:00
}
}
return Message{}, errors.New("No messages found.")
}
// Take an input string and mutate it based on $vars in the string
func (b *bot) Filter(message Message, input string) string {
rand.Seed(time.Now().Unix())
if strings.Contains(input, "$NICK") {
nick := strings.ToUpper(message.User.Name)
input = strings.Replace(input, "$NICK", nick, -1)
}
// Let's be bucket compatible for this var
2012-08-27 00:33:33 +00:00
input = strings.Replace(input, "$who", "$nick", -1)
if strings.Contains(input, "$nick") {
nick := message.User.Name
input = strings.Replace(input, "$nick", nick, -1)
}
2013-08-31 02:09:45 +00:00
for strings.Contains(input, "$someone") {
nicks := b.Who(message.Channel)
someone := nicks[rand.Intn(len(nicks))].Name
2013-08-31 02:09:45 +00:00
input = strings.Replace(input, "$someone", someone, 1)
}
for strings.Contains(input, "$digit") {
num := strconv.Itoa(rand.Intn(9))
input = strings.Replace(input, "$digit", num, 1)
}
for strings.Contains(input, "$nonzero") {
num := strconv.Itoa(rand.Intn(8) + 1)
input = strings.Replace(input, "$nonzero", num, 1)
}
r, err := regexp.Compile("\\$[A-z]+")
if err != nil {
panic(err)
}
varname := r.FindString(input)
blacklist := make(map[string]bool)
blacklist["$and"] = true
for len(varname) > 0 && !blacklist[varname] {
text, err := b.getVar(varname)
if err != nil {
blacklist[varname] = true
continue
}
input = strings.Replace(input, varname, text, 1)
varname = r.FindString(input)
}
return input
}
func (b *bot) getVar(varName string) (string, error) {
var text string
err := b.db.QueryRow(`select v.value from variables as va inner join "values" as v on va.id = va.id = v.varId order by random() limit 1`).Scan(&text)
switch {
case err == sql.ErrNoRows:
return "", fmt.Errorf("No factoid found")
case err != nil:
log.Fatal("getVar error: ", err)
}
return text, nil
}
func (b *bot) listVars(channel string, parts []string) {
rows, err := b.db.Query(`select name from variables`)
2012-08-27 00:30:23 +00:00
if err != nil {
log.Fatal(err)
2012-08-27 00:30:23 +00:00
}
msg := "I know: $who, $someone, $digit, $nonzero"
for rows.Next() {
var variable string
err := rows.Scan(&variable)
if err != nil {
log.Println("Error scanning variable.")
continue
}
2012-08-27 00:30:23 +00:00
msg = fmt.Sprintf("%s, %s", msg, variable)
}
b.SendMessage(channel, msg)
}
func (b *bot) Help(channel string, parts []string) {
msg := fmt.Sprintf("Hi, I'm based on godeepintir version %s. I'm written in Go, and you "+
"can find my source code on the internet here: "+
"http://github.com/velour/catbase", b.version)
b.SendMessage(channel, msg)
}
// Send our own musings to the plugins
func (b *bot) selfSaid(channel, message string, action bool) {
msg := Message{
User: &b.me, // hack
Channel: channel,
Body: message,
Raw: message, // hack
Action: action,
Command: false,
Time: time.Now(),
Host: "0.0.0.0", // hack
}
for _, name := range b.pluginOrdering {
p := b.plugins[name]
if p.BotMessage(msg) {
break
}
}
}