move chat mechanism into their own location

This commit is contained in:
Aaron Bieber 2021-04-22 17:08:24 -06:00
parent d011103d57
commit b07eab5135
5 changed files with 241 additions and 8 deletions

25
chats/chats.go Normal file
View File

@ -0,0 +1,25 @@
package chats
import (
"suah.dev/mcchunkie/plugins"
)
// ChatStore matches MCStore. This allows the main store to be used by
// plugins.
type ChatStore interface {
Set(key, values string)
Get(key string) (string, error)
}
// Chat represents a mode of communication like Matrix, IRC or SMS.
type Chat interface {
// Connect connects
Connect(s plugins.PluginStore) error
}
// Chats is a collection of our chat methods. An instance of this is iterated
// over for each message the bot responds to.
type Chats []Chat
// ChatMethods defines the "enabled" chat methogs.
var ChatMethods = Chats{}

102
chats/irc.go Normal file
View File

@ -0,0 +1,102 @@
package chats
import (
"crypto/tls"
"fmt"
"log"
"strings"
"gopkg.in/irc.v3"
"suah.dev/mcchunkie/plugins"
)
// IRCConnect connects to our irc server
func IRCConnect(store ChatStore, 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, ",") {
log.Printf("IRC: joining %q\n", r)
c.Write(fmt.Sprintf("JOIN %s", r))
}
case "PING":
server := m.Trailing()
log.Printf("IRC: pong %q\n", server)
c.Write(fmt.Sprintf("PONG %s", server))
case "INVITE":
room := m.Trailing()
log.Printf("IRC: joining %q\n", room)
c.Write(fmt.Sprintf("JOIN %s", room))
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
}
if resp != "" {
log.Printf("IRC: sending: %q to %q\n", resp, to)
c.WriteMessage(&irc.Message{
Command: "PRIVMSG",
Params: []string{
to,
resp,
},
})
}
default:
log.Printf("IRC: unhandled - %q", m.String())
}
}),
}
client := irc.NewClient(conn, config)
err = client.Run()
if err != nil {
return err
}
}
return nil
}

7
chats/matrix.go Normal file
View File

@ -0,0 +1,7 @@
package chats
/*
func matrixConnect() {
}
*/

94
chats/sms.go Normal file
View File

@ -0,0 +1,94 @@
package chats
import (
"fmt"
"log"
"net/http"
"strings"
"golang.org/x/crypto/bcrypt"
"suah.dev/mcchunkie/plugins"
)
func smsCanSend(number string, numbers []string) bool {
for _, s := range numbers {
if number == s {
return true
}
}
return false
}
// SMSListen listens for our incoming sms
func SMSListen(store ChatStore, plugins *plugins.Plugins) {
var smsPort, _ = store.Get("sms_listen")
var smsAllowed, _ = store.Get("sms_users")
var smsUsers = strings.Split(smsAllowed, ",")
if smsPort != "" {
var htpass, _ = store.Get("sms_htpass")
log.Printf("SMS: listening on %q\n", smsPort)
http.HandleFunc("/_sms", func(w http.ResponseWriter, r *http.Request) {
var msg, from string
user, pass, ok := r.BasicAuth()
err := bcrypt.CompareHashAndPassword([]byte(htpass), []byte(pass))
if !(ok && err == nil && user == "sms") {
log.Printf("SMS: failed auth %q %q\n", user, pass)
w.Header().Set("WWW-Authenticate", `Basic realm="sms notify"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
err = r.ParseForm()
if err != nil {
http.Error(w, "invalid request", http.StatusBadRequest)
return
}
log.Println(r.Method)
switch r.Method {
case http.MethodPost:
msg = r.Form.Get("Body")
from = r.Form.Get("From")
default:
http.Error(
w,
fmt.Sprintf("method %q not implemented", r.Method),
http.StatusMethodNotAllowed,
)
return
}
if smsCanSend(from, smsUsers) {
msg = strings.TrimSuffix(msg, "\n")
if msg == "" {
fmt.Fprintf(w, "empty message")
return
}
for _, p := range *plugins {
if p.Match(from, msg) {
log.Printf("%s: responding to '%s'", p.Name(), from)
p.SetStore(store)
resp := p.Process(from, msg)
fmt.Fprint(w, resp)
}
}
} else {
log.Printf("number not allowed (%q)", from)
http.Error(
w,
fmt.Sprintf("number not allowed (%q)", from),
http.StatusMethodNotAllowed,
)
return
}
})
log.Fatal(http.ListenAndServe(smsPort, nil))
}
}

21
main.go
View File

@ -14,6 +14,7 @@ import (
"time"
"github.com/matrix-org/gomatrix"
"suah.dev/mcchunkie/chats"
"suah.dev/mcchunkie/plugins"
"suah.dev/protect"
)
@ -198,12 +199,21 @@ func main() {
}()
go func() {
smsListen(store, &plugins.Plugs)
chats.SMSListen(store, &plugins.Plugs)
}()
go func() {
log.Println("MATRIX: syncing..")
if err := matrixCLI.Sync(); err != nil {
fmt.Println("Sync() returned ", err)
}
time.Sleep(1 * time.Second)
}()
go func() {
for {
err := ircConnect(store, &plugins.Plugs)
err := chats.IRCConnect(store, &plugins.Plugs)
if err != nil {
log.Println(err)
}
@ -350,11 +360,6 @@ func main() {
}
for {
log.Println("syncing..")
if err := matrixCLI.Sync(); err != nil {
fmt.Println("Sync() returned ", err)
}
time.Sleep(1 * time.Second)
time.Sleep(time.Second * 60)
}
}