github.com/sharovik/devbot@v1.0.1-0.20240308094637-4a0387c40516/events/repeatevent/event.go (about)

     1  package repeatevent
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/sharovik/devbot/internal/service/message/conversation"
     9  	"github.com/sharovik/devbot/internal/service/schedule"
    10  
    11  	"github.com/sharovik/devbot/internal/container"
    12  	"github.com/sharovik/devbot/internal/database"
    13  	"github.com/sharovik/devbot/internal/dto"
    14  	"github.com/sharovik/devbot/internal/dto/databasedto"
    15  	"github.com/sharovik/devbot/internal/log"
    16  	"github.com/sharovik/orm/clients"
    17  	cdto "github.com/sharovik/orm/dto"
    18  	"github.com/sharovik/orm/query"
    19  )
    20  
    21  const (
    22  	//EventName the name of the event
    23  	EventName = "repeatevent"
    24  
    25  	//EventVersion the version of the event
    26  	EventVersion = "1.0.0"
    27  
    28  	helpMessage = "Ask me `repeat` and I will try repeat again the event I previously executed by your command. Eg: You ask me to run something and then you need to rerun in again. You write repeat and I repeat the event."
    29  )
    30  
    31  // EventStruct the struct for the event object. It will be used for initialisation of the event in defined-events.go file.
    32  type EventStruct struct {
    33  }
    34  
    35  // Event - object which is ready to use
    36  var (
    37  	Event = EventStruct{}
    38  )
    39  
    40  // Help retrieves the help message
    41  func (e EventStruct) Help() string {
    42  	return helpMessage
    43  }
    44  
    45  // Alias retrieves the event alias
    46  func (e EventStruct) Alias() string {
    47  	return EventName
    48  }
    49  
    50  // Execute method which is called by message processor
    51  func (e EventStruct) Execute(message dto.BaseChatMessage) (dto.BaseChatMessage, error) {
    52  	executedEvent, err := lastExecutedEvent(message)
    53  	if err != nil {
    54  		message.Text = "Failed to fetch the last executed events for that channel."
    55  		return message, err
    56  	}
    57  
    58  	if executedEvent.GetField("id").Value == nil {
    59  		message.Text = "It looks like you didn't executed any event yet at this channel."
    60  		return message, nil
    61  	}
    62  
    63  	answer, err := triggerScenario(executedEvent)
    64  	if err != nil {
    65  		message.Text = fmt.Sprintf("Failed to execute the event.\n```%s```", err)
    66  		return message, err
    67  	}
    68  
    69  	message.Text = answer.Text
    70  	return message, nil
    71  }
    72  
    73  func getRepeatEventID() (int64, error) {
    74  	eventID, err := container.C.Dictionary.FindEventByAlias(EventName)
    75  	if err != nil {
    76  		return 0, err
    77  	}
    78  
    79  	return eventID, nil
    80  }
    81  
    82  // Install method for installation of event
    83  func (e EventStruct) Install() error {
    84  	log.Logger().Debug().
    85  		Str("event_name", EventName).
    86  		Str("event_version", EventVersion).
    87  		Msg("Triggered event installation")
    88  
    89  	return container.C.Dictionary.InstallNewEventScenario(database.EventScenario{
    90  		EventName:    EventName,
    91  		EventVersion: EventVersion,
    92  		Questions: []database.Question{
    93  			{
    94  				Question:      "repeat",
    95  				Answer:        "one sec",
    96  				QuestionRegex: "(?i)repeat",
    97  				QuestionGroup: "",
    98  			},
    99  		},
   100  	})
   101  }
   102  
   103  func lastExecutedEvent(message dto.BaseChatMessage) (cdto.ModelInterface, error) {
   104  	currentEventID, err := getRepeatEventID()
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	item, err := container.C.Dictionary.GetDBClient().Execute(new(clients.Query).
   110  		Select([]interface{}{}).From(databasedto.EventTriggerHistoryModel).
   111  		Where(query.Where{
   112  			First:    "channel",
   113  			Operator: "=",
   114  			Second: query.Bind{
   115  				Field: "channel",
   116  				Value: message.Channel,
   117  			},
   118  		}).Where(query.Where{
   119  		First:    "user",
   120  		Operator: "=",
   121  		Second: query.Bind{
   122  			Field: "user",
   123  			Value: message.OriginalMessage.User,
   124  		},
   125  	}).Where(query.Where{
   126  		First:    "event_id",
   127  		Operator: "<>",
   128  		Second: query.Bind{
   129  			Field: "event_id",
   130  			Value: currentEventID,
   131  		},
   132  	}).OrderBy("id", query.OrderDirectionDesc).Limit(query.Limit{
   133  		From: 0,
   134  		To:   1,
   135  	}))
   136  
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	if len(item.Items()) == 0 {
   142  		return nil, nil
   143  	}
   144  
   145  	model := databasedto.EventTriggerHistoryModel
   146  
   147  	for _, field := range item.Items()[0].GetColumns() {
   148  		switch f := field.(type) {
   149  		case cdto.ModelField:
   150  			model.AddModelField(cdto.ModelField{
   151  				Name:  f.Name,
   152  				Value: f.Value,
   153  			})
   154  		default:
   155  			continue
   156  		}
   157  
   158  	}
   159  
   160  	return model, nil
   161  }
   162  
   163  func getEventAliasByID(eventID int) (string, error) {
   164  	item, err := container.C.Dictionary.GetDBClient().Execute(new(clients.Query).
   165  		Select([]interface{}{"alias"}).From(databasedto.EventModel).Where(query.Where{
   166  		First:    "id",
   167  		Operator: "=",
   168  		Second: query.Bind{
   169  			Field: "id",
   170  			Value: eventID,
   171  		},
   172  	}))
   173  	if err != nil {
   174  		return "", err
   175  	}
   176  
   177  	if len(item.Items()) == 0 {
   178  		return "", fmt.Errorf("failed to find the event alias for selected ID")
   179  	}
   180  
   181  	return item.Items()[0].GetField("alias").Value.(string), nil
   182  }
   183  
   184  func triggerScenario(item cdto.ModelInterface) (dto.BaseChatMessage, error) {
   185  	eventAlias, err := getEventAliasByID(item.GetField("event_id").Value.(int))
   186  	if err != nil {
   187  		return dto.BaseChatMessage{}, err
   188  	}
   189  
   190  	var (
   191  		variables []string
   192  		channel   = item.GetField("channel").Value.(string)
   193  	)
   194  
   195  	if item.GetField("variables").Value.(string) != "" {
   196  		scenario := database.EventScenario{
   197  			RequiredVariables: nil,
   198  		}
   199  
   200  		variables = strings.Split(item.GetField("variables").Value.(string), schedule.VariablesDelimiter)
   201  		for _, variable := range variables {
   202  			scenario.RequiredVariables = append(scenario.RequiredVariables, database.ScenarioVariable{
   203  				Value: variable,
   204  			})
   205  		}
   206  
   207  		dmAnswer := dto.DictionaryMessage{
   208  			ScenarioID:   int64(item.GetField("scenario_id").Value.(int)),
   209  			Question:     item.GetField("command").Value.(string),
   210  			QuestionID:   int64(item.GetField("last_question_id").Value.(int)),
   211  			EventID:      int64(item.GetField("event_id").Value.(int)),
   212  			ReactionType: eventAlias,
   213  		}
   214  
   215  		conversation.AddConversation(scenario, dto.BaseChatMessage{
   216  			Channel:           channel,
   217  			Text:              item.GetField("command").Value.(string),
   218  			AsUser:            false,
   219  			Ts:                time.Now(),
   220  			DictionaryMessage: dmAnswer,
   221  			OriginalMessage:   dto.BaseOriginalMessage{},
   222  		})
   223  
   224  		return container.C.DefinedEvents[eventAlias].Execute(conversation.GetConversation(channel).LastQuestion)
   225  	}
   226  
   227  	return container.C.DefinedEvents[eventAlias].Execute(dto.BaseChatMessage{
   228  		Channel: channel,
   229  		Text:    item.GetField("command").Value.(string),
   230  		AsUser:  false,
   231  		Ts:      time.Time{},
   232  		DictionaryMessage: dto.DictionaryMessage{
   233  			ScenarioID: int64(item.GetField("scenario_id").Value.(int)),
   234  			Question:   "",
   235  			QuestionID: int64(item.GetField("last_question_id").Value.(int)),
   236  			EventID:    int64(item.GetField("event_id").Value.(int)),
   237  		},
   238  		OriginalMessage: dto.BaseOriginalMessage{
   239  			Text:  item.GetField("command").Value.(string),
   240  			User:  item.GetField("user").Value.(string),
   241  			Files: nil,
   242  		},
   243  	})
   244  }
   245  
   246  // Update for event update actions
   247  func (e EventStruct) Update() error {
   248  	return nil
   249  }