imap: add User.receiveEvents
This commit is contained in:
parent
60b4122c1d
commit
38af52e857
|
@ -335,7 +335,7 @@ func (ab *addressBook) CreateAddressObject(card vcard.Card) (carddav.AddressObje
|
|||
func (ab *addressBook) receiveEvents(events <-chan *protonmail.Event) {
|
||||
for event := range events {
|
||||
ab.locker.Lock()
|
||||
if event.Refresh == 1 {
|
||||
if event.Refresh&protonmail.EventRefreshContacts != 0 {
|
||||
ab.cache = make(map[string]*addressObject)
|
||||
ab.total = -1
|
||||
} else if len(event.Contacts) > 0 {
|
||||
|
|
|
@ -174,3 +174,18 @@ func (mbox *Mailbox) ForEach(f func(seqNum, uid uint32, apiID string) error) err
|
|||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Reset() error {
|
||||
return mbox.u.db.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(mailboxesBucket)
|
||||
if b == nil {
|
||||
return errors.New("cannot find mailboxes bucket")
|
||||
}
|
||||
k := []byte(mbox.name)
|
||||
if err := b.DeleteBucket(k); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := b.CreateBucket(k)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
|
|
@ -78,6 +78,16 @@ func (u *User) Message(apiID string) (*protonmail.Message, error) {
|
|||
return msg, err
|
||||
}
|
||||
|
||||
func (u *User) ResetMessages() error {
|
||||
return u.db.Update(func(tx *bolt.Tx) error {
|
||||
return tx.DeleteBucket(messagesBucket)
|
||||
})
|
||||
}
|
||||
|
||||
func (u *User) Close() error {
|
||||
return u.db.Close()
|
||||
}
|
||||
|
||||
func Open(path string) (*User, error) {
|
||||
db, err := bolt.Open(path, 0700, nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -130,6 +130,15 @@ func (mbox *mailbox) init() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mbox *mailbox) reset() error {
|
||||
mbox.initializedLock.Lock()
|
||||
defer mbox.initializedLock.Unlock()
|
||||
|
||||
mbox.initialized = false
|
||||
|
||||
return mbox.db.Reset()
|
||||
}
|
||||
|
||||
func (mbox *mailbox) fetchMessage(isUid bool, id uint32, items []imap.FetchItem) (*imap.Message, error) {
|
||||
var apiID string
|
||||
var err error
|
||||
|
|
94
imap/user.go
94
imap/user.go
|
@ -1,6 +1,9 @@
|
|||
package imap
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"github.com/emersion/go-imap"
|
||||
imapbackend "github.com/emersion/go-imap/backend"
|
||||
|
@ -31,6 +34,8 @@ type user struct {
|
|||
privateKeys openpgp.EntityList
|
||||
|
||||
db *database.User
|
||||
|
||||
locker sync.Mutex
|
||||
mailboxes map[string]*mailbox
|
||||
}
|
||||
|
||||
|
@ -39,7 +44,6 @@ func newUser(c *protonmail.Client, u *protonmail.User, privateKeys openpgp.Entit
|
|||
c: c,
|
||||
u: u,
|
||||
privateKeys: privateKeys,
|
||||
mailboxes: make(map[string]*mailbox),
|
||||
}
|
||||
|
||||
db, err := database.Open(u.Name+".db")
|
||||
|
@ -48,34 +52,49 @@ func newUser(c *protonmail.Client, u *protonmail.User, privateKeys openpgp.Entit
|
|||
}
|
||||
uu.db = db
|
||||
|
||||
if err := uu.initMailboxes(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: go uu.receiveEvents(events)
|
||||
|
||||
return uu, nil
|
||||
}
|
||||
|
||||
func (u *user) initMailboxes() error {
|
||||
u.locker.Lock()
|
||||
defer u.locker.Unlock()
|
||||
|
||||
u.mailboxes = make(map[string]*mailbox)
|
||||
|
||||
for _, data := range systemMailboxes {
|
||||
mboxDB, err := db.Mailbox(data.label)
|
||||
mboxDB, err := u.db.Mailbox(data.label)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
uu.mailboxes[data.label] = &mailbox{
|
||||
u.mailboxes[data.label] = &mailbox{
|
||||
name: data.name,
|
||||
label: data.label,
|
||||
flags: data.flags,
|
||||
u: uu,
|
||||
u: u,
|
||||
db: mboxDB,
|
||||
}
|
||||
}
|
||||
|
||||
counts, err := c.CountMessages("")
|
||||
counts, err := u.c.CountMessages("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
for _, count := range counts {
|
||||
if mbox, ok := uu.mailboxes[count.LabelID]; ok {
|
||||
if mbox, ok := u.mailboxes[count.LabelID]; ok {
|
||||
mbox.total = count.Total
|
||||
mbox.unread = count.Unread
|
||||
}
|
||||
}
|
||||
|
||||
return uu, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *user) Username() string {
|
||||
|
@ -83,6 +102,9 @@ func (u *user) Username() string {
|
|||
}
|
||||
|
||||
func (u *user) ListMailboxes(subscribed bool) ([]imapbackend.Mailbox, error) {
|
||||
u.locker.Lock()
|
||||
defer u.locker.Unlock()
|
||||
|
||||
list := make([]imapbackend.Mailbox, 0, len(u.mailboxes))
|
||||
for _, mbox := range u.mailboxes {
|
||||
list = append(list, mbox)
|
||||
|
@ -91,6 +113,9 @@ func (u *user) ListMailboxes(subscribed bool) ([]imapbackend.Mailbox, error) {
|
|||
}
|
||||
|
||||
func (u *user) GetMailbox(name string) (imapbackend.Mailbox, error) {
|
||||
u.locker.Lock()
|
||||
defer u.locker.Unlock()
|
||||
|
||||
for _, mbox := range u.mailboxes {
|
||||
if mbox.name == name {
|
||||
return mbox, nil
|
||||
|
@ -112,8 +137,59 @@ func (u *user) RenameMailbox(existingName, newName string) error {
|
|||
}
|
||||
|
||||
func (u *user) Logout() error {
|
||||
if err := u.db.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.c = nil
|
||||
u.u = nil
|
||||
u.privateKeys = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *user) receiveEvents(events <-chan *protonmail.Event) {
|
||||
for event := range events {
|
||||
if event.Refresh&protonmail.EventRefreshMail != 0 {
|
||||
log.Println("Reinitializing the whole IMAP database")
|
||||
|
||||
u.locker.Lock()
|
||||
for _, mbox := range u.mailboxes {
|
||||
if err := mbox.reset(); err != nil {
|
||||
log.Printf("cannot reset mailbox %s: %v", mbox.name, err)
|
||||
}
|
||||
}
|
||||
u.locker.Unlock()
|
||||
|
||||
if err := u.db.ResetMessages(); err != nil {
|
||||
log.Printf("cannot reset user: %v", err)
|
||||
}
|
||||
|
||||
if err := u.initMailboxes(); err != nil {
|
||||
log.Printf("cannot reinitialize mailboxes: %v", err)
|
||||
}
|
||||
} else {
|
||||
u.locker.Lock()
|
||||
for _, count := range event.MessageCounts {
|
||||
if mbox, ok := u.mailboxes[count.LabelID]; ok {
|
||||
mbox.total = count.Total
|
||||
mbox.unread = count.Unread
|
||||
// TODO: send update
|
||||
}
|
||||
}
|
||||
u.locker.Unlock()
|
||||
|
||||
for _, eventMessage := range event.Messages {
|
||||
switch eventMessage.Action {
|
||||
case protonmail.EventCreate:
|
||||
// TODO
|
||||
case protonmail.EventUpdate:
|
||||
// TODO
|
||||
case protonmail.EventUpdateFlags:
|
||||
// TODO
|
||||
case protonmail.EventDelete:
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,17 @@ import (
|
|||
"net/http"
|
||||
)
|
||||
|
||||
type EventRefresh int
|
||||
|
||||
const (
|
||||
EventRefreshMail EventRefresh = 1 << iota
|
||||
EventRefreshContacts
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
ID string `json:"EventID"`
|
||||
Refresh int
|
||||
//Messages
|
||||
Refresh EventRefresh
|
||||
Messages []*EventMessage
|
||||
Contacts []*EventContact
|
||||
//ContactEmails
|
||||
//Labels
|
||||
|
@ -15,7 +22,7 @@ type Event struct {
|
|||
//Members
|
||||
//Domains
|
||||
//Organization
|
||||
//MessageCounts
|
||||
MessageCounts []*MessageCount
|
||||
//ConversationCounts
|
||||
//UsedSpace
|
||||
Notices []string
|
||||
|
@ -27,8 +34,17 @@ const (
|
|||
EventDelete EventAction = iota
|
||||
EventCreate
|
||||
EventUpdate
|
||||
|
||||
// For messages
|
||||
EventUpdateFlags
|
||||
)
|
||||
|
||||
type EventMessage struct {
|
||||
ID string
|
||||
Action EventAction
|
||||
Message *Message
|
||||
}
|
||||
|
||||
type EventContact struct {
|
||||
ID string
|
||||
Action EventAction
|
||||
|
|
Loading…
Reference in New Issue