2018-03-27 22:26:26 +00:00
|
|
|
package xmpp
|
|
|
|
|
|
|
|
import (
|
2018-03-31 23:53:40 +00:00
|
|
|
"crypto/tls"
|
2018-03-27 22:26:26 +00:00
|
|
|
"fmt"
|
|
|
|
"log"
|
2018-03-31 22:51:41 +00:00
|
|
|
"net"
|
2018-03-27 22:26:26 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"git.hacknology.de/projekte/spaceapi"
|
2018-03-31 22:51:41 +00:00
|
|
|
"github.com/mattn/go-xmpp"
|
2018-03-27 22:26:26 +00:00
|
|
|
)
|
|
|
|
|
2018-04-01 13:58:17 +00:00
|
|
|
const (
|
2018-04-17 21:34:19 +00:00
|
|
|
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."
|
2018-04-01 13:58:17 +00:00
|
|
|
)
|
|
|
|
|
2018-03-27 22:26:26 +00:00
|
|
|
func AddXMPPListener(storage *spaceapi.Storage, jid, password, target, handle string) error {
|
2018-03-31 22:51:41 +00:00
|
|
|
xmppHost, err := lookupHost(jid)
|
2018-03-27 22:26:26 +00:00
|
|
|
if err != nil {
|
2018-03-31 22:51:41 +00:00
|
|
|
return fmt.Errorf("can not find SRV record: %s", err)
|
2018-03-27 22:26:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-31 23:53:40 +00:00
|
|
|
clientOpts := xmpp.Options{
|
|
|
|
Host: xmppHost,
|
|
|
|
User: jid,
|
|
|
|
Password: password,
|
|
|
|
NoTLS: true,
|
|
|
|
Debug: false,
|
|
|
|
Session: false,
|
|
|
|
TLSConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2018-03-31 22:51:41 +00:00
|
|
|
log.Printf("Connecting to %s as %s", xmppHost, jid)
|
2018-03-31 23:53:40 +00:00
|
|
|
client, err := clientOpts.NewClient()
|
2018-03-31 22:51:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("can not connect to server: %s", err)
|
2018-03-27 22:26:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-31 22:51:41 +00:00
|
|
|
if _, err := client.JoinMUCNoHistory(target, handle); err != nil {
|
|
|
|
return fmt.Errorf("can not join room: %s", err)
|
2018-03-27 22:26:26 +00:00
|
|
|
}
|
|
|
|
|
2018-04-01 13:58:17 +00:00
|
|
|
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 {
|
2018-04-17 21:34:19 +00:00
|
|
|
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 {
|
2018-04-01 13:58:17 +00:00
|
|
|
log.Printf("Error sending message: %s", err)
|
|
|
|
}
|
|
|
|
case commandClose:
|
|
|
|
open := false
|
|
|
|
storage.Modify(func(status *spaceapi.SpaceStatus) {
|
|
|
|
status.State.Open = &open
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-04-17 21:28:01 +00:00
|
|
|
storage.AddListener(func(old, new spaceapi.SpaceStatus) {
|
|
|
|
if new.State.Open == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if old.State.Open == new.State.Open {
|
2018-03-27 22:26:26 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-04-17 21:28:44 +00:00
|
|
|
msg := "Space ist jetzt OFFEN!"
|
2018-04-17 21:28:01 +00:00
|
|
|
if !*new.State.Open {
|
2018-04-17 21:28:44 +00:00
|
|
|
msg = "Space ist jetzt ZU!"
|
2018-03-27 22:26:26 +00:00
|
|
|
}
|
|
|
|
|
2018-04-01 13:58:17 +00:00
|
|
|
if err := sendGroupMessage(client, target, msg); err != nil {
|
2018-03-31 22:51:41 +00:00
|
|
|
log.Printf("Error sending status update: %s", err)
|
2018-03-27 22:26:26 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-03-31 22:51:41 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2018-04-01 13:58:17 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|