Support vCard4 via PubSub

This commit is contained in:
Bohdan Horbeshko 2022-06-28 19:34:14 -04:00
parent 3a43c6223f
commit 76ac662366
2 changed files with 129 additions and 12 deletions

View file

@ -119,7 +119,7 @@ func (c IqVcardTemp) Namespace() string {
return c.XMLName.Space return c.XMLName.Space
} }
// Namespace is a namespace! // GetSet getsets!
func (c IqVcardTemp) GetSet() *stanza.ResultSet { func (c IqVcardTemp) GetSet() *stanza.ResultSet {
return c.ResultSet return c.ResultSet
} }

View file

@ -3,6 +3,7 @@ package xmpp
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/xml"
"github.com/pkg/errors" "github.com/pkg/errors"
"io" "io"
"strconv" "strconv"
@ -17,6 +18,12 @@ import (
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
const (
TypeVCardTemp byte = iota
TypeVCard4
)
const NodeVCard4 string = "urn:xmpp:vcard4"
func logPacketType(p stanza.Packet) { func logPacketType(p stanza.Packet) {
log.Warnf("Ignoring packet: %T\n", p) log.Warnf("Ignoring packet: %T\n", p)
} }
@ -33,9 +40,16 @@ func HandleIq(s xmpp.Sender, p stanza.Packet) {
if iq.Type == "get" { if iq.Type == "get" {
_, ok := iq.Payload.(*extensions.IqVcardTemp) _, ok := iq.Payload.(*extensions.IqVcardTemp)
if ok { if ok {
go handleGetVcardTempIq(s, iq) go handleGetVcardIq(s, iq, TypeVCardTemp)
return return
} }
pubsub, ok := iq.Payload.(*stanza.PubSubGeneric)
if ok {
if pubsub.Items != nil && pubsub.Items.Node == NodeVCard4 {
go handleGetVcardIq(s, iq, TypeVCard4)
return
}
}
_, ok = iq.Payload.(*stanza.DiscoInfo) _, ok = iq.Payload.(*stanza.DiscoInfo)
if ok { if ok {
go handleGetDiscoInfo(s, iq) go handleGetDiscoInfo(s, iq)
@ -216,7 +230,7 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
} }
} }
func handleGetVcardTempIq(s xmpp.Sender, iq *stanza.IQ) { func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"from": iq.From, "from": iq.From,
"to": iq.To, "to": iq.To,
@ -246,9 +260,9 @@ func handleGetVcardTempIq(s xmpp.Sender, iq *stanza.IQ) {
return return
} }
vcard := extensions.IqVcardTemp{} var fn, photo, nickname, given, family, tel string
if chat != nil { if chat != nil {
vcard.Fn.Text = chat.Title fn = chat.Title
if chat.Photo != nil { if chat.Photo != nil {
file, path, err := session.OpenPhotoFile(chat.Photo.Small, 32) file, path, err := session.OpenPhotoFile(chat.Photo.Small, 32)
@ -260,8 +274,7 @@ func handleGetVcardTempIq(s xmpp.Sender, iq *stanza.IQ) {
_, err = io.Copy(binval, file) _, err = io.Copy(binval, file)
binval.Close() binval.Close()
if err == nil { if err == nil {
vcard.Photo.Type.Text = "image/jpeg" photo = buf.String()
vcard.Photo.Binval.Text = buf.String()
} else { } else {
log.Errorf("Error calculating base64: %v", path) log.Errorf("Error calculating base64: %v", path)
} }
@ -273,10 +286,10 @@ func handleGetVcardTempIq(s xmpp.Sender, iq *stanza.IQ) {
} }
} }
if user != nil { if user != nil {
vcard.Nickname.Text = user.Username nickname = user.Username
vcard.N.Given.Text = user.FirstName given = user.FirstName
vcard.N.Family.Text = user.LastName family = user.LastName
vcard.Tel.Number.Text = user.PhoneNumber tel = user.PhoneNumber
} }
answer := stanza.IQ{ answer := stanza.IQ{
@ -286,7 +299,7 @@ func handleGetVcardTempIq(s xmpp.Sender, iq *stanza.IQ) {
Id: iq.Id, Id: iq.Id,
Type: "result", Type: "result",
}, },
Payload: vcard, Payload: makeVCardPayload(typ, iq.To, fn, photo, nickname, given, family, tel),
} }
log.Debugf("%#v", answer) log.Debugf("%#v", answer)
@ -357,3 +370,107 @@ func toToID(to string) (int64, bool) {
} }
return toID, true return toID, true
} }
func makeVCardPayload(typ byte, id string, fn string, photo string, nickname string, given string, family string, tel string) stanza.IQPayload {
if typ == TypeVCardTemp {
vcard := &extensions.IqVcardTemp{}
vcard.Fn.Text = fn
if photo != "" {
vcard.Photo.Type.Text = "image/jpeg"
vcard.Photo.Binval.Text = photo
}
vcard.Nickname.Text = nickname
vcard.N.Given.Text = given
vcard.N.Family.Text = family
vcard.Tel.Number.Text = tel
return vcard
} else if typ == TypeVCard4 {
nodes := []stanza.Node{}
if fn != "" {
nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "fn"},
Nodes: []stanza.Node{
stanza.Node{
XMLName: xml.Name{Local: "text"},
Content: fn,
},
},
})
}
if photo != "" {
nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "photo"},
Nodes: []stanza.Node{
stanza.Node{
XMLName: xml.Name{Local: "uri"},
Content: "data:image/jpeg;base64," + photo,
},
},
})
}
if nickname != "" {
nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "nickname"},
Nodes: []stanza.Node{
stanza.Node{
XMLName: xml.Name{Local: "text"},
Content: nickname,
},
},
})
}
if family != "" || given != "" {
nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "n"},
Nodes: []stanza.Node{
stanza.Node{
XMLName: xml.Name{Local: "surname"},
Content: family,
},
stanza.Node{
XMLName: xml.Name{Local: "given"},
Content: given,
},
},
})
}
if tel != "" {
nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "tel"},
Nodes: []stanza.Node{
stanza.Node{
XMLName: xml.Name{Local: "uri"},
Content: "tel:" + tel,
},
},
})
}
pubsub := &stanza.PubSubGeneric{
Items: &stanza.Items{
Node: NodeVCard4,
List: []stanza.Item{
stanza.Item{
Id: id,
Any: &stanza.Node{
XMLName: xml.Name{Local: "vcard"},
Attrs: []xml.Attr{
xml.Attr{
Name: xml.Name{Local: "xmlns"},
Value: "urn:ietf:params:xml:ns:vcard-4.0",
},
},
Nodes: nodes,
},
},
},
},
}
return pubsub
}
return nil
}