-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.go
132 lines (109 loc) · 2.89 KB
/
database.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
package punish
import (
"strings"
"time"
"github.com/pkg/errors"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/Luzifer/twitch-bot/v3/pkg/database"
)
type (
punishLevel struct {
Key string `gorm:"primaryKey"`
LastLevel int
Executed time.Time
Cooldown time.Duration
}
)
func calculateCurrentPunishments(db database.Connector) (err error) {
var ps []punishLevel
if err = db.DB().Find(&ps).Error; err != nil {
return errors.Wrap(err, "querying punish_levels")
}
for _, p := range ps {
var (
actUpdate bool
lvl = &levelConfig{
LastLevel: p.LastLevel,
Executed: p.Executed,
Cooldown: p.Cooldown,
}
)
for {
cooldownTime := lvl.Executed.Add(lvl.Cooldown)
if cooldownTime.After(time.Now().UTC()) {
break
}
lvl.Executed = cooldownTime
lvl.LastLevel--
actUpdate = true
}
// Level 0 is the first punishment level, so only remove if it drops below 0
if lvl.LastLevel < 0 {
if err = deletePunishmentForKey(db, p.Key); err != nil {
return errors.Wrap(err, "cleaning up expired punishment")
}
continue
}
if actUpdate {
if err = setPunishmentForKey(db, p.Key, lvl); err != nil {
return errors.Wrap(err, "updating punishment")
}
}
}
return nil
}
func deletePunishment(db database.Connector, channel, user, uuid string) error {
return deletePunishmentForKey(db, getDBKey(channel, user, uuid))
}
func deletePunishmentForKey(db database.Connector, key string) error {
return errors.Wrap(
db.DB().Delete(&punishLevel{}, "key = ?", key).Error,
"deleting punishment info",
)
}
func getPunishment(db database.Connector, channel, user, uuid string) (*levelConfig, error) {
if err := calculateCurrentPunishments(db); err != nil {
return nil, errors.Wrap(err, "updating punishment states")
}
var (
lc = &levelConfig{LastLevel: -1}
p punishLevel
)
err := db.DB().First(&p, "key = ?", getDBKey(channel, user, uuid)).Error
switch {
case err == nil:
return &levelConfig{
LastLevel: p.LastLevel,
Executed: p.Executed,
Cooldown: p.Cooldown,
}, nil
case errors.Is(err, gorm.ErrRecordNotFound):
return lc, nil
default:
return nil, errors.Wrap(err, "getting punishment from database")
}
}
func setPunishment(db database.Connector, channel, user, uuid string, lc *levelConfig) error {
return setPunishmentForKey(db, getDBKey(channel, user, uuid), lc)
}
func setPunishmentForKey(db database.Connector, key string, lc *levelConfig) error {
if lc == nil {
return errors.New("nil levelConfig given")
}
return errors.Wrap(
db.DB().Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
UpdateAll: true,
}).Create(punishLevel{
Key: key,
LastLevel: lc.LastLevel,
Executed: lc.Executed,
Cooldown: lc.Cooldown,
}).Error,
"updating punishment info",
)
}
func getDBKey(channel, user, uuid string) string {
return strings.Join([]string{channel, user, uuid}, "::")
}