forked from botlabs-gg/yagpdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
history.go
136 lines (110 loc) · 2.75 KB
/
history.go
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
package bot
import (
"github.com/jonas747/discordgo"
"github.com/jonas747/dutil/dstate"
"github.com/jonas747/yagpdb/common"
log "github.com/sirupsen/logrus"
"sort"
)
type WrappedMessage struct {
*discordgo.Message
Deleted bool
}
// GetMessages Gets messages from state if possible, if not then it retrieves from the discord api
// Puts the messages in the state aswell
func GetMessages(channelID int64, limit int, deleted bool) ([]*WrappedMessage, error) {
if limit < 1 {
return []*WrappedMessage{}, nil
}
// check state
msgBuf := make([]*WrappedMessage, limit)
cs := State.Channel(true, channelID)
cs.Owner.RLock()
n := len(msgBuf) - 1
for i := len(cs.Messages) - 1; i >= 0; i-- {
if !deleted {
if cs.Messages[i].Deleted {
continue
}
}
m := cs.Messages[i].Copy(true)
msgBuf[n] = &WrappedMessage{Message: m}
if cs.Messages[i].Deleted {
msgBuf[n].Deleted = true
}
n--
if n < 0 {
break
}
}
cs.Owner.RUnlock()
// Check if the state was full
if n >= limit {
return msgBuf, nil
}
// Not enough messages in state, retrieve them from the api
// Initialize the before id
var before int64
if n+1 < len(msgBuf) {
if msgBuf[n+1] != nil {
before = msgBuf[n+1].ID
}
}
// Start fetching from the api
for n >= 0 {
toFetch := n + 1
if toFetch > 100 {
toFetch = 100
}
msgs, err := common.BotSession.ChannelMessages(channelID, toFetch, before, 0, 0)
if err != nil {
return nil, err
}
log.WithField("num_msgs", len(msgs)).Info("API history req finished")
if len(msgs) < 1 { // Nothing more
break
}
// Copy over to buffer
for k, m := range msgs {
msgBuf[n-k] = &WrappedMessage{Message: m}
}
// Oldest message is last
before = msgs[len(msgs)-1].ID
n -= len(msgs)
if len(msgs) < toFetch {
break
}
}
// remove nil entries if it wasn't big enough
if n+1 > 0 {
msgBuf = msgBuf[n+1:]
}
// merge the current state with this new one and sort
cs.Owner.Lock()
defer cs.Owner.Unlock()
for _, m := range msgBuf {
cs.MessageAddUpdate(false, m.Message, -1, 0)
}
sort.Sort(DiscordMessages(cs.Messages))
cs.UpdateMessages(false, State.MaxChannelMessages, State.MaxMessageAge)
// Return at most limit results
if limit < len(msgBuf) {
return msgBuf[len(msgBuf)-limit:], nil
} else {
return msgBuf, nil
}
}
type DiscordMessages []*dstate.MessageState
// Len is the number of elements in the collection.
func (d DiscordMessages) Len() int { return len(d) }
// Less reports whether the element with
// index i should sort before the element with index j.
func (d DiscordMessages) Less(i, j int) bool {
return d[i].ParsedCreated.Before(d[j].ParsedCreated)
}
// Swap swaps the elements with indexes i and j.
func (d DiscordMessages) Swap(i, j int) {
temp := d[i]
d[i] = d[j]
d[j] = temp
}