add Re and Descr functions so we can produce better docs

This commit is contained in:
Aaron Bieber 2020-02-11 07:56:19 -07:00
parent 02b75ee7b0
commit 27f4a7e6e2
13 changed files with 151 additions and 38 deletions

View File

@ -2,14 +2,15 @@
[![builds.sr.ht status](https://builds.sr.ht/~qbit/mcchunkie.svg)](https://builds.sr.ht/~qbit/mcchunkie?) [![builds.sr.ht status](https://builds.sr.ht/~qbit/mcchunkie.svg)](https://builds.sr.ht/~qbit/mcchunkie?)
| Plugin | Match | Purpose |
|----------|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| beer | '^beer: ' | Queries [OpenDataSoft](https://public-us.opendatasoft.com/explore/dataset/open-beer-database/table/)'s beer database for a given beer. |
| botsnack | name: 'botsnack$' | Consumes a botsnack. This pleases mcchunkie and brings balance to the universe. |
| hi | name: '^hi' or 'hi$' | Friendly bots say hi. |
| highfive | name: 'o/' or '\o' | Everyone loves highfives. |
| love | name: 'i love you' | Spreading love where ever we can. |
| source | name: 'where is your source?' | Tell people where they can find more information on mcchunkie. |
| version | name: 'version$' | Bit of information about what we are. |
|Plugin Name|Match|Description|
|Beer|`(?i)^beer: `|Queries [OpenDataSoft](https://public-us.opendatasoft.com/explore/dataset/open-beer-database/table/)'s beer database for a given beer.|
|BotSnack|`(?i)botsnack`|Consumes a botsnack. This pleases mcchunkie and brings balance to the universe.|
|HighFive|`o/|\o`|Everyone loves highfives.|
|Hi|`(?i)^hi|hi$`|Friendly bots say hi.|
|LoveYou|`(?i)i love you`|Spreading love where ever we can by responding when someone shows us love.|
|OpenBSDMan|`(?i)^man: ([1-9]?p?)\s?(\w+)$`|Produces a link to man.openbsd.org.|
|Source|`(?i)where is your (source|code)`|Tell people where they can find more information about myself.|
|Version|`(?i)version$`|Show a bit of information about what we are.|
|Wb|`(?i)^welcome back|welcome back$|^wb|wb$`|Respond to welcome back messages.|
|Weather|`(?i)^weather: (\d+)$`|Produce weather information for a given ZIP code. Data comes from openweathermap.org.|

22
main.go
View File

@ -15,16 +15,18 @@ import (
func main() { func main() {
var username, password, userID, accessToken, server, db, avatar string var username, password, userID, accessToken, server, db, avatar string
var key, value, get string var key, value, get string
var setup bool var setup, doc bool
flag.StringVar(&username, "user", "", "username to connect to matrix server with") flag.BoolVar(&doc, "doc", false, "print plugin information and exit")
flag.BoolVar(&setup, "s", false, "setup account")
flag.StringVar(&avatar, "avatar", "", "set the avatar of the bot to specified url")
flag.StringVar(&db, "db", "db", "full path to database directory")
flag.StringVar(&get, "get", "", "grab an entry from the store") flag.StringVar(&get, "get", "", "grab an entry from the store")
flag.StringVar(&key, "key", "", "create an entry in the data store listed under 'key'") flag.StringVar(&key, "key", "", "create an entry in the data store listed under 'key'")
flag.StringVar(&value, "value", "", "set the value of 'key' to be stored")
flag.StringVar(&server, "server", "", "matrix server") flag.StringVar(&server, "server", "", "matrix server")
flag.StringVar(&avatar, "avatar", "", "set the avatar of the bot to specified url") flag.StringVar(&username, "user", "", "username to connect to matrix server with")
flag.BoolVar(&setup, "s", false, "setup account") flag.StringVar(&value, "value", "", "set the value of 'key' to be stored")
flag.StringVar(&db, "db", "db", "full path to database directory")
flag.Parse() flag.Parse()
@ -44,6 +46,14 @@ func main() {
os.Exit(0) os.Exit(0)
} }
if doc {
fmt.Println("|Plugin Name|Match|Description|")
for _, p := range plugins.Plugs {
fmt.Printf("|%s|`%s`|%s|\n", p.Name(), p.Re(), p.Descr())
}
os.Exit(0)
}
if get != "" { if get != "" {
val, err := store.Get(get) val, err := store.Get(get)
if err != nil { if err != nil {

View File

@ -74,18 +74,24 @@ type Records struct {
RecordTimestamp time.Time `json:"record_timestamp"` RecordTimestamp time.Time `json:"record_timestamp"`
} }
func (h *Beer) re() string { // Descr describes this plugin
func (h *Beer) Descr() string {
return "Queries [OpenDataSoft](https://public-us.opendatasoft.com/explore/dataset/open-beer-database/table/)'s beer database for a given beer."
}
// Re returns the beer matching string
func (h *Beer) Re() string {
return `(?i)^beer: ` return `(?i)^beer: `
} }
func (h *Beer) fix(msg string) string { func (h *Beer) fix(msg string) string {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
return re.ReplaceAllString(msg, "$1") return re.ReplaceAllString(msg, "$1")
} }
// Match determines if we should call the response for Beer // Match determines if we should call the response for Beer
func (h *Beer) Match(user, msg string) bool { func (h *Beer) Match(user, msg string) bool {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) return re.MatchString(msg)
} }

View File

@ -13,9 +13,19 @@ import (
type BotSnack struct { type BotSnack struct {
} }
// Descr returns a description
func (h *BotSnack) Descr() string {
return "Consumes a botsnack. This pleases mcchunkie and brings balance to the universe."
}
// Re matches "botsnack" in a given string
func (h *BotSnack) Re() string {
return `(?i)botsnack`
}
// Match determines if we should execute BotSnack // Match determines if we should execute BotSnack
func (h *BotSnack) Match(user, msg string) bool { func (h *BotSnack) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)botsnack`) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) return re.MatchString(msg)
} }

View File

@ -12,9 +12,19 @@ import (
type Hi struct { type Hi struct {
} }
// Descr describes this plugin
func (h *Hi) Descr() string {
return "Friendly bots say hi."
}
// Re is the regex for matching hi messages.
func (h *Hi) Re() string {
return `(?i)^hi|hi$`
}
// Match determines if we are highfiving // Match determines if we are highfiving
func (h *Hi) Match(user, msg string) bool { func (h *Hi) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)^hi|hi$`) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) && ToMe(user, msg) return re.MatchString(msg) && ToMe(user, msg)
} }

View File

@ -12,6 +12,24 @@ import (
type HighFive struct { type HighFive struct {
} }
func rightFive() string {
return "o/"
}
func leftFive() string {
return "\\o"
}
// Descr describes this plugin
func (h *HighFive) Descr() string {
return "Everyone loves highfives."
}
// Re are the regexes that high five uses
func (h *HighFive) Re() string {
return fmt.Sprintf("%s|%s", rightFive(), leftFive())
}
// SetStore we don't need a store here. // SetStore we don't need a store here.
func (h *HighFive) SetStore(s PluginStore) {} func (h *HighFive) SetStore(s PluginStore) {}
@ -24,11 +42,11 @@ func (h *HighFive) Match(user, msg string) bool {
func (h *HighFive) RespondText(c *gomatrix.Client, ev *gomatrix.Event, user, post string) { func (h *HighFive) RespondText(c *gomatrix.Client, ev *gomatrix.Event, user, post string) {
s := NameRE.ReplaceAllString(ev.Sender, "$1") s := NameRE.ReplaceAllString(ev.Sender, "$1")
if strings.Contains(post, "o/") { if strings.Contains(post, rightFive()) {
log.Printf("%s: responding to '%s'", h.Name(), ev.Sender) log.Printf("%s: responding to '%s'", h.Name(), ev.Sender)
SendText(c, ev.RoomID, fmt.Sprintf("\\o %s", s)) SendText(c, ev.RoomID, fmt.Sprintf("\\o %s", s))
} }
if strings.Contains(post, "\\o") { if strings.Contains(post, leftFive()) {
log.Printf("%s: responding to '%s'", h.Name(), ev.Sender) log.Printf("%s: responding to '%s'", h.Name(), ev.Sender)
SendText(c, ev.RoomID, fmt.Sprintf("%s o/", s)) SendText(c, ev.RoomID, fmt.Sprintf("%s o/", s))
} }

View File

@ -13,9 +13,19 @@ import (
type LoveYou struct { type LoveYou struct {
} }
// Descr describes this plugin
func (h *LoveYou) Descr() string {
return "Spreading love where ever we can by responding when someone shows us love."
}
// Re matches "i love you"
func (h *LoveYou) Re() string {
return `(?i)i love you`
}
// Match checks for 'i love you' and a reference to the bot name // Match checks for 'i love you' and a reference to the bot name
func (h *LoveYou) Match(user, msg string) bool { func (h *LoveYou) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)i love you`) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) && ToMe(user, msg) return re.MatchString(msg) && ToMe(user, msg)
} }

View File

@ -12,12 +12,18 @@ import (
type OpenBSDMan struct { type OpenBSDMan struct {
} }
func (h *OpenBSDMan) re() string { // Descr describes this plugin
func (h *OpenBSDMan) Descr() string {
return "Produces a link to man.openbsd.org."
}
// Re matches our man format
func (h *OpenBSDMan) Re() string {
return `(?i)^man: ([1-9]?p?)\s?(\w+)$` return `(?i)^man: ([1-9]?p?)\s?(\w+)$`
} }
func (h *OpenBSDMan) fix(msg string) string { func (h *OpenBSDMan) fix(msg string) string {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
resp := "" resp := ""
section := re.ReplaceAllString(msg, "$1") section := re.ReplaceAllString(msg, "$1")
if section == msg { if section == msg {
@ -34,7 +40,7 @@ func (h *OpenBSDMan) fix(msg string) string {
// Match checks for our man page re // Match checks for our man page re
func (h *OpenBSDMan) Match(user, msg string) bool { func (h *OpenBSDMan) Match(user, msg string) bool {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) return re.MatchString(msg)
} }

View File

@ -17,16 +17,22 @@ type PluginStore interface {
// Plugin defines the interface a plugin must implement to be used by // Plugin defines the interface a plugin must implement to be used by
// mcchunkie. // mcchunkie.
type Plugin interface { type Plugin interface {
// RespondText responds to a "m.text" event // Descr returns a brief description of the plugin.
RespondText(c *gomatrix.Client, ev *gomatrix.Event, user, path string) Descr() string
// Name should return the human readable name of the bot
Name() string
// Match determines if the plugin's main Respond function should be // Match determines if the plugin's main Respond function should be
// called // called
Match(user, message string) bool Match(user, message string) bool
// Name should return the human readable name of the bot
Name() string
// Re returns the regular expression that a plugin uses to "match"
Re() string
// RespondText responds to a "m.text" event
RespondText(c *gomatrix.Client, ev *gomatrix.Event, user, path string)
// SetStore exposes the top level MCStore to a plugin // SetStore exposes the top level MCStore to a plugin
SetStore(s PluginStore) SetStore(s PluginStore)
} }

View File

@ -12,9 +12,19 @@ import (
type Source struct { type Source struct {
} }
// Descr describes this plugin
func (h *Source) Descr() string {
return "Tell people where they can find more information about myself."
}
// Re matches the source code question
func (h *Source) Re() string {
return `(?i)where is your (source|code)`
}
// Match determins if someone is asking about the source code // Match determins if someone is asking about the source code
func (h *Source) Match(user, msg string) bool { func (h *Source) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)where is your (source|code)`) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) && ToMe(user, msg) return re.MatchString(msg) && ToMe(user, msg)
} }

View File

@ -13,10 +13,20 @@ import (
type Version struct { type Version struct {
} }
// Descr describes this plugin
func (v *Version) Descr() string {
return "Show a bit of information about what we are."
}
// Re matches version
func (v *Version) Re() string {
return `(?i)version$`
}
// Match checks for "version" anywhere. Might want to tighten this one down at // Match checks for "version" anywhere. Might want to tighten this one down at
// some point // some point
func (v *Version) Match(user, msg string) bool { func (v *Version) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)version$`) re := regexp.MustCompile(v.Re())
return re.MatchString(msg) && ToMe(user, msg) return re.MatchString(msg) && ToMe(user, msg)
} }

View File

@ -142,18 +142,24 @@ func (h *Weather) get(loc string) (*WeatherResp, error) {
return w, nil return w, nil
} }
func (h *Weather) re() string { // Descr describes this plugin
func (h *Weather) Descr() string {
return "Produce weather information for a given ZIP code. Data comes from openweathermap.org."
}
// Re is what our weather matches
func (h *Weather) Re() string {
return `(?i)^weather: (\d+)$` return `(?i)^weather: (\d+)$`
} }
// Match checks for "weather: " messages // Match checks for "weather: " messages
func (h *Weather) Match(user, msg string) bool { func (h *Weather) Match(user, msg string) bool {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) return re.MatchString(msg)
} }
func (h *Weather) fix(msg string) string { func (h *Weather) fix(msg string) string {
re := regexp.MustCompile(h.re()) re := regexp.MustCompile(h.Re())
return re.ReplaceAllString(msg, "$1") return re.ReplaceAllString(msg, "$1")
} }

View File

@ -12,9 +12,19 @@ import (
type Wb struct { type Wb struct {
} }
// Descr describes this plugin
func (h *Wb) Descr() string {
return "Respond to welcome back messages."
}
// Re checks for various welcome back things
func (h *Wb) Re() string {
return `(?i)^welcome back|welcome back$|^wb|wb$`
}
// Match determins if we are welcomed back // Match determins if we are welcomed back
func (h *Wb) Match(user, msg string) bool { func (h *Wb) Match(user, msg string) bool {
re := regexp.MustCompile(`(?i)^welcome back|welcome back$|^wb|wb$`) re := regexp.MustCompile(h.Re())
return re.MatchString(msg) && ToMe(user, msg) return re.MatchString(msg) && ToMe(user, msg)
} }