diff --git a/README.md b/README.md index fcfbe10..86855ea 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ A [Matrix](https://matrix.org) chat bot. |Snap|`(?i)^snap:$`|checks the current build date of OpenBSD snapshots.| |Source|`(?i)where is your (source\|code)`|Tell people where they can find more information about myself.| |Thanks|`(?i)^thank you\|thank you$\|^thanks\|thanks$\|^ty\|ty$`|Bots should be respectful. Respond to thanks.| +|Homestead|`(?i)^home:\|^homestead:\s?(\w+)?$`|Display weather information for the Homestead| |Toki|`(?i)^(toki[\?]?):? (.+)$`|Toki Pona dictionary| |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.| diff --git a/go.mod b/go.mod index 62a810f..f408b90 100644 --- a/go.mod +++ b/go.mod @@ -10,5 +10,6 @@ require ( golang.org/x/net v0.0.0-20210326220855-61e056675ecf golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 // indirect golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 + gopkg.in/irc.v3 v3.1.4 suah.dev/protect v1.0.0 ) diff --git a/go.sum b/go.sum index 863702c..e41f5b2 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,16 @@ github.com/caneroj1/stemmer v0.0.0-20170128035808-c9f2ce1504d5 h1:KrgIOxLMw9OvGiPOX1WlxUOZzhJ6NvslCVEMb3SrIXQ= github.com/caneroj1/stemmer v0.0.0-20170128035808-c9f2ce1504d5/go.mod h1:FX8SGAdUYnFYgGoy+xeGdnVIEq/ITKM7iMewnmng4Y4= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 h1:nWU6p08f1VgIalT6iZyqXi4o5cZsz4X6qa87nusfcsc= github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -20,5 +27,12 @@ golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0 golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/irc.v3 v3.1.4 h1:DYGMRFbtseXEh+NadmMUFzMraqyuUj4I3iWYFEzDZPc= +gopkg.in/irc.v3 v3.1.4/go.mod h1:shO2gz8+PVeS+4E6GAny88Z0YVVQSxQghdrMVGQsR9s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= suah.dev/protect v1.0.0 h1:X8pzDvDIZIiugmkmr6DES6JFO1XUdJWi34Ffmk6CMZY= suah.dev/protect v1.0.0/go.mod h1:ZSgyBM30JUwhVPWJzVHh0jlu5W6Qz1VR6tIhAzqJZ9Y= diff --git a/irc.go b/irc.go new file mode 100644 index 0000000..0e74fc6 --- /dev/null +++ b/irc.go @@ -0,0 +1,89 @@ +package main + +import ( + "crypto/tls" + "fmt" + "log" + "strings" + + "gopkg.in/irc.v3" + "suah.dev/mcchunkie/plugins" +) + +func ircConnect(store *FStore, plugins *plugins.Plugins) error { + var ircServer, _ = store.Get("irc_server") + var ircPort, _ = store.Get("irc_port") + var ircNick, _ = store.Get("irc_nick") + var ircPass, _ = store.Get("irc_pass") + var ircRooms, _ = store.Get("irc_rooms") + //var toRE = regexp.MustCompile(`^:(\w+)\s`) + + if ircServer != "" { + + log.Printf("IRC: connecting to %q\n", ircServer) + + dialStr := fmt.Sprintf("%s:%s", ircServer, ircPort) + conn, err := tls.Dial("tcp", dialStr, &tls.Config{ + ServerName: ircServer, + }) + if err != nil { + return err + } + + config := irc.ClientConfig{ + Nick: ircNick, + Pass: ircPass, + User: ircNick, + Name: "McChunkie", + Handler: irc.HandlerFunc(func(c *irc.Client, m *irc.Message) { + switch m.Command { + case "001": + for _, r := range strings.Split(ircRooms, ",") { + c.Write(fmt.Sprintf("JOIN %s", r)) + } + case "PRIVMSG": + msg := m.Trailing() + from := m.Prefix.Name + to := m.Params[0] + + if from == c.CurrentNick() { + // Ignore messages from ourselves + return + } + + resp := "" + for _, p := range *plugins { + if p.Match(c.CurrentNick(), msg) { + p.SetStore(store) + + resp = p.Process(from, msg) + } + } + + if !c.FromChannel(m) { + // in a private chat + to = from + + } + + log.Printf("IRC: sending: %q to %q\n", resp, to) + + c.WriteMessage(&irc.Message{ + Command: "PRIVMSG", + Params: []string{ + to, + resp, + }, + }) + } + }), + } + + client := irc.NewClient(conn, config) + err = client.Run() + if err != nil { + log.Fatalln(err) + } + } + return nil +} diff --git a/main.go b/main.go index b95b853..492d4de 100644 --- a/main.go +++ b/main.go @@ -125,7 +125,7 @@ func main() { go func() { log.Println(s.Serve(lis)) }() } - cli, err := gomatrix.NewClient( + matrixCLI, err := gomatrix.NewClient( server, "", "", @@ -142,7 +142,7 @@ func main() { } fmt.Println() - resp, err := cli.Login(&gomatrix.ReqLogin{ + resp, err := matrixCLI.Login(&gomatrix.ReqLogin{ Type: "m.login.password", User: username, Password: password, @@ -169,11 +169,11 @@ func main() { shortName = plugins.NameRE.ReplaceAllString(username, "$1") - cli.SetCredentials(userID, accessToken) - cli.Store = store + matrixCLI.SetCredentials(userID, accessToken) + matrixCLI.Store = store syncer := gomatrix.NewDefaultSyncer(username, store) - cli.Client = http.DefaultClient - cli.Syncer = syncer + matrixCLI.Client = http.DefaultClient + matrixCLI.Syncer = syncer syncer.OnEventType("m.room.member", func(ev *gomatrix.Event) { if ev.Sender == username { @@ -183,7 +183,7 @@ func main() { case botOwner: if ev.Content["membership"] == "invite" { log.Printf("Joining %s (invite from %s)\n", ev.RoomID, ev.Sender) - if _, err := cli.JoinRoom(ev.RoomID, "", nil); err != nil { + if _, err := matrixCLI.JoinRoom(ev.RoomID, "", nil); err != nil { log.Fatalln(err) } return @@ -192,13 +192,24 @@ func main() { }) go func() { - gotListen(store, cli) + gotListen(store, matrixCLI) }() go func() { smsListen(store, &plugins.Plugs) }() + go func() { + for { + err := ircConnect(store, &plugins.Plugs) + if err != nil { + log.Println(err) + } + log.Println("IRC: reconnecting in 60 seconds") + time.Sleep(time.Second * 60) + } + }() + go func() { for { errataCount := 0 @@ -229,7 +240,7 @@ func main() { break } for _, room := range strings.Split(alertRooms, ",") { - err = plugins.SendMDNotice(cli, room, PrintErrataMD(&erratum)) + err = plugins.SendMDNotice(matrixCLI, room, PrintErrataMD(&erratum)) if err != nil { fmt.Println(err) } @@ -265,7 +276,7 @@ func main() { val := kvRE.ReplaceAllString(mp, "$2") store.Set(key, val) log.Printf("Setting %q to %q", key, val) - err := plugins.SendMD(cli, ev.RoomID, fmt.Sprintf("Set **%q** = *%q*", key, val)) + err := plugins.SendMD(matrixCLI, ev.RoomID, fmt.Sprintf("Set **%q** = *%q*", key, val)) if err != nil { log.Println(err) } @@ -300,7 +311,7 @@ func main() { p.SetStore(store) start := time.Now() - err := p.RespondText(cli, ev, username, post) + err := p.RespondText(matrixCLI, ev, username, post) if err != nil { fmt.Println(err) } @@ -313,7 +324,7 @@ func main() { } } if len(helps) > 0 { - err := plugins.SendMD(cli, ev.RoomID, strings.Join(helps, "\n")) + err := plugins.SendMD(matrixCLI, ev.RoomID, strings.Join(helps, "\n")) if err != nil { log.Println(err) } @@ -322,13 +333,13 @@ func main() { if avatar != "" { log.Printf("Setting avatar to: '%s'", avatar) - rmu, err := cli.UploadLink(avatar) + rmu, err := matrixCLI.UploadLink(avatar) if err != nil { fmt.Println(err) os.Exit(1) } - err = cli.SetAvatarURL(rmu.ContentURI) + err = matrixCLI.SetAvatarURL(rmu.ContentURI) if err != nil { fmt.Println(err) os.Exit(1) @@ -338,7 +349,7 @@ func main() { for { log.Println("syncing..") - if err := cli.Sync(); err != nil { + if err := matrixCLI.Sync(); err != nil { fmt.Println("Sync() returned ", err) } diff --git a/plugins/version.go b/plugins/version.go index 8f7f858..1fdda38 100644 --- a/plugins/version.go +++ b/plugins/version.go @@ -10,11 +10,7 @@ import ( var version string -const response = ` -**%s** running on: **%s** - -Built with Go: **%s** -` +const response = `**%s** running on: **%s**. Built with Go: **%s**.` // Version responds to hi messages type Version struct { @@ -37,6 +33,7 @@ func (v *Version) Match(user, msg string) bool { return re.MatchString(msg) && ToMe(user, msg) } +// Process does the heavy lifting func (v *Version) Process(_, _ string) string { if version == "" { version = "unknown version"