package gateway import ( "encoding/xml" "github.com/pkg/errors" "dev.narayana.im/narayana/telegabber/xmpp/extensions" log "github.com/sirupsen/logrus" "github.com/soheilhy/args" "gosrc.io/xmpp" "gosrc.io/xmpp/stanza" ) // Queue stores presences to send later type Queue map[string]*stanza.Presence // Jid stores the component's JID object var Jid *xmpp.Jid // SendMessage creates and sends a message stanza func SendMessage(to string, from string, body string, component *xmpp.Component) { componentJid := Jid.Full() var logFrom string var messageFrom string if from == "" { logFrom = componentJid messageFrom = componentJid } else { logFrom = from messageFrom = from + "@" + componentJid } log.WithFields(log.Fields{ "from": logFrom, "to": to, }).Warn("Got message") message := stanza.Message{ Attrs: stanza.Attrs{ From: messageFrom, To: to, Type: "chat", }, Body: body, } // explicit check, as marshalling is expensive if log.GetLevel() == log.DebugLevel { xmlMessage, err := xml.Marshal(message) if err == nil { log.Debug(string(xmlMessage)) } else { log.Debugf("%#v", message) } } _ = component.Send(message) } // LogBadPresence verbosely logs a presence func LogBadPresence(err error, presence *stanza.Presence) { log.WithFields(log.Fields{ "presence": *presence, }).Error(errors.Wrap(err, "Couldn't send presence")) } // SPFrom is a Telegram user id var SPFrom = args.NewString() // SPType is a presence type var SPType = args.NewString() // SPShow is a availability status var SPShow = args.NewString() // SPStatus is a verbose status var SPStatus = args.NewString() // SPNickname is a XEP-0172 nickname var SPNickname = args.NewString() // SPPhoto is a XEP-0153 hash of avatar in vCard var SPPhoto = args.NewString() // SPImmed skips queueing var SPImmed = args.NewBool(args.Default(true)) func newPresence(bareJid string, to string, args ...args.V) stanza.Presence { var presenceFrom string if SPFrom.IsSet(args) { presenceFrom = SPFrom.Get(args) + "@" + bareJid } else { presenceFrom = bareJid } presence := stanza.Presence{Attrs: stanza.Attrs{ From: presenceFrom, To: to, }} if SPType.IsSet(args) { presence.Attrs.Type = stanza.StanzaType(SPType.Get(args)) } if SPShow.IsSet(args) { presence.Show = stanza.PresenceShow(SPShow.Get(args)) } if SPStatus.IsSet(args) { presence.Status = SPStatus.Get(args) } if SPNickname.IsSet(args) { presence.Extensions = append(presence.Extensions, extensions.PresenceNickExtension{ Text: SPNickname.Get(args), }) } if SPPhoto.IsSet(args) { presence.Extensions = append(presence.Extensions, extensions.PresenceXVCardUpdateExtension{ Photo: extensions.PresenceXVCardUpdatePhoto{ Text: SPPhoto.Get(args), }, }) } return presence } // SendPresence creates and sends a presence stanza func SendPresence(component *xmpp.Component, queue Queue, to string, args ...args.V) error { var logFrom string bareJid := Jid.Bare() if SPFrom.IsSet(args) { logFrom = SPFrom.Get(args) } else { logFrom = bareJid } log.WithFields(log.Fields{ "type": SPType.Get(args), "from": logFrom, "to": to, }).Info("Got presence") presence := newPresence(bareJid, to, args...) // explicit check, as marshalling is expensive if log.GetLevel() == log.DebugLevel { xmlPresence, err := xml.Marshal(presence) if err == nil { log.Debug(string(xmlPresence)) } else { log.Debugf("%#v", presence) } } immed := SPImmed.Get(args) if immed { err := component.Send(presence) if err != nil { LogBadPresence(err, &presence) return err } } else { queue[presence.From+presence.To] = &presence } return nil }