Skip to content

Commit

Permalink
[MM-21140] Daily summary job (#36)
Browse files Browse the repository at this point in the history
* Daily summary job

* PR feedback
* improve error messages
* reformat daily summary output
* introduce LastPostTime to store

* add missing mocks

* change job interval to 15 minutes

* make daily summary time window more sophisticated, rename DailySummaryAll to ProcessAllDailySummary, move view render logic to its own package

* update mocks

* change function name

* address Dylan's PR feedback

* PR feedback:

Make time range of summary be 12am-12am of current day
Changed error string user not connected error
  • Loading branch information
mickmister authored Mar 26, 2020
1 parent 4ad02af commit e58eca8
Show file tree
Hide file tree
Showing 21 changed files with 957 additions and 32 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/mattermost/mattermost-plugin-mscalendar
go 1.13

require (
github.com/benbjohnson/clock v1.0.0
github.com/golang/mock v1.2.0
github.com/gorilla/mux v1.7.3
github.com/jarcoal/httpmock v1.0.4
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1/go.mod h1:noBAuukeYOXa0aXGqxr24tADqkwDO2KRD15FsuaZ5a8=
github.com/aws/aws-sdk-go v1.19.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/benbjohnson/clock v1.0.0 h1:78Jk/r6m4wCi6sndMpty7A//t4dw/RW5fV4ZgDVfX1w=
github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
Expand Down
7 changes: 7 additions & 0 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@
"type": "bool",
"help_text": "When enabled, a Mattermost user's status will automatically update based on their Microsoft Calendar availability. This runs every 5 minutes.",
"default": false
},
{
"key": "EnableDailySummary",
"display_name": "Enable Daily Summary",
"type": "bool",
"help_text": "When enabled, Mattermost users will a receive a daily summary of their scheduled events in Microsoft Calendar. Users can choose when the summary will be sent to them.",
"default": true
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions server/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func Register(registerFunc RegisterFunc) {
DisplayName: "Microsoft Calendar",
Description: "Interact with your outlook calendar.",
AutoComplete: true,
AutoCompleteDesc: "help, info, connect, disconnect, connect_bot, disconnect_bot, subscribe, showcals, viewcal, createcal, deletecal, createevent, findmeetings, availability",
AutoCompleteDesc: "help, info, connect, disconnect, connect_bot, disconnect_bot, subscribe, showcals, viewcal, createcal, deletecal, createevent, findmeetings, availability, summary",
AutoCompleteHint: "(subcommand)",
})
}
Expand All @@ -69,6 +69,8 @@ func (c *Command) Handle() (string, error) {
handler = c.disconnect
case "disconnect_bot":
handler = c.disconnectBot
case "summary":
handler = c.dailySummary
case "viewcal":
handler = c.viewCalendar
case "createcal":
Expand All @@ -88,7 +90,7 @@ func (c *Command) Handle() (string, error) {
}
out, err := handler(parameters...)
if err != nil {
return "", errors.WithMessagef(err, "Command /%s %s failed", config.CommandTrigger, cmd)
return out, errors.WithMessagef(err, "Command /%s %s failed", config.CommandTrigger, cmd)
}

return out, nil
Expand Down
77 changes: 77 additions & 0 deletions server/command/daily_summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package command

import (
"fmt"

"github.com/mattermost/mattermost-plugin-mscalendar/server/store"
)

const dailySummaryHelp = "### Daily summary commands:\n" +
"`/mscalendar summary view` - View your daily summary\n" +
"`/mscalendar summary settings` - View your settings for the daily summary\n" +
"`/mscalendar summary time 8:00AM` - Set the time you would like to receive your daily summary\n" +
"`/mscalendar summary enable` - Enable your daily summary\n" +
"`/mscalendar summary disable` - Disable your daily summary"

const dailySummarySetTimeErrorMessage = "Please enter a time, for example:\n`/mscalendar summary time 8:00AM`"

func (c *Command) dailySummary(parameters ...string) (string, error) {
if len(parameters) == 0 {
return dailySummaryHelp, nil
}

switch parameters[0] {
case "view":
postStr, err := c.MSCalendar.GetDailySummary(c.user())
if err != nil {
return err.Error(), err
}
return postStr, nil
case "time":
if len(parameters) != 2 {
return dailySummarySetTimeErrorMessage, nil
}
val := parameters[1]

dsum, err := c.MSCalendar.SetDailySummaryPostTime(c.user(), val)
if err != nil {
return err.Error() + "\n" + dailySummarySetTimeErrorMessage, nil
}

return dailySummaryResponse(dsum), nil
case "settings":
dsum, err := c.MSCalendar.GetDailySummarySettingsForUser(c.user())
if err != nil {
return err.Error() + "\nYou may need to configure your daily summary using the commands below.\n" + dailySummaryHelp, nil
}

return dailySummaryResponse(dsum), nil
case "enable":
dsum, err := c.MSCalendar.SetDailySummaryEnabled(c.user(), true)
if err != nil {
return err.Error(), err
}

return dailySummaryResponse(dsum), nil
case "disable":
dsum, err := c.MSCalendar.SetDailySummaryEnabled(c.user(), false)
if err != nil {
return err.Error(), err
}
return dailySummaryResponse(dsum), nil
default:
return "Invalid command. Please try again\n\n" + dailySummaryHelp, nil
}
}

func dailySummaryResponse(dsum *store.DailySummarySettings) string {
if dsum.PostTime == "" {
return "Your daily summary time is not yet configured.\n" + dailySummarySetTimeErrorMessage
}

enableStr := ""
if !dsum.Enable {
enableStr = ", but is disabled. Enable it with `/mscalendar summary enable`"
}
return fmt.Sprintf("Your daily summary is configured to show at %s %s%s.", dsum.PostTime, dsum.Timezone, enableStr)
}
29 changes: 7 additions & 22 deletions server/command/view_calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,19 @@ package command
import (
"time"

"github.com/mattermost/mattermost-plugin-mscalendar/server/utils"
"github.com/mattermost/mattermost-plugin-mscalendar/server/mscalendar/views"
)

func (c *Command) viewCalendar(parameters ...string) (string, error) {
events, err := c.MSCalendar.ViewCalendar(c.user(), time.Now(), time.Now().Add(14*24*time.Hour))
if err != nil {
return "", err
}

var timeZone string
tz, err := c.MSCalendar.GetTimezone(c.user())
if err == nil {
timeZone = tz
}

if timeZone != "" {
for _, event := range events {
event.Start = event.Start.In(timeZone)
event.End = event.End.In(timeZone)
}
if err != nil {
return "Error: No timezone found", err
}

resp := ""
for _, e := range events {
e.Start = e.Start.In(timeZone)
e.End = e.End.In(timeZone)
resp += " - " + e.ID + utils.JSONBlock(e)
events, err := c.MSCalendar.ViewCalendar(c.user(), time.Now().Add(-24*time.Hour), time.Now().Add(14*24*time.Hour))
if err != nil {
return "", err
}

return resp, nil
return views.RenderCalendarView(events, tz)
}
3 changes: 2 additions & 1 deletion server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ type StoredConfig struct {
OAuth2ClientID string
OAuth2ClientSecret string

EnableStatusSync bool
EnableStatusSync bool
EnableDailySummary bool

bot.BotConfig
}
Expand Down
3 changes: 0 additions & 3 deletions server/jobs/job_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,18 @@ func (jm *JobManager) OnConfigurationChange(env mscalendar.Env) error {
jm.mux.Lock()
defer jm.mux.Unlock()
jm.env = env
jm.env.Logger.Debugf("OnConfigurationChange", "yes", "for sure")

jm.registeredJobs.Range(func(k interface{}, v interface{}) bool {
job := v.(RegisteredJob)
enabled := job.isEnabledByConfig(env)
_, active := jm.activeJobs.Load(job.id)

// Config is set to enable. Job is inactive, so activate the job.
jm.env.Logger.Debugf("OnConfigurationChange", "enabled", enabled, "active", active)
if enabled && !active {
err := jm.activateJob(job)
if err != nil {
jm.env.Logger.Errorf("Error activating job", "id", job.id, "error", err.Error())
}
jm.env.Logger.Debugf("activated job")
}

// Config is set to disable. Job is active, so deactivate the job.
Expand Down
21 changes: 21 additions & 0 deletions server/mscalendar/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ func (m *mscalendar) ViewCalendar(user *User, from, to time.Time) ([]*remote.Eve
return m.client.GetDefaultCalendarView(user.Remote.ID, from, to)
}

func (m *mscalendar) getTodayCalendar(user *User, timezone string) ([]*remote.Event, error) {
err := m.Filter(
withClient,
)
if err != nil {
return nil, err
}

err = m.ExpandRemoteUser(user)
if err != nil {
return nil, err
}

now := time.Now().UTC()
t := remote.NewDateTime(now, "UTC").In(timezone).Time()

from := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
to := from.Add(24 * time.Hour)
return m.client.GetDefaultCalendarView(user.Remote.ID, from, to)
}

func (m *mscalendar) CreateCalendar(user *User, calendar *remote.Calendar) (*remote.Calendar, error) {
err := m.Filter(
withClient,
Expand Down
Loading

0 comments on commit e58eca8

Please sign in to comment.