hydroxide-push/imap/database/user.go

99 lines
1.7 KiB
Go

package database
import (
"encoding/json"
"errors"
"github.com/boltdb/bolt"
"github.com/emersion/hydroxide/protonmail"
)
var ErrNotFound = errors.New("message not found in local database")
var (
mailboxesBucket = []byte("mailboxes")
messagesBucket = []byte("messages")
)
type User struct {
db *bolt.DB
}
func (u *User) Mailbox(name string) (*Mailbox, error) {
err := u.db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists(mailboxesBucket)
if err != nil {
return err
}
_, err = b.CreateBucketIfNotExists([]byte(name))
return err
})
if err != nil {
return nil, err
}
return &Mailbox{name, u}, nil
}
func (u *User) sync(messages []*protonmail.Message) error {
return u.db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists(messagesBucket)
if err != nil {
return err
}
for _, msg := range messages {
k := []byte(msg.ID)
v, err := json.Marshal(msg)
if err != nil {
return err
}
if err := b.Put(k, v); err != nil {
return err
}
}
return nil
})
}
func (u *User) Message(apiID string) (*protonmail.Message, error) {
var msg *protonmail.Message
err := u.db.View(func (tx *bolt.Tx) error {
b := tx.Bucket(messagesBucket)
if b == nil {
return ErrNotFound
}
k := []byte(apiID)
v := b.Get(k)
if v == nil {
return ErrNotFound
}
msg = &protonmail.Message{}
return json.Unmarshal(v, msg)
})
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 {
return nil, err
}
return &User{db}, nil
}