183 lines
4.9 KiB
Go
183 lines
4.9 KiB
Go
package xmpp_manager
|
||
|
||
|
||
import (
|
||
"github.com/astaxie/beego"
|
||
"github.com/astaxie/beego/logs"
|
||
|
||
"git.kingpenguin.tk/chteufleur/go-xmpp.git"
|
||
"git.kingpenguin.tk/chteufleur/datahouse.git/models"
|
||
"git.kingpenguin.tk/chteufleur/datahouse.git/models/relay"
|
||
"git.kingpenguin.tk/chteufleur/datahouse.git/models/variables"
|
||
)
|
||
|
||
|
||
const (
|
||
Status_online = ""
|
||
Status_offline = ""
|
||
Status_away = "away"
|
||
Status_chat = "chat"
|
||
Status_do_not_disturb = "dnd"
|
||
Status_extended_away = "xa"
|
||
|
||
Type_available = ""
|
||
Type_unavailable = "unavailable"
|
||
Type_subscribe = "subscribe"
|
||
Type_subscribed = "subscribed"
|
||
Type_unsubscribe = "unsubscribe"
|
||
Type_unsubscribed = "unsubscribed"
|
||
Type_probe = "probe"
|
||
Type_error = "error"
|
||
|
||
EndRun = "EndRunXMPP"
|
||
)
|
||
|
||
var (
|
||
log = logs.NewLogger(10000)
|
||
|
||
JidStr = beego.AppConfig.String("JID")
|
||
passwdStr = beego.AppConfig.String("PWD")
|
||
serverPort = beego.AppConfig.String("PORT")
|
||
|
||
jid xmpp.JID
|
||
stream = new(xmpp.Stream)
|
||
client = new(xmpp.XMPP)
|
||
|
||
Debug = true
|
||
)
|
||
|
||
func init() {
|
||
log.SetLogger(variables.LogType, variables.LogParams)
|
||
}
|
||
|
||
|
||
func must(v interface{}, err error) interface{} {
|
||
if err != nil {
|
||
log.Error("Must error : ", err)
|
||
}
|
||
return v
|
||
}
|
||
|
||
func Run() {
|
||
// Create stream and configure it as a component connection.
|
||
log.Info("XMPP Run()")
|
||
jid = must(xmpp.ParseJID(JidStr)).(xmpp.JID)
|
||
stream = must(xmpp.NewStream(jid.Domain+":"+serverPort, &xmpp.StreamConfig{LogStanzas: Debug})).(*xmpp.Stream)
|
||
client = must(xmpp.NewClientXMPP(stream, jid, passwdStr, &xmpp.ClientConfig{InsecureSkipVerify: true})).(*xmpp.XMPP)
|
||
|
||
mainXMPP()
|
||
log.Debug("xmpp.Run Ended")
|
||
models.ChanRuns <- EndRun
|
||
}
|
||
|
||
|
||
func mainXMPP() {
|
||
SendPresence(Status_online, Type_available, "")
|
||
|
||
for x := range client.In {
|
||
switch v := x.(type) {
|
||
case *xmpp.Iq:
|
||
// TODO check if the caller has privilege to ask
|
||
switch v.PayloadName().Space {
|
||
case xmpp.NsDiscoItems:
|
||
execDiscoCommand(v)
|
||
|
||
case xmpp.NodeAdHocCommand:
|
||
execCommandAdHoc(v)
|
||
}
|
||
|
||
default:
|
||
log.Info("recv: %v", x)
|
||
}
|
||
}
|
||
|
||
// Send deconnexion
|
||
SendPresence(Status_offline, Type_unavailable, "")
|
||
log.Debug("mainXMPP Ended")
|
||
}
|
||
|
||
|
||
func SendPresence(status, tpye, message string) {
|
||
client.Out <- xmpp.Presence{From: jid.Domain, Show: status, Type: tpye, Status: message}
|
||
}
|
||
|
||
|
||
func execDiscoCommand(iq *xmpp.Iq) {
|
||
log.Info("Discovery item iq received")
|
||
reply := iq.Response(xmpp.IqTypeResult)
|
||
discoItem := &xmpp.DiscoItems{Node: xmpp.NodeAdHocCommand}
|
||
|
||
relays := relay.GetAllRelay()
|
||
for _, r := range relays {
|
||
discoI := &xmpp.DiscoItem{JID: client.JID.Full(), Node: r.Mac, Name: "Relay : "}
|
||
if (r.Description == "") {
|
||
discoI.Name += r.Mac
|
||
} else {
|
||
discoI.Name += r.Description
|
||
}
|
||
discoItem.Item = append(discoItem.Item, *discoI)
|
||
}
|
||
|
||
reply.PayloadEncode(discoItem)
|
||
client.Out <- reply
|
||
}
|
||
|
||
func execCommandAdHoc(iq *xmpp.Iq) {
|
||
adHoc := &xmpp.AdHocCommand{}
|
||
iq.PayloadDecode(adHoc)
|
||
log.Info("Commande Ad-Hoc reçut. Node : %s", adHoc.Node)
|
||
|
||
// For now, we know that the node is the Mac address for a relay
|
||
relais := relay.GetRelayByMac(adHoc.Node)
|
||
descriptionRelais := relais.Description
|
||
if descriptionRelais == "" {
|
||
descriptionRelais = relais.Mac
|
||
}
|
||
if adHoc.SessionId == "" && adHoc.Action == xmpp.ActionAdHocExecute {
|
||
// First step in the command
|
||
if relais.Id != 0 {
|
||
reply := iq.Response(xmpp.IqTypeResult)
|
||
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocExecute, SessionId: xmpp.SessionId()/*+";"+relais.Mac*/}
|
||
|
||
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocForm, Title: "Commande relais "+descriptionRelais}
|
||
field := &xmpp.AdHocField{Var: "command", Label: "Commande a executer", Type: "list-single"}
|
||
fieldOption := &xmpp.AdHocFieldOption{Value: "toggle"}
|
||
field.Options = append(field.Options, *fieldOption)
|
||
cmdXForm.Fields = append(cmdXForm.Fields, *field)
|
||
// TODO, ajouter des commandes pour allumer X seconde (par exemple)
|
||
|
||
cmd.XForm = *cmdXForm
|
||
|
||
reply.PayloadEncode(cmd)
|
||
client.Out <- reply
|
||
}
|
||
} else if adHoc.Action == xmpp.ActionAdHocExecute {
|
||
// Last step in the command
|
||
|
||
err := relais.Toggle()
|
||
|
||
reply := iq.Response(xmpp.IqTypeResult)
|
||
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocCompleted, SessionId: adHoc.SessionId}
|
||
|
||
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Commande relais "+descriptionRelais}
|
||
cmd.XForm = *cmdXForm
|
||
|
||
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo}
|
||
if err == nil {
|
||
note.Value = "Commande effectuée avec succes !"
|
||
} else {
|
||
note.Value = "Une erreur c'est produite à l'exécution de la commande…"
|
||
}
|
||
cmd.Note = *note
|
||
|
||
reply.PayloadEncode(cmd)
|
||
client.Out <- reply
|
||
} else if adHoc.Action == xmpp.ActionAdHocCancel {
|
||
// command canceled
|
||
reply := iq.Response(xmpp.IqTypeResult)
|
||
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocCanceled, SessionId: adHoc.SessionId}
|
||
reply.PayloadEncode(cmd)
|
||
client.Out <- reply
|
||
}
|
||
}
|