From 49ff810a484420816c1a1eec8d16a761bbe58000 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Sep 2017 22:45:13 +0200 Subject: [PATCH] carddav: implement AddressBook.CreateAddressObject --- carddav/carddav.go | 46 ++++++++++++++++++++++++++++++++++++++++-- protonmail/contacts.go | 13 ++++++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/carddav/carddav.go b/carddav/carddav.go index 10a335f..e691090 100644 --- a/carddav/carddav.go +++ b/carddav/carddav.go @@ -1,6 +1,8 @@ package carddav import ( + "bytes" + "errors" "net/http" "os" "strings" @@ -53,6 +55,10 @@ func (ao *addressObject) ID() string { return ao.contact.ID } +func (ao *addressObject) Stat() (os.FileInfo, error) { + return &addressFileInfo{ao.contact}, nil +} + func (ao *addressObject) Card() (vcard.Card, error) { card := make(vcard.Card) @@ -80,8 +86,8 @@ func (ao *addressObject) Card() (vcard.Card, error) { return card, nil } -func (ao *addressObject) Stat() (os.FileInfo, error) { - return &addressFileInfo{ao.contact}, nil +func (ao *addressObject) SetCard(card vcard.Card) error { + return errors.New("hydroxide/carddav: not yet implemented") } type addressBook struct { @@ -207,6 +213,42 @@ func (ab *addressBook) GetAddressObject(id string) (carddav.AddressObject, error return ao, nil } +func (ab *addressBook) CreateAddressObject(card vcard.Card) (carddav.AddressObject, error) { + // TODO: sign/encrypt stuff + + var b bytes.Buffer + if err := vcard.NewEncoder(&b).Encode(card); err != nil { + return nil, err + } + + contactImport := &protonmail.ContactImport{ + Cards: []*protonmail.ContactCard{ + {Data: b.String()}, + }, + } + + resps, err := ab.c.CreateContacts([]*protonmail.ContactImport{contactImport}) + if err != nil { + return nil, err + } + if len(resps) != 1 { + return nil, errors.New("hydroxide/carddav: expected exactly one response when creating contact") + } + resp := resps[0] + if err := resp.Err(); err != nil { + return nil, err + } + contact := resp.Response.Contact + contact.Cards = contactImport.Cards // Not returned by the server + + ao := &addressObject{ + c: ab.c, + contact: contact, + } + ab.cacheAddressObject(ao) + return ao, nil +} + func (ab *addressBook) receiveEvents(events <-chan *protonmail.Event) { for event := range events { ab.locker.Lock() diff --git a/protonmail/contacts.go b/protonmail/contacts.go index daf30e5..409afe9 100644 --- a/protonmail/contacts.go +++ b/protonmail/contacts.go @@ -73,6 +73,10 @@ type ContactExport struct { Cards []*ContactCard } +type ContactImport struct { + Cards []*ContactCard +} + func (c *Client) ListContacts(page, pageSize int) (total int, contacts []*Contact, err error) { v := url.Values{} v.Set("Page", strconv.Itoa(page)) @@ -163,7 +167,7 @@ func (c *Client) GetContact(id string) (*Contact, error) { } type CreateContactResp struct { - Input *Contact + Index int Response struct { resp Contact *Contact @@ -174,10 +178,11 @@ func (resp *CreateContactResp) Err() error { return resp.Response.Err() } -func (c *Client) CreateContacts(contacts []*Contact) ([]*CreateContactResp, error) { +func (c *Client) CreateContacts(contacts []*ContactImport) ([]*CreateContactResp, error) { reqData := struct { - Contacts []*Contact - }{contacts} + Contacts []*ContactImport + Overwrite, Groups, Labels int + }{contacts, 0, 0, 0} req, err := c.newJSONRequest(http.MethodPost, "/contacts", &reqData) if err != nil { return nil, err