vCard support

This commit is contained in:
bodqhrohro 2019-12-10 20:34:55 +02:00
parent ae2470dcb7
commit 416c708909
2 changed files with 173 additions and 1 deletions

View file

@ -24,6 +24,85 @@ type PresenceXVCardUpdatePhoto struct {
Text string `xml:",chardata"` Text string `xml:",chardata"`
} }
// IqVcardTemp is from XEP-0054
type IqVcardTemp struct {
XMLName xml.Name `xml:"vcard-temp vCard"`
Fn IqVcardFn
Nickname IqVcardNickname
N IqVcardN
Tel IqVcardTel
Photo IqVcardPhoto
}
// IqVcardFn is vCard/FN
type IqVcardFn struct {
XMLName xml.Name `xml:"FN"`
Text string `xml:",chardata"`
}
// IqVcardNickname is vCard/NICKNAME
type IqVcardNickname struct {
XMLName xml.Name `xml:"NICKNAME"`
Text string `xml:",chardata"`
}
// IqVcardN is vCard/N
type IqVcardN struct {
XMLName xml.Name `xml:"N"`
Family IqVcardNFamily
Given IqVcardNGiven
Middle IqVcardNMiddle
}
// IqVcardNFamily is vCard/N/FAMILY
type IqVcardNFamily struct {
XMLName xml.Name `xml:"FAMILY"`
Text string `xml:",chardata"`
}
// IqVcardNGiven is vCard/N/GIVEN
type IqVcardNGiven struct {
XMLName xml.Name `xml:"GIVEN"`
Text string `xml:",chardata"`
}
// IqVcardNMiddle is vCard/N/MIDDLE
type IqVcardNMiddle struct {
XMLName xml.Name `xml:"MIDDLE"`
Text string `xml:",chardata"`
}
// IqVcardTel is vCard/TEL
type IqVcardTel struct {
XMLName xml.Name `xml:"TEL"`
Number IqVcardTelNumber
}
// IqVcardTelNumber is vCard/TEL/NUMBER
type IqVcardTelNumber struct {
XMLName xml.Name `xml:"NUMBER"`
Text string `xml:",chardata"`
}
// IqVcardPhoto is vCard/PHOTO
type IqVcardPhoto struct {
XMLName xml.Name `xml:"PHOTO"`
Type IqVcardPhotoType
Binval IqVcardPhotoBinval
}
// IqVcardPhotoType is vCard/PHOTO/TYPE
type IqVcardPhotoType struct {
XMLName xml.Name `xml:"TYPE"`
Text string `xml:",chardata"`
}
// IqVcardPhotoBinval is vCard/PHOTO/BINVAL
type IqVcardPhotoBinval struct {
XMLName xml.Name `xml:"BINVAL"`
Text string `xml:",chardata"`
}
// Namespace is a namespace! // Namespace is a namespace!
func (c PresenceNickExtension) Namespace() string { func (c PresenceNickExtension) Namespace() string {
return c.XMLName.Space return c.XMLName.Space
@ -34,6 +113,11 @@ func (c PresenceXVCardUpdateExtension) Namespace() string {
return c.XMLName.Space return c.XMLName.Space
} }
// Namespace is a namespace!
func (c IqVcardTemp) Namespace() string {
return c.XMLName.Space
}
func init() { func init() {
// presence nick // presence nick
stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{ stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{
@ -46,4 +130,10 @@ func init() {
"vcard-temp:x:update", "vcard-temp:x:update",
"x", "x",
}, PresenceXVCardUpdateExtension{}) }, PresenceXVCardUpdateExtension{})
// iq vcard request
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{
"vcard-temp",
"vCard",
}, IqVcardTemp{})
} }

View file

@ -1,11 +1,16 @@
package xmpp package xmpp
import ( import (
"bytes"
"encoding/base64"
"github.com/pkg/errors" "github.com/pkg/errors"
"io"
"os"
"strconv" "strconv"
"strings" "strings"
"dev.narayana.im/narayana/telegabber/persistence" "dev.narayana.im/narayana/telegabber/persistence"
"dev.narayana.im/narayana/telegabber/xmpp/extensions"
"dev.narayana.im/narayana/telegabber/xmpp/gateway" "dev.narayana.im/narayana/telegabber/xmpp/gateway"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -25,7 +30,84 @@ func HandleIq(s xmpp.Sender, p stanza.Packet) {
return return
} }
log.Printf("Iq: %#v\n", iq) log.Debugf("%#v", iq)
if iq.Type == "get" {
_, ok := iq.Payload.(*extensions.IqVcardTemp)
if ok {
log.WithFields(log.Fields{
"from": iq.From,
"to": iq.To,
}).Warn("VCard request")
fromJid, err := xmpp.NewJid(iq.From)
if err != nil {
log.Error("Invalid from JID!")
return
}
session, ok := sessions[fromJid.Bare()]
if !ok {
log.Error("IQ from stranger")
return
}
toParts := strings.Split(iq.To, "@")
toID, err := strconv.ParseInt(toParts[0], 10, 64)
if err != nil {
log.Error("Invalid IQ to")
return
}
chat, user, err := session.GetContactByID(toID, nil)
if err != nil {
log.Error(err)
return
}
vcard := extensions.IqVcardTemp{}
if chat != nil {
vcard.Fn.Text = chat.Title
if chat.Photo != nil {
path := chat.Photo.Small.Local.Path
file, err := os.Open(path)
if err == nil {
defer file.Close()
buf := new(bytes.Buffer)
binval := base64.NewEncoder(base64.StdEncoding, buf)
_, err = io.Copy(binval, file)
if err == nil {
vcard.Photo.Type.Text = "image/jpeg"
vcard.Photo.Binval.Text = buf.String()
} else {
log.Errorf("Error calculating hash: %v", path)
}
} else if path != "" {
log.Errorf("Photo does not exist: %v", path)
}
}
}
if user != nil {
vcard.Nickname.Text = user.Username
vcard.N.Given.Text = user.FirstName
vcard.N.Family.Text = user.LastName
vcard.Tel.Number.Text = user.PhoneNumber
}
answer := stanza.IQ{
Attrs: stanza.Attrs{
From: iq.To,
To: iq.From,
Id: iq.Id,
Type: "result",
},
Payload: vcard,
}
log.Debugf("%#v", answer)
_ = s.Send(answer)
}
}
} }
// HandleMessage processes an incoming XMPP message // HandleMessage processes an incoming XMPP message