quintilesims / slackbot

Slack bot for IQVIA
MIT License
2 stars 0 forks source link

Add !redo command #29

Closed zpatrick closed 6 years ago

zpatrick commented 6 years ago

Implement the inverse of !undo: repeat the last action done by the slackbot on the channel the command was sent on. This actually seems like it will be a little tricky to implement; we may want a behavior that tracks the "last" command (or message event?) received by the slackbot in each channel (without counting the !redo command as one, since we want people to be able to call !redo many times in a row).

I'm also worried aliases will make this implementation difficult; e.g. if the following alias exists:

!alias add !mo !redo

How would the tracker know to ignore "!mo" as the last command?

zpatrick commented 6 years ago

Some ideas:

Tracking the last action

It seems like the "last action" that anyone would reasonably want to execute with !redo would be the last message in the specified channel that got to this line in main:

 if err := app.Run(args); err != nil {

If we recorded that event right before we executed that line, we may be able to successfully track the last "action". It's also worth noting that anything that got to this line in main would have already been parsed through the aliases, so I think that may alleviate some concerns I had about the aliases I had earlier.

Executing the last action

One problem to solve is how do we tell the bot to "do" the last thing it just did. One way might be to fold the rtm.IncomingEvents channel with a RedoBehavior's channel, and allow RedoBehavior to send events to that channel.

current:

for event := range rtm.IncomingEvents {

new:

for event := range fold(rtm.IncomingEvents, redoBehavior.IncomingEvents) {

Impl of fold:

func fold(input1, input2 <- chan *slack.IncomingEvent) chan *slack.IncomingEvent {
    c := make(<- chan *slack.IncomingEvent)
    go func() { for { c <- <-input1 } }()
    go func() { for { c <- <-input2 } }()
    return c
}