-
Notifications
You must be signed in to change notification settings - Fork 42
/
delay.go
111 lines (94 loc) · 2.68 KB
/
delay.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
package command
import (
"errors"
"fmt"
"sync"
"time"
"github.com/innogames/slack-bot/bot"
"github.com/innogames/slack-bot/bot/matcher"
"github.com/innogames/slack-bot/bot/msg"
"github.com/innogames/slack-bot/bot/util"
"github.com/innogames/slack-bot/client"
"github.com/innogames/slack-bot/command/queue"
)
// NewDelayCommand delays the command execution by the given time
func NewDelayCommand(base bot.BaseCommand) bot.Command {
return &delayCommand{BaseCommand: base, timers: make([]*time.Timer, 0)}
}
type delayCommand struct {
bot.BaseCommand
timers []*time.Timer
mu sync.Mutex
}
func (c *delayCommand) GetMatcher() matcher.Matcher {
return matcher.NewGroupMatcher(
matcher.NewRegexpMatcher("delay (?P<delay>[\\w]+) (?P<quiet>quiet )?(?P<command>.*)", c.Delay),
matcher.NewRegexpMatcher("stop (delay|timer) (?P<timer>\\d+)", c.Stop),
)
}
func (c *delayCommand) Delay(match matcher.Result, message msg.Message) {
delay, err := util.ParseDuration(match.GetString("delay"))
if err != nil {
c.SendMessage(message, "Invalid duration: "+err.Error())
return
}
quietMode := match.GetString("quiet") != ""
command := match.GetString("command")
c.mu.Lock()
defer c.mu.Unlock()
timer := time.NewTimer(delay)
c.timers = append(c.timers, timer)
if !quietMode {
c.SendMessage(message, fmt.Sprintf(
"I queued the command `%s` for %s. Use `stop timer %d` to stop the timer",
command,
delay,
len(c.timers)-1,
))
}
done := queue.AddRunningCommand(message, "")
go func() {
<-timer.C // todo abort here when it was aborted + more random stop key
done <- true
client.InternalMessages <- message.WithText(command)
}()
}
func (c *delayCommand) Stop(match matcher.Result, message msg.Message) {
// avoid racing conditions when it's used multiple times in parallel
c.mu.Lock()
defer c.mu.Unlock()
timerNr := match.GetInt("timer")
if timerNr < len(c.timers) && c.timers[timerNr] != nil {
c.timers[timerNr].Stop()
c.timers[timerNr] = nil
c.SendMessage(message, "Stopped timer!")
} else {
c.ReplyError(message, errors.New("invalid timer"))
}
}
var delayCategory = bot.Category{
Name: "Delay",
HelpURL: "https://github.com/innogames/slack-bot#delay",
}
func (c *delayCommand) GetHelp() []bot.Help {
return []bot.Help{
{
Command: "delay",
Description: "delay a command by the given offset",
Examples: []string{
"delay 1h rely remind me to go to toilet",
"delay 15m30s trigger job DeployBeta",
"delay 15min trigger job DeployBeta",
},
Category: delayCategory,
},
{
Command: "stop delay",
Description: "cancel a planned delayCommand",
Examples: []string{
"stop timer 1243",
},
Category: delayCategory,
},
}
}