forked from botlabs-gg/yagpdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interval.go
114 lines (94 loc) · 3.05 KB
/
interval.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
package customcommands
import (
"context"
"time"
"github.com/jonas747/yagpdb/common"
"github.com/jonas747/yagpdb/common/scheduledevents2"
schEventsModels "github.com/jonas747/yagpdb/common/scheduledevents2/models"
"github.com/jonas747/yagpdb/customcommands/models"
"github.com/pkg/errors"
"github.com/volatiletech/null"
"github.com/volatiletech/sqlboiler/boil"
"github.com/volatiletech/sqlboiler/queries/qm"
)
func CalcNextRunTime(cc *models.CustomCommand, now time.Time) time.Time {
if len(cc.TimeTriggerExcludingDays) >= 7 || len(cc.TimeTriggerExcludingHours) >= 24 {
// this can never be ran...
return time.Time{}
}
tNext := cc.LastRun.Time.Add(time.Minute * time.Duration(cc.TimeTriggerInterval))
// run it immedietely if this is the case
if tNext.Before(now) {
tNext = now
}
// ensure were dealing with utc
tNext = tNext.UTC()
// check for blacklisted days
if common.ContainsInt64Slice(cc.TimeTriggerExcludingDays, int64(tNext.Weekday())) {
// find the next available day
for {
tNext = tNext.Add(time.Hour * 24)
if !common.ContainsInt64Slice(cc.TimeTriggerExcludingDays, int64(tNext.Weekday())) {
break
}
}
// if we went forward a day, force the clock to 0 to run it as soon as possible
h, m, s := tNext.Clock()
tNext = tNext.Add((-time.Hour * time.Duration(h)))
tNext = tNext.Add((-time.Minute * time.Duration(m)))
tNext = tNext.Add((-time.Second * time.Duration(s)))
}
// check for blacklisted hours
if common.ContainsInt64Slice(cc.TimeTriggerExcludingHours, int64(tNext.Hour())) {
// find the next available hour
for {
tNext = tNext.Add(time.Hour)
if !common.ContainsInt64Slice(cc.TimeTriggerExcludingHours, int64(tNext.Hour())) {
break
}
}
}
return tNext
}
type NextRunScheduledEvent struct {
CmdID int64 `json:"cmd_id"`
}
func DelNextRunEvent(guildID int64, cmdID int64) error {
_, err := schEventsModels.ScheduledEvents(qm.Where("event_name='cc_next_run' AND guild_id = ? AND (data->>'cmd_id')::bigint = ?", guildID, cmdID)).DeleteAll(context.Background(), common.PQ)
return err
}
// TODO: Run this all in a transaction?
func UpdateCommandNextRunTime(cc *models.CustomCommand, updateLastRun bool) error {
// remove the old events
err := DelNextRunEvent(cc.GuildID, cc.LocalID)
if err != nil {
return errors.Wrap(err, "del_old_events")
}
if cc.TriggerType != int(CommandTriggerInterval) || cc.TimeTriggerInterval < 1 {
return nil
}
// calculate the next run time
nextRun := CalcNextRunTime(cc, time.Now())
if nextRun.IsZero() {
return nil
}
// update the command
cc.NextRun = null.TimeFrom(nextRun)
toUpdate := []string{"next_run"}
if updateLastRun {
toUpdate = append(toUpdate, "last_run")
}
_, err = cc.UpdateG(context.Background(), boil.Whitelist(toUpdate...))
if err != nil {
return errors.Wrap(err, "update_cc")
}
evt := &NextRunScheduledEvent{
CmdID: cc.LocalID,
}
// create a scheduled event to run the command again
err = scheduledevents2.ScheduleEvent("cc_next_run", cc.GuildID, nextRun, evt)
if err != nil {
return errors.Wrap(err, "schedule_event")
}
return nil
}