github.com/sharovik/devbot@v1.0.1-0.20240308094637-4a0387c40516/internal/service/analiser/analyser.go (about) 1 package analiser 2 3 import ( 4 "github.com/sharovik/devbot/internal/service/message/conversation" 5 _time "github.com/sharovik/devbot/internal/service/time" 6 7 "github.com/sharovik/devbot/internal/container" 8 "github.com/sharovik/devbot/internal/database" 9 "github.com/sharovik/devbot/internal/dto" 10 "github.com/sharovik/devbot/internal/helper" 11 "github.com/sharovik/devbot/internal/log" 12 ) 13 14 // Message the message object, from which we will generate the dto.DictionaryMessage 15 type Message struct { 16 Channel string 17 User string 18 Text string 19 } 20 21 // GetDmAnswer retrieves the Dictionary Message Answer 22 func GetDmAnswer(message Message) (dmAnswer dto.DictionaryMessage, err error) { 23 //Now we need to check if there was already opened conversation for this channel 24 //If so, then we need to get the Answer from this scenario 25 openConversation := conversation.GetConversation(message.Channel) 26 27 //If that was a stop word, we need to cancel the conversation 28 IsScenarioStopTriggered := conversation.IsScenarioStopTriggered(message.Text) 29 if IsScenarioStopTriggered { 30 dmAnswer = dto.DictionaryMessage{ 31 ScenarioID: 0, 32 EventID: 0, 33 Answer: "Ok, no more questions!", 34 QuestionID: 0, 35 Question: message.Text, 36 Regex: "", 37 MainGroupIndexInRegex: "", 38 ReactionType: "text", 39 } 40 conversation.FinaliseConversation(message.Channel) 41 42 return dmAnswer, nil 43 } 44 45 //If there was a scenario triggered for this conversation, we trigger the scenario handling logic 46 if openConversation.ScenarioID != 0 { 47 setAnswerToVariable(message.Text, &openConversation) 48 49 return generateDmForConversation(message, openConversation) 50 } 51 52 dmAnswer, err = container.C.Dictionary.FindAnswer(message.Text) 53 if err != nil { 54 return dto.DictionaryMessage{}, err 55 } 56 57 questions, err := getVariableQuestionsByScenarioID(dmAnswer.ScenarioID) 58 //if we don't have an error here, then we can proceed with the questions preparing for scenarios 59 if err != nil { 60 log.Logger().AddError(err).Msg("Failed to get the list of question by the scenarioID") 61 } 62 63 isHelpAnswerTriggered, err := helper.HelpMessageShouldBeTriggered(message.Text) 64 if err != nil { 65 log.Logger().AddError(err).Msg("Failed to parse the help template") 66 } 67 68 if dmAnswer.ReactionType != "" && isHelpAnswerTriggered { 69 dmAnswer.Answer = container.C.DefinedEvents[dmAnswer.ReactionType].Help() 70 dmAnswer.IsHelpTriggered = true 71 72 return dmAnswer, nil 73 } 74 75 //If the questions amount is more than 1, we need to start the conversation algorithm 76 if len(questions) > 1 && !isHelpAnswerTriggered { 77 scenario := database.EventScenario{} 78 SetScenarioQuestions(&scenario, questions) 79 conversation.AddConversation(scenario, dto.BaseChatMessage{ 80 Channel: message.Channel, 81 Text: message.Text, 82 AsUser: false, 83 Ts: _time.Service.Now(), 84 DictionaryMessage: dmAnswer, 85 OriginalMessage: dto.BaseOriginalMessage{ 86 Text: message.Text, 87 User: message.User, 88 }, 89 }) 90 91 dmAnswer.Answer = scenario.GetUnAnsweredQuestion() 92 } 93 94 return dmAnswer, nil 95 } 96 97 func SetScenarioQuestions(scenario *database.EventScenario, questions []database.QuestionObject) { 98 for _, q := range questions { 99 scenario.Questions = append(scenario.Questions, database.Question{ 100 Question: q.Question, 101 Answer: q.Answer, 102 }) 103 104 if q.IsVariable { 105 scenario.RequiredVariables = append(scenario.RequiredVariables, database.ScenarioVariable{ 106 Question: q.Answer, 107 }) 108 } 109 } 110 } 111 112 func getVariableQuestionsByScenarioID(scenarioID int64) (result []database.QuestionObject, err error) { 113 questions, err := container.C.Dictionary.GetQuestionsByScenarioID(scenarioID, true) 114 if err != nil { 115 log.Logger().AddError(err).Msg("Failed to get the list of questions by the scenarioID") 116 return result, err 117 } 118 119 for _, q := range questions { 120 if q.Question != "" { 121 continue 122 } 123 124 result = append(result, q) 125 } 126 127 return result, err 128 } 129 130 func setAnswerToVariable(answer string, openConversation *conversation.Conversation) { 131 if len(openConversation.Scenario.RequiredVariables) == 0 { 132 return 133 } 134 135 for i, variable := range openConversation.Scenario.RequiredVariables { 136 if variable.Value != "" || openConversation.LastQuestion.Text != variable.Question { 137 continue 138 } 139 140 openConversation.Scenario.RequiredVariables[i].Value = answer 141 return 142 } 143 } 144 145 func generateDmForConversation(message Message, openConversation conversation.Conversation) (dto.DictionaryMessage, error) { 146 if len(openConversation.Scenario.RequiredVariables) == 0 { 147 return dto.DictionaryMessage{}, nil 148 } 149 150 for _, variable := range openConversation.Scenario.RequiredVariables { 151 if variable.Value != "" { 152 continue 153 } 154 155 dmAnswer := dto.DictionaryMessage{ 156 ScenarioID: openConversation.ScenarioID, 157 EventID: openConversation.EventID, 158 Answer: variable.Question, 159 ReactionType: openConversation.ReactionType, 160 } 161 162 return dmAnswer, nil 163 } 164 165 conversation.MarkAsReadyEventToBeExecuted(message.Channel) 166 167 return dto.DictionaryMessage{ 168 ScenarioID: openConversation.ScenarioID, 169 EventID: openConversation.ScenarioID, 170 Answer: "Ok", 171 ReactionType: openConversation.ReactionType, 172 }, nil 173 }