2017-09-24 18:44:39 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"os"
|
2017-09-25 12:59:08 +00:00
|
|
|
"time"
|
2017-09-24 18:44:39 +00:00
|
|
|
|
|
|
|
"github.com/emgee/go-xmpp/src/xmpp"
|
|
|
|
)
|
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
const (
|
2017-09-25 12:59:08 +00:00
|
|
|
envXMPPID = "XMPP_ID"
|
|
|
|
envXMPPPASS = "XMPP_PASS"
|
|
|
|
errWrongArgs = "XMPP_ID or XMPP_PASS not set"
|
|
|
|
xmppBotAnswer = "im a dumb bot"
|
|
|
|
xmppConnErr = "failed to connect "
|
|
|
|
xmppFailedPause = 30
|
2017-09-25 11:33:43 +00:00
|
|
|
)
|
|
|
|
|
2017-09-25 12:59:08 +00:00
|
|
|
// starts xmpp session and returns the xmpp client
|
|
|
|
func xmppLogin(id string, pass string) (*xmpp.XMPP, error) {
|
2017-09-25 11:33:43 +00:00
|
|
|
// parse jid structure
|
2017-09-25 08:54:06 +00:00
|
|
|
jid, err := xmpp.ParseJID(id)
|
2017-09-25 12:59:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-09-24 18:44:39 +00:00
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
// extract/generate address:port from jid
|
2017-09-24 18:44:39 +00:00
|
|
|
addr, err := xmpp.HomeServerAddrs(jid)
|
2017-09-25 12:59:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-09-24 18:44:39 +00:00
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
// create xml stream to address
|
2017-09-24 18:44:39 +00:00
|
|
|
stream, err := xmpp.NewStream(addr[0], nil)
|
2017-09-25 12:59:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-09-24 18:44:39 +00:00
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
// create client (login)
|
2017-09-25 08:54:06 +00:00
|
|
|
client, err := xmpp.NewClientXMPP(stream, jid, pass, nil)
|
2017-09-25 12:59:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-09-24 18:44:39 +00:00
|
|
|
|
2017-09-25 12:59:08 +00:00
|
|
|
return client, nil
|
2017-09-25 08:54:06 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
// creates MessageBody slice suitable for xmpp.Message
|
|
|
|
func xmppBodyCreate(message string) []xmpp.MessageBody {
|
|
|
|
return []xmpp.MessageBody{
|
|
|
|
xmpp.MessageBody{
|
|
|
|
Value: message,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handles incoming stanzas
|
|
|
|
func handleXMPPStanza(in <-chan interface{}, out chan<- interface{}) {
|
|
|
|
for stanza := range in {
|
|
|
|
// check if stanza is a message
|
|
|
|
message, ok := stanza.(*xmpp.Message)
|
|
|
|
if ok && len(message.Body) > 0 {
|
|
|
|
// send constant as answer
|
|
|
|
out <- xmpp.Message{
|
|
|
|
To: message.From,
|
|
|
|
Body: xmppBodyCreate(xmppBotAnswer),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-25 12:59:08 +00:00
|
|
|
// func returns when in chan is closed (server terminated stream)
|
2017-09-25 11:33:43 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 08:54:06 +00:00
|
|
|
func main() {
|
2017-09-25 11:33:43 +00:00
|
|
|
// get xmpp credentials from ENV
|
2017-09-25 12:59:08 +00:00
|
|
|
xi := os.Getenv(envXMPPID)
|
|
|
|
xp := os.Getenv(envXMPPPASS)
|
2017-09-25 08:54:06 +00:00
|
|
|
|
2017-09-25 11:33:43 +00:00
|
|
|
// check if xmpp credentials are supplied
|
2017-09-25 08:54:06 +00:00
|
|
|
if len(xi) < 1 || len(xp) < 1 {
|
2017-09-25 12:59:08 +00:00
|
|
|
log.Fatal(errWrongArgs)
|
2017-09-25 08:54:06 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:59:08 +00:00
|
|
|
// connect xmpp client and observe connection - reconnect if needed
|
|
|
|
var xc *xmpp.XMPP
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
// try to connect to xmpp server
|
|
|
|
var err error
|
|
|
|
xc, err = xmppLogin(xi, xp)
|
|
|
|
if err != nil {
|
|
|
|
// report failure and wait
|
|
|
|
log.Print(xmppConnErr, err)
|
|
|
|
time.Sleep(time.Second * time.Duration(xmppFailedPause))
|
|
|
|
} else {
|
|
|
|
// send initial presence and dispatch channels to handler
|
|
|
|
xc.Out <- xmpp.Presence{}
|
|
|
|
handleXMPPStanza(xc.In, xc.Out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
2017-09-24 18:44:39 +00:00
|
|
|
|
|
|
|
select {}
|
|
|
|
}
|