forked from kubernetes-sigs/slack-infra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
131 lines (108 loc) · 3.34 KB
/
main.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
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"time"
"gopkg.in/yaml.v3"
"sigs.k8s.io/slack-infra/slack"
"sigs.k8s.io/slack-infra/slack-moderator-words/model"
)
type options struct {
configPath string
filterConfigPath string
}
func parseFlags() options {
o := options{}
flag.StringVar(&o.configPath, "config-path", "config.json", "Path to a file containing the slack config")
flag.StringVar(&o.filterConfigPath, "filter-config-path", "filters.yaml", "Path to a file containing the filter config")
flag.Parse()
return o
}
func runServer(h *handler) error {
http.Handle(os.Getenv("PATH_PREFIX")+"/webhook", h)
http.HandleFunc("/healthz", handleHealthz)
port := os.Getenv("PORT")
if port == "" {
port = "8077"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Listening on port %s", port)
return http.ListenAndServe(fmt.Sprintf(":%s", port), nil)
}
func loadFilterConfig(path string) (model.FilterConfig, error) {
content, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("couldn't open file: %v", err)
}
filterConfig := &model.FilterConfig{}
if err := yaml.Unmarshal(content, filterConfig); err != nil {
return nil, fmt.Errorf("couldn't parse filter config: %v", err)
}
return *filterConfig, nil
}
func main() {
o := parseFlags()
c, err := slack.LoadConfig(o.configPath)
if err != nil {
log.Fatalf("Failed to load config from %s: %v", o.configPath, err)
}
filters, err := loadFilterConfig(o.filterConfigPath)
if err != nil {
log.Fatalf("Failed to load filter config from %s: %v", o.filterConfigPath, err)
}
s := slack.New(c)
// List all public channels and try to join.
// This is needed otherwise the bot cannot receive the events for the channels
// and cannot moderate it
channels, err := s.GetPublicChannels()
if err != nil {
log.Fatalf("Failed to list all public channels: %v", err)
}
for _, channel := range channels {
log.Printf("Public Channel: %s/%s\n", channel.ID, channel.Name)
if channel.IsArchived {
log.Printf("Public Channel: %s/%s is archived, skipping...\n", channel.ID, channel.Name)
continue
}
if channel.IsMember {
log.Printf("Bot is already member of public Channel: %s/%s, skipping...\n", channel.ID, channel.Name)
continue
}
for {
req := map[string]string{
"channel": channel.ID,
}
err := s.CallMethod("conversations.join", req, nil)
if err == nil {
break
}
if timeout, ok := err.(slack.ErrRateLimit); ok {
log.Printf("Slack is rate limiting us, trying again in %s...\n", timeout.Wait)
time.Sleep(timeout.Wait)
continue
}
if err != nil {
log.Fatalf("Failed to join channel %s: %v", channel.Name, err)
}
}
time.Sleep(500 * time.Millisecond)
}
h := &handler{client: s, filters: filters}
log.Fatal(runServer(h))
}