mirror of
https://github.com/1f349/lotus.git
synced 2024-12-22 08:04:06 +00:00
Save before recoding imap to use websockets
This commit is contained in:
parent
dfc74925cd
commit
cd9a6074d3
8
.idea/.gitignore
vendored
8
.idea/.gitignore
vendored
@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
@ -1,5 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="ASK" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="PROJECT" dialect="MySQL" />
|
||||
</component>
|
||||
</project>
|
105
api/api.go
105
api/api.go
@ -3,7 +3,8 @@ package api
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/1f349/lotus/imap"
|
||||
json2 "github.com/1f349/lotus/imap/json"
|
||||
"github.com/1f349/lotus/imap/marshal"
|
||||
imap2 "github.com/emersion/go-imap"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -14,18 +15,105 @@ func SetupApiServer(listen string, auth func(callback AuthCallback) httprouter.H
|
||||
r := httprouter.New()
|
||||
|
||||
// === ACCOUNT ===
|
||||
r.GET("/account", auth(func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
|
||||
r.GET("/identities", auth(func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
|
||||
// TODO(melon): find users aliases and other account data
|
||||
}))
|
||||
|
||||
// === SMTP ===
|
||||
r.POST("/message", auth(MessageSender(send)))
|
||||
|
||||
r.Handle(http.MethodConnect, "/", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
|
||||
|
||||
})
|
||||
|
||||
// === IMAP ===
|
||||
type statusJson struct {
|
||||
type mailboxStatusJson struct {
|
||||
Folder string `json:"folder"`
|
||||
}
|
||||
r.GET("/status", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t statusJson) {
|
||||
r.GET("/mailbox/status", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t mailboxStatusJson) error {
|
||||
status, err := cli.Status(t.Folder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(rw).Encode(status)
|
||||
})))
|
||||
|
||||
type mailboxListJson struct {
|
||||
Folder string `json:"folder"`
|
||||
Pattern string `json:"pattern"`
|
||||
}
|
||||
r.GET("/mailbox/list", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t mailboxListJson) error {
|
||||
list, err := cli.List(t.Folder, t.Pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(rw).Encode(list)
|
||||
})))
|
||||
|
||||
type mailboxCreateJson struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
r.POST("/mailbox/create", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t mailboxCreateJson) error {
|
||||
err := cli.Create(t.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(rw).Encode(map[string]string{"Status": "OK"})
|
||||
})))
|
||||
|
||||
type messagesListJson struct {
|
||||
Folder string `json:"folder"`
|
||||
Start uint32 `json:"start"`
|
||||
End uint32 `json:"end"`
|
||||
Limit uint32 `json:"limit"`
|
||||
}
|
||||
r.GET("/list-messages", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t messagesListJson) error {
|
||||
messages, err := cli.Fetch(t.Folder, t.Start, t.End, t.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(rw).Encode(marshal.MessageSliceJson(messages))
|
||||
})))
|
||||
|
||||
type messagesSearchJson struct {
|
||||
Folder string `json:"folder"`
|
||||
SeqNum imap2.SeqSet
|
||||
Uid imap2.SeqSet
|
||||
Since time.Time
|
||||
Before time.Time
|
||||
SentSince time.Time
|
||||
SentBefore time.Time
|
||||
Body []string
|
||||
Text []string
|
||||
WithFlags []string
|
||||
WithoutFlags []string
|
||||
Larger uint32
|
||||
Smaller uint32
|
||||
}
|
||||
r.GET("/search-messages", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t messagesSearchJson) error {
|
||||
status, err := cli.Search(&imap2.SearchCriteria{
|
||||
SeqNum: t.SeqNum,
|
||||
Uid: t.Uid,
|
||||
Since: time.Time{},
|
||||
Before: time.Time{},
|
||||
SentSince: time.Time{},
|
||||
SentBefore: time.Time{},
|
||||
Header: nil,
|
||||
Body: nil,
|
||||
Text: nil,
|
||||
WithFlags: nil,
|
||||
WithoutFlags: nil,
|
||||
Larger: 0,
|
||||
Smaller: 0,
|
||||
Not: nil,
|
||||
Or: nil,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(rw).Encode(status)
|
||||
})))
|
||||
r.POST("/update-messages-flags", auth(imapClient(recv, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t mailboxStatusJson) {
|
||||
status, err := cli.Status(t.Folder)
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
@ -39,7 +127,7 @@ func SetupApiServer(listen string, auth func(callback AuthCallback) httprouter.H
|
||||
rw.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
err = json.NewEncoder(rw).Encode(json2.ListMessagesJson(messages))
|
||||
err = json.NewEncoder(rw).Encode(marshal.ListMessagesJson(messages))
|
||||
if err != nil {
|
||||
log.Println("list-messages json encode error:", err)
|
||||
}
|
||||
@ -96,7 +184,7 @@ func apiError(rw http.ResponseWriter, code int, m string) {
|
||||
})
|
||||
}
|
||||
|
||||
type IcCallback[T any] func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, cli *imap.Client, t T)
|
||||
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) {
|
||||
@ -114,6 +202,9 @@ func imapClient[T any](recv Imap, cb IcCallback[T]) AuthCallback {
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
cb(rw, req, params, cli, t)
|
||||
err = cb(rw, req, params, cli, t)
|
||||
if err != nil {
|
||||
log.Println("[ImapClient] Error:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
38
imap/marshal/message.go
Normal file
38
imap/marshal/message.go
Normal file
@ -0,0 +1,38 @@
|
||||
package marshal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
var _, _ json.Marshaler = &MessageSliceJson{}, &MessageJson{}
|
||||
|
||||
type MessageSliceJson []*imap.Message
|
||||
|
||||
func (m MessageSliceJson) MarshalJSON() ([]byte, error) {
|
||||
a := make([]MessageJson, len(m))
|
||||
for i := range a {
|
||||
a[i] = MessageJson(*m[i])
|
||||
}
|
||||
return json.Marshal(a)
|
||||
}
|
||||
|
||||
type MessageJson imap.Message
|
||||
|
||||
func (m MessageJson) MarshalJSON() ([]byte, error) {
|
||||
body := make(map[string]imap.Literal, len(m.Body))
|
||||
for k, v := range m.Body {
|
||||
body[string(k.FetchItem())] = v
|
||||
}
|
||||
return json.Marshal(map[string]any{
|
||||
"SeqNum": m.SeqNum,
|
||||
"Items": m.Items,
|
||||
"Envelope": m.Envelope,
|
||||
"BodyStructure": m.BodyStructure,
|
||||
"Flags": m.Flags,
|
||||
"InternalDate": m.InternalDate,
|
||||
"Size": m.Size,
|
||||
"Uid": m.Uid,
|
||||
"$Body": body,
|
||||
})
|
||||
}
|
7
imap/marshal/seqset.go
Normal file
7
imap/marshal/seqset.go
Normal file
@ -0,0 +1,7 @@
|
||||
package marshal
|
||||
|
||||
import imap2 "github.com/emersion/go-imap"
|
||||
|
||||
type SeqSet imap2.SeqSet
|
||||
|
||||
var json.mar
|
Loading…
Reference in New Issue
Block a user