aboutsummaryrefslogtreecommitdiff
path: root/xmpp/gateway
diff options
context:
space:
mode:
authorbodqhrohro <bodqhrohro@gmail.com>2019-11-25 01:20:07 +0300
committerbodqhrohro <bodqhrohro@gmail.com>2019-11-25 01:20:07 +0300
commitd6f6207ebb3d5256256a7810a3d3d0bdc8ba04a5 (patch)
treed52c3e2f4c7b4a46505b882782d850d28988ca11 /xmpp/gateway
parent653b1bde94b89d91862007a18b8730ff58673f59 (diff)
Refactoring: move SendPresence to xmpp/gateway package
Diffstat (limited to 'xmpp/gateway')
-rw-r--r--xmpp/gateway/gateway.go115
-rw-r--r--xmpp/gateway/gateway_test.go54
2 files changed, 169 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
+}
diff --git a/xmpp/gateway/gateway_test.go b/xmpp/gateway/gateway_test.go
new file mode 100644
index 0000000..6191844
--- /dev/null
+++ b/xmpp/gateway/gateway_test.go
@@ -0,0 +1,54 @@
+package gateway
+
+import (
+ "encoding/xml"
+ "testing"
+
+ "gosrc.io/xmpp/stanza"
+)
+
+func testPresence(t *testing.T, presence stanza.Presence, reference string) {
+ byteXML, err := xml.Marshal(presence)
+ if err != nil {
+ t.Errorf("XML parse error: %v", err)
+ }
+ xmlText := string(byteXML)
+ if xmlText != reference {
+ t.Errorf("%v does not match %v", xmlText, reference)
+ }
+}
+
+func TestPresenceFrom(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPFrom("test"))
+ testPresence(t, presence, "<presence from=\"test@from@test\" to=\"to@test\"></presence>")
+}
+
+func TestPresenceNoFrom(t *testing.T) {
+ presence := newPresence("from@test", "to@test")
+ testPresence(t, presence, "<presence from=\"from@test\" to=\"to@test\"></presence>")
+}
+
+func TestPresenceType(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPType("subscribe"))
+ testPresence(t, presence, "<presence type=\"subscribe\" from=\"from@test\" to=\"to@test\"></presence>")
+}
+
+func TestPresenceShow(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPShow("dnd"))
+ testPresence(t, presence, "<presence from=\"from@test\" to=\"to@test\"><show>dnd</show></presence>")
+}
+
+func TestPresenceStatus(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPStatus("cooking"))
+ testPresence(t, presence, "<presence from=\"from@test\" to=\"to@test\"><status>cooking</status></presence>")
+}
+
+func TestPresenceNickname(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPNickname("Ishmael"))
+ testPresence(t, presence, "<presence from=\"from@test\" to=\"to@test\"><nick xmlns=\"http://jabber.org/protocol/nick\">Ishmael</nick></presence>")
+}
+
+func TestPresencePhoto(t *testing.T) {
+ presence := newPresence("from@test", "to@test", SPPhoto("01b87fcd030b72895ff8e88db57ec525450f000d"))
+ testPresence(t, presence, "<presence from=\"from@test\" to=\"to@test\"><x xmlns=\"vcard-temp:x:update\"><photo>01b87fcd030b72895ff8e88db57ec525450f000d</photo></x></presence>")
+}