diff options
Diffstat (limited to 'xmpp/gateway/gateway.go')
-rw-r--r-- | xmpp/gateway/gateway.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go index 0c22677..11f68c1 100644 --- a/xmpp/gateway/gateway.go +++ b/xmpp/gateway/gateway.go @@ -2,12 +2,19 @@ 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 @@ -51,3 +58,111 @@ func SendMessage(to string, from string, body string, component *xmpp.Component) _ = 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 +} |