/
reservebot.go
120 lines (102 loc) · 3.4 KB
/
reservebot.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
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"net/http"
"time"
"github.com/ameliagapin/reservebot/data"
"github.com/ameliagapin/reservebot/handler"
"github.com/ameliagapin/reservebot/util"
log "github.com/sirupsen/logrus"
"github.com/slack-go/slack"
"github.com/slack-go/slack/slackevents"
)
var (
token string
challenge string
listenPort int
debug bool
admins string
reqResourceEnv bool
pruneEnabled bool
pruneInterval int
pruneExpire int
)
func main() {
flag.StringVar(&token, "token", util.LookupEnvOrString("SLACK_TOKEN", ""), "Slack API Token")
flag.StringVar(&challenge, "challenge", util.LookupEnvOrString("SLACK_CHALLENGE", ""), "Slack verification token")
flag.IntVar(&listenPort, "listen-port", util.LookupEnvOrInt("LISTEN_PORT", 666), "Listen port")
flag.BoolVar(&debug, "debug", util.LookupEnvOrBool("DEBUG", false), "Debug mode")
flag.StringVar(&admins, "admins", util.LookupEnvOrString("SLACK_ADMINS", ""), "Turn on administrative commands for specific admins, comma separated list")
flag.BoolVar(&reqResourceEnv, "require-resource-env", util.LookupEnvOrBool("REQUIRE_RESOURCE_ENV", true), "Require resource reservation to include environment")
flag.BoolVar(&pruneEnabled, "prune-enabled", util.LookupEnvOrBool("PRUNE_ENABLED", true), "Enable pruning available resources automatically")
flag.IntVar(&pruneInterval, "prune-interval", util.LookupEnvOrInt("PRUNE_INTERVAL", 1), "Automatic pruning interval in hours")
flag.IntVar(&pruneExpire, "prune-expire", util.LookupEnvOrInt("PRUNE_EXPIRE", 168), "Automatic prune expiration time in hours")
flag.Parse()
// Make sure required vars are set
if token == "" {
log.Error("Slack token is required")
return
}
if challenge == "" {
log.Error("Slack verification token is required")
return
}
api := slack.New(token, slack.OptionDebug(debug))
data := data.NewMemory()
if pruneEnabled {
// Prune inactive resources
log.Infof("Automatic Pruning is enabled.")
go func() {
for {
time.Sleep(time.Duration(pruneInterval) * time.Hour)
err := data.PruneInactiveResources(pruneExpire)
if err != nil {
log.Errorf("Error pruning resources: %+v", err)
} else {
log.Infof("Pruned resources")
}
}
}()
} else {
log.Infof("Automatic pruning is disabled.")
}
handler := handler.New(api, data, reqResourceEnv, util.ParseAdmins(admins))
http.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
body := buf.String()
api.Debugf("Request: %s", body)
eventsAPIEvent, err := slackevents.ParseEvent(
json.RawMessage(body),
slackevents.OptionVerifyToken(
&slackevents.TokenComparator{VerificationToken: challenge},
),
)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Errorf("%+v", err)
return
}
switch eventsAPIEvent.Type {
case slackevents.URLVerification:
var r *slackevents.ChallengeResponse
err := json.Unmarshal([]byte(body), &r)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
w.Header().Set("Content-Type", "text")
w.Write([]byte(r.Challenge))
case slackevents.CallbackEvent:
err := handler.CallbackEvent(eventsAPIEvent)
if err != nil {
log.Errorf("%+v", err)
}
default:
}
})
log.Infof("Server listening on port %d", listenPort)
http.ListenAndServe(fmt.Sprintf(":%v", listenPort), nil)
}