mirror of https://github.com/velour/catbase.git
Merge branch 'counterstuff'
* counterstuff: Fix #19: Merge beers and counters Migrate to sqlx; modularize counters Move counter to its own package Fix a few minor govet issues
This commit is contained in:
commit
15602defbc
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/config"
|
"github.com/velour/catbase/config"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
@ -35,7 +36,7 @@ type Bot struct {
|
||||||
// TODO: I think it'd be nice to use https://github.com/jmoiron/sqlx so that
|
// TODO: I think it'd be nice to use https://github.com/jmoiron/sqlx so that
|
||||||
// the select/update/etc statements could be simplified with struct
|
// the select/update/etc statements could be simplified with struct
|
||||||
// marshalling.
|
// marshalling.
|
||||||
DB *sql.DB
|
DB *sqlx.DB
|
||||||
DBVersion int64
|
DBVersion int64
|
||||||
|
|
||||||
logIn chan Message
|
logIn chan Message
|
||||||
|
@ -98,7 +99,7 @@ type Variable struct {
|
||||||
|
|
||||||
// NewBot creates a Bot for a given connection and set of handlers.
|
// NewBot creates a Bot for a given connection and set of handlers.
|
||||||
func NewBot(config *config.Config, connector Connector) *Bot {
|
func NewBot(config *config.Config, connector Connector) *Bot {
|
||||||
sqlDB, err := sql.Open("sqlite3", config.DB.File)
|
sqlDB, err := sqlx.Open("sqlite3", config.DB.File)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
3
main.go
3
main.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/velour/catbase/config"
|
"github.com/velour/catbase/config"
|
||||||
"github.com/velour/catbase/irc"
|
"github.com/velour/catbase/irc"
|
||||||
"github.com/velour/catbase/plugins"
|
"github.com/velour/catbase/plugins"
|
||||||
|
"github.com/velour/catbase/plugins/counter"
|
||||||
"github.com/velour/catbase/slack"
|
"github.com/velour/catbase/slack"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ func main() {
|
||||||
b.AddHandler("talker", plugins.NewTalkerPlugin(b))
|
b.AddHandler("talker", plugins.NewTalkerPlugin(b))
|
||||||
b.AddHandler("dice", plugins.NewDicePlugin(b))
|
b.AddHandler("dice", plugins.NewDicePlugin(b))
|
||||||
b.AddHandler("beers", plugins.NewBeersPlugin(b))
|
b.AddHandler("beers", plugins.NewBeersPlugin(b))
|
||||||
b.AddHandler("counter", plugins.NewCounterPlugin(b))
|
b.AddHandler("counter", counter.NewCounterPlugin(b))
|
||||||
b.AddHandler("remember", plugins.NewRememberPlugin(b))
|
b.AddHandler("remember", plugins.NewRememberPlugin(b))
|
||||||
b.AddHandler("skeleton", plugins.NewSkeletonPlugin(b))
|
b.AddHandler("skeleton", plugins.NewSkeletonPlugin(b))
|
||||||
b.AddHandler("your", plugins.NewYourPlugin(b))
|
b.AddHandler("your", plugins.NewYourPlugin(b))
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ import (
|
||||||
|
|
||||||
type AdminPlugin struct {
|
type AdminPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
DB *sql.DB
|
DB *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface
|
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface
|
||||||
|
|
101
plugins/beers.go
101
plugins/beers.go
|
@ -3,7 +3,6 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -15,22 +14,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
|
"github.com/velour/catbase/plugins/counter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a skeleton plugin to serve as an example and quick copy/paste for new plugins.
|
// This is a skeleton plugin to serve as an example and quick copy/paste for new plugins.
|
||||||
|
|
||||||
type BeersPlugin struct {
|
type BeersPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
db *sql.DB
|
db *sqlx.DB
|
||||||
}
|
|
||||||
|
|
||||||
type userBeers struct {
|
|
||||||
id int64
|
|
||||||
nick string
|
|
||||||
count int
|
|
||||||
lastDrunk time.Time
|
|
||||||
saved bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type untappdUser struct {
|
type untappdUser struct {
|
||||||
|
@ -74,58 +67,6 @@ func NewBeersPlugin(bot *bot.Bot) *BeersPlugin {
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userBeers) Save(db *sql.DB) error {
|
|
||||||
if !u.saved {
|
|
||||||
res, err := db.Exec(`insert into beers (
|
|
||||||
nick,
|
|
||||||
count,
|
|
||||||
lastDrunk
|
|
||||||
) values (?, ?, ?)`, u.nick, u.count, u.lastDrunk)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
id, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
u.id = id
|
|
||||||
} else {
|
|
||||||
_, err := db.Exec(`update beers set
|
|
||||||
count = ?,
|
|
||||||
lastDrunk = ?
|
|
||||||
where id = ?;`, u.count, time.Now(), u.id)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Error updating beers: ", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserBeers(db *sql.DB, nick string) *userBeers {
|
|
||||||
ub := userBeers{saved: true}
|
|
||||||
err := db.QueryRow(`select id, nick, count, lastDrunk from beers
|
|
||||||
where nick = ?`, nick).Scan(
|
|
||||||
&ub.id,
|
|
||||||
&ub.nick,
|
|
||||||
&ub.count,
|
|
||||||
&ub.lastDrunk,
|
|
||||||
)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
log.Println("DIDN'T FIND THAT USER: ", err)
|
|
||||||
return &userBeers{
|
|
||||||
nick: nick,
|
|
||||||
count: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
log.Println("Error finding beers: ", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ub
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -159,7 +100,7 @@ func (p *BeersPlugin) Message(message bot.Message) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if parts[1] == "+=" {
|
if parts[1] == "+=" {
|
||||||
p.setBeers(nick, p.getBeers(nick)+count)
|
p.addBeers(nick, count)
|
||||||
p.randomReply(channel)
|
p.randomReply(channel)
|
||||||
} else if parts[1] == "=" {
|
} else if parts[1] == "=" {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
|
@ -185,16 +126,15 @@ func (p *BeersPlugin) Message(message bot.Message) bool {
|
||||||
// no matter what, if we're in here, then we've responded
|
// no matter what, if we're in here, then we've responded
|
||||||
return true
|
return true
|
||||||
} else if parts[0] == "beers--" {
|
} else if parts[0] == "beers--" {
|
||||||
p.setBeers(nick, p.getBeers(nick)-1)
|
p.addBeers(nick, -1)
|
||||||
p.Bot.SendAction(channel, "flushes")
|
p.Bot.SendAction(channel, "flushes")
|
||||||
return true
|
return true
|
||||||
} else if parts[0] == "beers++" {
|
} else if parts[0] == "beers++" {
|
||||||
p.addBeers(nick)
|
p.addBeers(nick, 1)
|
||||||
p.randomReply(channel)
|
p.randomReply(channel)
|
||||||
return true
|
return true
|
||||||
} else if parts[0] == "bourbon++" {
|
} else if parts[0] == "bourbon++" {
|
||||||
p.addBeers(nick)
|
p.addBeers(nick, 2)
|
||||||
p.addBeers(nick)
|
|
||||||
p.randomReply(channel)
|
p.randomReply(channel)
|
||||||
return true
|
return true
|
||||||
} else if parts[0] == "puke" {
|
} else if parts[0] == "puke" {
|
||||||
|
@ -203,7 +143,7 @@ func (p *BeersPlugin) Message(message bot.Message) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.Command && parts[0] == "imbibe" {
|
if message.Command && parts[0] == "imbibe" {
|
||||||
p.addBeers(nick)
|
p.addBeers(nick, 1)
|
||||||
p.randomReply(channel)
|
p.randomReply(channel)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -291,22 +231,30 @@ func (p *BeersPlugin) Help(channel string, parts []string) {
|
||||||
p.Bot.SendMessage(channel, msg)
|
p.Bot.SendMessage(channel, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getUserBeers(db *sqlx.DB, user string) counter.Item {
|
||||||
|
booze, _ := counter.GetItem(db, user, "booze")
|
||||||
|
return booze
|
||||||
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) setBeers(user string, amount int) {
|
func (p *BeersPlugin) setBeers(user string, amount int) {
|
||||||
ub := getUserBeers(p.db, user)
|
ub := getUserBeers(p.db, user)
|
||||||
ub.count = amount
|
err := ub.Update(amount)
|
||||||
ub.lastDrunk = time.Now()
|
if err != nil {
|
||||||
if err := ub.Save(p.db); err != nil {
|
|
||||||
log.Println("Error saving beers: ", err)
|
log.Println("Error saving beers: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) addBeers(user string) {
|
func (p *BeersPlugin) addBeers(user string, delta int) {
|
||||||
p.setBeers(user, p.getBeers(user)+1)
|
ub := getUserBeers(p.db, user)
|
||||||
|
err := ub.UpdateDelta(delta)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error saving beers: ", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) getBeers(nick string) int {
|
func (p *BeersPlugin) getBeers(nick string) int {
|
||||||
ub := getUserBeers(p.db, nick)
|
ub := getUserBeers(p.db, nick)
|
||||||
return ub.count
|
return ub.Count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) reportCount(nick, channel string, himself bool) {
|
func (p *BeersPlugin) reportCount(nick, channel string, himself bool) {
|
||||||
|
@ -401,7 +349,8 @@ func (p *BeersPlugin) pullUntappd() ([]checkin, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) checkUntappd(channel string) {
|
func (p *BeersPlugin) checkUntappd(channel string) {
|
||||||
if p.Bot.Config.Untappd.Token == "<Your Token>" {
|
token := p.Bot.Config.Untappd.Token
|
||||||
|
if token == "" || token == "<Your Token>" {
|
||||||
log.Println("No Untappd token, cannot enable plugin.")
|
log.Println("No Untappd token, cannot enable plugin.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -450,7 +399,7 @@ func (p *BeersPlugin) checkUntappd(channel string) {
|
||||||
}
|
}
|
||||||
log.Printf("user.chanNick: %s, user.untappdUser: %s, checkin.User.User_name: %s",
|
log.Printf("user.chanNick: %s, user.untappdUser: %s, checkin.User.User_name: %s",
|
||||||
user.chanNick, user.untappdUser, checkin.User.User_name)
|
user.chanNick, user.untappdUser, checkin.User.User_name)
|
||||||
p.addBeers(user.chanNick)
|
p.addBeers(user.chanNick, 1)
|
||||||
drunken := p.getBeers(user.chanNick)
|
drunken := p.getBeers(user.chanNick)
|
||||||
|
|
||||||
msg := fmt.Sprintf("%s just drank %s by %s%s, bringing his drunkeness to %d",
|
msg := fmt.Sprintf("%s just drank %s by %s%s, bringing his drunkeness to %d",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
|
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
|
||||||
|
|
||||||
package plugins
|
package counter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
@ -8,6 +8,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,16 +16,91 @@ import (
|
||||||
|
|
||||||
type CounterPlugin struct {
|
type CounterPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
DB *sql.DB
|
DB *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
|
*sqlx.DB
|
||||||
|
|
||||||
ID int64
|
ID int64
|
||||||
Nick string
|
Nick string
|
||||||
Item string
|
Item string
|
||||||
Count int
|
Count int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetItems returns all counters for a subject
|
||||||
|
func GetItems(db *sqlx.DB, nick string) ([]Item, error) {
|
||||||
|
var items []Item
|
||||||
|
err := db.Select(&items, `select * from counter where nick = ?`, nick)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Don't forget to embed the DB into all of that shiz
|
||||||
|
for _, i := range items {
|
||||||
|
i.DB = db
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetItem returns a specific counter for a subject
|
||||||
|
func GetItem(db *sqlx.DB, nick, itemName string) (Item, error) {
|
||||||
|
var item Item
|
||||||
|
item.DB = db
|
||||||
|
log.Printf("GetItem db: %#v", db)
|
||||||
|
err := db.Get(&item, `select * from counter where nick = ? and item= ?`,
|
||||||
|
nick, itemName)
|
||||||
|
switch err {
|
||||||
|
case sql.ErrNoRows:
|
||||||
|
item.ID = -1
|
||||||
|
item.Nick = nick
|
||||||
|
item.Item = itemName
|
||||||
|
case nil:
|
||||||
|
default:
|
||||||
|
return Item{}, err
|
||||||
|
}
|
||||||
|
log.Printf("Got item %s.%s: %#v", nick, itemName, item)
|
||||||
|
return item, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create saves a counter
|
||||||
|
func (i *Item) Create() error {
|
||||||
|
res, err := i.Exec(`insert into counter (nick, item, count) values (?, ?, ?);`,
|
||||||
|
i.Nick, i.Item, i.Count)
|
||||||
|
id, _ := res.LastInsertId()
|
||||||
|
// hackhackhack?
|
||||||
|
i.ID = id
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDelta sets a value
|
||||||
|
// This will create or delete the item if necessary
|
||||||
|
func (i *Item) Update(value int) error {
|
||||||
|
i.Count = value
|
||||||
|
if i.Count == 0 && i.ID != -1 {
|
||||||
|
return i.Delete()
|
||||||
|
}
|
||||||
|
if i.ID == -1 {
|
||||||
|
i.Create()
|
||||||
|
}
|
||||||
|
log.Printf("Updating item: %#v, value: %d", i, value)
|
||||||
|
_, err := i.Exec(`update counter set count = ? where id = ?`, i.Count, i.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDelta changes a value according to some delta
|
||||||
|
// This will create or delete the item if necessary
|
||||||
|
func (i *Item) UpdateDelta(delta int) error {
|
||||||
|
i.Count += delta
|
||||||
|
return i.Update(i.Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes a counter from the database
|
||||||
|
func (i *Item) Delete() error {
|
||||||
|
_, err := i.Exec(`delete from counter where id = ?`, i.ID)
|
||||||
|
i.ID = -1
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// NewCounterPlugin creates a new CounterPlugin with the Plugin interface
|
// NewCounterPlugin creates a new CounterPlugin with the Plugin interface
|
||||||
func NewCounterPlugin(bot *bot.Bot) *CounterPlugin {
|
func NewCounterPlugin(bot *bot.Bot) *CounterPlugin {
|
||||||
if bot.DBVersion == 1 {
|
if bot.DBVersion == 1 {
|
||||||
|
@ -63,36 +139,32 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
if parts[1] == "me" {
|
if parts[1] == "me" {
|
||||||
subject = strings.ToLower(nick)
|
subject = strings.ToLower(nick)
|
||||||
} else {
|
} else {
|
||||||
subject = parts[1]
|
subject = strings.ToLower(parts[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Getting counter for %s", subject)
|
log.Printf("Getting counter for %s", subject)
|
||||||
// pull all of the items associated with "subject"
|
// pull all of the items associated with "subject"
|
||||||
rows, err := p.DB.Query(`select nick, item, count from counter where nick = ?`, subject)
|
items, err := GetItems(p.DB, subject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatalf("Error retrieving items for %s: %s", subject, err)
|
||||||
|
p.Bot.SendMessage(channel, "Something went wrong finding that counter;")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := fmt.Sprintf("%s has the following counters:", subject)
|
resp := fmt.Sprintf("%s has the following counters:", subject)
|
||||||
count := 0
|
count := 0
|
||||||
for rows.Next() {
|
for _, it := range items {
|
||||||
count += 1
|
count += 1
|
||||||
var it Item
|
|
||||||
err := rows.Scan(&it.Nick, &it.Item, &it.Count)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error getting counter: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
resp = fmt.Sprintf("%s, ", resp)
|
resp += ", "
|
||||||
}
|
}
|
||||||
resp = fmt.Sprintf("%s %s: %d", resp, it.Item, it.Count)
|
resp += fmt.Sprintf(" %s: %d", it.Item, it.Count)
|
||||||
if count > 20 {
|
if count > 20 {
|
||||||
fmt.Sprintf("%s, and a few others", resp)
|
resp += ", and a few others"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp = fmt.Sprintf("%s.", resp)
|
resp += "."
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("%s has no counters.", subject))
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has no counters.", subject))
|
||||||
|
@ -105,7 +177,15 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
subject := strings.ToLower(nick)
|
subject := strings.ToLower(nick)
|
||||||
itemName := strings.ToLower(parts[1])
|
itemName := strings.ToLower(parts[1])
|
||||||
|
|
||||||
if _, err := p.DB.Exec(`delete from counter where nick = ? and item = ?`, subject, itemName); err != nil {
|
it, err := GetItem(p.DB, subject, itemName)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting item to remove %s.%s: %s", subject, itemName, err)
|
||||||
|
p.Bot.SendMessage(channel, "Something went wrong removing that counter;")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
err = it.Delete()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error removing item %s.%s: %s", subject, itemName, err)
|
||||||
p.Bot.SendMessage(channel, "Something went wrong removing that counter;")
|
p.Bot.SendMessage(channel, "Something went wrong removing that counter;")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -130,17 +210,15 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
var item Item
|
var item Item
|
||||||
err := p.DB.QueryRow(`select nick, item, count from counter
|
item, err := GetItem(p.DB, subject, itemName)
|
||||||
where nick = ? and item = ?`, subject, itemName).Scan(
|
|
||||||
&item.Nick, &item.Item, &item.Count,
|
|
||||||
)
|
|
||||||
switch {
|
switch {
|
||||||
case err == sql.ErrNoRows:
|
case err == sql.ErrNoRows:
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("I don't think %s has any %s.",
|
p.Bot.SendMessage(channel, fmt.Sprintf("I don't think %s has any %s.",
|
||||||
subject, itemName))
|
subject, itemName))
|
||||||
return true
|
return true
|
||||||
case err != nil:
|
case err != nil:
|
||||||
log.Println(err)
|
log.Printf("Error retrieving item count for %s.%s: %s",
|
||||||
|
subject, itemName, err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +227,7 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} else if len(parts) == 1 {
|
} else if len(parts) == 1 {
|
||||||
|
// Need to have at least 3 characters to ++ or --
|
||||||
if len(parts[0]) < 3 {
|
if len(parts[0]) < 3 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -163,13 +242,26 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
|
|
||||||
if strings.HasSuffix(parts[0], "++") {
|
if strings.HasSuffix(parts[0], "++") {
|
||||||
// ++ those fuckers
|
// ++ those fuckers
|
||||||
item := p.update(subject, itemName, 1)
|
item, err := GetItem(p.DB, subject, itemName)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error finding item %s.%s: %s.", subject, itemName, err)
|
||||||
|
// Item ain't there, I guess
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
log.Printf("About to update item: %#v", item)
|
||||||
|
item.UpdateDelta(1)
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
||||||
item.Count, item.Item))
|
item.Count, item.Item))
|
||||||
return true
|
return true
|
||||||
} else if strings.HasSuffix(parts[0], "--") {
|
} else if strings.HasSuffix(parts[0], "--") {
|
||||||
// -- those fuckers
|
// -- those fuckers
|
||||||
item := p.update(subject, itemName, -1)
|
item, err := GetItem(p.DB, subject, itemName)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error finding item %s.%s: %s.", subject, itemName, err)
|
||||||
|
// Item ain't there, I guess
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
item.UpdateDelta(-1)
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject,
|
||||||
item.Count, item.Item))
|
item.Count, item.Item))
|
||||||
return true
|
return true
|
||||||
|
@ -179,35 +271,6 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CounterPlugin) update(subject, itemName string, delta int) Item {
|
|
||||||
var item Item
|
|
||||||
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:
|
|
||||||
// insert it
|
|
||||||
res, err := p.DB.Exec(`insert into counter (nick, item, count)
|
|
||||||
values (?, ?, ?)`, subject, itemName, delta)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
id, err := res.LastInsertId()
|
|
||||||
return Item{id, subject, itemName, delta}
|
|
||||||
case err != nil:
|
|
||||||
log.Println(err)
|
|
||||||
return item
|
|
||||||
default:
|
|
||||||
item.Count += delta
|
|
||||||
_, err := p.DB.Exec(`update counter set count = ? where id = ?`, item.Count, item.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadData imports any configuration data into the plugin. This is not
|
// LoadData imports any configuration data into the plugin. This is not
|
||||||
// strictly necessary other than the fact that the Plugin interface demands it
|
// strictly necessary other than the fact that the Plugin interface demands it
|
||||||
// exist. This may be deprecated at a later date.
|
// exist. This may be deprecated at a later date.
|
|
@ -5,6 +5,7 @@ package plugins
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ import (
|
||||||
|
|
||||||
type DowntimePlugin struct {
|
type DowntimePlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
db *sql.DB
|
db *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type idleEntry struct {
|
type idleEntry struct {
|
||||||
|
@ -29,7 +30,7 @@ type idleEntry struct {
|
||||||
lastSeen time.Time
|
lastSeen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry idleEntry) saveIdleEntry(db *sql.DB) error {
|
func (entry idleEntry) saveIdleEntry(db *sqlx.DB) error {
|
||||||
var err error
|
var err error
|
||||||
if entry.id.Valid {
|
if entry.id.Valid {
|
||||||
log.Println("Updating downtime for: ", entry)
|
log.Println("Updating downtime for: ", entry)
|
||||||
|
@ -44,7 +45,7 @@ func (entry idleEntry) saveIdleEntry(db *sql.DB) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIdleEntryByNick(db *sql.DB, nick string) (idleEntry, error) {
|
func getIdleEntryByNick(db *sqlx.DB, nick string) (idleEntry, error) {
|
||||||
var id sql.NullInt64
|
var id sql.NullInt64
|
||||||
var lastSeen sql.NullInt64
|
var lastSeen sql.NullInt64
|
||||||
err := db.QueryRow(`select id, max(lastSeen) from downtime
|
err := db.QueryRow(`select id, max(lastSeen) from downtime
|
||||||
|
@ -66,7 +67,7 @@ func getIdleEntryByNick(db *sql.DB, nick string) (idleEntry, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllIdleEntries(db *sql.DB) (idleEntries, error) {
|
func getAllIdleEntries(db *sqlx.DB) (idleEntries, error) {
|
||||||
rows, err := db.Query(`select id, nick, max(lastSeen) from downtime
|
rows, err := db.Query(`select id, nick, max(lastSeen) from downtime
|
||||||
group by nick`)
|
group by nick`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ type factoid struct {
|
||||||
count int
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *factoid) save(db *sql.DB) error {
|
func (f *factoid) save(db *sqlx.DB) error {
|
||||||
var err error
|
var err error
|
||||||
if f.id.Valid {
|
if f.id.Valid {
|
||||||
// update
|
// update
|
||||||
|
@ -82,7 +83,7 @@ func (f *factoid) save(db *sql.DB) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *factoid) delete(db *sql.DB) error {
|
func (f *factoid) delete(db *sqlx.DB) error {
|
||||||
var err error
|
var err error
|
||||||
if f.id.Valid {
|
if f.id.Valid {
|
||||||
_, err = db.Exec(`delete from factoid where id=?`, f.id)
|
_, err = db.Exec(`delete from factoid where id=?`, f.id)
|
||||||
|
@ -91,7 +92,7 @@ func (f *factoid) delete(db *sql.DB) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFacts(db *sql.DB, fact string) ([]*factoid, error) {
|
func getFacts(db *sqlx.DB, fact string) ([]*factoid, error) {
|
||||||
var fs []*factoid
|
var fs []*factoid
|
||||||
rows, err := db.Query(`select
|
rows, err := db.Query(`select
|
||||||
id,
|
id,
|
||||||
|
@ -129,7 +130,7 @@ func getFacts(db *sql.DB, fact string) ([]*factoid, error) {
|
||||||
return fs, err
|
return fs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSingle(db *sql.DB) (*factoid, error) {
|
func getSingle(db *sqlx.DB) (*factoid, error) {
|
||||||
var f factoid
|
var f factoid
|
||||||
var tmpCreated int64
|
var tmpCreated int64
|
||||||
var tmpAccessed int64
|
var tmpAccessed int64
|
||||||
|
@ -158,7 +159,7 @@ func getSingle(db *sql.DB) (*factoid, error) {
|
||||||
return &f, err
|
return &f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSingleFact(db *sql.DB, fact string) (*factoid, error) {
|
func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) {
|
||||||
var f factoid
|
var f factoid
|
||||||
var tmpCreated int64
|
var tmpCreated int64
|
||||||
var tmpAccessed int64
|
var tmpAccessed int64
|
||||||
|
@ -194,7 +195,7 @@ type FactoidPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
NotFound []string
|
NotFound []string
|
||||||
LastFact *factoid
|
LastFact *factoid
|
||||||
db *sql.DB
|
db *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface
|
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface
|
||||||
|
@ -229,18 +230,18 @@ func NewFactoidPlugin(botInst *bot.Bot) *FactoidPlugin {
|
||||||
for _, channel := range botInst.Config.Channels {
|
for _, channel := range botInst.Config.Channels {
|
||||||
go p.factTimer(channel)
|
go p.factTimer(channel)
|
||||||
|
|
||||||
go func() {
|
go func(ch string) {
|
||||||
// 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(bot.Message{
|
||||||
Channel: channel,
|
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,
|
||||||
Action: false,
|
Action: false,
|
||||||
}, *fact)
|
}, *fact)
|
||||||
}
|
}
|
||||||
}()
|
}(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ import (
|
||||||
type FirstPlugin struct {
|
type FirstPlugin struct {
|
||||||
First *FirstEntry
|
First *FirstEntry
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
db *sql.DB
|
db *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type FirstEntry struct {
|
type FirstEntry struct {
|
||||||
|
@ -31,7 +32,7 @@ type FirstEntry struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert or update the first entry
|
// Insert or update the first entry
|
||||||
func (fe *FirstEntry) save(db *sql.DB) error {
|
func (fe *FirstEntry) save(db *sqlx.DB) error {
|
||||||
if _, err := db.Exec(`insert into first (day, time, body, nick)
|
if _, err := db.Exec(`insert into first (day, time, body, nick)
|
||||||
values (?, ?, ?, ?)`,
|
values (?, ?, ?, ?)`,
|
||||||
fe.day.Unix(),
|
fe.day.Unix(),
|
||||||
|
@ -73,7 +74,7 @@ func NewFirstPlugin(b *bot.Bot) *FirstPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLastFirst(db *sql.DB) (*FirstEntry, error) {
|
func getLastFirst(db *sqlx.DB) (*FirstEntry, error) {
|
||||||
// Get last first entry
|
// Get last first entry
|
||||||
var id sql.NullInt64
|
var id sql.NullInt64
|
||||||
var day sql.NullInt64
|
var day sql.NullInt64
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import (
|
||||||
type RememberPlugin struct {
|
type RememberPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
Log map[string][]bot.Message
|
Log map[string][]bot.Message
|
||||||
db *sql.DB
|
db *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRememberPlugin creates a new RememberPlugin with the Plugin interface
|
// NewRememberPlugin creates a new RememberPlugin with the Plugin interface
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Package to connect to slack service
|
// Package slack connects to slack service
|
||||||
package slack
|
package slack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -113,7 +113,7 @@ func (s *Slack) Serve() {
|
||||||
for {
|
for {
|
||||||
msg, err := s.receiveMessage()
|
msg, err := s.receiveMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Slack API error: ", err)
|
log.Fatalf("Slack API error: %s", err)
|
||||||
}
|
}
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case "message":
|
case "message":
|
||||||
|
@ -134,7 +134,7 @@ func (s *Slack) Serve() {
|
||||||
|
|
||||||
// Convert a slackMessage to a bot.Message
|
// Convert a slackMessage to a bot.Message
|
||||||
func (s *Slack) buildMessage(msg slackMessage) bot.Message {
|
func (s *Slack) buildMessage(msg slackMessage) bot.Message {
|
||||||
log.Println("DEBUG: msg: %%#v", msg)
|
log.Printf("DEBUG: msg: %#v", msg)
|
||||||
text := html.UnescapeString(msg.Text)
|
text := html.UnescapeString(msg.Text)
|
||||||
|
|
||||||
isCmd, text := bot.IsCmd(s.config, text)
|
isCmd, text := bot.IsCmd(s.config, text)
|
||||||
|
|
Loading…
Reference in New Issue