From 3bc5846498201f0e184577521df3b688bfd6b213 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Thu, 27 Jul 2023 10:10:06 +0200 Subject: [PATCH 01/10] feat: added today and tomorrow commands with attachments --- server/command/command.go | 7 +++ server/command/daily_summary.go | 14 +++-- server/mscalendar/calendar.go | 17 +++++ server/mscalendar/daily_summary.go | 17 +++-- .../mock_mscalendar/mock_mscalendar.go | 28 ++++----- server/mscalendar/views/calendar.go | 62 +++++++++++++++++++ server/utils/bot/mock_bot/mock_poster.go | 20 ++++++ server/utils/bot/poster.go | 10 +++ 8 files changed, 153 insertions(+), 22 deletions(-) diff --git a/server/command/command.go b/server/command/command.go index 4ff03ec6..076e78ea 100644 --- a/server/command/command.go +++ b/server/command/command.go @@ -111,6 +111,13 @@ func (c *Command) Handle() (string, bool, error) { handler = c.requireConnectedUser(c.requireAdminUser(c.debugAvailability)) case "settings": handler = c.requireConnectedUser(c.settings) + // Aliases + case "today": + parameters = []string{"today"} + handler = c.requireConnectedUser(c.dailySummary) + case "tomorrow": + parameters = []string{"tomorrow"} + handler = c.requireConnectedUser(c.dailySummary) } out, mustRedirectToDM, err := handler(parameters...) if err != nil { diff --git a/server/command/daily_summary.go b/server/command/daily_summary.go index 3c5ac33d..b83da4ae 100644 --- a/server/command/daily_summary.go +++ b/server/command/daily_summary.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "time" "github.com/mattermost/mattermost-plugin-mscalendar/server/store" ) @@ -21,12 +22,18 @@ func (c *Command) dailySummary(parameters ...string) (string, bool, error) { } switch parameters[0] { - case "view": - postStr, err := c.MSCalendar.GetDailySummaryForUser(c.user()) + case "view", "today": + postStr, err := c.MSCalendar.GetDaySummaryForUser(time.Now(), c.user()) if err != nil { return err.Error(), false, err } return postStr, false, nil + case "tomorrow": + _, err := c.MSCalendar.GetDaySummaryForUser(time.Now().Add(time.Hour*24), c.user()) + if err != nil { + return err.Error(), false, err + } + return "", false, nil case "time": if len(parameters) != 2 { return dailySummarySetTimeErrorMessage, false, nil @@ -59,9 +66,8 @@ func (c *Command) dailySummary(parameters ...string) (string, bool, error) { return err.Error(), false, err } return dailySummaryResponse(dsum), false, nil - default: - return "Invalid command. Please try again\n\n" + dailySummaryHelp, false, nil } + return "Invalid command. Please try again\n\n" + dailySummaryHelp, false, nil } func dailySummaryResponse(dsum *store.DailySummaryUserSettings) string { diff --git a/server/mscalendar/calendar.go b/server/mscalendar/calendar.go index ce77562a..bd4c9e45 100644 --- a/server/mscalendar/calendar.go +++ b/server/mscalendar/calendar.go @@ -46,6 +46,23 @@ func (m *mscalendar) getTodayCalendarEvents(user *User, now time.Time, timezone return m.client.GetDefaultCalendarView(user.Remote.ID, from, to) } +func (m *mscalendar) getTomorrowCalendarEvents(user *User, now time.Time, 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 + } + + from, to := getTodayHoursForTimezone(now.Add(time.Hour*24), timezone) + 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, diff --git a/server/mscalendar/daily_summary.go b/server/mscalendar/daily_summary.go index ad57b1a0..bac529b1 100644 --- a/server/mscalendar/daily_summary.go +++ b/server/mscalendar/daily_summary.go @@ -21,7 +21,7 @@ const dailySummaryTimeWindow = time.Minute * 2 const DailySummaryJobInterval = 15 * time.Minute type DailySummary interface { - GetDailySummaryForUser(user *User) (string, error) + GetDaySummaryForUser(now time.Time, user *User) (string, error) GetDailySummarySettingsForUser(user *User) (*store.DailySummaryUserSettings, error) SetDailySummaryPostTime(user *User, timeStr string) (*store.DailySummaryUserSettings, error) SetDailySummaryEnabled(user *User, enable bool) (*store.DailySummaryUserSettings, error) @@ -174,18 +174,27 @@ func (m *mscalendar) ProcessAllDailySummary(now time.Time) error { return nil } -func (m *mscalendar) GetDailySummaryForUser(user *User) (string, error) { +func (m *mscalendar) GetDaySummaryForUser(now time.Time, user *User) (string, error) { tz, err := m.GetTimezone(user) if err != nil { return "", err } - calendarData, err := m.getTodayCalendarEvents(user, time.Now(), tz) + calendarData, err := m.getTodayCalendarEvents(user, now, tz) if err != nil { return "Failed to get calendar events", err } - return views.RenderCalendarView(calendarData, tz) + message, attachments, err := views.RenderDaySummary(calendarData, tz) + if err != nil { + return "", errors.Wrap(err, "failed to render daily summary") + } + + if _, err := m.Poster.DMWithMessageAndAttachments(user.MattermostUserID, message, attachments...); err != nil { + return "", errors.Wrap(err, "failed to send message to user") + } + + return "", nil } func shouldPostDailySummary(dsum *store.DailySummaryUserSettings, now time.Time) (bool, error) { diff --git a/server/mscalendar/mock_mscalendar/mock_mscalendar.go b/server/mscalendar/mock_mscalendar/mock_mscalendar.go index 05e380aa..4bf00817 100644 --- a/server/mscalendar/mock_mscalendar/mock_mscalendar.go +++ b/server/mscalendar/mock_mscalendar/mock_mscalendar.go @@ -265,34 +265,34 @@ func (mr *MockMSCalendarMockRecorder) GetCalendars(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCalendars", reflect.TypeOf((*MockMSCalendar)(nil).GetCalendars), arg0) } -// GetDailySummaryForUser mocks base method. -func (m *MockMSCalendar) GetDailySummaryForUser(arg0 *mscalendar.User) (string, error) { +// GetDailySummarySettingsForUser mocks base method. +func (m *MockMSCalendar) GetDailySummarySettingsForUser(arg0 *mscalendar.User) (*store.DailySummaryUserSettings, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDailySummaryForUser", arg0) - ret0, _ := ret[0].(string) + ret := m.ctrl.Call(m, "GetDailySummarySettingsForUser", arg0) + ret0, _ := ret[0].(*store.DailySummaryUserSettings) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetDailySummaryForUser indicates an expected call of GetDailySummaryForUser. -func (mr *MockMSCalendarMockRecorder) GetDailySummaryForUser(arg0 interface{}) *gomock.Call { +// GetDailySummarySettingsForUser indicates an expected call of GetDailySummarySettingsForUser. +func (mr *MockMSCalendarMockRecorder) GetDailySummarySettingsForUser(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDailySummaryForUser", reflect.TypeOf((*MockMSCalendar)(nil).GetDailySummaryForUser), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDailySummarySettingsForUser", reflect.TypeOf((*MockMSCalendar)(nil).GetDailySummarySettingsForUser), arg0) } -// GetDailySummarySettingsForUser mocks base method. -func (m *MockMSCalendar) GetDailySummarySettingsForUser(arg0 *mscalendar.User) (*store.DailySummaryUserSettings, error) { +// GetDaySummaryForUser mocks base method. +func (m *MockMSCalendar) GetDaySummaryForUser(arg0 time.Time, arg1 *mscalendar.User) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDailySummarySettingsForUser", arg0) - ret0, _ := ret[0].(*store.DailySummaryUserSettings) + ret := m.ctrl.Call(m, "GetDaySummaryForUser", arg0, arg1) + ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetDailySummarySettingsForUser indicates an expected call of GetDailySummarySettingsForUser. -func (mr *MockMSCalendarMockRecorder) GetDailySummarySettingsForUser(arg0 interface{}) *gomock.Call { +// GetDaySummaryForUser indicates an expected call of GetDaySummaryForUser. +func (mr *MockMSCalendarMockRecorder) GetDaySummaryForUser(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDailySummarySettingsForUser", reflect.TypeOf((*MockMSCalendar)(nil).GetDailySummarySettingsForUser), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDaySummaryForUser", reflect.TypeOf((*MockMSCalendar)(nil).GetDaySummaryForUser), arg0, arg1) } // GetRemoteUser mocks base method. diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index 8cbbebd1..cc8a4650 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -7,6 +7,7 @@ import ( "time" "github.com/mattermost/mattermost-plugin-mscalendar/server/remote" + "github.com/mattermost/mattermost-server/v6/model" ) func RenderCalendarView(events []*remote.Event, timeZone string) (string, error) { @@ -41,6 +42,67 @@ func RenderCalendarView(events []*remote.Event, timeZone string) (string, error) return resp, nil } +func RenderDaySummary(events []*remote.Event, timezone string) (string, []*model.SlackAttachment, error) { + if len(events) == 0 { + return "You have no events for that day", nil, nil + } + + if timezone != "" { + for _, e := range events { + e.Start = e.Start.In(timezone) + e.End = e.End.In(timezone) + } + } + + message := fmt.Sprintf("Agenda for %s.\nTimes are shown in %s", events[0].Start.Time().Format("Monday, 02 January"), events[0].Start.TimeZone) + + var attachments []*model.SlackAttachment + for _, event := range events { + var actions []*model.PostAction + + fields := []*model.SlackAttachmentField{} + if event.Location != nil && event.Location.DisplayName != "" { + fields = append(fields, &model.SlackAttachmentField{ + Title: "Location", + Value: event.Location.DisplayName, + Short: true, + }) + + // Add actions for known links + // Disable join meeting button for now, since we don't have a handler and + // the location url is shown parsed and clickable anyway. + // if joinMeetingAction := getActionForLocation(event.Location); joinMeetingAction != nil { + // actions = append(actions, joinMeetingAction) + // } + } + + attachments = append(attachments, &model.SlackAttachment{ + Title: event.Subject, + // Text: event.BodyPreview, + Text: fmt.Sprintf("(%s - %s)", event.Start.In(timezone).Time().Format(time.Kitchen), event.End.In(timezone).Time().Format(time.Kitchen)), + Fields: fields, + Actions: actions, + }) + } + + return message, attachments, nil +} + +// func getActionForLocation(loc *remote.Location) (action *model.PostAction) { +// if strings.Contains(loc.DisplayName, "zoom.us/j/") || strings.Contains(loc.DisplayName, "meet.google.com") || strings.Contains(loc.DisplayName, "discord.gg") { +// action = &model.PostAction{ +// Type: model.PostActionTypeButton, +// Name: "Join Meeting", +// Style: "good", +// Integration: &model.PostActionIntegration{ +// URL: loc.DisplayName, +// }, +// } +// } + +// return +// } + func renderTableHeader() string { return `| Time | Subject | | :--: | :-- |` diff --git a/server/utils/bot/mock_bot/mock_poster.go b/server/utils/bot/mock_bot/mock_poster.go index f8872470..7e83e517 100644 --- a/server/utils/bot/mock_bot/mock_poster.go +++ b/server/utils/bot/mock_bot/mock_poster.go @@ -93,6 +93,26 @@ func (mr *MockPosterMockRecorder) DMWithAttachments(arg0 interface{}, arg1 ...in return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DMWithAttachments", reflect.TypeOf((*MockPoster)(nil).DMWithAttachments), varargs...) } +// DMWithMessageAndAttachments mocks base method. +func (m *MockPoster) DMWithMessageAndAttachments(arg0, arg1 string, arg2 ...*model.SlackAttachment) (string, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DMWithMessageAndAttachments", varargs...) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DMWithMessageAndAttachments indicates an expected call of DMWithMessageAndAttachments. +func (mr *MockPosterMockRecorder) DMWithMessageAndAttachments(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DMWithMessageAndAttachments", reflect.TypeOf((*MockPoster)(nil).DMWithMessageAndAttachments), varargs...) +} + // DeletePost mocks base method. func (m *MockPoster) DeletePost(arg0 string) error { m.ctrl.T.Helper() diff --git a/server/utils/bot/poster.go b/server/utils/bot/poster.go index aa9f6787..52128f65 100644 --- a/server/utils/bot/poster.go +++ b/server/utils/bot/poster.go @@ -18,6 +18,9 @@ type Poster interface { // Often used to include post actions. DMWithAttachments(mattermostUserID string, attachments ...*model.SlackAttachment) (string, error) + // DMWithMessageAndAttachments posts a Direct Message that contains Slack attachments and a message. + DMWithMessageAndAttachments(mattermostUserID, message string, attachments ...*model.SlackAttachment) (string, error) + // Ephemeral sends an ephemeral message to a user Ephemeral(mattermostUserID, channelID, format string, args ...interface{}) @@ -50,6 +53,13 @@ func (bot *bot) DMWithAttachments(mattermostUserID string, attachments ...*model return bot.dm(mattermostUserID, &post) } +// DMWithMessageAndAttachments posts a Direct Message that contains Slack attachments and a message. +func (bot *bot) DMWithMessageAndAttachments(mattermostUserID, message string, attachments ...*model.SlackAttachment) (string, error) { + post := model.Post{Message: message} + model.ParseSlackAttachment(&post, attachments) + return bot.dm(mattermostUserID, &post) +} + func (bot *bot) dm(mattermostUserID string, post *model.Post) (string, error) { channel, err := bot.pluginAPI.GetDirectChannel(mattermostUserID, bot.mattermostUserID) if err != nil { From 92a91c129bd824f51a4e922435ab9d7a9cdbf817 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Thu, 27 Jul 2023 10:28:48 +0200 Subject: [PATCH 02/10] remove unused function --- server/mscalendar/calendar.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/server/mscalendar/calendar.go b/server/mscalendar/calendar.go index bd4c9e45..ce77562a 100644 --- a/server/mscalendar/calendar.go +++ b/server/mscalendar/calendar.go @@ -46,23 +46,6 @@ func (m *mscalendar) getTodayCalendarEvents(user *User, now time.Time, timezone return m.client.GetDefaultCalendarView(user.Remote.ID, from, to) } -func (m *mscalendar) getTomorrowCalendarEvents(user *User, now time.Time, 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 - } - - from, to := getTodayHoursForTimezone(now.Add(time.Hour*24), timezone) - 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, From 627397724d86b051bd7770c676d7b823fda4fea1 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Thu, 27 Jul 2023 10:56:19 +0200 Subject: [PATCH 03/10] linted --- server/mscalendar/views/calendar.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index cc8a4650..0cff8c03 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -6,8 +6,9 @@ import ( "sort" "time" - "github.com/mattermost/mattermost-plugin-mscalendar/server/remote" "github.com/mattermost/mattermost-server/v6/model" + + "github.com/mattermost/mattermost-plugin-mscalendar/server/remote" ) func RenderCalendarView(events []*remote.Event, timeZone string) (string, error) { From 002786c80857963983077c0ceb527aa7bfdc962d Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Sat, 29 Jul 2023 07:43:14 +0200 Subject: [PATCH 04/10] now -> day --- server/mscalendar/daily_summary.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/mscalendar/daily_summary.go b/server/mscalendar/daily_summary.go index bac529b1..c617ee23 100644 --- a/server/mscalendar/daily_summary.go +++ b/server/mscalendar/daily_summary.go @@ -174,13 +174,13 @@ func (m *mscalendar) ProcessAllDailySummary(now time.Time) error { return nil } -func (m *mscalendar) GetDaySummaryForUser(now time.Time, user *User) (string, error) { +func (m *mscalendar) GetDaySummaryForUser(day time.Time, user *User) (string, error) { tz, err := m.GetTimezone(user) if err != nil { return "", err } - calendarData, err := m.getTodayCalendarEvents(user, now, tz) + calendarData, err := m.getTodayCalendarEvents(user, day, tz) if err != nil { return "Failed to get calendar events", err } From ed9d16bad34875f11af97e700f2073559fc40beb Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Sat, 29 Jul 2023 07:44:09 +0200 Subject: [PATCH 05/10] remove unused code --- server/mscalendar/views/calendar.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index 0cff8c03..15284f7b 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -68,13 +68,6 @@ func RenderDaySummary(events []*remote.Event, timezone string) (string, []*model Value: event.Location.DisplayName, Short: true, }) - - // Add actions for known links - // Disable join meeting button for now, since we don't have a handler and - // the location url is shown parsed and clickable anyway. - // if joinMeetingAction := getActionForLocation(event.Location); joinMeetingAction != nil { - // actions = append(actions, joinMeetingAction) - // } } attachments = append(attachments, &model.SlackAttachment{ @@ -89,21 +82,6 @@ func RenderDaySummary(events []*remote.Event, timezone string) (string, []*model return message, attachments, nil } -// func getActionForLocation(loc *remote.Location) (action *model.PostAction) { -// if strings.Contains(loc.DisplayName, "zoom.us/j/") || strings.Contains(loc.DisplayName, "meet.google.com") || strings.Contains(loc.DisplayName, "discord.gg") { -// action = &model.PostAction{ -// Type: model.PostActionTypeButton, -// Name: "Join Meeting", -// Style: "good", -// Integration: &model.PostActionIntegration{ -// URL: loc.DisplayName, -// }, -// } -// } - -// return -// } - func renderTableHeader() string { return `| Time | Subject | | :--: | :-- |` From 18c6e37d64278b3a326a01b7c0c9e3703e663a39 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Mon, 31 Jul 2023 18:05:54 +0200 Subject: [PATCH 06/10] today/tomorrow autocomplete --- server/command/command.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/command/command.go b/server/command/command.go index 382797d6..cb47d0a0 100644 --- a/server/command/command.go +++ b/server/command/command.go @@ -38,6 +38,8 @@ var cmds = []*model.AutocompleteData{ model.NewAutocompleteData("disconnect", "", fmt.Sprintf("Disconnect from your %s account", config.Provider.DisplayName)), model.NewAutocompleteData("summary", "", "View your events for today, or edit the settings for your daily summary."), model.NewAutocompleteData("viewcal", "", "View your events for the upcoming week."), + model.NewAutocompleteData("today", "", "Display today's events."), + model.NewAutocompleteData("tomorrow", "", "Display tomorrow's events."), model.NewAutocompleteData("settings", "", "Edit your user personal settings."), model.NewAutocompleteData("subscribe", "", "Enable notifications for event invitations and updates."), model.NewAutocompleteData("unsubscribe", "", "Disable notifications for event invitations and updates."), From c738f90389ce4fbf957ae3dbe6bbec8f86756b19 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Mon, 31 Jul 2023 18:06:31 +0200 Subject: [PATCH 07/10] return tables on today/tomorrow commands --- server/command/daily_summary.go | 4 ++-- server/mscalendar/daily_summary.go | 8 ++------ server/mscalendar/views/calendar.go | 18 ++++++++++++++---- .../remote/gcal/get_default_calendar_view.go | 14 +++++++------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/server/command/daily_summary.go b/server/command/daily_summary.go index b83da4ae..5848c57e 100644 --- a/server/command/daily_summary.go +++ b/server/command/daily_summary.go @@ -29,11 +29,11 @@ func (c *Command) dailySummary(parameters ...string) (string, bool, error) { } return postStr, false, nil case "tomorrow": - _, err := c.MSCalendar.GetDaySummaryForUser(time.Now().Add(time.Hour*24), c.user()) + postStr, err := c.MSCalendar.GetDaySummaryForUser(time.Now().Add((time.Hour*24)*4), c.user()) if err != nil { return err.Error(), false, err } - return "", false, nil + return postStr, false, nil case "time": if len(parameters) != 2 { return dailySummarySetTimeErrorMessage, false, nil diff --git a/server/mscalendar/daily_summary.go b/server/mscalendar/daily_summary.go index c617ee23..d24eb780 100644 --- a/server/mscalendar/daily_summary.go +++ b/server/mscalendar/daily_summary.go @@ -185,16 +185,12 @@ func (m *mscalendar) GetDaySummaryForUser(day time.Time, user *User) (string, er return "Failed to get calendar events", err } - message, attachments, err := views.RenderDaySummary(calendarData, tz) + messageString, err := views.RenderCalendarView(calendarData, tz) if err != nil { return "", errors.Wrap(err, "failed to render daily summary") } - if _, err := m.Poster.DMWithMessageAndAttachments(user.MattermostUserID, message, attachments...); err != nil { - return "", errors.Wrap(err, "failed to send message to user") - } - - return "", nil + return messageString, nil } func shouldPostDailySummary(dsum *store.DailySummaryUserSettings, now time.Time) (bool, error) { diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index 15284f7b..581df1aa 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "sort" + "strings" "time" "github.com/mattermost/mattermost-server/v6/model" @@ -83,8 +84,8 @@ func RenderDaySummary(events []*remote.Event, timezone string) (string, []*model } func renderTableHeader() string { - return `| Time | Subject | -| :--: | :-- |` + return `| Time | Subject | | + | :-- | :-- | :--` } func renderEvent(event *remote.Event, asRow bool, timeZone string) (string, error) { @@ -93,7 +94,7 @@ func renderEvent(event *remote.Event, asRow bool, timeZone string) (string, erro format := "(%s - %s) [%s](%s)" if asRow { - format = "| %s - %s | [%s](%s) |" + format = "| %s - %s | [%s](%s) | %s |" } link, err := url.QueryUnescape(event.Weblink) @@ -101,9 +102,18 @@ func renderEvent(event *remote.Event, asRow bool, timeZone string) (string, erro return "", err } + var other string + if isKnownMeetingURL(event.Location.DisplayName) { + other = "[Join meeting](" + event.Location.DisplayName + ")" + } + subject := EnsureSubject(event.Subject) - return fmt.Sprintf(format, start, end, subject, link), nil + return fmt.Sprintf(format, start, end, subject, link, other), nil +} + +func isKnownMeetingURL(location string) bool { + return strings.Contains(location, "zoom.us/j/") || strings.Contains(location, "discord.gg") || strings.Contains(location, "meet.google.com") } func groupEventsByDate(events []*remote.Event) [][]*remote.Event { diff --git a/server/remote/gcal/get_default_calendar_view.go b/server/remote/gcal/get_default_calendar_view.go index 2e345345..9c017654 100644 --- a/server/remote/gcal/get_default_calendar_view.go +++ b/server/remote/gcal/get_default_calendar_view.go @@ -54,23 +54,23 @@ func (c *client) GetDefaultCalendarView(_ string, start, end time.Time) ([]*remo req.SingleEvents(true) req.OrderBy("startTime") - events, err := req.Do() + result, err := req.Do() if err != nil { return nil, errors.Wrap(err, "gcal GetDefaultCalendarView, error performing request") } - result := []*remote.Event{} - if len(events.Items) == 0 { - return result, nil + if len(result.Items) == 0 { + return []*remote.Event{}, nil } - for _, event := range events.Items { + events := []*remote.Event{} + for _, event := range result.Items { if event.ICalUID != "" { - result = append(result, convertGCalEventToRemoteEvent(event)) + events = append(events, convertGCalEventToRemoteEvent(event)) } } - return result, nil + return events, nil } func convertGCalEventDateTimeToRemoteDateTime(dt *calendar.EventDateTime) *remote.DateTime { From a35e3dec2d84623b5c3479b6b06bc810da5ac5e5 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Mon, 31 Jul 2023 19:14:36 +0200 Subject: [PATCH 08/10] check for nil location --- server/mscalendar/views/calendar.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index 581df1aa..f87cab37 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -103,7 +103,7 @@ func renderEvent(event *remote.Event, asRow bool, timeZone string) (string, erro } var other string - if isKnownMeetingURL(event.Location.DisplayName) { + if event.Location != nil && isKnownMeetingURL(event.Location.DisplayName) { other = "[Join meeting](" + event.Location.DisplayName + ")" } From 64e22f50de61018fce7ca8094a7e9b0f2b76c3a0 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Tue, 1 Aug 2023 08:43:59 +0200 Subject: [PATCH 09/10] revert tomorrow day times four --- server/command/daily_summary.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/command/daily_summary.go b/server/command/daily_summary.go index 5848c57e..ee03023c 100644 --- a/server/command/daily_summary.go +++ b/server/command/daily_summary.go @@ -29,7 +29,7 @@ func (c *Command) dailySummary(parameters ...string) (string, bool, error) { } return postStr, false, nil case "tomorrow": - postStr, err := c.MSCalendar.GetDaySummaryForUser(time.Now().Add((time.Hour*24)*4), c.user()) + postStr, err := c.MSCalendar.GetDaySummaryForUser(time.Now().Add(time.Hour*24), c.user()) if err != nil { return err.Error(), false, err } From cfe4ba36f312577748831a2b5e4922e0061f778b Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Tue, 1 Aug 2023 08:52:01 +0200 Subject: [PATCH 10/10] fix markdown table render and test --- server/mscalendar/daily_summary_test.go | 6 +++--- server/mscalendar/views/calendar.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/mscalendar/daily_summary_test.go b/server/mscalendar/daily_summary_test.go index 92beb8c7..16cc5c96 100644 --- a/server/mscalendar/daily_summary_test.go +++ b/server/mscalendar/daily_summary_test.go @@ -150,9 +150,9 @@ func TestProcessAllDailySummary(t *testing.T) { mockPoster.EXPECT().DM("user2_mm_id", `Times are shown in Pacific Standard Time Wednesday February 12, 2020 -| Time | Subject | -| :--: | :-- | -| 9:00AM - 11:00AM | [The subject]() |`).Return("postID2", nil).Times(1), +| Time | Subject | | +| :-- | :-- | :-- | +| 9:00AM - 11:00AM | [The subject]() | |`).Return("postID2", nil).Times(1), ) s.EXPECT().StoreUser(gomock.Any()).Times(2).DoAndReturn(func(u *store.User) error { diff --git a/server/mscalendar/views/calendar.go b/server/mscalendar/views/calendar.go index f87cab37..3df32960 100644 --- a/server/mscalendar/views/calendar.go +++ b/server/mscalendar/views/calendar.go @@ -85,7 +85,7 @@ func RenderDaySummary(events []*remote.Event, timezone string) (string, []*model func renderTableHeader() string { return `| Time | Subject | | - | :-- | :-- | :--` +| :-- | :-- | :-- |` } func renderEvent(event *remote.Event, asRow bool, timeZone string) (string, error) {