// Copyright Martin Dosch. // Use of this source code is governed by the BSD-2-clause // license that can be found in the LICENSE file. package main import ( "log" "github.com/beevik/etree" // BSD-2-clause "github.com/mattn/go-xmpp" // BSD-3-Clause ) func sendIQ(client *xmpp.Client, iqc chan xmpp.IQ, target string, iQtype string, content string) (xmpp.IQ, error) { var iq xmpp.IQ id := getID() c := make(chan xmpp.IQ) go getIQ(client, id, c, iqc) _, err := client.RawInformation(client.JID(), target, id, iQtype, content+"\n") if err != nil { return iq, err } iq = <-c return iq, nil } func getIQ(client *xmpp.Client, id string, c chan xmpp.IQ, iqc chan xmpp.IQ) { for { iq := <-iqc if iq.ID == id { c <- iq return } } } func rcvStanzas(client *xmpp.Client, iqc chan xmpp.IQ, msgc chan xmpp.Chat) { for { received, err := client.Recv() if err != nil { log.Println(err) } switch v := received.(type) { case xmpp.Chat: msgc <- v case xmpp.IQ: switch v.Type { case "get": var xmlns *etree.Attr iq := etree.NewDocument() err = iq.ReadFromBytes(v.Query) if err != nil { log.Println("Couldn't parse IQ:", string(v.Query), err) } query := iq.SelectElement("query") if query != nil { xmlns = query.SelectAttr("xmlns") } switch xmlns.Value { case nsDiscoInfo: root := etree.NewDocument() root.WriteSettings.AttrSingleQuote = true reply := root.CreateElement("iq") reply.CreateAttr("type", "result") reply.CreateAttr("from", client.JID()) reply.CreateAttr("to", v.From) reply.CreateAttr("id", v.ID) replyQuery := reply.CreateElement("query") replyQuery.CreateAttr("xmlns", nsDiscoInfo) identity := replyQuery.CreateElement("identity") identity.CreateAttr("category", "client") identity.CreateAttr("type", "bot") identity.CreateAttr("name", "go-sendxmpp") feat := replyQuery.CreateElement("feature") feat.CreateAttr("var", nsDiscoInfo) xmlString, err := root.WriteToString() if err == nil { _, err = client.SendOrg(xmlString) if err != nil { log.Println(err) } } default: root := etree.NewDocument() root.WriteSettings.AttrSingleQuote = true reply := root.CreateElement("iq") reply.CreateAttr("type", "error") reply.CreateAttr("from", client.JID()) reply.CreateAttr("to", v.From) reply.CreateAttr("id", v.ID) errorReply := reply.CreateElement("error") errorReply.CreateAttr("type", "cancel") su := errorReply.CreateElement("service-unavailable") su.CreateAttr("xmlns", nsXMPPStanzas) xmlString, err := root.WriteToString() if err == nil { _, err = client.SendOrg(xmlString) if err != nil { log.Println(err) } } } case "set": root := etree.NewDocument() root.WriteSettings.AttrSingleQuote = true reply := root.CreateElement("iq") reply.CreateAttr("type", "error") reply.CreateAttr("from", client.JID()) reply.CreateAttr("to", v.From) reply.CreateAttr("id", v.ID) errorReply := reply.CreateElement("error") errorReply.CreateAttr("type", "cancel") su := errorReply.CreateElement("service-unavailable") su.CreateAttr("xmlns", nsXMPPStanzas) xmlString, err := root.WriteToString() if err == nil { _, err = client.SendOrg(xmlString) if err != nil { log.Println(err) } } case "reply", "error": iqc <- v default: iqc <- v } } } }