diff --git a/go.mod b/go.mod index 5e3af06..a696823 100644 --- a/go.mod +++ b/go.mod @@ -2,27 +2,24 @@ module github.com/velour/catbase require ( github.com/PuerkitoBio/goquery v1.5.0 // indirect - github.com/boltdb/bolt v1.3.1 github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff - github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-sql-driver/mysql v1.4.1 // indirect github.com/gorilla/websocket v1.4.0 // indirect github.com/jmoiron/sqlx v1.2.0 + github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect + github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect github.com/mattn/go-sqlite3 v1.10.0 - github.com/mitchellh/mapstructure v1.1.2 // indirect github.com/mmcdole/gofeed v1.0.0-beta2 github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf // indirect github.com/nlopes/slack v0.5.0 - github.com/pkg/errors v0.8.1 // indirect + github.com/olebedev/when v0.0.0-20190131080308-164b69386514 github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d // indirect github.com/rs/zerolog v1.12.0 github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/testify v1.3.0 github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89 github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 - github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 - github.com/yuin/gopher-lua v0.0.0-20190125051437-7b9317363aa9 golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect - golang.org/x/text v0.3.0 // indirect + google.golang.org/appengine v1.4.0 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect ) diff --git a/go.sum b/go.sum index 5ee01c2..f531cc7 100644 --- a/go.sum +++ b/go.sum @@ -1,31 +1,39 @@ +github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE= +github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8= github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk= github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff/go.mod h1:QCRjR0b4qiJiNjuP7RFM89bh4UExGJalcWmYeSvlnRc= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU= +github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0= +github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 h1:iOAVXzZyXtW408TMYejlUPo6BIn92HmOacWtIfNyYns= +github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E= github.com/mmcdole/gofeed v1.0.0-beta2/go.mod h1:/BF9JneEL2/flujm8XHoxUcghdTV6vvb3xx/vKyChFU= github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI= github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8= github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0= github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= +github.com/olebedev/when v0.0.0-20190131080308-164b69386514 h1:xpZutaUgtGPKT2JFaH72/yby908QS9ORlnrAkkdJ4m0= +github.com/olebedev/when v0.0.0-20190131080308-164b69386514/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -43,13 +51,14 @@ github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89 h1:3D3M900hEBJJAqyKl70 github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89/go.mod h1:ejwOYCjnDMyO5LXFXRARQJGBZ6xQJZ3rgAHE5drSuMM= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 h1:p3rTUXxzuKsBOsHlkly7+rj9wagFBKeIsCDKkDII9sw= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158/go.mod h1:Ojy3BTOiOTwpHpw7/HNi+TVTFppao191PQs+Qc3sqpE= -github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7/go.mod h1:bbMEM6aU1WDF1ErA5YJ0p91652pGv140gGw4Ww3RGp8= -github.com/yuin/gopher-lua v0.0.0-20190125051437-7b9317363aa9/go.mod h1:fFiAh+CowNFr0NK5VASokuwKwkbacRmHsVA7Yb1Tqac= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= diff --git a/plugins/reminder/reminder.go b/plugins/reminder/reminder.go index cd6cd58..3704d36 100644 --- a/plugins/reminder/reminder.go +++ b/plugins/reminder/reminder.go @@ -10,9 +10,13 @@ import ( "sync" "time" + "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" - "github.com/jmoiron/sqlx" + "github.com/olebedev/when" + "github.com/olebedev/when/rules/common" + "github.com/olebedev/when/rules/en" + "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" "github.com/velour/catbase/config" @@ -28,6 +32,7 @@ type ReminderPlugin struct { mutex *sync.Mutex timer *time.Timer config *config.Config + when *when.Parser } type Reminder struct { @@ -55,12 +60,17 @@ func New(b bot.Bot) *ReminderPlugin { timer := time.NewTimer(dur) timer.Stop() + w := when.New(nil) + w.Add(en.All...) + w.Add(common.All...) + plugin := &ReminderPlugin{ Bot: b, db: b.DB(), mutex: &sync.Mutex{}, timer: timer, config: b.Config(), + when: w, } plugin.queueUpNextReminder() @@ -77,6 +87,13 @@ func (p *ReminderPlugin) message(kind bot.Kind, message msg.Message, args ...int channel := message.Channel from := message.User.Name + var dur, dur2 time.Duration + t, err := p.when.Parse(message.Body, time.Now()) + // Allowing err to fallthrough for other parsing + if t != nil && err == nil { + t2 := time.Now().Sub(t.Time).String() + message.Body = string(message.Body[0:t.Index]) + t2 + string(message.Body[t.Index+len(t.Text):]) + } parts := strings.Fields(message.Body) if len(parts) >= 5 { @@ -86,17 +103,16 @@ func (p *ReminderPlugin) message(kind bot.Kind, message msg.Message, args ...int who = from } - dur, err := time.ParseDuration(parts[3]) + dur, err = time.ParseDuration(parts[3]) if err != nil { p.Bot.Send(bot.Message, channel, "Easy cowboy, not sure I can parse that duration. Try something like '1.5h' or '2h45m'.") return true } operator := strings.ToLower(parts[2]) - doConfirm := true - if operator == "in" { + if operator == "in" || operator == "at" || operator == "on" { //one off reminder //remind who in dur blah when := time.Now().UTC().Add(dur) @@ -114,8 +130,9 @@ func (p *ReminderPlugin) message(kind bot.Kind, message msg.Message, args ...int } 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]) + dur2, err = time.ParseDuration(parts[5]) if err != nil { + log.Error().Err(err) p.Bot.Send(bot.Message, channel, "Easy cowboy, not sure I can parse that duration. Try something like '1.5h' or '2h45m'.") return true } diff --git a/plugins/reminder/reminder_test.go b/plugins/reminder/reminder_test.go index 457397d..cbe5c43 100644 --- a/plugins/reminder/reminder_test.go +++ b/plugins/reminder/reminder_test.go @@ -58,6 +58,24 @@ func TestReminder(t *testing.T) { assert.Contains(t, mb.Messages[1], "Hey testuser, tester wanted you to be reminded: don't fail this test") } +func TestReminderDate(t *testing.T) { + c, mb := setup(t) + m0 := fmt.Sprintf("!remind testuser at %s don't fail this test 2", + time.Now().Add(3*time.Second).Format("15:04")) + res := c.message(makeMessage(m0)) + assert.True(t, res) + m1 := fmt.Sprintf("!remind testuser at %s don't fail this test 1", + time.Now().Add(2*time.Second).Format("15:04")) + res = c.message(makeMessage(m1)) + 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], "Hey testuser, tester wanted you to be reminded: don't fail this test 2") + assert.Contains(t, mb.Messages[2], "Sure tester, I'll remind testuser.") + assert.Contains(t, mb.Messages[3], "Hey testuser, tester wanted you to be reminded: don't fail this test 1") +} + func TestReminderReorder(t *testing.T) { c, mb := setup(t) res := c.message(makeMessage("!remind testuser in 2s don't fail this test 2"))