A simple server for serving our SpaceAPI interactively.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spaceapi/xmpp/xmpp.go

157 lines
3.1 KiB

package xmpp
import (
"crypto/tls"
"fmt"
"log"
"net"
"strings"
"git.hacknology.de/projekte/spaceapi"
"github.com/mattn/go-xmpp"
)
const (
commandHelp = "!help"
commandState = "!state"
commandClose = "!closed"
helpMessage = `Spacebot hat folgende Kommandos:
!help - Diese Nachricht.
!state - Ist der Space offen?
!closed - Space ist zu.
Gern geschehen.`
stateUnknown = "Ich weiß leider nicht ob der Space offen ist."
stateOpen = "Space ist OFFEN."
stateClosed = "Space ist zu."
)
func AddXMPPListener(storage *spaceapi.Storage, jid, password, target, handle string) error {
xmppHost, err := lookupHost(jid)
if err != nil {
return fmt.Errorf("can not find SRV record: %s", err)
}
clientOpts := xmpp.Options{
Host: xmppHost,
User: jid,
Password: password,
NoTLS: true,
Debug: false,
Session: false,
TLSConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
log.Printf("Connecting to %s as %s", xmppHost, jid)
client, err := clientOpts.NewClient()
if err != nil {
return fmt.Errorf("can not connect to server: %s", err)
}
if _, err := client.JoinMUCNoHistory(target, handle); err != nil {
return fmt.Errorf("can not join room: %s", err)
}
go func() {
for {
chat, err := client.Recv()
if err != nil {
log.Printf("Error receiving XMPP message: %s", err)
continue
}
switch v := chat.(type) {
case xmpp.Chat:
switch v.Text {
case commandHelp:
if err := sendGroupMessage(client, target, helpMessage); err != nil {
log.Printf("Error sending message: %s", err)
}
case commandState:
state := storage.Status().State
msg := stateUnknown
if state.Open != nil {
switch *state.Open {
case true:
msg = stateOpen
case false:
msg = stateClosed
}
}
if err := sendGroupMessage(client, target, msg); err != nil {
log.Printf("Error sending message: %s", err)
}
case commandClose:
open := false
storage.Modify(func(status *spaceapi.SpaceStatus) {
status.State.Open = &open
})
}
}
}
}()
storage.AddListener(func(old, new spaceapi.SpaceStatus) {
if new.State.Open == nil {
return
}
if old.State.Open == new.State.Open {
return
}
msg := "Space ist jetzt OFFEN!"
if !*new.State.Open {
msg = "Space ist jetzt ZU!"
}
if err := sendGroupMessage(client, target, msg); err != nil {
log.Printf("Error sending status update: %s", err)
}
})
return nil
}
const defaultClientPort = 5222
func lookupHost(jid string) (string, error) {
if !strings.Contains(jid, "@") {
return "", fmt.Errorf("not a valid JID: %s", jid)
}
parts := strings.SplitN(jid, "@", 2)
_, addrs, err := net.LookupSRV("xmpp-client", "tcp", parts[1])
if err != nil {
return "", fmt.Errorf("%s", err)
}
if len(addrs) == 0 {
return fmt.Sprintf("%s:%d", parts[1], defaultClientPort), nil
}
return fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port), nil
}
func sendGroupMessage(client *xmpp.Client, target, msg string) error {
chat := xmpp.Chat{
Remote: target,
Type: "groupchat",
Text: msg,
}
if _, err := client.Send(chat); err != nil {
return err
}
return nil
}