mirror of https://github.com/velour/catbase.git
Added "what was that?", merged remember and factoid a bit, added fields to factoids, todo: stats on factoids, documentation.
This commit is contained in:
parent
0970ee980f
commit
89072fafb4
|
@ -14,18 +14,24 @@ import (
|
||||||
// This is a factoid plugin to serve as an example and quick copy/paste for new plugins.
|
// This is a factoid plugin to serve as an example and quick copy/paste for new plugins.
|
||||||
|
|
||||||
// factoid stores info about our factoid for lookup and later interaction
|
// factoid stores info about our factoid for lookup and later interaction
|
||||||
type factoid struct {
|
type Factoid struct {
|
||||||
|
_id bson.ObjectId `bson:"_id"`
|
||||||
Id int
|
Id int
|
||||||
Trigger string
|
Trigger string
|
||||||
Operator string
|
Operator string
|
||||||
FullText string
|
FullText string
|
||||||
|
Action string
|
||||||
CreatedBy string
|
CreatedBy string
|
||||||
|
DateCreated time.Time
|
||||||
|
LastAccessed time.Time
|
||||||
|
AccessCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
type FactoidPlugin struct {
|
type FactoidPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
Coll *mgo.Collection
|
Coll *mgo.Collection
|
||||||
NotFound []string
|
NotFound []string
|
||||||
|
LastFact Factoid
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface
|
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface
|
||||||
|
@ -43,6 +49,9 @@ func NewFactoidPlugin(bot *bot.Bot) *FactoidPlugin {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
p.LoadData()
|
p.LoadData()
|
||||||
|
for _, channel := range bot.Config.Channels {
|
||||||
|
go p.factTimer(channel)
|
||||||
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,19 +77,28 @@ func (p *FactoidPlugin) learnFact(message bot.Message, trigger, operator, fact s
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
newfact := factoid{
|
var funcres bson.M
|
||||||
Id: 0,
|
err := p.Bot.Db.Run(bson.M{"eval": "return counter(\"factoid\");"}, &funcres)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
id := int(funcres["retval"].(float64))
|
||||||
|
|
||||||
|
newfact := Factoid{
|
||||||
|
_id: bson.NewObjectId(),
|
||||||
|
Id: id,
|
||||||
Trigger: trigger,
|
Trigger: trigger,
|
||||||
Operator: operator,
|
Operator: operator,
|
||||||
FullText: full,
|
FullText: full,
|
||||||
|
Action: fact,
|
||||||
CreatedBy: message.User.Name,
|
CreatedBy: message.User.Name,
|
||||||
}
|
}
|
||||||
p.Coll.Insert(newfact)
|
p.Coll.Insert(newfact)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FactoidPlugin) findTrigger(message string) (bool, *factoid) {
|
func (p *FactoidPlugin) findTrigger(message string) (bool, *Factoid) {
|
||||||
var results []factoid
|
var results []Factoid
|
||||||
iter := p.Coll.Find(bson.M{"trigger": strings.ToLower(message)}).Iter()
|
iter := p.Coll.Find(bson.M{"trigger": strings.ToLower(message)}).Iter()
|
||||||
err := iter.All(&results)
|
err := iter.All(&results)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,9 +114,7 @@ func (p *FactoidPlugin) findTrigger(message string) (bool, *factoid) {
|
||||||
return true, &fact
|
return true, &fact
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FactoidPlugin) trigger(message bot.Message) bool {
|
func (p *FactoidPlugin) sayFact(message bot.Message, fact Factoid) {
|
||||||
if len(message.Body) > 4 || message.Command {
|
|
||||||
if ok, fact := p.findTrigger(message.Body); ok {
|
|
||||||
msg := p.Bot.Filter(message, fact.FullText)
|
msg := p.Bot.Filter(message, fact.FullText)
|
||||||
for i, m := 0, strings.Split(msg, "$and"); i < len(m) && i < 4; i++ {
|
for i, m := 0, strings.Split(msg, "$and"); i < len(m) && i < 4; i++ {
|
||||||
msg := strings.TrimSpace(m[i])
|
msg := strings.TrimSpace(m[i])
|
||||||
|
@ -112,6 +128,14 @@ func (p *FactoidPlugin) trigger(message bot.Message) bool {
|
||||||
p.Bot.SendMessage(message.Channel, msg)
|
p.Bot.SendMessage(message.Channel, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.LastFact = fact
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FactoidPlugin) trigger(message bot.Message) bool {
|
||||||
|
if len(message.Body) > 4 || message.Command || message.Body == "..." {
|
||||||
|
if ok, fact := p.findTrigger(message.Body); ok {
|
||||||
|
p.sayFact(message, *fact)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,6 +150,13 @@ func (p *FactoidPlugin) Message(message bot.Message) bool {
|
||||||
// This bot does not reply to anything
|
// This bot does not reply to anything
|
||||||
body := strings.TrimSpace(message.Body)
|
body := strings.TrimSpace(message.Body)
|
||||||
|
|
||||||
|
if strings.ToLower(message.Body) == "what was that?" {
|
||||||
|
fact := p.LastFact
|
||||||
|
msg := fmt.Sprintf("That was (#%d) '%s <%s> %s'", fact.Id, fact.Trigger, fact.Operator, fact.Action)
|
||||||
|
p.Bot.SendMessage(message.Channel, msg)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// This plugin has no business with normal messages
|
// This plugin has no business with normal messages
|
||||||
if !message.Command {
|
if !message.Command {
|
||||||
// look for any triggers in the db matching this message
|
// look for any triggers in the db matching this message
|
||||||
|
@ -193,3 +224,40 @@ func (p *FactoidPlugin) Help(channel string, parts []string) {
|
||||||
func (p *FactoidPlugin) Event(kind string, message bot.Message) bool {
|
func (p *FactoidPlugin) Event(kind string, message bot.Message) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *FactoidPlugin) randomFact() *Factoid {
|
||||||
|
var results []Factoid
|
||||||
|
iter := p.Coll.Find(bson.M{}).Iter()
|
||||||
|
err := iter.All(&results)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nfacts := len(results)
|
||||||
|
if nfacts == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fact := results[rand.Intn(nfacts)]
|
||||||
|
return &fact
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FactoidPlugin) factTimer(channel string) {
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Duration(p.Bot.Config.QuoteTime) * time.Minute)
|
||||||
|
chance := 1.0 / p.Bot.Config.QuoteChance
|
||||||
|
if rand.Intn(int(chance)) == 0 {
|
||||||
|
fact := p.randomFact()
|
||||||
|
if fact == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to fabricate a message so that bot.Filter can operate
|
||||||
|
message := bot.Message{
|
||||||
|
User: &p.Bot.Users[rand.Intn(len(p.Bot.Users))],
|
||||||
|
Channel: channel,
|
||||||
|
}
|
||||||
|
p.sayFact(message, *fact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,12 +12,6 @@ import (
|
||||||
|
|
||||||
// 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 userRemember struct {
|
|
||||||
Nick string
|
|
||||||
Message string
|
|
||||||
Date time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type RememberPlugin struct {
|
type RememberPlugin struct {
|
||||||
Bot *bot.Bot
|
Bot *bot.Bot
|
||||||
Coll *mgo.Collection
|
Coll *mgo.Collection
|
||||||
|
@ -31,9 +25,9 @@ func NewRememberPlugin(b *bot.Bot) *RememberPlugin {
|
||||||
Log: make(map[string][]bot.Message),
|
Log: make(map[string][]bot.Message),
|
||||||
}
|
}
|
||||||
p.LoadData()
|
p.LoadData()
|
||||||
for _, channel := range b.Config.Channels {
|
// for _, channel := range b.Config.Channels {
|
||||||
go p.quoteTimer(channel)
|
// go p.quoteTimer(channel)
|
||||||
}
|
// }
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +45,7 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user := message.User
|
||||||
parts := strings.Fields(message.Body)
|
parts := strings.Fields(message.Body)
|
||||||
if message.Command && len(parts) >= 3 && parts[0] == "remember" {
|
if message.Command && len(parts) >= 3 && parts[0] == "remember" {
|
||||||
// we have a remember!
|
// we have a remember!
|
||||||
|
@ -58,7 +53,7 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
nick := parts[1]
|
nick := parts[1]
|
||||||
snip := strings.Join(parts[2:], " ")
|
snip := strings.Join(parts[2:], " ")
|
||||||
|
|
||||||
if nick == message.User.Name {
|
if nick == user.Name {
|
||||||
msg := fmt.Sprintf("Don't try to quote yourself, %s.", nick)
|
msg := fmt.Sprintf("Don't try to quote yourself, %s.", nick)
|
||||||
p.Bot.SendMessage(message.Channel, msg)
|
p.Bot.SendMessage(message.Channel, msg)
|
||||||
return true
|
return true
|
||||||
|
@ -66,8 +61,6 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
|
|
||||||
for i := len(p.Log[message.Channel]) - 1; i >= 0; i-- {
|
for i := len(p.Log[message.Channel]) - 1; i >= 0; i-- {
|
||||||
entry := p.Log[message.Channel][i]
|
entry := p.Log[message.Channel][i]
|
||||||
// find the entry we want
|
|
||||||
fmt.Printf("Comparing '%s' to '%s'\n", entry.Raw, snip)
|
|
||||||
if entry.User.Name == nick && strings.Contains(entry.Body, snip) {
|
if entry.User.Name == nick && strings.Contains(entry.Body, snip) {
|
||||||
// insert new remember entry
|
// insert new remember entry
|
||||||
var msg string
|
var msg string
|
||||||
|
@ -78,12 +71,20 @@ func (p *RememberPlugin) Message(message bot.Message) bool {
|
||||||
} else {
|
} else {
|
||||||
msg = fmt.Sprintf("<%s> %s", entry.User.Name, entry.Raw)
|
msg = fmt.Sprintf("<%s> %s", entry.User.Name, entry.Raw)
|
||||||
}
|
}
|
||||||
u := userRemember{
|
|
||||||
Nick: entry.User.Name,
|
trigger := fmt.Sprintf("%s quotes", entry.User.Name)
|
||||||
Message: msg,
|
|
||||||
Date: time.Now(),
|
fact := Factoid{
|
||||||
|
Trigger: trigger,
|
||||||
|
Operator: "<reply>",
|
||||||
|
FullText: msg,
|
||||||
|
Action: msg,
|
||||||
|
CreatedBy: user.Name,
|
||||||
|
DateCreated: time.Now(),
|
||||||
|
LastAccessed: time.Now(),
|
||||||
|
AccessCount: 0,
|
||||||
}
|
}
|
||||||
p.Coll.Insert(u)
|
p.Coll.Insert(fact)
|
||||||
|
|
||||||
// sorry, not creative with names so we're reusing msg
|
// sorry, not creative with names so we're reusing msg
|
||||||
msg = fmt.Sprintf("Okay, %s, remembering '%s'.",
|
msg = fmt.Sprintf("Okay, %s, remembering '%s'.",
|
||||||
|
@ -103,7 +104,7 @@ func (p *RememberPlugin) 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 *RememberPlugin) LoadData() {
|
func (p *RememberPlugin) LoadData() {
|
||||||
p.Coll = p.Bot.Db.C("remember")
|
p.Coll = p.Bot.Db.C("factoid")
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,21 +116,18 @@ func (p *RememberPlugin) Help(channel string, parts []string) {
|
||||||
p.Bot.SendMessage(channel, msg)
|
p.Bot.SendMessage(channel, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RememberPlugin) record(nick, msg string) {
|
|
||||||
message := userRemember{
|
|
||||||
Nick: nick,
|
|
||||||
Message: msg,
|
|
||||||
Date: time.Now(),
|
|
||||||
}
|
|
||||||
p.Coll.Insert(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// deliver a random quote out of the db.
|
// deliver a random quote out of the db.
|
||||||
// Note: this is the same cache for all channels joined. This plugin needs to be expanded
|
// Note: this is the same cache for all channels joined. This plugin needs to be expanded
|
||||||
// to have this function execute a quote for a particular channel
|
// to have this function execute a quote for a particular channel
|
||||||
func (p *RememberPlugin) randQuote() string {
|
func (p *RememberPlugin) randQuote() string {
|
||||||
var quotes []userRemember
|
var quotes []Factoid
|
||||||
iter := p.Coll.Find(bson.M{}).Iter()
|
// todo: find anything with the word "quotes" in the trigger
|
||||||
|
query := bson.M{
|
||||||
|
"trigger": bson.M{
|
||||||
|
"$regex": "quotes$",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
iter := p.Coll.Find(query).Iter()
|
||||||
err := iter.All("es)
|
err := iter.All("es)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(iter.Err())
|
panic(iter.Err())
|
||||||
|
@ -141,7 +139,7 @@ func (p *RememberPlugin) randQuote() string {
|
||||||
return "Sorry, I don't know any quotes."
|
return "Sorry, I don't know any quotes."
|
||||||
}
|
}
|
||||||
quote := quotes[rand.Intn(nquotes)]
|
quote := quotes[rand.Intn(nquotes)]
|
||||||
return quote.Message
|
return quote.FullText
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RememberPlugin) quoteTimer(channel string) {
|
func (p *RememberPlugin) quoteTimer(channel string) {
|
||||||
|
@ -152,7 +150,6 @@ func (p *RememberPlugin) quoteTimer(channel string) {
|
||||||
chance := 1.0 / p.Bot.Config.QuoteChance
|
chance := 1.0 / p.Bot.Config.QuoteChance
|
||||||
if rand.Intn(int(chance)) == 0 {
|
if rand.Intn(int(chance)) == 0 {
|
||||||
msg := p.randQuote()
|
msg := p.randQuote()
|
||||||
fmt.Println("Delivering quote.")
|
|
||||||
p.Bot.SendMessage(channel, msg)
|
p.Bot.SendMessage(channel, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue