-
Notifications
You must be signed in to change notification settings - Fork 927
/
deletequeue.go
125 lines (101 loc) · 2.6 KB
/
deletequeue.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
package bot
import (
"sync"
"github.com/jonas747/discordgo"
"github.com/jonas747/yagpdb/common"
)
var MessageDeleteQueue = &messageDeleteQueue{
channels: make(map[int64]*messageDeleteQueueChannel),
}
type messageDeleteQueue struct {
sync.RWMutex
channels map[int64]*messageDeleteQueueChannel
customdeleteFunc func(channel int64, msg []int64) error // for testing
}
func (q *messageDeleteQueue) DeleteMessages(guildID int64, channel int64, ids ...int64) {
q.Lock()
if cq, ok := q.channels[channel]; ok {
cq.Lock()
if !cq.Exiting {
for _, id := range ids {
if !common.ContainsInt64Slice(cq.Processing, id) && !common.ContainsInt64Slice(cq.Queued, id) {
cq.Queued = append(cq.Queued, id)
}
}
cq.Unlock()
q.Unlock()
return
}
}
if guildID != 0 {
if !BotProbablyHasPermission(guildID, channel, discordgo.PermissionManageMessages) {
q.Unlock()
return
}
}
// create a new channel queue
cq := &messageDeleteQueueChannel{
Parent: q,
Channel: channel,
Queued: ids,
}
q.channels[channel] = cq
go cq.run()
q.Unlock()
}
type messageDeleteQueueChannel struct {
sync.RWMutex
Parent *messageDeleteQueue
Channel int64
Exiting bool
Queued []int64
Processing []int64
}
func (cq *messageDeleteQueueChannel) run() {
for {
cq.Lock()
cq.Processing = nil
// nothing more to process
if len(cq.Queued) < 1 {
cq.Exiting = true
// remove from parent tracker
cq.Unlock()
cq.Parent.Lock()
// its possible while we unlocked the cq and locked the manager that another queue was launched on the same channel
// (since we marked cq.Exiting), therefor only delete it from the parent map if we are still the only queue
if cq.Parent.channels[cq.Channel] == cq {
delete(cq.Parent.channels, cq.Channel)
}
cq.Parent.Unlock()
return
}
if len(cq.Queued) < 100 {
cq.Processing = cq.Queued
cq.Queued = nil
} else {
cq.Processing = cq.Queued[:99]
cq.Queued = cq.Queued[99:]
}
cq.Unlock()
cq.processBatch(cq.Processing)
}
}
func (cq *messageDeleteQueueChannel) processBatch(ids []int64) {
var err error
if cq.Parent.customdeleteFunc != nil {
err = cq.Parent.customdeleteFunc(cq.Channel, ids)
} else {
if len(ids) == 1 {
err = common.BotSession.ChannelMessageDelete(cq.Channel, ids[0])
if err != nil && common.IsDiscordErr(err, discordgo.ErrCodeUnknownMessage) {
err = nil
}
} else {
err = common.BotSession.ChannelMessagesBulkDelete(cq.Channel, ids)
}
}
if err != nil {
logger.WithError(err).Error("delete queue failed deleting messages")
}
logger.Debug("Delete queue: deleted msgs ", ids)
}