Files
houston-be/cmd/app/handler/slack_handler.go
Gullipalli Chetan Kumar 2dd4d710e5 TP-47360 : Created service for uploading slack conversations to s3 and send request to maverick for generating RCA (#290)
* TP-47360| created services to upload slack conversation to cloud and send urls to generate RCA

* created rca input repository

* TP-47360| enabled generating rca service on resolution

* resolved merge conflicts

* TP-47360| added migration script for creating rca input table

* changed json response structure according to contract

* added unit tests

* removed api to make gen ai call

* made changes in message format posted in slack

* changed entity struct and adding flag to enable rca generation

* attaching title, description and replies related to incident status block

* made design changes in message format
2023-11-24 14:39:34 +05:30

197 lines
7.0 KiB
Go

package handler
import (
"encoding/json"
"houston/common/util"
"houston/internal/cron"
"houston/internal/diagnostic"
"houston/internal/processor"
"houston/internal/resolver"
"houston/model/incident"
"houston/model/log"
"houston/model/severity"
"houston/model/shedlock"
"houston/model/tag"
"houston/model/team"
"houston/model/user"
"houston/pkg/rest"
"houston/pkg/slackbot"
rcaRepository "houston/repository/rca/impl"
"houston/repository/rcaInput"
"houston/service/documentService"
incidentServiceV2 "houston/service/incident"
"houston/service/rca"
slack2 "houston/service/slack"
"github.com/slack-go/slack"
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
"github.com/spf13/viper"
"go.uber.org/zap"
"gorm.io/gorm"
logger "houston/logger"
)
type slackHandler struct {
socketModeClient *socketmode.Client
slashCommandProcessor *processor.SlashCommandProcessor
memberJoinCallbackProcessor *processor.MemberJoinedCallbackEventProcessor
blockActionProcessor *processor.BlockActionProcessor
viewSubmissionProcessor *processor.ViewSubmissionProcessor
slashCommandResolver *resolver.SlashCommandResolver
diagnosticCommandProcessor *processor.DiagnosticCommandProcessor
userChangeEventProcessor *processor.UserChangeEventProcessor
}
func NewSlackHandler(gormClient *gorm.DB, socketModeClient *socketmode.Client) *slackHandler {
severityService := severity.NewSeverityRepository(gormClient)
logRepository := log.NewLogRepository(gormClient)
tagService := tag.NewTagRepository(gormClient)
teamService := team.NewTeamRepository(gormClient, logRepository)
incidentService := incident.NewIncidentRepository(gormClient, severityService, logRepository, teamService, socketModeClient)
userService := user.NewUserRepository(gormClient)
shedlockService := shedlock.NewShedlockRepository(gormClient)
slackbotClient := slackbot.NewSlackClient(socketModeClient)
slashCommandProcessor := processor.NewSlashCommandProcessor(socketModeClient, incidentService, slackbotClient)
grafanaRepository := diagnostic.NewDiagnoseRepository(gormClient)
diagnosticCommandProcessor := processor.NewDiagnosticCommandProcessor(socketModeClient, grafanaRepository)
incidentServiceV2 := incidentServiceV2.NewIncidentServiceV2(gormClient)
slackService := slack2.NewSlackService()
// new services
rcaRepository := rcaRepository.NewRcaRepository(gormClient)
rcaInputRepository := rcaInput.NewRcaInputRepository(gormClient)
restClient := rest.NewClientActionsImpl()
documentService := documentService.NewActionsImpl(restClient)
rcaService := rca.NewRcaService(incidentServiceV2, slackService, restClient, documentService, rcaRepository, rcaInputRepository, userService)
cron.RunJob(
socketModeClient,
gormClient,
incidentService,
severityService,
teamService,
shedlockService,
userService,
incidentServiceV2,
slackService,
)
return &slackHandler{
socketModeClient: socketModeClient,
slashCommandProcessor: slashCommandProcessor,
diagnosticCommandProcessor: diagnosticCommandProcessor,
memberJoinCallbackProcessor: processor.NewMemberJoinedCallbackEventProcessor(
socketModeClient, incidentService, teamService, severityService,
),
blockActionProcessor: processor.NewBlockActionProcessor(
socketModeClient, incidentService, teamService, severityService, tagService, slackbotClient, incidentServiceV2, slackService, rcaService,
),
viewSubmissionProcessor: processor.NewViewSubmissionProcessor(
socketModeClient, incidentService, teamService, severityService, tagService, teamService, slackbotClient, gormClient,
),
slashCommandResolver: resolver.NewSlashCommandResolver(
diagnosticCommandProcessor, slashCommandProcessor,
),
userChangeEventProcessor: processor.NewUserChangeEventProcessor(
socketModeClient, userService,
),
}
}
func (sh *slackHandler) HoustonConnect() {
go func() {
for evt := range sh.socketModeClient.Events {
switch evt.Type {
case socketmode.EventTypeConnecting:
{
logger.Info("houston connecting to slackbot with socket mode")
}
case socketmode.EventTypeConnectionError:
{
logger.Error("appToken : " + viper.GetString("houston.slack.app.token"))
logger.Error("botToken : " + viper.GetString("houston.slack.bot.token"))
logger.Error("houston connection failed.")
}
case socketmode.EventTypeConnected:
{
logger.Info("houston connected to slackbot with socket mode")
}
case socketmode.EventTypeEventsAPI:
{
ev, _ := evt.Data.(slackevents.EventsAPIEvent)
eventJson := &ev
serializedEventJson, eventErr := json.Marshal(eventJson)
if eventErr != nil {
logger.Error("error occurred while serializing the event object", zap.Any("error", eventErr))
} else {
if ev.InnerEvent.Type != util.UserChangeEvent {
logger.Info("event api", zap.String("event", string(serializedEventJson)))
}
}
switch ev.Type {
case slackevents.CallbackEvent:
innerEvent := ev.InnerEvent
switch innerEvent.Type {
case util.UserChangeEvent:
sh.userChangeEventProcessor.ProcessCommand(ev, evt.Request)
}
switch innerEventData := innerEvent.Data.(type) {
case *slackevents.MemberJoinedChannelEvent:
sh.memberJoinCallbackProcessor.ProcessCommand(innerEventData, evt.Request)
}
}
}
case socketmode.EventTypeInteractive:
{
callback, _ := evt.Data.(slack.InteractionCallback)
switch callback.Type {
case slack.InteractionTypeBlockActions:
{
logger.Info(
"received interaction type block action",
zap.String("action_id", callback.ActionID), zap.String("block_id", callback.BlockID),
)
sh.blockActionProcessor.ProcessCommand(callback, evt.Request)
}
case slack.InteractionTypeViewSubmission:
{
logger.Info(
"received interaction type view submission",
zap.String("action_id", callback.ActionID), zap.String("block_id", callback.BlockID),
)
callbackJson := &callback
serializedCallbackJson, callbackErr := json.Marshal(callbackJson)
if callbackErr != nil {
logger.Error("error occurred while serializing the callback object", zap.Any("error", callbackErr))
} else {
logger.Info("callback data", zap.String("callback", string(serializedCallbackJson)))
}
requestJson := &evt.Request
serializedRequestJson, requestErr := json.Marshal(requestJson)
if requestErr != nil {
logger.Error("error occurred while serializing the request object", zap.Any("error", requestErr))
} else {
logger.Info("request data", zap.String("request", string(serializedRequestJson)))
}
sh.viewSubmissionProcessor.ProcessCommand(callback, evt.Request)
}
}
}
case socketmode.EventTypeSlashCommand:
{
sh.slashCommandResolver.Resolve(&evt)
}
default:
{
logger.Error("houston unexpected event type received", zap.String("event_type", string(evt.Type)))
}
}
}
}()
go sh.socketModeClient.Run()
}