package xmpp import ( "github.com/pkg/errors" "strconv" "strings" "dev.narayana.im/narayana/telegabber/persistence" "dev.narayana.im/narayana/telegabber/xmpp/gateway" log "github.com/sirupsen/logrus" "gosrc.io/xmpp" "gosrc.io/xmpp/stanza" ) func logPacketType(p stanza.Packet) { log.Warnf("Ignoring packet: %T\n", p) } // HandleIq processes an incoming XMPP iq func HandleIq(s xmpp.Sender, p stanza.Packet) { iq, ok := p.(stanza.IQ) if !ok { logPacketType(p) return } log.Printf("Iq: %#v\n", iq) } // HandleMessage processes an incoming XMPP message func HandleMessage(s xmpp.Sender, p stanza.Packet) { msg, ok := p.(stanza.Message) if !ok { logPacketType(p) return } component, ok := s.(*xmpp.Component) if !ok { log.Error("Not a component") return } if msg.Type != "error" && msg.Body != "" { log.WithFields(log.Fields{ "from": msg.From, "to": msg.To, }).Warn("Message") log.Debugf("%#v", msg) fromJid, err := xmpp.NewJid(msg.From) if err != nil { log.Error("Invalid from JID!") return } session, ok := sessions[fromJid.Bare()] if !ok { log.Error("Message from stranger") return } toParts := strings.Split(msg.To, "@") toID := toParts[0] if len(toParts) > 1 { toIDInt, err := strconv.Atoi(toID) if err != nil { session.ProcessOutgoingMessage(toIDInt, msg.Body, 0) return } } else if toID == gateway.Jid.Bare() { bodyFields := strings.Fields(msg.Body) cmd := bodyFields[0] if strings.HasPrefix(cmd, "/") { response := session.ProcessTransportCommand(cmd[1:], bodyFields[1:]) if response != "" { gateway.SendMessage(msg.From, "", response, component) } return } } log.Warn("Unknown purpose of the message, skipping") } } // HandlePresence processes an incoming XMPP presence func HandlePresence(s xmpp.Sender, p stanza.Packet) { prs, ok := p.(stanza.Presence) if !ok { logPacketType(p) return } if prs.Type == "subscribe" { handleSubscription(s, prs) } if prs.To == gateway.Jid.Bare() { handlePresence(s, prs) } } func handleSubscription(s xmpp.Sender, p stanza.Presence) { log.WithFields(log.Fields{ "from": p.From, "to": p.To, }).Warn("Subscription request") log.Debugf("%#v", p) reply := stanza.Presence{Attrs: stanza.Attrs{ From: p.To, To: p.From, Id: p.Id, Type: "subscribed", }} _ = s.Send(reply) } func handlePresence(s xmpp.Sender, p stanza.Presence) { presenceType := p.Type if presenceType == "" { presenceType = "online" } component, ok := s.(*xmpp.Component) if !ok { log.Error("Not a component") return } log.WithFields(log.Fields{ "type": presenceType, "from": p.From, "to": p.To, }).Warn("Presence") log.Debugf("%#v", p) fromJid, err := xmpp.NewJid(p.From) if err != nil { log.Error("Invalid from JID!") return } bareFromJid := fromJid.Bare() session, ok := getTelegramInstance(bareFromJid, &persistence.Session{}, component) if !ok { return } switch p.Type { case "unsubscribed", "unsubscribe": session.Disconnect() delete(sessions, bareFromJid) case "unavailable", "error": session.Disconnect() case "", "online": // due to the weird implentation of go-tdlib wrapper, it won't // return the client instance until successful authorization go func() { err = session.Connect() if err != nil { log.Error(errors.Wrap(err, "TDlib connection failure")) } }() } }