diff --git a/config/config.go b/config/config.go index 21c1129..eafa002 100644 --- a/config/config.go +++ b/config/config.go @@ -72,6 +72,9 @@ type Config struct { Babbler struct { DefaultUsers []string } + Reminder struct { + MaxBatchAdd int + } } // Readconfig loads the config data out of a JSON file located in cfile diff --git a/example_config.json b/example_config.json index 63b28b0..11c5bd4 100644 --- a/example_config.json +++ b/example_config.json @@ -64,5 +64,8 @@ "DefaultUsers": [ "seabass" ] + }, + "Reminder": { + "MaxBatchAdd" : 10 } } diff --git a/plugins/reminder/reminder.go b/plugins/reminder/reminder.go index f610412..f2ac29c 100644 --- a/plugins/reminder/reminder.go +++ b/plugins/reminder/reminder.go @@ -11,6 +11,7 @@ import ( "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/config" ) type ReminderPlugin struct { @@ -18,6 +19,7 @@ type ReminderPlugin struct { reminders []*Reminder mutex *sync.Mutex timer *time.Timer + config *config.Config } type Reminder struct { @@ -52,6 +54,7 @@ func New(bot bot.Bot) *ReminderPlugin { reminders: []*Reminder{}, mutex: &sync.Mutex{}, timer: timer, + config: bot.Config(), } go reminderer(plugin) @@ -97,33 +100,83 @@ func (p *ReminderPlugin) Message(message msg.Message) bool { if who == "me" { who = from } + dur, err := time.ParseDuration(parts[3]) if err != nil { p.Bot.SendMessage(channel, "Easy cowboy, not sure I can parse that duration.") return true } - when := time.Now().Add(dur) - what := strings.Join(parts[4:], " ") + reminders := []*Reminder{} - response := fmt.Sprintf("Sure %s, I'll remind %s.", from, who) - p.Bot.SendMessage(channel, response) + operator := strings.ToLower(parts[2]) + + doConfirm := true + + if operator == "in" { + //one off reminder + //remind who in dur blah + when := time.Now().Add(dur) + what := strings.Join(parts[4:], " ") + + reminders = append(reminders, &Reminder{ + from: from, + who: who, + what: what, + when: when, + channel: channel, + }) + } else if operator == "every" && strings.ToLower(parts[4]) == "for" { + //batch add, especially for reminding msherms to buy a kit + //remind who every dur for dur2 blah + dur2, err := time.ParseDuration(parts[5]) + if err != nil { + p.Bot.SendMessage(channel, "Easy cowboy, not sure I can parse that duration.") + return true + } + + when := time.Now().Add(dur) + endTime := time.Now().Add(dur2) + what := strings.Join(parts[6:], " ") + + for i := 0; when.Before(endTime); i++ { + if i >= p.config.Reminder.MaxBatchAdd { + p.Bot.SendMessage(channel, "Easy cowboy, that's a lot of reminders. I'll add some of them.") + doConfirm = false + break + } + + reminders = append(reminders, &Reminder{ + from: from, + who: who, + what: what, + when: when, + channel: channel, + }) + + when = when.Add(dur) + } + } else { + p.Bot.SendMessage(channel, "Easy cowboy, not sure I comprehend what you're asking.") + return true + } + + if doConfirm { + response := fmt.Sprintf("Sure %s, I'll remind %s.", from, who) + p.Bot.SendMessage(channel, response) + } p.mutex.Lock() p.timer.Stop() - p.reminders = append(p.reminders, &Reminder{ - from: from, - who: who, - what: what, - when: when, - channel: channel, - }) + p.reminders = append(p.reminders, reminders...) sort.Sort(reminderSlice(p.reminders)) - p.timer.Reset(p.reminders[0].when.Sub(time.Now())) + if len(p.reminders) > 0 { + p.timer.Reset(p.reminders[0].when.Sub(time.Now())) + } p.mutex.Unlock() diff --git a/plugins/reminder/reminder_test.go b/plugins/reminder/reminder_test.go index 907f1b5..453445f 100644 --- a/plugins/reminder/reminder_test.go +++ b/plugins/reminder/reminder_test.go @@ -3,6 +3,7 @@ package reminder import ( + "fmt" "strings" "testing" "time" @@ -89,6 +90,37 @@ func TestList(t *testing.T) { assert.Contains(t, mb.Messages[2], "2) tester -> testuser :: don't fail this test 2 @ ") } +func TestBatch(t *testing.T) { + mb := bot.NewMockBot() + c := New(mb) + c.config.Reminder.MaxBatchAdd = 50 + assert.NotNil(t, c) + res := c.Message(makeMessage("!remind testuser every 1s for 5s yikes")) + assert.True(t, res) + time.Sleep(6 * time.Second) + assert.Len(t, mb.Messages, 6) + for i := 0; i < 5; i++ { + assert.Contains(t, mb.Messages[i+1], "Hey testuser, tester wanted you to be reminded: yikes") + } +} + +func TestBatchMax(t *testing.T) { + mb := bot.NewMockBot() + c := New(mb) + c.config.Reminder.MaxBatchAdd = 10 + assert.NotNil(t, c) + res := c.Message(makeMessage("!remind testuser every 1h for 24h yikes")) + assert.True(t, res) + res = c.Message(makeMessage("!list reminders")) + assert.True(t, res) + time.Sleep(6 * time.Second) + assert.Len(t, mb.Messages, 2) + assert.Contains(t, mb.Messages[0], "Easy cowboy, that's a lot of reminders. I'll add some of them.") + + for i := 0; i < 10; i++ { + assert.Contains(t, mb.Messages[1], fmt.Sprintf("%d) tester -> testuser :: yikes", i+1)) + } +} func TestHelp(t *testing.T) { mb := bot.NewMockBot()