[go: up one dir, main page]

File: db.go

package info (click to toggle)
soju 0.10.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,016 kB
  • sloc: sql: 243; sh: 55; makefile: 49; python: 32
file content (163 lines) | stat: -rw-r--r-- 4,105 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package msgstore

import (
	"context"
	"time"

	"codeberg.org/emersion/soju/database"
	"git.sr.ht/~sircmpwn/go-bare"
	"gopkg.in/irc.v4"
)

type dbMsgID struct {
	ID bare.Uint
}

func (dbMsgID) msgIDType() msgIDType {
	return msgIDDB
}

func parseDBMsgID(s string) (msgID int64, err error) {
	var id dbMsgID
	_, _, err = ParseMsgID(s, &id)
	if err != nil {
		return 0, err
	}
	return int64(id.ID), nil
}

func formatDBMsgID(netID int64, target string, msgID int64) string {
	id := dbMsgID{bare.Uint(msgID)}
	return formatMsgID(netID, target, &id)
}

// dbMessageStore is a persistent store for IRC messages, that
// stores messages in the soju database.
type dbMessageStore struct {
	db database.Database
}

var (
	_ Store            = (*dbMessageStore)(nil)
	_ ChatHistoryStore = (*dbMessageStore)(nil)
	_ SearchStore      = (*dbMessageStore)(nil)
)

func NewDBStore(db database.Database) *dbMessageStore {
	return &dbMessageStore{
		db: db,
	}
}

func (ms *dbMessageStore) Close() error {
	return nil
}

func (ms *dbMessageStore) LastMsgID(ctx context.Context, network *database.Network, entity string, t time.Time) (string, error) {
	// TODO: what should we do with t?

	id, err := ms.db.GetMessageLastID(ctx, network.ID, entity)
	if err != nil {
		return "", err
	}
	return formatDBMsgID(network.ID, entity, id), nil
}

func (ms *dbMessageStore) LoadLatestID(ctx context.Context, id string, options *LoadMessageOptions) ([]*irc.Message, error) {
	msgID, err := parseDBMsgID(id)
	if err != nil {
		return nil, err
	}

	l, err := ms.db.ListMessages(ctx, options.Network.ID, options.Entity, &database.MessageOptions{
		AfterID:  msgID,
		Limit:    options.Limit,
		TakeLast: true,
	})
	if err != nil {
		return nil, err
	}
	return l, nil
}

func (ms *dbMessageStore) Append(ctx context.Context, network *database.Network, entity string, msg *irc.Message) (string, error) {
	ids, err := ms.db.StoreMessages(ctx, network.ID, entity, []*irc.Message{msg})
	if err != nil {
		return "", err
	}
	return formatDBMsgID(network.ID, entity, ids[0]), nil
}

func (ms *dbMessageStore) ListTargets(ctx context.Context, network *database.Network, start, end time.Time, limit int, events bool) ([]ChatHistoryTarget, error) {
	var opts *database.MessageOptions
	if start.Before(end) {
		opts = &database.MessageOptions{
			AfterTime:  start,
			BeforeTime: end,
			Limit:      limit,
			Events:     events,
		}
	} else {
		opts = &database.MessageOptions{
			AfterTime:  end,
			BeforeTime: start,
			Limit:      limit,
			Events:     events,
			TakeLast:   true,
		}
	}
	l, err := ms.db.ListMessageLastPerTarget(ctx, network.ID, opts)
	if err != nil {
		return nil, err
	}
	targets := make([]ChatHistoryTarget, len(l))
	for i, v := range l {
		targets[i] = ChatHistoryTarget{
			Name:          v.Name,
			LatestMessage: v.LatestMessage,
		}
	}
	return targets, nil
}

func (ms *dbMessageStore) LoadBeforeTime(ctx context.Context, start, end time.Time, options *LoadMessageOptions) ([]*irc.Message, error) {
	l, err := ms.db.ListMessages(ctx, options.Network.ID, options.Entity, &database.MessageOptions{
		AfterTime:  end,
		BeforeTime: start,
		Limit:      options.Limit,
		Events:     options.Events,
		TakeLast:   true,
	})
	if err != nil {
		return nil, err
	}
	return l, nil
}

func (ms *dbMessageStore) LoadAfterTime(ctx context.Context, start, end time.Time, options *LoadMessageOptions) ([]*irc.Message, error) {
	l, err := ms.db.ListMessages(ctx, options.Network.ID, options.Entity, &database.MessageOptions{
		AfterTime:  start,
		BeforeTime: end,
		Limit:      options.Limit,
		Events:     options.Events,
	})
	if err != nil {
		return nil, err
	}
	return l, nil
}

func (ms *dbMessageStore) Search(ctx context.Context, network *database.Network, options *SearchMessageOptions) ([]*irc.Message, error) {
	l, err := ms.db.ListMessages(ctx, network.ID, options.In, &database.MessageOptions{
		AfterTime:  options.Start,
		BeforeTime: options.End,
		Limit:      options.Limit,
		Sender:     options.From,
		Text:       options.Text,
		TakeLast:   true,
	})
	if err != nil {
		return nil, err
	}
	return l, nil
}