2012-08-26 19:15:04 +00:00
package plugins
import (
"bitbucket.org/phlyingpenguin/godeepintir/bot"
"fmt"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"math/rand"
"regexp"
"strings"
"time"
)
// 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
type factoid struct {
Id int
Trigger string
Operator string
FullText string
CreatedBy string
}
type FactoidPlugin struct {
Bot * bot . Bot
Coll * mgo . Collection
}
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface
func NewFactoidPlugin ( bot * bot . Bot ) * FactoidPlugin {
p := & FactoidPlugin {
Bot : bot ,
Coll : nil ,
}
p . LoadData ( )
return p
}
func ( p * FactoidPlugin ) findAction ( message string ) string {
2012-08-26 19:40:57 +00:00
r , err := regexp . Compile ( "<.+?>| is | are " )
2012-08-26 19:15:04 +00:00
if err != nil {
panic ( err )
}
action := r . FindString ( message )
return action
}
func ( p * FactoidPlugin ) learnFact ( message bot . Message , trigger , operator , fact string ) {
// if it's an action, we only want the fact part of it in the fulltext
full := fact
if operator != "action" && operator != "reply" {
full = fmt . Sprintf ( "%s %s %s" , trigger , operator , fact )
}
2012-08-26 19:52:38 +00:00
trigger = strings . ToLower ( trigger )
2012-08-26 19:15:04 +00:00
newfact := factoid {
Id : 0 ,
Trigger : trigger ,
Operator : operator ,
FullText : full ,
CreatedBy : message . User . Name ,
}
p . Coll . Insert ( newfact )
}
func ( p * FactoidPlugin ) findTrigger ( message string ) ( bool , string ) {
var results [ ] factoid
2012-08-26 19:21:21 +00:00
iter := p . Coll . Find ( bson . M { "trigger" : strings . ToLower ( message ) } ) . Iter ( )
2012-08-26 19:15:04 +00:00
err := iter . All ( & results )
if err != nil {
panic ( err )
}
nfacts := len ( results )
if nfacts == 0 {
return false , ""
}
fact := results [ rand . Intn ( nfacts ) ]
return true , fact . FullText
}
// 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 * FactoidPlugin ) Message ( message bot . Message ) bool {
// This bot does not reply to anything
2012-08-26 19:40:57 +00:00
body := strings . TrimSpace ( message . Body )
2012-08-26 19:15:04 +00:00
// This plugin has no business with normal messages
if ! message . Command {
2012-08-26 19:52:38 +00:00
// look for any triggers in the db matching this message
if len ( message . Body ) > 4 {
if ok , fact := p . findTrigger ( body ) ; ok {
fact = p . Bot . Filter ( message , fact )
p . Bot . SendMessage ( message . Channel , fact )
return true
}
}
2012-08-26 19:15:04 +00:00
return false
}
2012-08-26 19:40:57 +00:00
action := p . findAction ( body )
2012-08-26 19:15:04 +00:00
if action != "" {
2012-08-26 19:40:57 +00:00
parts := strings . SplitN ( body , action , 2 )
2012-08-26 19:15:04 +00:00
// This could fail if is were the last word or it weren't in the sentence (like no spaces)
if len ( parts ) != 2 {
return false
}
trigger := strings . TrimSpace ( parts [ 0 ] )
fact := strings . TrimSpace ( parts [ 1 ] )
action := strings . TrimSpace ( action )
2012-08-26 19:40:57 +00:00
if len ( trigger ) == 0 || len ( fact ) == 0 || len ( action ) == 0 {
p . Bot . SendMessage ( message . Channel , "I don't want to learn that." )
return false
}
2012-08-26 19:15:04 +00:00
strippedaction := strings . Replace ( strings . Replace ( action , "<" , "" , 1 ) , ">" , "" , 1 )
p . learnFact ( message , trigger , strippedaction , fact )
p . Bot . SendMessage ( message . Channel , fmt . Sprintf ( "Okay, %s." , message . User . Name ) )
return true
}
// look for any triggers in the db matching this message
2012-08-26 19:40:57 +00:00
if ok , fact := p . findTrigger ( body ) ; ok {
2012-08-26 19:15:04 +00:00
fact = p . Bot . Filter ( message , fact )
p . Bot . SendMessage ( message . Channel , fact )
return true
}
p . Bot . SendMessage ( message . Channel , "I don't know." )
return true
}
// 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 * FactoidPlugin ) LoadData ( ) {
// This bot has no data to load
p . Coll = p . Bot . Db . C ( "factoid" )
rand . Seed ( time . Now ( ) . Unix ( ) )
}
// Help responds to help requests. Every plugin must implement a help function.
func ( p * FactoidPlugin ) Help ( channel string , parts [ ] string ) {
2012-08-26 19:29:34 +00:00
p . Bot . SendMessage ( channel , "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples." )
p . Bot . SendMessage ( channel , "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone." )
2012-08-26 19:15:04 +00:00
}
// Empty event handler because this plugin does not do anything on event recv
func ( p * FactoidPlugin ) Event ( kind string , message bot . Message ) bool {
return false
}