1package sqlite23import (4 "bytes"5 "context"6 "database/sql"7 "encoding/json"8 "fmt"9 "strings"10 "time"1112 "git.lin.moe/go/mlisting/storage"13 gomsg "github.com/emersion/go-message"14 "github.com/emersion/go-message/mail"15)1617type Message struct {18 id int6419 messageID string20 mpath string21 subject string22 header mail.Header23 body []byte24 createAt time.Time25 text string2627 db *sql.DB28}2930func (m *Message) CreateAt() time.Time {31 return m.createAt32}33func (m *Message) Subject() string {34 return m.subject35}3637func (m *Message) Header() *mail.Header {38 h := m.header.Copy()39 return &h40}4142func (m *Message) Entity() *gomsg.Entity {43 entity, err := gomsg.New(m.header.Header, bytes.NewReader(m.body))44 if err != nil {45 // TODO: handle this properly46 panic(err)47 }48 return entity49}50func (m *Message) Text() string {51 return m.text52}5354func (m *Message) SubMessages(ctx context.Context, recursive bool) ([]storage.Message, error) {55 prefix := fmt.Sprintf("%s%d/", m.mpath, m.id)56 var (57 rows *sql.Rows58 condition string59 err error60 )61 if recursive {62 condition = `mpath LIKE ? || '%'`63 } else {64 condition = fmt.Sprintf(`mpath = ?`)65 }66 _sql := fmt.Sprintf(`SELECT id, message_id, create_at, subject, header, body, text, mpath from message WHERE %s ORDER BY create_at DESC, id DESC`, condition)67 rows, err = m.db.QueryContext(ctx, _sql, prefix)68 if err != nil {69 return nil, err70 }71 defer rows.Close()7273 var result = []storage.Message{}74 for rows.Next() {75 var rheader []byte76 msg := new(Message)77 if err := rows.Scan(78 &msg.id,79 &msg.messageID,80 &msg.createAt,81 &msg.subject,82 &rheader,83 &msg.body,84 &msg.text,85 &msg.mpath,86 ); err != nil {87 return nil, err88 }89 hmap := make(map[string][]string)90 if err := json.Unmarshal(rheader, &hmap); err != nil {91 return nil, err92 }93 msg.header = mail.HeaderFromMap(hmap)9495 result = append(result, msg)96 }97 return result, nil98}99100func (m *Message) Parent(ctx context.Context) storage.Message {101 if m.mpath == "/" || m.mpath == "" {102 return nil103 }104 var pid_str string105 parts := strings.Split(m.mpath, "/")106 if parts[len(parts)-1] == "" {107 if len(parts) <= 1 {108 return nil109 }110 pid_str = parts[len(parts)-2]111 } else {112 pid_str = parts[len(parts)-1]113 }114115 _sql := `SELECT id, message_id, create_at, subject, header, body, text, mpath from message WHERE id=? ORDER BY create_at DESC, id DESC`116 msg := new(Message)117 var rheader []byte118 m.db.QueryRowContext(ctx, _sql, pid_str).Scan(119 &msg.id,120 &msg.messageID,121 &msg.createAt,122 &msg.subject,123 &rheader,124 &msg.body,125 &msg.text,126 &msg.mpath,127 )128 hmap := make(map[string][]string)129 if err := json.Unmarshal(rheader, &hmap); err != nil {130 return nil131 }132 msg.header = mail.HeaderFromMap(hmap)133 return msg134}