mirror of https://github.com/velour/catbase.git
new reminder plugin
This commit is contained in:
parent
b687078c1a
commit
2764410ad4
2
main.go
2
main.go
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/velour/catbase/plugins/downtime"
|
||||
"github.com/velour/catbase/plugins/fact"
|
||||
"github.com/velour/catbase/plugins/leftpad"
|
||||
"github.com/velour/catbase/plugins/reminder"
|
||||
"github.com/velour/catbase/plugins/talker"
|
||||
"github.com/velour/catbase/plugins/your"
|
||||
"github.com/velour/catbase/slack"
|
||||
|
@ -51,6 +52,7 @@ func main() {
|
|||
b.AddHandler("remember", fact.NewRemember(b))
|
||||
b.AddHandler("your", your.New(b))
|
||||
b.AddHandler("counter", counter.New(b))
|
||||
b.AddHandler("reminder", reminder.New(b))
|
||||
// catches anything left, will always return true
|
||||
b.AddHandler("factoid", fact.New(b))
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
|
||||
|
||||
package reminder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/velour/catbase/bot"
|
||||
"github.com/velour/catbase/bot/msg"
|
||||
)
|
||||
|
||||
type ReminderPlugin struct {
|
||||
Bot bot.Bot
|
||||
reminders []*Reminder
|
||||
mutex *sync.Mutex
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
type Reminder struct {
|
||||
from string
|
||||
who string
|
||||
what string
|
||||
when time.Time
|
||||
channel string
|
||||
}
|
||||
|
||||
type reminderSlice []*Reminder
|
||||
|
||||
func (s reminderSlice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s reminderSlice) Less(i, j int) bool {
|
||||
return s[i].when.Before(s[j].when)
|
||||
}
|
||||
|
||||
func (s reminderSlice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func New(bot bot.Bot) *ReminderPlugin {
|
||||
dur, _ := time.ParseDuration("1h")
|
||||
timer := time.NewTimer(dur)
|
||||
timer.Stop()
|
||||
|
||||
plugin := &ReminderPlugin{
|
||||
Bot: bot,
|
||||
reminders: []*Reminder{},
|
||||
mutex: &sync.Mutex{},
|
||||
timer: timer,
|
||||
}
|
||||
go reminderer(plugin)
|
||||
|
||||
return plugin
|
||||
}
|
||||
|
||||
func reminderer(p *ReminderPlugin) {
|
||||
//welcome to the reminderererererererererer
|
||||
for {
|
||||
fmt.Println()
|
||||
fmt.Println("waiting...")
|
||||
fmt.Println()
|
||||
|
||||
<-p.timer.C
|
||||
|
||||
p.mutex.Lock()
|
||||
|
||||
reminder := p.reminders[0]
|
||||
if len(p.reminders) >= 2 {
|
||||
p.reminders = p.reminders[1:]
|
||||
p.timer.Reset(p.reminders[0].when.Sub(time.Now()))
|
||||
} else {
|
||||
p.reminders = []*Reminder{}
|
||||
}
|
||||
|
||||
p.mutex.Unlock()
|
||||
|
||||
message := fmt.Sprintf("Hey %s, %s wanted you to be reminded: %s", reminder.who, reminder.from, reminder.what)
|
||||
p.Bot.SendMessage(reminder.channel, message)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *ReminderPlugin) Message(message msg.Message) bool {
|
||||
channel := message.Channel
|
||||
from := message.User.Name
|
||||
|
||||
parts := strings.Fields(message.Body)
|
||||
|
||||
if len(parts) > 5 {
|
||||
if strings.ToLower(parts[0]) == "remind" {
|
||||
who := parts[1]
|
||||
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:], " ")
|
||||
|
||||
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,
|
||||
})
|
||||
|
||||
sort.Sort(reminderSlice(p.reminders))
|
||||
|
||||
p.timer.Reset(p.reminders[0].when.Sub(time.Now()))
|
||||
|
||||
p.mutex.Unlock()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *ReminderPlugin) Help(channel string, parts []string) {
|
||||
p.Bot.SendMessage(channel, "Pester someone with a reminder. Try \"remind <user> in <duration> message\".\n\nUnsure about duration syntax? Check https://golang.org/pkg/time/#ParseDuration")
|
||||
}
|
||||
|
||||
func (p *ReminderPlugin) Event(kind string, message msg.Message) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *ReminderPlugin) BotMessage(message msg.Message) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *ReminderPlugin) RegisterWeb() *string {
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
|
||||
|
||||
package reminder
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/velour/catbase/bot"
|
||||
"github.com/velour/catbase/bot/msg"
|
||||
"github.com/velour/catbase/bot/user"
|
||||
)
|
||||
|
||||
func makeMessage(payload string) msg.Message {
|
||||
isCmd := strings.HasPrefix(payload, "!")
|
||||
if isCmd {
|
||||
payload = payload[1:]
|
||||
}
|
||||
return msg.Message{
|
||||
User: &user.User{Name: "tester"},
|
||||
Channel: "test",
|
||||
Body: payload,
|
||||
Command: isCmd,
|
||||
}
|
||||
}
|
||||
|
||||
func TestReminder(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
res := c.Message(makeMessage("!remind testuser in 1s don't fail this test"))
|
||||
time.Sleep(2 * time.Second)
|
||||
assert.Len(t, mb.Messages, 2)
|
||||
assert.True(t, res)
|
||||
assert.Contains(t, mb.Messages[0], "Sure tester, I'll remind testuser.")
|
||||
assert.Contains(t, mb.Messages[1], "Hey testuser, tester wanted you to be reminded: don't fail this test")
|
||||
}
|
||||
|
||||
func TestReminderReorder(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
res := c.Message(makeMessage("!remind testuser in 2s don't fail this test 2"))
|
||||
assert.True(t, res)
|
||||
res = c.Message(makeMessage("!remind testuser in 1s don't fail this test 1"))
|
||||
assert.True(t, res)
|
||||
time.Sleep(5 * time.Second)
|
||||
assert.Len(t, mb.Messages, 4)
|
||||
assert.Contains(t, mb.Messages[0], "Sure tester, I'll remind testuser.")
|
||||
assert.Contains(t, mb.Messages[1], "Sure tester, I'll remind testuser.")
|
||||
assert.Contains(t, mb.Messages[2], "Hey testuser, tester wanted you to be reminded: don't fail this test 1")
|
||||
assert.Contains(t, mb.Messages[3], "Hey testuser, tester wanted you to be reminded: don't fail this test 2")
|
||||
}
|
||||
|
||||
func TestReminderParse(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
res := c.Message(makeMessage("!remind testuser in unparseable don't fail this test"))
|
||||
assert.Len(t, mb.Messages, 1)
|
||||
assert.True(t, res)
|
||||
assert.Contains(t, mb.Messages[0], "Easy cowboy, not sure I can parse that duration.")
|
||||
}
|
||||
|
||||
func TestHelp(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
c.Help("channel", []string{})
|
||||
assert.Len(t, mb.Messages, 1)
|
||||
}
|
||||
|
||||
func TestBotMessage(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
assert.False(t, c.BotMessage(makeMessage("test")))
|
||||
}
|
||||
|
||||
func TestEvent(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
assert.False(t, c.Event("dummy", makeMessage("test")))
|
||||
}
|
||||
|
||||
func TestRegisterWeb(t *testing.T) {
|
||||
mb := bot.NewMockBot()
|
||||
c := New(mb)
|
||||
assert.NotNil(t, c)
|
||||
assert.Nil(t, c.RegisterWeb())
|
||||
}
|
Loading…
Reference in New Issue