Add better list and fetch actions

This commit is contained in:
Melon 2023-09-11 22:42:51 +01:00
parent f90abb3d74
commit 7629c5aa8e
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
2 changed files with 40 additions and 61 deletions

View File

@ -3,7 +3,6 @@ package api
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/1f349/lotus/imap"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"log" "log"
@ -141,28 +140,3 @@ func apiError(rw http.ResponseWriter, code int, m string) {
"error": m, "error": m,
}) })
} }
type IcCallback[T any] func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t T) error
func imapClient[T any](recv Imap, cb IcCallback[T]) AuthCallback {
return func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
if req.Body == nil {
rw.WriteHeader(http.StatusBadRequest)
return
}
var t T
if json.NewDecoder(req.Body).Decode(&t) != nil {
rw.WriteHeader(http.StatusBadRequest)
return
}
cli, err := recv.MakeClient(b.Subject)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
return
}
err = cb(rw, req, params, cli, t)
if err != nil {
log.Println("[ImapClient] Error:", err)
}
}
}

View File

@ -1,9 +1,10 @@
package imap package imap
import ( import (
"errors"
"github.com/emersion/go-imap" "github.com/emersion/go-imap"
"github.com/emersion/go-imap/client" "github.com/emersion/go-imap/client"
"time" "strconv"
) )
var imapStatusFlags = []imap.StatusItem{ var imapStatusFlags = []imap.StatusItem{
@ -18,6 +19,8 @@ type Client struct {
ic *client.Client ic *client.Client
} }
var ErrInvalidArguments = errors.New("invalid arguments")
func (c *Client) HandleWS(action string, args []string) (map[string]any, error) { func (c *Client) HandleWS(action string, args []string) (map[string]any, error) {
switch action { switch action {
case "copy": case "copy":
@ -26,23 +29,42 @@ func (c *Client) HandleWS(action string, args []string) (map[string]any, error)
// TODO: implementation // TODO: implementation
case "delete": case "delete":
// TODO: implementation // TODO: implementation
case "select":
// TODO: implementation
case "fetch":
// TODO: implementation
case "list": case "list":
a := make([]*imap.MailboxInfo, 0) if len(args) != 2 {
b := make(chan *imap.MailboxInfo, 10) return nil, ErrInvalidArguments
go func() {
for info := range b {
a = append(a, info)
} }
}()
err := c.ic.List(args[0], args[1], b) // do list
list, err := c.list(args[0], args[1])
if err != nil { if err != nil {
return nil, err return nil, err
} }
return map[string]any{"info": a}, nil return map[string]any{"type": "list", "value": list}, nil
case "fetch":
if len(args) != 4 {
return nil, ErrInvalidArguments
}
// parse numeric parameters
arg1i, err := strconv.Atoi(args[1])
if err != nil {
return nil, err
}
arg2i, err := strconv.Atoi(args[2])
if err != nil {
return nil, err
}
arg3i, err := strconv.Atoi(args[3])
if err != nil {
return nil, err
}
// do fetch
fetch, err := c.fetch(args[0], uint32(arg1i), uint32(arg2i), uint32(arg3i))
if err != nil {
return nil, err
}
return map[string]any{"type": "fetch", "value": fetch}, nil
case "move": case "move":
// TODO: implementation // TODO: implementation
case "rename": case "rename":
@ -52,27 +74,10 @@ func (c *Client) HandleWS(action string, args []string) (map[string]any, error)
case "status": case "status":
// TODO: implementation // TODO: implementation
} }
_ = args return map[string]any{"error": "Not implemented"}, nil
return map[string]any{"Error": "Not implemented"}, nil
} }
func (c *Client) Append(name string, flags []string, date time.Time, msg imap.Literal) error { func (c *Client) fetch(folder string, start, end, limit uint32) ([]*imap.Message, error) {
return c.ic.Append(name, flags, date, msg)
}
func (c *Client) Copy(seqset *imap.SeqSet, dest string) error {
return c.ic.Copy(seqset, dest)
}
func (c *Client) Create(name string) error {
return c.ic.Create(name)
}
func (c *Client) Delete(name string) error {
return c.ic.Delete(name)
}
func (c *Client) Fetch(folder string, start, end, limit uint32) ([]*imap.Message, error) {
// select the mailbox // select the mailbox
mbox, err := c.ic.Select(folder, false) mbox, err := c.ic.Select(folder, false)
if err != nil { if err != nil {
@ -92,7 +97,7 @@ func (c *Client) Fetch(folder string, start, end, limit uint32) ([]*imap.Message
messages := make(chan *imap.Message, limit) messages := make(chan *imap.Message, limit)
done := make(chan error, 1) done := make(chan error, 1)
go func() { go func() {
done <- c.ic.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope}, messages) done <- c.ic.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid, imap.FetchFlags}, messages)
}() }()
out := make([]*imap.Message, 0, limit) out := make([]*imap.Message, 0, limit)
@ -105,7 +110,7 @@ func (c *Client) Fetch(folder string, start, end, limit uint32) ([]*imap.Message
return out, nil return out, nil
} }
func (c *Client) List(ref, name string) ([]*imap.MailboxInfo, error) { func (c *Client) list(ref, name string) ([]*imap.MailboxInfo, error) {
infos := make(chan *imap.MailboxInfo, 1) infos := make(chan *imap.MailboxInfo, 1)
done := make(chan error, 1) done := make(chan error, 1)
go func() { go func() {