Skip to content

Commit

Permalink
chore: remove non-functional code (#337)
Browse files Browse the repository at this point in the history
  • Loading branch information
wass3r authored Sep 12, 2022
1 parent 666d41e commit 506a4dc
Show file tree
Hide file tree
Showing 15 changed files with 18 additions and 349 deletions.
8 changes: 0 additions & 8 deletions config-example/bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ debug: true
# true: enable logging to console
# false: disable logging

log_json: false
# true: logs will be in JOSN format
# false: logs will be in plain text

interactive_components: false
# true: enables users to create and interact with chat platforms interactive components (e.g. Slack message attachments)
# false (defualt): disables interactive components for all supported chat platform

## heroku deploys require an injected listener port; only works for Slack Apps
# slack_listener_port: ${PORT}

Expand Down
42 changes: 18 additions & 24 deletions core/configure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,37 +115,32 @@ func Test_configureChatApplication(t *testing.T) {
validateRemoteSetup(testBotTelegramBadToken)

tests := []struct {
name string
args args
shouldRunChat bool
shouldRunInteractiveComponents bool
name string
args args
shouldRunChat bool
}{
{"Fail", args{bot: testBot}, false, false},
{"Fail - no chat_application not set", args{bot: testBotNoChat}, false, false},
{"Fail - Invalid value for chat_application", args{bot: testBotInvalidChat}, false, false},
{"Bad Name", args{bot: testBotBadName}, false, false},
{"Slack - no token", args{bot: testBotSlackNoToken}, false, false},
{"Slack - bad token", args{bot: testBotSlackBadToken}, false, false},
{"Slack - bad signing secret", args{bot: testBotSlackBadSigningSecret}, false, false},
{"Slack", args{bot: testBotSlack}, true, false},
{"Discord - no token", args{bot: testBotDiscordNoToken}, false, false},
{"Discord - bad token", args{bot: testBotDiscordBadToken}, false, false},
{"Discord w/ server id", args{bot: testBotDiscordServerID}, true, false},
{"Discord w/ bad server id", args{bot: testBotDiscordBadServerID}, false, false},
{"Telegram", args{bot: testBotTelegram}, true, false},
{"Telegram - no token", args{bot: testBotTelegramNoToken}, false, false},
{"Telegram - bad token", args{bot: testBotTelegramBadToken}, false, false},
{"Fail", args{bot: testBot}, false},
{"Fail - no chat_application not set", args{bot: testBotNoChat}, false},
{"Fail - Invalid value for chat_application", args{bot: testBotInvalidChat}, false},
{"Bad Name", args{bot: testBotBadName}, false},
{"Slack - no token", args{bot: testBotSlackNoToken}, false},
{"Slack - bad token", args{bot: testBotSlackBadToken}, false},
{"Slack - bad signing secret", args{bot: testBotSlackBadSigningSecret}, false},
{"Slack", args{bot: testBotSlack}, true},
{"Discord - no token", args{bot: testBotDiscordNoToken}, false},
{"Discord - bad token", args{bot: testBotDiscordBadToken}, false},
{"Discord w/ server id", args{bot: testBotDiscordServerID}, true},
{"Discord w/ bad server id", args{bot: testBotDiscordBadServerID}, false},
{"Telegram", args{bot: testBotTelegram}, true},
{"Telegram - no token", args{bot: testBotTelegramNoToken}, false},
{"Telegram - bad token", args{bot: testBotTelegramBadToken}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
configureChatApplication(tt.args.bot)
if tt.shouldRunChat != tt.args.bot.RunChat {
t.Errorf("configureChatApplication() wanted RunChat set to %v, but got %v", tt.shouldRunChat, tt.args.bot.RunChat)
}

if tt.shouldRunInteractiveComponents != tt.args.bot.InteractiveComponents {
t.Errorf("configureChatApplication() wanted InteractiveComponents set to %v, but got %v", tt.shouldRunInteractiveComponents, tt.args.bot.InteractiveComponents)
}
})
}
}
Expand All @@ -157,7 +152,6 @@ func Test_setSlackListenerPort(t *testing.T) {
baseBot := func() *models.Bot {
bot := new(models.Bot)
bot.CLI = true
bot.InteractiveComponents = true
bot.ChatApplication = "slack"
bot.SlackToken = "${TEST_SLACK_TOKEN}"
bot.SlackInteractionsCallbackPath = "${TEST_SLACK_INTERACTIONS_CALLBACK_PATH}"
Expand Down
4 changes: 0 additions & 4 deletions core/outputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ func Outputs(outputMsgs <-chan models.Message, hitRule <-chan models.Rule, bot *
}

if service == models.MsgServiceChat {
if bot.InteractiveComponents {
remoteSlack.InteractiveComponents(nil, &message, rule, bot)
}

remoteSlack.Reaction(message, rule, bot)
}

Expand Down
1 change: 0 additions & 1 deletion core/remotes.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ func Remotes(inputMsgs chan<- models.Message, rules map[string]models.Rule, bot
}
// Read messages from Slack
go remoteSlack.Read(inputMsgs, rules, bot)
go remoteSlack.InteractiveComponents(inputMsgs, nil, rules[""], bot)
// Setup remote to use the Telegram client to read from Telegram
case "telegram":
remoteTelegram := &telegram.Client{
Expand Down
1 change: 0 additions & 1 deletion models/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ type Bot struct {
Scheduler bool `mapstructure:"scheduler,omitempty"`
ChatApplication string `mapstructure:"chat_application" binding:"required"`
Debug bool `mapstructure:"debug,omitempty"`
InteractiveComponents bool `mapstructure:"interactive_components,omitempty"`
Metrics bool `mapstructure:"metrics,omitempty"`
CustomHelpText string `mapstructure:"custom_help_text,omitempty"`
DisableNoMatchHelp bool `mapstructure:"disable_no_match_help,omitempty"`
Expand Down
5 changes: 0 additions & 5 deletions remote/cli/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,3 @@ func (c *Client) Send(message models.Message, bot *models.Bot) {
fmt.Fprint(w, user+"> ")
w.Flush()
}

// InteractiveComponents implementation to satisfy remote interface.
func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) {
// not implemented for CLI
}
5 changes: 0 additions & 5 deletions remote/discord/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,6 @@ func (c *Client) Send(message models.Message, bot *models.Bot) {
}
}

// InteractiveComponents implementation to satisfy remote interface.
func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) {
// not implemented for Discord
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the authenticated bot has access to.
func handleDiscordMessage(bot *models.Bot, inputMsgs chan<- models.Message) any {
Expand Down
5 changes: 0 additions & 5 deletions remote/gchat/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@ func (c *Client) Send(message models.Message, bot *models.Bot) {
}
}

// InteractiveComponents implementation to satisfy remote interface.
func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) {
// TODO: add support for InteractiveComponents with Google Chat Cards
}

// Reaction implementation to satisfy remote interface.
func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models.Bot) {
// Not implemented for Google Chat
Expand Down
7 changes: 0 additions & 7 deletions remote/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ type Remote interface {

Send(message models.Message, bot *models.Bot)

InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot)

Name() string
}

Expand All @@ -45,11 +43,6 @@ func Send(c context.Context, message models.Message, bot *models.Bot) {
FromContext(c).Send(message, bot)
}

// InteractiveComponents enables the bot to listen to Interactive Components coming from a remote.
func InteractiveComponents(c context.Context, inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) {
FromContext(c).InteractiveComponents(inputMsgs, message, rule, bot)
}

// Name returns the name of the remote.
func Name(c context.Context) string {
return FromContext(c).Name()
Expand Down
5 changes: 0 additions & 5 deletions remote/scheduler/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,6 @@ func (c *Client) Send(message models.Message, bot *models.Bot) {
// not implemented for Scheduler
}

// InteractiveComponents implementation to satisfy remote interface.
func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) {
// not implemented for Scheduler
}

// Process the Cron jobs.
func processJobs(jobs []*cron.Cron) {
// Create wait group for cron jobs and execute them
Expand Down
186 changes: 0 additions & 186 deletions remote/slack/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/slack-go/slack/socketmode"

"github.com/target/flottbot/models"
"github.com/target/flottbot/utils"
)

/*
Expand All @@ -28,71 +27,6 @@ Slack helper functions (anything that uses the 'slack-go/slack' package)
======================================================================
*/

// constructInteractiveComponentMessage creates a message specifically for a matched rule from the Interactive Components server.
func constructInteractiveComponentMessage(callback slack.AttachmentActionCallback, bot *models.Bot) models.Message {
text := ""

if len(callback.ActionCallback.AttachmentActions) > 0 {
for _, action := range callback.ActionCallback.AttachmentActions {
if action.Value != "" {
text = fmt.Sprintf("<@%s> %s", bot.ID, action.Value)
break
}
}
}

message := models.NewMessage()

messageType, err := getMessageType(callback.Channel.ID)
if err != nil {
log.Error().Msg(err.Error())
}

userNames := strings.Split(callback.User.Name, ".")
user := &slack.User{
ID: callback.User.ID,
TeamID: callback.User.TeamID,
Name: callback.User.Name,
Color: callback.User.Color,
RealName: callback.User.RealName,
TZ: callback.User.TZ,
TZLabel: callback.User.TZLabel,
TZOffset: callback.User.TZOffset,
Profile: slack.UserProfile{
FirstName: userNames[0],
LastName: userNames[len(userNames)-1],
RealNameNormalized: callback.User.Profile.RealNameNormalized,
DisplayName: callback.User.Profile.DisplayName,
DisplayNameNormalized: callback.User.Profile.DisplayName,
Email: callback.User.Profile.Email,
Skype: callback.User.Profile.Skype,
Phone: callback.User.Profile.Phone,
Title: callback.User.Profile.Title,
StatusText: callback.User.Profile.StatusText,
StatusEmoji: callback.User.Profile.StatusEmoji,
Team: callback.User.Profile.Team,
},
}
channel := callback.Channel.Name

if callback.Channel.IsPrivate {
channel = callback.Channel.ID
}

msgType, err := getMessageType(callback.Channel.ID)
if err != nil {
log.Error().Msg(err.Error())
}

if msgType == models.MsgTypePrivateChannel {
channel = callback.Channel.ID
}

contents, mentioned := removeBotMention(text, bot.ID)

return populateMessage(message, messageType, channel, contents, callback.MessageTs, callback.MessageTs, "", mentioned, user, bot)
}

// getEventsAPIHealthHandler creates and returns the handler for health checks on the Slack Events API reader.
func getEventsAPIHealthHandler(bot *models.Bot) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -284,101 +218,6 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs
}
}

// getInteractiveComponentHealthHandler creates and returns the handler for health checks on the Interactive Component server.
func getInteractiveComponentHealthHandler(bot *models.Bot) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
log.Error().Msgf("received invalid method: %s", r.Method)
w.WriteHeader(http.StatusMethodNotAllowed)

return
}

log.Debug().Msg("bot interaction health endpoint hit")

w.WriteHeader(http.StatusOK)

_, err := w.Write([]byte("OK"))
if err != nil {
log.Error().Msgf("failed to handle interactive component: %v", err)
}
}
}

// getInteractiveComponentRuleHandler creates and returns the handler for processing and sending out messages from the Interactive Component server.
func getInteractiveComponentRuleHandler(inputMsgs chan<- models.Message, rule models.Rule, bot *models.Bot) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
log.Error().Msgf("received invalid method: %s", r.Method)

w.WriteHeader(http.StatusMethodNotAllowed)
w.Header().Set("Content-Type", "text/plain")

_, err := w.Write([]byte("Oops! I encountered an unexpected HTTP verb"))
if err != nil {
log.Error().Msgf("failed to send response for interactive component handler: %v", err)
}

return
}

buff, err := io.ReadAll(r.Body)
if err != nil {
log.Error().Msgf("failed to read request body: %v", err)
}

contents, err := sanitizeContents(buff)
if err != nil {
log.Error().Msgf("failed to sanitize content: %v", err)
}

var callback slack.AttachmentActionCallback
if err := json.Unmarshal([]byte(contents), &callback); err != nil {
log.Error().Msgf("failed to decode callback json %#q: %v", contents, err)

w.WriteHeader(http.StatusInternalServerError)
w.Header().Set("Content-Type", "text/plain")

_, err := w.Write([]byte("Oops! Looks like I failed to decode some JSON in the backend. Please contact admins for more info!"))
if err != nil {
log.Error().Msgf("failed to send response for error during unmarshal process: %v", err)
}

return
}

// Only accept message from slack with valid token
if callback.Token != bot.SlackSigningSecret {
log.Error().Msg("invalid 'slack_signing_secret'")

w.WriteHeader(http.StatusUnauthorized)
w.Header().Set("Content-Type", "text/plain")

_, err := w.Write([]byte("Sorry, but I didn't recognize your signing secret! Perhaps check if it's a valid secret."))
if err != nil {
log.Error().Msg("failed to send response for validating secret.")
}

return
}

// Construct and send out message
message := constructInteractiveComponentMessage(callback, bot)
inputMsgs <- message

// Respond
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain")

_, err = w.Write([]byte("Rodger that!"))
if err != nil {
log.Error().Msgf("failed to send response: %v", err)
}

log.Info().Msgf("triggering rule: %s", rule.Name)
}
}

// getRooms - return a map of rooms.
func getRooms(api *slack.Client) map[string]string {
rooms := make(map[string]string)
Expand Down Expand Up @@ -603,31 +442,6 @@ func populateMessage(message models.Message, msgType models.MessageType, channel
}
}

// processInteractiveComponentRule processes a rule that was triggered by an interactive component, e.g. Slack interactive messages.
func processInteractiveComponentRule(rule models.Rule, message *models.Message) {
// Get slack attachments from hit rule and append to outgoing message
config := rule.Remotes.Slack
if config.Attachments != nil {
log.Debug().Msgf("found attachment for rule %#q", rule.Name)

config.Attachments[0].CallbackID = message.ID

if len(config.Attachments[0].Actions) > 0 {
for i, action := range config.Attachments[0].Actions {
actionValue, err := utils.Substitute(action.Value, message.Vars)
if err != nil {
log.Warn().Msg(err.Error())
}

config.Attachments[0].Actions[i].Value = actionValue
}
}

message.Remotes.Slack.Attachments = config.Attachments
message.IsEphemeral = true // We default Slack Message attachment's as ephemeral
}
}

// readFromEventsAPI utilizes the Slack API client to read event-based messages.
// This method of reading is preferred over the RTM method.
func readFromEventsAPI(api *slack.Client, vToken string, inputMsgs chan<- models.Message, bot *models.Bot) {
Expand Down
Loading

0 comments on commit 506a4dc

Please sign in to comment.