mirror of https://github.com/velour/catbase.git
Initial mongo->sqlite move
Tons of bugs, I'm sure. This commit mostly gets the bot moving towards SQLite. It builds, but many plugins have a log.Fatal to prevent their use and it has not been tested.
This commit is contained in:
parent
cdbe9a81d7
commit
1efa7ebcd4
67
bot/bot.go
67
bot/bot.go
|
@ -3,6 +3,7 @@
|
||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -11,7 +12,8 @@ import (
|
||||||
|
|
||||||
"code.google.com/p/velour/irc"
|
"code.google.com/p/velour/irc"
|
||||||
"github.com/chrissexton/alepale/config"
|
"github.com/chrissexton/alepale/config"
|
||||||
"labix.org/v2/mgo"
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const actionPrefix = "\x01ACTION"
|
const actionPrefix = "\x01ACTION"
|
||||||
|
@ -35,11 +37,9 @@ type Bot struct {
|
||||||
|
|
||||||
Config *config.Config
|
Config *config.Config
|
||||||
|
|
||||||
// Mongo connection and db allow botwide access to the database
|
// SQL DB
|
||||||
DbSession *mgo.Session
|
DB *sql.DB
|
||||||
Db *mgo.Database
|
DBVersion int64
|
||||||
|
|
||||||
varColl *mgo.Collection
|
|
||||||
|
|
||||||
logIn chan Message
|
logIn chan Message
|
||||||
logOut chan Messages
|
logOut chan Messages
|
||||||
|
@ -101,13 +101,11 @@ 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, c *irc.Client) *Bot {
|
func NewBot(config *config.Config, c *irc.Client) *Bot {
|
||||||
session, err := mgo.Dial(config.DbServer)
|
sqlDB, err := sql.Open("sqlite3", config.DbFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := session.DB(config.DbName)
|
|
||||||
|
|
||||||
logIn := make(chan Message)
|
logIn := make(chan Message)
|
||||||
logOut := make(chan Messages)
|
logOut := make(chan Messages)
|
||||||
|
|
||||||
|
@ -126,15 +124,15 @@ func NewBot(config *config.Config, c *irc.Client) *Bot {
|
||||||
Users: users,
|
Users: users,
|
||||||
Me: users[0],
|
Me: users[0],
|
||||||
Client: c,
|
Client: c,
|
||||||
DbSession: session,
|
DB: sqlDB,
|
||||||
Db: db,
|
|
||||||
varColl: db.C("variables"),
|
|
||||||
logIn: logIn,
|
logIn: logIn,
|
||||||
logOut: logOut,
|
logOut: logOut,
|
||||||
Version: config.Version,
|
Version: config.Version,
|
||||||
httpEndPoints: make(map[string]string),
|
httpEndPoints: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bot.migrateDB()
|
||||||
|
|
||||||
http.HandleFunc("/", bot.serveRoot)
|
http.HandleFunc("/", bot.serveRoot)
|
||||||
if config.HttpAddr == "" {
|
if config.HttpAddr == "" {
|
||||||
config.HttpAddr = "127.0.0.1:1337"
|
config.HttpAddr = "127.0.0.1:1337"
|
||||||
|
@ -144,6 +142,49 @@ func NewBot(config *config.Config, c *irc.Client) *Bot {
|
||||||
return bot
|
return bot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create any tables if necessary based on version of DB
|
||||||
|
// Plugins should create their own tables, these are only for official bot stuff
|
||||||
|
// Note: This does not return an error. Database issues are all fatal at this stage.
|
||||||
|
func (b *Bot) migrateDB() {
|
||||||
|
_, err := b.DB.Exec(`create table if not exists version (version integer);`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
var version int64
|
||||||
|
err = b.DB.QueryRow("select max(version) from version").Scan(&version)
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
log.Printf("No versions, we're the first!.")
|
||||||
|
_, err := b.DB.Exec(`insert into version (version) values (1)`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
case err != nil:
|
||||||
|
log.Fatal(err)
|
||||||
|
default:
|
||||||
|
b.DBVersion = version
|
||||||
|
log.Printf("Database version: %d\n", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if version == 1 {
|
||||||
|
if _, err := b.DB.Exec(`create table if not exists variables (
|
||||||
|
id integer primary key,
|
||||||
|
name string,
|
||||||
|
perms string,
|
||||||
|
type string
|
||||||
|
);`); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := b.DB.Exec(`create table if not exists values (
|
||||||
|
id integer primary key,
|
||||||
|
varId integer,
|
||||||
|
value string
|
||||||
|
);`); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a constructed handler to the bots handlers list
|
// Adds a constructed handler to the bots handlers list
|
||||||
func (b *Bot) AddHandler(name string, h Handler) {
|
func (b *Bot) AddHandler(name string, h Handler) {
|
||||||
b.Plugins[strings.ToLower(name)] = h
|
b.Plugins[strings.ToLower(name)] = h
|
||||||
|
|
|
@ -3,15 +3,17 @@
|
||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/velour/irc"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"labix.org/v2/mgo/bson"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.google.com/p/velour/irc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface used for compatibility with the Plugin interface
|
// Interface used for compatibility with the Plugin interface
|
||||||
|
@ -180,28 +182,43 @@ func (b *Bot) Filter(message Message, input string) string {
|
||||||
blacklist := make(map[string]bool)
|
blacklist := make(map[string]bool)
|
||||||
blacklist["$and"] = true
|
blacklist["$and"] = true
|
||||||
for len(varname) > 0 && !blacklist[varname] {
|
for len(varname) > 0 && !blacklist[varname] {
|
||||||
var result []Variable
|
text, err := b.getVar(varname)
|
||||||
b.varColl.Find(bson.M{"variable": varname}).All(&result)
|
if err != nil {
|
||||||
if len(result) == 0 {
|
|
||||||
blacklist[varname] = true
|
blacklist[varname] = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
variable := result[rand.Intn(len(result))]
|
input = strings.Replace(input, varname, text, 1)
|
||||||
input = strings.Replace(input, varname, variable.Value, 1)
|
|
||||||
varname = r.FindString(input)
|
varname = r.FindString(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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(err)
|
||||||
|
}
|
||||||
|
return text, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bot) listVars(channel string, parts []string) {
|
func (b *Bot) listVars(channel string, parts []string) {
|
||||||
var result []string
|
rows, err := b.DB.Query(`select name from variables`)
|
||||||
err := b.varColl.Find(bson.M{}).Distinct("variable", &result)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
msg := "I know: $who, $someone, $digit, $nonzero"
|
msg := "I know: $who, $someone, $digit, $nonzero"
|
||||||
for _, variable := range result {
|
for rows.Next() {
|
||||||
|
var variable string
|
||||||
|
err := rows.Scan(&variable)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error scanning variable.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg = fmt.Sprintf("%s, %s", msg, variable)
|
msg = fmt.Sprintf("%s, %s", msg, variable)
|
||||||
}
|
}
|
||||||
b.SendMessage(channel, msg)
|
b.SendMessage(channel, msg)
|
||||||
|
|
90
bot/users.go
90
bot/users.go
|
@ -2,13 +2,6 @@
|
||||||
|
|
||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
|
||||||
// "labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// User type stores user history. This is a vehicle that will follow the user for the active
|
// User type stores user history. This is a vehicle that will follow the user for the active
|
||||||
// session
|
// session
|
||||||
type User struct {
|
type User struct {
|
||||||
|
@ -26,6 +19,18 @@ type User struct {
|
||||||
//bot *Bot
|
//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 {
|
func (b *Bot) NewUser(nick string) *User {
|
||||||
return &User{
|
return &User{
|
||||||
Name: nick,
|
Name: nick,
|
||||||
|
@ -33,77 +38,6 @@ func (b *Bot) NewUser(nick string) *User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bot) GetUser(nick string) *User {
|
|
||||||
coll := b.Db.C("users")
|
|
||||||
query := coll.Find(bson.M{"name": nick})
|
|
||||||
var user *User
|
|
||||||
|
|
||||||
count, err := query.Count()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
user = b.NewUser(nick)
|
|
||||||
coll.Insert(*user)
|
|
||||||
} else if count == 1 {
|
|
||||||
err = query.One(&user)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("ERROR adding user: %s -- %s\n", nick, err)
|
|
||||||
}
|
|
||||||
} else if count == 0 {
|
|
||||||
// create the user
|
|
||||||
log.Printf("Creating new user: %s\n", nick)
|
|
||||||
user = b.NewUser(nick)
|
|
||||||
coll.Insert(user)
|
|
||||||
} else {
|
|
||||||
log.Printf("Error: %s appears to have more than one user?\n", nick)
|
|
||||||
query.One(&user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// grab linked user, if any
|
|
||||||
if user.Parent != "" {
|
|
||||||
query := coll.Find(bson.M{"Name": user.Parent})
|
|
||||||
if count, err := query.Count(); err != nil && count == 1 {
|
|
||||||
query.One(user)
|
|
||||||
} else {
|
|
||||||
log.Printf("Error: bad linkage on %s -> %s.\n",
|
|
||||||
user.Name,
|
|
||||||
user.Parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, u := range b.Users {
|
|
||||||
if u.Name == user.Name {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
b.Users = append(b.Users, *user)
|
|
||||||
}
|
|
||||||
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify user entry to be a link to other, return other
|
|
||||||
func (u *User) LinkUser(coll *mgo.Collection, other *User) *User {
|
|
||||||
user := u
|
|
||||||
|
|
||||||
other.Alts = append(other.Alts, user.Alts...)
|
|
||||||
user.Alts = []string{}
|
|
||||||
user.Parent = other.Name
|
|
||||||
|
|
||||||
err := coll.Update(bson.M{"name": u.Name}, u)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error updating user: %s\n", u.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = coll.Update(bson.M{"name": other.Name}, other)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error updating other user: %s\n", other.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return other
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bot) checkAdmin(nick string) bool {
|
func (b *Bot) checkAdmin(nick string) bool {
|
||||||
for _, u := range b.Config.Admins {
|
for _, u := range b.Config.Admins {
|
||||||
if nick == u {
|
if nick == u {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import "io/ioutil"
|
||||||
// Config stores any system-wide startup information that cannot be easily configured via
|
// Config stores any system-wide startup information that cannot be easily configured via
|
||||||
// the database
|
// the database
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
DbFile string
|
||||||
DbName string
|
DbName string
|
||||||
DbServer string
|
DbServer string
|
||||||
Channels []string
|
Channels []string
|
||||||
|
|
|
@ -3,26 +3,28 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrissexton/alepale/bot"
|
"log"
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrissexton/alepale/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
||||||
type AdminPlugin struct {
|
type AdminPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
factC, remC, beerC, varC *mgo.Collection
|
DB *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface
|
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface
|
||||||
func NewAdminPlugin(bot *bot.Bot) *AdminPlugin {
|
func NewAdminPlugin(bot *bot.Bot) *AdminPlugin {
|
||||||
p := &AdminPlugin{
|
p := &AdminPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
|
DB: bot.DB,
|
||||||
}
|
}
|
||||||
p.LoadData()
|
p.LoadData()
|
||||||
return p
|
return p
|
||||||
|
@ -56,20 +58,25 @@ func (p *AdminPlugin) handleVariables(message bot.Message) bool {
|
||||||
variable := strings.TrimSpace(parts[0])
|
variable := strings.TrimSpace(parts[0])
|
||||||
value := parts[1]
|
value := parts[1]
|
||||||
|
|
||||||
q := p.varC.Find(bson.M{"variable": variable, "value": value})
|
var count int64
|
||||||
if n, _ := q.Count(); n != 0 {
|
var varId int64
|
||||||
p.Bot.SendMessage(message.Channel, "I've already got that one.")
|
err := p.DB.QueryRow(`select count(*), varId from variables vs inner join values v on vs.id = v.varId where vs.name = ? and v.value = ?`, variable, value).Scan(&count)
|
||||||
return true
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
_, err := p.DB.Exec(`insert into values (varId, value) values (?, ?)`, varId, value)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.varC.Insert(bot.Variable{
|
|
||||||
Variable: variable,
|
|
||||||
Value: value,
|
|
||||||
})
|
|
||||||
|
|
||||||
msg := fmt.Sprintf("Added '%s' to %s.\n", value, variable)
|
msg := fmt.Sprintf("Added '%s' to %s.\n", value, variable)
|
||||||
p.Bot.SendMessage(message.Channel, msg)
|
p.Bot.SendMessage(message.Channel, msg)
|
||||||
return true
|
return true
|
||||||
|
case err != nil:
|
||||||
|
p.Bot.SendMessage(message.Channel, "I'm broke and need attention in my variable creation code.")
|
||||||
|
log.Println(err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
p.Bot.SendMessage(message.Channel, "I've already got that one.")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadData imports any configuration data into the plugin. This is not strictly necessary other
|
// LoadData imports any configuration data into the plugin. This is not strictly necessary other
|
||||||
|
@ -78,10 +85,6 @@ func (p *AdminPlugin) handleVariables(message bot.Message) bool {
|
||||||
func (p *AdminPlugin) LoadData() {
|
func (p *AdminPlugin) LoadData() {
|
||||||
// This bot has no data to load
|
// This bot has no data to load
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
p.factC = p.Bot.Db.C("factoid")
|
|
||||||
p.remC = p.Bot.Db.C("remember")
|
|
||||||
p.beerC = p.Bot.Db.C("beers")
|
|
||||||
p.varC = p.Bot.Db.C("variables")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help responds to help requests. Every plugin must implement a help function.
|
// Help responds to help requests. Every plugin must implement a help function.
|
||||||
|
|
174
plugins/beers.go
174
plugins/beers.go
|
@ -3,6 +3,7 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -15,21 +16,56 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/chrissexton/alepale/bot"
|
"github.com/chrissexton/alepale/bot"
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
Coll *mgo.Collection
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
type userBeers struct {
|
||||||
|
id int64
|
||||||
|
nick string
|
||||||
|
count int
|
||||||
|
lastDrunk time.Time
|
||||||
|
saved bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type untappdUser struct {
|
||||||
|
id int64
|
||||||
|
untappdUser string
|
||||||
|
channel string
|
||||||
|
lastCheckin int
|
||||||
|
chanNick string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBeersPlugin creates a new BeersPlugin with the Plugin interface
|
// NewBeersPlugin creates a new BeersPlugin with the Plugin interface
|
||||||
func NewBeersPlugin(bot *bot.Bot) *BeersPlugin {
|
func NewBeersPlugin(bot *bot.Bot) *BeersPlugin {
|
||||||
|
if bot.DBVersion == 1 {
|
||||||
|
if _, err := bot.DB.Exec(`create table if not exists beers (
|
||||||
|
id integer primary key,
|
||||||
|
nick string,
|
||||||
|
count integer,
|
||||||
|
lastDrunk integer
|
||||||
|
);`); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := bot.DB.Exec(`create table if not exists untappd (
|
||||||
|
id integer primary key,
|
||||||
|
untappdUser string
|
||||||
|
channel string
|
||||||
|
lastCheckin integer
|
||||||
|
chanNick string
|
||||||
|
);`); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
p := BeersPlugin{
|
p := BeersPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
|
db: bot.DB,
|
||||||
}
|
}
|
||||||
p.LoadData()
|
p.LoadData()
|
||||||
for _, channel := range bot.Config.UntappdChannels {
|
for _, channel := range bot.Config.UntappdChannels {
|
||||||
|
@ -38,31 +74,39 @@ func NewBeersPlugin(bot *bot.Bot) *BeersPlugin {
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
type userBeers struct {
|
func (u *userBeers) Save(db *sql.DB) error {
|
||||||
Nick string
|
if !u.saved {
|
||||||
Beercount int
|
res, err := db.Exec(`insert into beers (
|
||||||
Lastdrunk time.Time
|
nick string,
|
||||||
Momentum float64
|
count integer,
|
||||||
New bool
|
lastDrunk integer
|
||||||
}
|
) values (?, ?, ?)`, u.nick, u.count, u.lastDrunk)
|
||||||
|
|
||||||
func (u *userBeers) Save(coll *mgo.Collection) {
|
|
||||||
_, err := coll.Upsert(bson.M{"nick": u.Nick}, u)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
id, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.id = id
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserBeers(coll *mgo.Collection, nick string) *userBeers {
|
func getUserBeers(db *sql.DB, nick string) *userBeers {
|
||||||
ub := userBeers{New: true}
|
var ub userBeers
|
||||||
coll.Find(bson.M{"nick": nick}).One(&ub)
|
err := db.QueryRow(`select id, nick, count, lastDrunk from beers
|
||||||
if ub.New == true {
|
where nick = ?`, nick).Scan(
|
||||||
ub.New = false
|
&ub.id,
|
||||||
ub.Nick = nick
|
&ub.nick,
|
||||||
ub.Beercount = 0
|
&ub.count,
|
||||||
ub.Momentum = 0
|
&ub.lastDrunk,
|
||||||
ub.Save(coll)
|
)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
log.Println(err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ub
|
return &ub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,16 +204,33 @@ func (p *BeersPlugin) Message(message bot.Message) bool {
|
||||||
channel = parts[3]
|
channel = parts[3]
|
||||||
}
|
}
|
||||||
u := untappdUser{
|
u := untappdUser{
|
||||||
UntappdUser: parts[1],
|
untappdUser: parts[1],
|
||||||
ChanNick: chanNick,
|
chanNick: chanNick,
|
||||||
Channel: channel,
|
channel: channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Creating Untappd user:", u.UntappdUser, "nick:", u.ChanNick)
|
log.Println("Creating Untappd user:", u.untappdUser, "nick:", u.chanNick)
|
||||||
|
|
||||||
_, err := p.Coll.Upsert(bson.M{"untappduser": u.UntappdUser}, u)
|
var count int
|
||||||
|
err := p.db.QueryRow(`select count(*) from untappd
|
||||||
|
where untappdUser = ?`, u.untappdUser).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("ERROR!!!:", err)
|
log.Println("Error registering untappd: ", err)
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
p.Bot.SendMessage(channel, "I'm already watching you.")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_, err = p.db.Exec(`insert into untappd (
|
||||||
|
untappdUser,
|
||||||
|
channel,
|
||||||
|
lastCheckin,
|
||||||
|
chanNick
|
||||||
|
) values (?, ?, ?, ?);`)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error registering untappd: ", err)
|
||||||
|
p.Bot.SendMessage(channel, "I can't see.")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Bot.SendMessage(channel, "I'll be watching you.")
|
p.Bot.SendMessage(channel, "I'll be watching you.")
|
||||||
|
@ -196,7 +257,6 @@ func (p *BeersPlugin) Event(kind string, message bot.Message) bool {
|
||||||
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
||||||
// date.
|
// date.
|
||||||
func (p *BeersPlugin) LoadData() {
|
func (p *BeersPlugin) LoadData() {
|
||||||
p.Coll = p.Bot.Db.C("beers")
|
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,10 +269,10 @@ func (p *BeersPlugin) Help(channel string, parts []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) setBeers(user string, amount int) {
|
func (p *BeersPlugin) setBeers(user string, amount int) {
|
||||||
ub := getUserBeers(p.Coll, user)
|
ub := getUserBeers(p.db, user)
|
||||||
ub.Beercount = amount
|
ub.count = amount
|
||||||
ub.Lastdrunk = time.Now()
|
ub.lastDrunk = time.Now()
|
||||||
ub.Save(p.Coll)
|
ub.Save(p.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) addBeers(user string) {
|
func (p *BeersPlugin) addBeers(user string) {
|
||||||
|
@ -220,9 +280,8 @@ func (p *BeersPlugin) addBeers(user string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) getBeers(nick string) int {
|
func (p *BeersPlugin) getBeers(nick string) int {
|
||||||
ub := getUserBeers(p.Coll, nick)
|
ub := getUserBeers(p.db, nick)
|
||||||
|
return ub.count
|
||||||
return ub.Beercount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) reportCount(nick, channel string, himself bool) {
|
func (p *BeersPlugin) reportCount(nick, channel string, himself bool) {
|
||||||
|
@ -245,9 +304,10 @@ func (p *BeersPlugin) puke(user string, channel string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) doIKnow(nick string) bool {
|
func (p *BeersPlugin) doIKnow(nick string) bool {
|
||||||
count, err := p.Coll.Find(bson.M{"nick": nick}).Count()
|
var count int
|
||||||
|
err := p.db.QueryRow(`select count(*) from beers where nick = ?`, nick).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return false
|
||||||
}
|
}
|
||||||
return count > 0
|
return count > 0
|
||||||
}
|
}
|
||||||
|
@ -288,15 +348,6 @@ type Beers struct {
|
||||||
Response resp
|
Response resp
|
||||||
}
|
}
|
||||||
|
|
||||||
type untappdUser struct {
|
|
||||||
Id bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
UntappdUser string
|
|
||||||
Channel string
|
|
||||||
LastCheckin int
|
|
||||||
ChanNick string
|
|
||||||
KnownCheckins [5]int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *BeersPlugin) pullUntappd() ([]checkin, error) {
|
func (p *BeersPlugin) pullUntappd() ([]checkin, error) {
|
||||||
access_token := "?access_token=" + p.Bot.Config.UntappdToken
|
access_token := "?access_token=" + p.Bot.Config.UntappdToken
|
||||||
baseUrl := "https://api.untappd.com/v4/checkin/recent/"
|
baseUrl := "https://api.untappd.com/v4/checkin/recent/"
|
||||||
|
@ -331,11 +382,20 @@ func (p *BeersPlugin) checkUntappd(channel string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var users []untappdUser
|
var users []untappdUser
|
||||||
p.Coll.Find(bson.M{"untappduser": bson.M{"$exists": true}, "channel": channel}).All(&users)
|
rows, err := p.db.Query(`select *from untappd`)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error getting untappd users: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
u := untappdUser{}
|
||||||
|
rows.Scan(&u.id, &u.untappdUser, &u.channel, &u.lastCheckin, &u.chanNick)
|
||||||
|
users = append(users, u)
|
||||||
|
}
|
||||||
|
|
||||||
userMap := make(map[string]untappdUser)
|
userMap := make(map[string]untappdUser)
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
userMap[u.UntappdUser] = u
|
userMap[u.untappdUser] = u
|
||||||
}
|
}
|
||||||
|
|
||||||
chks, err := p.pullUntappd()
|
chks, err := p.pullUntappd()
|
||||||
|
@ -347,7 +407,7 @@ func (p *BeersPlugin) checkUntappd(channel string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if checkin.Checkin_id <= userMap[checkin.User.User_name].LastCheckin {
|
if checkin.Checkin_id <= userMap[checkin.User.User_name].lastCheckin {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,18 +422,20 @@ func (p *BeersPlugin) checkUntappd(channel string) {
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.addBeers(user.ChanNick)
|
p.addBeers(user.chanNick)
|
||||||
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",
|
||||||
user.ChanNick, beerName, breweryName, venue, drunken)
|
user.chanNick, beerName, breweryName, venue, drunken)
|
||||||
if checkin.Checkin_comment != "" {
|
if checkin.Checkin_comment != "" {
|
||||||
msg = fmt.Sprintf("%s -- %s",
|
msg = fmt.Sprintf("%s -- %s",
|
||||||
msg, checkin.Checkin_comment)
|
msg, checkin.Checkin_comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
user.LastCheckin = checkin.Checkin_id
|
user.lastCheckin = checkin.Checkin_id
|
||||||
err := p.Coll.Update(bson.M{"_id": user.Id}, user)
|
_, err := p.db.Exec(`update untappd set
|
||||||
|
lastCheckin = ?
|
||||||
|
where id = ?`, user.lastCheckin, user.id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("UPDATE ERROR!:", err)
|
log.Println("UPDATE ERROR!:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,23 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrissexton/alepale/bot"
|
"log"
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/chrissexton/alepale/bot"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a counter plugin to count arbitrary things.
|
// This is a counter plugin to count arbitrary things.
|
||||||
|
|
||||||
type CounterPlugin struct {
|
type CounterPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
Coll *mgo.Collection
|
DB *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
|
ID int64
|
||||||
Nick string
|
Nick string
|
||||||
Item string
|
Item string
|
||||||
Count int
|
Count int
|
||||||
|
@ -25,9 +27,19 @@ type Item struct {
|
||||||
|
|
||||||
// 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 _, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
return &CounterPlugin{
|
return &CounterPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
Coll: bot.Db.C("counter"),
|
DB: bot.DB,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,38 +67,47 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull all of the items associated with "subject"
|
// pull all of the items associated with "subject"
|
||||||
var items []Item
|
rows, err := p.DB.Query(`select * from counter where nick = ?`, subject)
|
||||||
p.Coll.Find(bson.M{"nick": subject}).All(&items)
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
if len(items) == 0 {
|
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("%s has no counters.", subject))
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := fmt.Sprintf("%s has the following counters:", subject)
|
resp := fmt.Sprintf("%s has the following counters:", subject)
|
||||||
for i, item := range items {
|
count := 0
|
||||||
if i != 0 {
|
for rows.Next() {
|
||||||
resp = fmt.Sprintf("%s,", resp)
|
count += 1
|
||||||
|
var it Item
|
||||||
|
rows.Scan(&it.Nick, &it.Item, &it.Count)
|
||||||
|
|
||||||
|
if count > 1 {
|
||||||
|
resp = fmt.Sprintf("%s, ", resp)
|
||||||
}
|
}
|
||||||
resp = fmt.Sprintf("%s %s: %d", resp, item.Item, item.Count)
|
resp = fmt.Sprintf("%s %s: %d", resp, it.Item, it.Count)
|
||||||
if i > 20 {
|
if count > 20 {
|
||||||
fmt.Sprintf("%s, and a few others", resp)
|
fmt.Sprintf("%s, and a few others", resp)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp = fmt.Sprintf("%s.", resp)
|
resp = fmt.Sprintf("%s.", resp)
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has no counters.", subject))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
p.Bot.SendMessage(channel, resp)
|
p.Bot.SendMessage(channel, resp)
|
||||||
return true
|
return true
|
||||||
} else if message.Command && len(parts) == 2 && parts[0] == "clear" {
|
} else if message.Command && len(parts) == 2 && parts[0] == "clear" {
|
||||||
subject := strings.ToLower(nick)
|
subject := strings.ToLower(nick)
|
||||||
itemName := strings.ToLower(parts[1])
|
itemName := strings.ToLower(parts[1])
|
||||||
|
|
||||||
p.Coll.Remove(bson.M{"nick": subject, "item": itemName})
|
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
|
||||||
|
}
|
||||||
|
|
||||||
p.Bot.SendAction(channel, fmt.Sprintf("chops a few %s out of his brain",
|
p.Bot.SendAction(channel, fmt.Sprintf("chops a few %s out of his brain",
|
||||||
itemName))
|
itemName))
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
} else if message.Command && parts[0] == "count" {
|
} else if message.Command && parts[0] == "count" {
|
||||||
|
@ -105,11 +126,18 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
var item Item
|
var item Item
|
||||||
err := p.Coll.Find(bson.M{"nick": subject, "item": itemName}).One(&item)
|
err := p.DB.QueryRow(`select nick, item, count from counters
|
||||||
if err != nil {
|
where nick = ? and item = ?`, subject, itemName).Scan(
|
||||||
|
&item.Nick, &item.Item, &item.Count,
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
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:
|
||||||
|
log.Println(err)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject, item.Count,
|
p.Bot.SendMessage(channel, fmt.Sprintf("%s has %d %s.", subject, item.Count,
|
||||||
|
@ -149,21 +177,31 @@ func (p *CounterPlugin) Message(message bot.Message) bool {
|
||||||
|
|
||||||
func (p *CounterPlugin) update(subject, itemName string, delta int) Item {
|
func (p *CounterPlugin) update(subject, itemName string, delta int) Item {
|
||||||
var item Item
|
var item Item
|
||||||
err := p.Coll.Find(bson.M{"nick": subject, "item": itemName}).One(&item)
|
err := p.DB.QueryRow(`select id, nick, item, count from counter
|
||||||
if err != nil {
|
where nick = ? and item = ?;`, subject, itemName).Scan(
|
||||||
|
&item.ID, &item.Nick, &item.Item, &item.Count,
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
// insert it
|
// insert it
|
||||||
item = Item{
|
res, err := p.DB.Exec(`insert into counter (nick, item, count)
|
||||||
Nick: subject,
|
values (?, ?, ?)`, subject, itemName, delta)
|
||||||
Item: itemName,
|
if err != nil {
|
||||||
Count: delta,
|
log.Println(err)
|
||||||
}
|
}
|
||||||
p.Coll.Insert(item)
|
id, err := res.LastInsertId()
|
||||||
} else {
|
return Item{id, subject, itemName, delta}
|
||||||
// update it
|
case err != nil:
|
||||||
|
log.Println(err)
|
||||||
|
return item
|
||||||
|
default:
|
||||||
item.Count += delta
|
item.Count += delta
|
||||||
p.Coll.Update(bson.M{"nick": subject, "item": itemName}, item)
|
_, err := p.DB.Exec(`update counter set count = ? where id = ?`, item.Count, item.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
}
|
}
|
||||||
return item
|
return item
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadData imports any configuration data into the plugin. This is not
|
// LoadData imports any configuration data into the plugin. This is not
|
||||||
|
|
|
@ -6,12 +6,13 @@ import "github.com/chrissexton/alepale/bot"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"log"
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"labix.org/v2/mgo"
|
||||||
|
"labix.org/v2/mgo/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a downtime plugin to monitor how much our users suck
|
// This is a downtime plugin to monitor how much our users suck
|
||||||
|
@ -123,7 +124,9 @@ func (p *DowntimePlugin) remove(user string) {
|
||||||
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
||||||
// date.
|
// date.
|
||||||
func (p *DowntimePlugin) LoadData() {
|
func (p *DowntimePlugin) LoadData() {
|
||||||
p.Coll = p.Bot.Db.C("downtime")
|
// Mongo is removed, this plugin will crash if started
|
||||||
|
log.Fatal("The Downtime plugin has not been upgraded to SQL yet.")
|
||||||
|
// p.Coll = p.Bot.Db.C("downtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help responds to help requests. Every plugin must implement a help function.
|
// Help responds to help requests. Every plugin must implement a help function.
|
||||||
|
|
|
@ -420,7 +420,9 @@ func (p *FactoidPlugin) Message(message bot.Message) bool {
|
||||||
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
||||||
// date.
|
// date.
|
||||||
func (p *FactoidPlugin) LoadData() {
|
func (p *FactoidPlugin) LoadData() {
|
||||||
p.Coll = p.Bot.Db.C("factoid")
|
// Mongo is removed, this plugin will crash if started
|
||||||
|
log.Fatal("The Factoid plugin has not been upgraded to SQL yet.")
|
||||||
|
// p.Coll = p.Bot.Db.C("factoid")
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,11 @@ type FeedPlugin struct {
|
||||||
|
|
||||||
// NewFeedPlugin creates a new FeedPlugin with the Plugin interface
|
// NewFeedPlugin creates a new FeedPlugin with the Plugin interface
|
||||||
func NewFeedPlugin(bot *bot.Bot) *FeedPlugin {
|
func NewFeedPlugin(bot *bot.Bot) *FeedPlugin {
|
||||||
|
// Mongo is removed, this plugin will crash if started
|
||||||
|
log.Fatal("The Feed plugin has not been upgraded to SQL yet.")
|
||||||
p := FeedPlugin{
|
p := FeedPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
Coll: bot.Db.C("feed"),
|
// Coll: bot.Db.C("feed"),
|
||||||
}
|
}
|
||||||
go p.pollFeeds()
|
go p.pollFeeds()
|
||||||
return &p
|
return &p
|
||||||
|
|
|
@ -4,13 +4,14 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrissexton/alepale/bot"
|
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrissexton/alepale/bot"
|
||||||
|
"labix.org/v2/mgo"
|
||||||
|
"labix.org/v2/mgo/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -30,7 +31,10 @@ type FirstEntry struct {
|
||||||
|
|
||||||
// NewFirstPlugin creates a new FirstPlugin with the Plugin interface
|
// NewFirstPlugin creates a new FirstPlugin with the Plugin interface
|
||||||
func NewFirstPlugin(b *bot.Bot) *FirstPlugin {
|
func NewFirstPlugin(b *bot.Bot) *FirstPlugin {
|
||||||
coll := b.Db.C("first")
|
// Mongo is removed, this plugin will crash if started
|
||||||
|
log.Fatal("The First plugin has not been upgraded to SQL yet.")
|
||||||
|
var coll *mgo.Collection
|
||||||
|
// coll := b.Db.C("first")
|
||||||
var firsts []FirstEntry
|
var firsts []FirstEntry
|
||||||
query := bson.M{"day": midnight(time.Now())}
|
query := bson.M{"day": midnight(time.Now())}
|
||||||
log.Println("Day:", midnight(time.Now()))
|
log.Println("Day:", midnight(time.Now()))
|
||||||
|
|
|
@ -4,17 +4,16 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrissexton/alepale/bot"
|
|
||||||
"github.com/chrissexton/kakapo/lisp"
|
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrissexton/alepale/bot"
|
||||||
|
"github.com/chrissexton/kakapo/lisp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LispPlugin struct {
|
type LispPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
Coll *mgo.Collection
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Program struct {
|
type Program struct {
|
||||||
|
@ -27,7 +26,6 @@ type Program struct {
|
||||||
func NewLispPlugin(bot *bot.Bot) *LispPlugin {
|
func NewLispPlugin(bot *bot.Bot) *LispPlugin {
|
||||||
return &LispPlugin{
|
return &LispPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
Coll: bot.Db.C("lisp"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +41,6 @@ func (p *LispPlugin) Message(message bot.Message) bool {
|
||||||
Contents: strings.Replace(message.Body, "lisp:", "", 1),
|
Contents: strings.Replace(message.Body, "lisp:", "", 1),
|
||||||
}
|
}
|
||||||
log.Println("Evaluating:", prog)
|
log.Println("Evaluating:", prog)
|
||||||
p.Coll.Insert(prog)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
|
|
@ -75,8 +75,7 @@ type PluginConfig struct {
|
||||||
Values map[string]interface{}
|
Values map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads plugin config out of the DB
|
// Loads plugin config (could be out of a DB or something)
|
||||||
// Stored in db.plugins.find("name": name)
|
|
||||||
func GetPluginConfig(name string) PluginConfig {
|
func GetPluginConfig(name string) PluginConfig {
|
||||||
return PluginConfig{
|
return PluginConfig{
|
||||||
Name: "TestPlugin",
|
Name: "TestPlugin",
|
||||||
|
|
|
@ -4,13 +4,14 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrissexton/alepale/bot"
|
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrissexton/alepale/bot"
|
||||||
|
"labix.org/v2/mgo"
|
||||||
|
"labix.org/v2/mgo/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -94,14 +95,15 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
if len(msgs) == len(snips) {
|
if len(msgs) == len(snips) {
|
||||||
msg := strings.Join(msgs, "$and")
|
msg := strings.Join(msgs, "$and")
|
||||||
var funcres bson.M
|
var funcres bson.M
|
||||||
err := p.Bot.Db.Run(
|
// Needs to be upgraded to SQL
|
||||||
bson.M{"eval": "return counter(\"factoid\");"},
|
// err := p.Bot.Db.Run(
|
||||||
&funcres,
|
// bson.M{"eval": "return counter(\"factoid\");"},
|
||||||
)
|
// &funcres,
|
||||||
|
// )
|
||||||
|
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
id := int(funcres["retval"].(float64))
|
id := int(funcres["retval"].(float64))
|
||||||
|
|
||||||
fact := Factoid{
|
fact := Factoid{
|
||||||
|
@ -116,7 +118,7 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
LastAccessed: time.Now(),
|
LastAccessed: time.Now(),
|
||||||
AccessCount: 0,
|
AccessCount: 0,
|
||||||
}
|
}
|
||||||
if err = p.Coll.Insert(fact); err != nil {
|
if err := p.Coll.Insert(fact); err != nil {
|
||||||
log.Println("ERROR!!!!:", err)
|
log.Println("ERROR!!!!:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +144,9 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
// necessary other than the fact that the Plugin interface demands it exist.
|
// necessary other than the fact that the Plugin interface demands it exist.
|
||||||
// This may be deprecated at a later date.
|
// This may be deprecated at a later date.
|
||||||
func (p *RememberPlugin) LoadData() {
|
func (p *RememberPlugin) LoadData() {
|
||||||
p.Coll = p.Bot.Db.C("factoid")
|
// Mongo is removed, this plugin will crash if started
|
||||||
|
log.Fatal("The Remember plugin has not been upgraded to SQL yet.")
|
||||||
|
// p.Coll = p.Bot.Db.C("factoid")
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,143 +0,0 @@
|
||||||
// © 2013 the AlePale Authors under the WTFPL. See AUTHORS for the list of authors.
|
|
||||||
|
|
||||||
package plugins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bitbucket.org/phlyingpenguin/twitter"
|
|
||||||
"github.com/chrissexton/alepale/bot"
|
|
||||||
"github.com/garyburd/go-oauth/oauth"
|
|
||||||
"labix.org/v2/mgo"
|
|
||||||
"labix.org/v2/mgo/bson"
|
|
||||||
"log"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Plugin to squak tweets at the channel.
|
|
||||||
|
|
||||||
type TwitterPlugin struct {
|
|
||||||
Bot *bot.Bot
|
|
||||||
Coll *mgo.Collection
|
|
||||||
Client *twitter.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
type twitterUser struct {
|
|
||||||
Id bson.ObjectId `bson:"_id,omitempty"`
|
|
||||||
User string
|
|
||||||
Tweets []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTwitterPlugin creates a new TwitterPlugin with the Plugin interface
|
|
||||||
func NewTwitterPlugin(bot *bot.Bot) *TwitterPlugin {
|
|
||||||
return &TwitterPlugin{
|
|
||||||
Bot: bot,
|
|
||||||
Coll: bot.Db.C("twitter"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *TwitterPlugin) say(message bot.Message, body string) bool {
|
|
||||||
p.Bot.SendMessage(message.Channel, body)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for commands accepted
|
|
||||||
// follow, unfollow
|
|
||||||
func (p *TwitterPlugin) checkCommand(message bot.Message) bool {
|
|
||||||
parts := strings.Split(message.Body, " ")
|
|
||||||
if parts[0] == "follow" {
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return p.say(message, "I don't get it.")
|
|
||||||
}
|
|
||||||
|
|
||||||
user := parts[1]
|
|
||||||
res := p.Coll.Find(bson.M{"user": user})
|
|
||||||
|
|
||||||
if count, _ := res.Count(); count > 0 {
|
|
||||||
return p.say(message, "I'm already following "+user+"!")
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Coll.Insert(twitterUser{User: user})
|
|
||||||
} else if parts[0] == "unfollow" {
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return p.say(message, "I don't get it.")
|
|
||||||
}
|
|
||||||
|
|
||||||
user := parts[1]
|
|
||||||
|
|
||||||
p.Coll.Remove(bson.M{"user": user})
|
|
||||||
return p.say(message, "Fuck "+user)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// Otherwise, the function returns false and the bot continues execution of other plugins.
|
|
||||||
func (p *TwitterPlugin) Message(message bot.Message) bool {
|
|
||||||
|
|
||||||
if message.Command {
|
|
||||||
return p.checkCommand(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadData imports any configuration data into the plugin. This is not strictly necessary other
|
|
||||||
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
|
|
||||||
// date.
|
|
||||||
func (p *TwitterPlugin) LoadData() {
|
|
||||||
// This bot has no data to load
|
|
||||||
p.Client = twitter.New(&oauth.Credentials{
|
|
||||||
Token: p.Bot.Config.TwitterConsumerKey,
|
|
||||||
Secret: p.Bot.Config.TwitterConsumerSecret,
|
|
||||||
})
|
|
||||||
|
|
||||||
p.Client.SetAuth(&oauth.Credentials{
|
|
||||||
Token: p.Bot.Config.TwitterUserKey,
|
|
||||||
Secret: p.Bot.Config.TwitterUserSecret,
|
|
||||||
})
|
|
||||||
|
|
||||||
_, err := p.Client.VerifyCredentials(nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Could not auth with twitter:", err)
|
|
||||||
} else {
|
|
||||||
go p.checkMessages()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Help responds to help requests. Every plugin must implement a help function.
|
|
||||||
func (p *TwitterPlugin) Help(channel string, parts []string) {
|
|
||||||
p.Bot.SendMessage(channel, "Tell me to follow or unfollow twitter users!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty event handler because this plugin does not do anything on event recv
|
|
||||||
func (p *TwitterPlugin) Event(kind string, message bot.Message) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *TwitterPlugin) checkMessages() {
|
|
||||||
for {
|
|
||||||
time.Sleep(time.Minute * 30)
|
|
||||||
var u url.Values
|
|
||||||
u.Set("screen_name", "phlyingpenguin")
|
|
||||||
data, err := p.Client.UserTimeline(u)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
} else {
|
|
||||||
log.Println(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler for bot's own messages
|
|
||||||
func (p *TwitterPlugin) BotMessage(message bot.Message) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register any web URLs desired
|
|
||||||
func (p *TwitterPlugin) RegisterWeb() *string {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -5,6 +5,8 @@ package plugins
|
||||||
// I hate this, but I'm creating strings of the templates to avoid having to
|
// I hate this, but I'm creating strings of the templates to avoid having to
|
||||||
// track where templates reside.
|
// track where templates reside.
|
||||||
|
|
||||||
|
// 2016-01-15 Later note, why are these in plugins and the server is in bot?
|
||||||
|
|
||||||
var factoidIndex string = `
|
var factoidIndex string = `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
Loading…
Reference in New Issue