-
Notifications
You must be signed in to change notification settings - Fork 42
/
tester.go
168 lines (140 loc) · 4.19 KB
/
tester.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Package tester provides functionality to test the bot against a fake slack server
package tester
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"github.com/gookit/color"
"github.com/innogames/slack-bot/v2/bot"
"github.com/innogames/slack-bot/v2/bot/config"
"github.com/innogames/slack-bot/v2/bot/msg"
"github.com/innogames/slack-bot/v2/client"
"github.com/innogames/slack-bot/v2/command"
log "github.com/sirupsen/logrus"
"github.com/slack-go/slack"
)
// TestChannel is just a test channel name which is used for testing
const (
TestChannel = "dev"
User = "cli"
botID = "W12345"
)
// FakeServerURL is the host for the fake Slack server endpoint. It can be also used to send fake responses.
var FakeServerURL string
// StartBot will start this bot against the fake slack instance
func StartBot(cfg config.Config) *bot.Bot {
slackClient, err := client.GetSlackClient(cfg.Slack)
checkError(err)
commands := command.GetCommands(
slackClient,
cfg,
)
realBot := bot.NewBot(
cfg,
slackClient,
commands,
)
err = realBot.Init()
checkError(err)
color.Info.Printf(
"Hey! I'm your Slack Emulator. Call or click '%s' to get a list of all supported commands\n",
formatSlackMessage(commandButton("help", "help")),
)
return realBot
}
// HandleMessage is used in the CLI context to process the given message test for the "cli" user
func HandleMessage(text string) {
message := msg.Message{}
message.Text = text
message.Channel = TestChannel
message.User = User
client.HandleMessageWithDoneHandler(message).Wait()
}
type usersResponse struct {
Members []slack.User
}
// kinda dirty grown function to format a /chat.postMessage /chat.postEphemeral message on the command like...somehow
func messageHandler(w http.ResponseWriter, r *http.Request, output io.Writer) {
payload, _ := ioutil.ReadAll(r.Body)
query, _ := url.ParseQuery(string(payload))
text := query.Get("text")
// extract text from TextBlock
if text == "" && query.Get("blocks") != "" {
blockJSON := query.Get("blocks")
var blocks []map[string]interface{}
_ = json.Unmarshal([]byte(blockJSON), &blocks)
for _, block := range blocks {
text += formatBlock(block) + "\n"
}
} else if text == "" && query.Get("attachments") != "" {
attachmentJSON := query.Get("attachments")
var attachments []map[string]interface{}
_ = json.Unmarshal([]byte(attachmentJSON), &attachments)
for _, attachment := range attachments {
if txt, ok := attachment["title"].(string); ok {
text += txt + "\n"
}
for _, action := range attachment["actions"].([]interface{}) {
actionMap := action.(map[string]interface{})
if actionMap["type"] == "button" {
text += fmt.Sprintf(
"<%s|%s>\n",
actionMap["url"],
actionMap["text"],
)
} else {
text += fmt.Sprintf("Attachment-actions are not supported yet:\n%v\n", action)
}
}
}
}
_, _ = fmt.Fprint(output, formatSlackMessage(text)+"\n")
response := slack.Message{}
response.Text = text
bytes, _ := json.Marshal(response)
_, _ = w.Write(bytes)
}
func formatBlock(block map[string]interface{}) string {
text := ""
switch block["type"] {
case "section":
return extractText(block)
case "actions":
for _, element := range block["elements"].([]interface{}) {
buttonText := extractText(element.(map[string]interface{}))
buttonValue := element.(map[string]interface{})["value"].(string)
return commandButton(buttonText, buttonValue)
}
default:
return fmt.Sprintf("invalid block: %v", block)
}
return text
}
// bit hacky way to extract the text from some kind of block element
func extractText(block map[string]interface{}) string {
if fields, ok := block["fields"]; ok {
result := ""
for _, field := range fields.([]interface{}) {
result += extractText(field.(map[string]interface{}))
}
return result
}
// contains "text" element
if txt, ok := block["text"].(string); ok {
return txt
} else if txt, ok := block["text"].(map[string]interface{}); ok {
if value, ok := txt["value"]; ok {
return value.(map[string]interface{})["text"].(string)
}
return txt["text"].(string)
}
return fmt.Sprintf("unknown: %v", block)
}
func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}