mlisting

Mailing list service

git clone git://git.lin.moe/go/mlisting.git

  1package sqlite
  2
  3import (
  4	"bytes"
  5	"context"
  6	"database/sql"
  7	"encoding/json"
  8	"fmt"
  9	"strings"
 10	"time"
 11
 12	"git.lin.moe/go/mlisting/storage"
 13	gomsg "github.com/emersion/go-message"
 14	"github.com/emersion/go-message/mail"
 15)
 16
 17type Message struct {
 18	id        int64
 19	messageID string
 20	mpath     string
 21	subject   string
 22	header    mail.Header
 23	body      []byte
 24	createAt  time.Time
 25	text      string
 26
 27	db *sql.DB
 28}
 29
 30func (m *Message) CreateAt() time.Time {
 31	return m.createAt
 32}
 33func (m *Message) Subject() string {
 34	return m.subject
 35}
 36
 37func (m *Message) Header() *mail.Header {
 38	h := m.header.Copy()
 39	return &h
 40}
 41
 42func (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 properly
 46		panic(err)
 47	}
 48	return entity
 49}
 50func (m *Message) Text() string {
 51	return m.text
 52}
 53
 54func (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.Rows
 58		condition string
 59		err       error
 60	)
 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, err
 70	}
 71	defer rows.Close()
 72
 73	var result = []storage.Message{}
 74	for rows.Next() {
 75		var rheader []byte
 76		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, err
 88		}
 89		hmap := make(map[string][]string)
 90		if err := json.Unmarshal(rheader, &hmap); err != nil {
 91			return nil, err
 92		}
 93		msg.header = mail.HeaderFromMap(hmap)
 94
 95		result = append(result, msg)
 96	}
 97	return result, nil
 98}
 99
100func (m *Message) Parent(ctx context.Context) storage.Message {
101	if m.mpath == "/" || m.mpath == "" {
102		return nil
103	}
104	var pid_str string
105	parts := strings.Split(m.mpath, "/")
106	if parts[len(parts)-1] == "" {
107		if len(parts) <= 1 {
108			return nil
109		}
110		pid_str = parts[len(parts)-2]
111	} else {
112		pid_str = parts[len(parts)-1]
113	}
114
115	_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 []byte
118	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 nil
131	}
132	msg.header = mail.HeaderFromMap(hmap)
133	return msg
134}