2013-12-10 23:37:07 +00:00
|
|
|
// © 2013 the AlePale Authors under the WTFPL. See AUTHORS for the list of authors.
|
|
|
|
|
2013-01-23 21:25:04 +00:00
|
|
|
package plugins
|
|
|
|
|
|
|
|
import (
|
2016-01-15 06:12:26 +00:00
|
|
|
"database/sql"
|
2013-01-23 21:25:04 +00:00
|
|
|
"fmt"
|
2016-01-15 06:12:26 +00:00
|
|
|
"log"
|
2013-01-23 21:25:04 +00:00
|
|
|
"strings"
|
2016-01-15 06:12:26 +00:00
|
|
|
|
|
|
|
"github.com/chrissexton/alepale/bot"
|
2013-01-23 21:25:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// This is a counter plugin to count arbitrary things.
|
|
|
|
|
|
|
|
type CounterPlugin struct {
|
2016-01-15 06:12:26 +00:00
|
|
|
Bot *bot.Bot
|
|
|
|
DB *sql.DB
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Item struct {
|
2016-01-15 06:12:26 +00:00
|
|
|
ID int64
|
2013-01-23 21:25:04 +00:00
|
|
|
Nick string
|
|
|
|
Item string
|
|
|
|
Count int
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewCounterPlugin creates a new CounterPlugin with the Plugin interface
|
|
|
|
func NewCounterPlugin(bot *bot.Bot) *CounterPlugin {
|
2016-01-15 06:12:26 +00:00
|
|
|
if bot.DBVersion == 1 {
|
|
|
|
if _, err := bot.DB.Exec(`create table if not exists counter (
|
|
|
|
id integer primary key,
|
|
|
|
nick string,
|
|
|
|
item string,
|
|
|
|
count integer
|
|
|
|
);`); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2013-01-23 21:25:04 +00:00
|
|
|
return &CounterPlugin{
|
2016-01-15 06:12:26 +00:00
|
|
|
Bot: bot,
|
|
|
|
DB: bot.DB,
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Message responds to the bot hook on recieving messages.
|
2013-05-07 23:30:37 +00:00
|
|
|
// 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
|
2013-01-24 15:20:15 +00:00
|
|
|
// execution of other plugins.
|
2013-01-23 21:25:04 +00:00
|
|
|
func (p *CounterPlugin) Message(message bot.Message) bool {
|
|
|
|
// This bot does not reply to anything
|
|
|
|
nick := message.User.Name
|
|
|
|
channel := message.Channel
|
2013-01-24 16:47:35 +00:00
|
|
|
parts := strings.Split(message.Body, " ")
|
2013-01-23 21:25:04 +00:00
|
|
|
|
|
|
|
if len(parts) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2013-01-23 21:40:51 +00:00
|
|
|
if message.Command && parts[0] == "inspect" && len(parts) == 2 {
|
|
|
|
var subject string
|
|
|
|
|
|
|
|
if parts[1] == "me" {
|
|
|
|
subject = strings.ToLower(nick)
|
|
|
|
} else {
|
|
|
|
subject = parts[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
// pull all of the items associated with "subject"
|
2016-01-15 06:12:26 +00:00
|
|
|
rows, err := p.DB.Query(`select * from counter where nick = ?`, subject)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
2013-01-23 21:45:37 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 21:40:51 +00:00
|
|
|
resp := fmt.Sprintf("%s has the following counters:", subject)
|
2016-01-15 06:12:26 +00:00
|
|
|
count := 0
|
|
|
|
for rows.Next() {
|
|
|
|
count += 1
|
|
|
|
var it Item
|
|
|
|
rows.Scan(&it.Nick, &it.Item, &it.Count)
|
|
|
|
|
|
|
|
if count > 1 {
|
|
|
|
resp = fmt.Sprintf("%s, ", resp)
|
2013-01-23 21:40:51 +00:00
|
|
|
}
|
2016-01-15 06:12:26 +00:00
|
|
|
resp = fmt.Sprintf("%s %s: %d", resp, it.Item, it.Count)
|
|
|
|
if count > 20 {
|
2013-01-23 21:40:51 +00:00
|
|
|
fmt.Sprintf("%s, and a few others", resp)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
resp = fmt.Sprintf("%s.", resp)
|
|
|
|
|
2016-01-15 06:12:26 +00:00
|
|
|
if count == 0 {
|
|
|
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has no counters.", subject))
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2013-01-23 21:40:51 +00:00
|
|
|
p.Bot.SendMessage(channel, resp)
|
|
|
|
return true
|
|
|
|
} else if message.Command && len(parts) == 2 && parts[0] == "clear" {
|
|
|
|
subject := strings.ToLower(nick)
|
|
|
|
itemName := strings.ToLower(parts[1])
|
|
|
|
|
2016-01-15 06:12:26 +00:00
|
|
|
if _, err := p.DB.Exec(`delete from counters where nick = ? and item = ?`, subject, itemName); err != nil {
|
|
|
|
p.Bot.SendMessage(channel, "Something went wrong removing that counter;")
|
|
|
|
return true
|
|
|
|
}
|
2013-01-23 21:40:51 +00:00
|
|
|
|
2013-01-24 15:20:15 +00:00
|
|
|
p.Bot.SendAction(channel, fmt.Sprintf("chops a few %s out of his brain",
|
|
|
|
itemName))
|
2013-01-23 21:40:51 +00:00
|
|
|
return true
|
|
|
|
|
|
|
|
} else if message.Command && parts[0] == "count" {
|
2013-01-23 21:25:04 +00:00
|
|
|
var subject string
|
|
|
|
var itemName string
|
|
|
|
|
|
|
|
if len(parts) == 3 {
|
|
|
|
// report count for parts[1]
|
|
|
|
subject = strings.ToLower(parts[1])
|
|
|
|
itemName = strings.ToLower(parts[2])
|
|
|
|
} else if len(parts) == 2 {
|
|
|
|
subject = strings.ToLower(nick)
|
|
|
|
itemName = strings.ToLower(parts[1])
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
var item Item
|
2016-01-15 06:12:26 +00:00
|
|
|
err := p.DB.QueryRow(`select nick, item, count from counters
|
|
|
|
where nick = ? and item = ?`, subject, itemName).Scan(
|
|
|
|
&item.Nick, &item.Item, &item.Count,
|
|
|
|
)
|
|
|
|
switch {
|
|
|
|
case err == sql.ErrNoRows:
|
2013-01-23 21:25:04 +00:00
|
|
|
p.Bot.SendMessage(channel, fmt.Sprintf("I don't think %s has any %s.",
|
|
|
|
subject, itemName))
|
|
|
|
return true
|
2016-01-15 06:12:26 +00:00
|
|
|
case err != nil:
|
|
|
|
log.Println(err)
|
|
|
|
return true
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
|
|
|
|
2013-01-24 15:20:15 +00:00
|
|
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject, item.Count,
|
|
|
|
itemName))
|
2013-01-23 21:25:04 +00:00
|
|
|
|
|
|
|
return true
|
|
|
|
} else if len(parts) == 1 {
|
2013-01-29 21:27:38 +00:00
|
|
|
if len(parts[0]) < 3 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2013-01-23 21:25:04 +00:00
|
|
|
subject := strings.ToLower(nick)
|
|
|
|
itemName := strings.ToLower(parts[0])[:len(parts[0])-2]
|
|
|
|
|
2013-01-24 15:35:39 +00:00
|
|
|
if nameParts := strings.SplitN(itemName, ".", 2); len(nameParts) == 2 {
|
|
|
|
subject = nameParts[0]
|
|
|
|
itemName = nameParts[1]
|
|
|
|
}
|
|
|
|
|
2013-01-23 21:25:04 +00:00
|
|
|
if strings.HasSuffix(parts[0], "++") {
|
|
|
|
// ++ those fuckers
|
|
|
|
item := p.update(subject, itemName, 1)
|
2013-01-24 15:35:39 +00:00
|
|
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
|
|
|
item.Count, item.Item))
|
2013-01-23 21:25:04 +00:00
|
|
|
return true
|
|
|
|
} else if strings.HasSuffix(parts[0], "--") {
|
|
|
|
// -- those fuckers
|
|
|
|
item := p.update(subject, itemName, -1)
|
2013-01-24 15:35:39 +00:00
|
|
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
|
|
|
item.Count, item.Item))
|
2013-01-23 21:25:04 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *CounterPlugin) update(subject, itemName string, delta int) Item {
|
|
|
|
var item Item
|
2016-01-15 06:12:26 +00:00
|
|
|
err := p.DB.QueryRow(`select id, nick, item, count from counter
|
|
|
|
where nick = ? and item = ?;`, subject, itemName).Scan(
|
|
|
|
&item.ID, &item.Nick, &item.Item, &item.Count,
|
|
|
|
)
|
|
|
|
switch {
|
|
|
|
case err == sql.ErrNoRows:
|
2013-01-23 21:25:04 +00:00
|
|
|
// insert it
|
2016-01-15 06:12:26 +00:00
|
|
|
res, err := p.DB.Exec(`insert into counter (nick, item, count)
|
|
|
|
values (?, ?, ?)`, subject, itemName, delta)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
2016-01-15 06:12:26 +00:00
|
|
|
id, err := res.LastInsertId()
|
|
|
|
return Item{id, subject, itemName, delta}
|
|
|
|
case err != nil:
|
|
|
|
log.Println(err)
|
|
|
|
return item
|
|
|
|
default:
|
2013-01-23 21:25:04 +00:00
|
|
|
item.Count += delta
|
2016-01-15 06:12:26 +00:00
|
|
|
_, err := p.DB.Exec(`update counter set count = ? where id = ?`, item.Count, item.ID)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
|
|
|
return item
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-07 23:30:37 +00:00
|
|
|
// LoadData imports any configuration data into the plugin. This is not
|
|
|
|
// strictly necessary other than the fact that the Plugin interface demands it
|
2013-01-24 15:20:15 +00:00
|
|
|
// exist. This may be deprecated at a later date.
|
2013-01-23 21:25:04 +00:00
|
|
|
func (p *CounterPlugin) LoadData() {
|
|
|
|
// This bot has no data to load
|
|
|
|
}
|
|
|
|
|
|
|
|
// Help responds to help requests. Every plugin must implement a help function.
|
|
|
|
func (p *CounterPlugin) Help(channel string, parts []string) {
|
2013-01-24 15:35:39 +00:00
|
|
|
p.Bot.SendMessage(channel, "You can set counters incrementally by using "+
|
|
|
|
"<noun>++ and <noun>--. You can see all of your counters using "+
|
|
|
|
"\"inspect\", erase them with \"clear\", and view single counters with "+
|
|
|
|
"\"count\".")
|
2013-01-23 21:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Empty event handler because this plugin does not do anything on event recv
|
|
|
|
func (p *CounterPlugin) Event(kind string, message bot.Message) bool {
|
|
|
|
return false
|
|
|
|
}
|
2013-05-08 00:08:18 +00:00
|
|
|
|
|
|
|
// Handler for bot's own messages
|
|
|
|
func (p *CounterPlugin) BotMessage(message bot.Message) bool {
|
|
|
|
return false
|
|
|
|
}
|
2013-06-01 17:10:15 +00:00
|
|
|
|
|
|
|
// Register any web URLs desired
|
|
|
|
func (p *CounterPlugin) RegisterWeb() *string {
|
|
|
|
return nil
|
|
|
|
}
|