-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MM-228] Add feature to update custom status and status of the user during meeting #359
Changes from 4 commits
ed87b58
b696601
d1c271b
a9c4531
10d6649
3c2ed2b
56441cc
8fd8412
642b212
59f5951
85fe326
ef5152e
67c24e7
dbd3e5d
14eddb0
8f503b1
0ad2bb8
03b1d25
5b08060
c7441e0
f287370
b851b21
716ebcc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,7 +110,7 @@ func (m *mscalendar) retrieveUsersToSync(userIndex store.UserIndex, syncJobSumma | |
} | ||
|
||
// If user does not have the proper features enabled, just go to the next one | ||
if !(user.Settings.UpdateStatusFromOptions != NotSetStatusOption || user.Settings.ReceiveReminders || user.Settings.SetCustomStatus) { | ||
if !(user.IsConfiguredForStatusUpdates() || user.IsConfiguredForCustomStatusUpdates() || user.Settings.ReceiveReminders) { | ||
continue | ||
} | ||
|
||
|
@@ -154,6 +154,13 @@ func (m *mscalendar) retrieveUsersToSync(userIndex store.UserIndex, syncJobSumma | |
return users, calendarViews, fmt.Errorf("no calendar views found") | ||
} | ||
|
||
for _, view := range calendarViews { | ||
ayusht2810 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
event := view.Events | ||
ayusht2810 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sort.Slice(event, func(i, j int) bool { | ||
return event[i].Start.Time().UnixMicro() < event[j].Start.Time().UnixMicro() | ||
}) | ||
} | ||
|
||
return users, calendarViews, nil | ||
} | ||
|
||
|
@@ -231,7 +238,7 @@ func (m *mscalendar) setUserStatuses(users []*store.User, calendarViews []*remot | |
numberOfLogs, numberOfUserStatusChange, numberOfUserErrorInStatusChange := 0, 0, 0 | ||
toUpdate := []*store.User{} | ||
for _, u := range users { | ||
if u.Settings.UpdateStatusFromOptions != NotSetStatusOption || u.Settings.SetCustomStatus { | ||
if u.IsConfiguredForStatusUpdates() || u.IsConfiguredForCustomStatusUpdates() { | ||
toUpdate = append(toUpdate, u) | ||
} | ||
} | ||
|
@@ -279,9 +286,12 @@ func (m *mscalendar) setUserStatuses(users []*store.User, calendarViews []*remot | |
continue | ||
} | ||
|
||
events := filterBusyAndAttendeeEvents(view.Events) | ||
events = getMergedEvents(events) | ||
|
||
var err error | ||
if user.Settings.UpdateStatusFromOptions != NotSetStatusOption { | ||
res, isStatusChanged, err = m.setStatusFromCalendarView(user, status, view) | ||
if user.IsConfiguredForStatusUpdates() { | ||
res, isStatusChanged, err = m.setStatusFromCalendarView(user, status, events) | ||
if err != nil { | ||
if numberOfLogs < logTruncateLimit { | ||
m.Logger.Warnf("Error setting user %s status. err=%v", user.MattermostUserID, err) | ||
|
@@ -296,11 +306,11 @@ func (m *mscalendar) setUserStatuses(users []*store.User, calendarViews []*remot | |
} | ||
} | ||
|
||
if user.Settings.SetCustomStatus { | ||
res, isStatusChanged, err = m.setCustomStatusFromCalendarView(user, view) | ||
if user.IsConfiguredForCustomStatusUpdates() { | ||
res, isStatusChanged, err = m.setCustomStatusFromCalendarView(user, events) | ||
if err != nil { | ||
if numberOfLogs < logTruncateLimit { | ||
m.Logger.Warnf("Error setting user %s status. err=%v", user.MattermostUserID, err) | ||
m.Logger.Warnf("Error setting user %s custom status. err=%v", user.MattermostUserID, err) | ||
} else if numberOfLogs == logTruncateLimit { | ||
m.Logger.Warnf(logTruncateMsg) | ||
} | ||
|
@@ -309,7 +319,7 @@ func (m *mscalendar) setUserStatuses(users []*store.User, calendarViews []*remot | |
} | ||
|
||
// Increment count only when we have not updated the status of the user from the options to have status change count per user. | ||
if isStatusChanged && user.Settings.UpdateStatusFromOptions == NotSetStatusOption { | ||
if isStatusChanged && user.Settings.UpdateStatusFromOptions == store.NotSetStatusOption { | ||
numberOfUserStatusChange++ | ||
} | ||
} | ||
|
@@ -322,13 +332,12 @@ func (m *mscalendar) setUserStatuses(users []*store.User, calendarViews []*remot | |
return utils.JSONBlock(calendarViews), numberOfUserStatusChange, numberOfUserErrorInStatusChange, nil | ||
} | ||
|
||
func (m *mscalendar) setCustomStatusFromCalendarView(user *store.User, res *remote.ViewCalendarResponse) (string, bool, error) { | ||
func (m *mscalendar) setCustomStatusFromCalendarView(user *store.User, events []*remote.Event) (string, bool, error) { | ||
isStatusChanged := false | ||
if !user.Settings.SetCustomStatus { | ||
if !user.IsConfiguredForCustomStatusUpdates() { | ||
return "User doesn't want to set custom status", isStatusChanged, nil | ||
} | ||
|
||
events := filterBusyEvents(res.Events) | ||
if len(events) == 0 { | ||
if user.IsCustomStatusSet { | ||
if err := m.PluginAPI.RemoveMattermostUserCustomStatus(user.MattermostUserID); err != nil { | ||
|
@@ -343,23 +352,14 @@ func (m *mscalendar) setCustomStatusFromCalendarView(user *store.User, res *remo | |
return "No event present to set custom status", isStatusChanged, nil | ||
} | ||
|
||
if checkOverlappingEvents(events) { | ||
return "Overlapping events, not setting a custom status", isStatusChanged, nil | ||
} | ||
|
||
// Not setting custom status for events without attendees since those are unlikely to be meetings. | ||
if len(events[0].Attendees) < 1 { | ||
return "No attendee present, not setting custom status", isStatusChanged, nil | ||
} | ||
|
||
currentUser, err := m.PluginAPI.GetMattermostUser(user.MattermostUserID) | ||
if err != nil { | ||
return "", isStatusChanged, err | ||
} | ||
|
||
currentCustomStatus := currentUser.GetCustomStatus() | ||
if currentCustomStatus != nil && !user.IsCustomStatusSet { | ||
return "User already have a custom status set, ignoring custom status change", isStatusChanged, nil | ||
return "User already has a custom status set, ignoring custom status change", isStatusChanged, nil | ||
} | ||
|
||
if appErr := m.PluginAPI.UpdateMattermostUserCustomStatus(user.MattermostUserID, &model.CustomStatus{ | ||
|
@@ -379,25 +379,19 @@ func (m *mscalendar) setCustomStatusFromCalendarView(user *store.User, res *remo | |
return "", isStatusChanged, nil | ||
} | ||
|
||
func (m *mscalendar) setStatusFromCalendarView(user *store.User, status *model.Status, res *remote.ViewCalendarResponse) (string, bool, error) { | ||
func (m *mscalendar) setStatusFromCalendarView(user *store.User, status *model.Status, events []*remote.Event) (string, bool, error) { | ||
isStatusChanged := false | ||
currentStatus := status.Status | ||
if user.Settings.UpdateStatusFromOptions == "" { | ||
if !user.IsConfiguredForStatusUpdates() { | ||
return "No value set from options to update status", isStatusChanged, nil | ||
} | ||
|
||
if currentStatus == model.StatusOffline && !user.Settings.GetConfirmation { | ||
return "User offline and does not want status change confirmations. No status change", isStatusChanged, nil | ||
} | ||
|
||
events := filterBusyEvents(res.Events) | ||
|
||
sort.Slice(events, func(i, j int) bool { | ||
return events[i].Start.Time().UnixMicro() < events[j].Start.Time().UnixMicro() | ||
}) | ||
|
||
busyStatus := model.StatusDnd | ||
if user.Settings.UpdateStatusFromOptions == AwayStatusOption { | ||
if user.Settings.UpdateStatusFromOptions == store.AwayStatusOption { | ||
busyStatus = model.StatusAway | ||
} | ||
|
||
|
@@ -426,15 +420,6 @@ func (m *mscalendar) setStatusFromCalendarView(user *store.User, status *model.S | |
return message, isStatusChanged, nil | ||
} | ||
|
||
if checkOverlappingEvents(events) { | ||
return "Overlapping events, not updating status", isStatusChanged, nil | ||
} | ||
|
||
// Not setting custom status for events without attendees since those are unlikely to be meetings. | ||
if len(events[0].Attendees) < 1 { | ||
return "No attendee present, not updating status", isStatusChanged, nil | ||
} | ||
|
||
remoteHashes := []string{} | ||
for _, e := range events { | ||
if e.IsCancelled { | ||
|
@@ -521,7 +506,7 @@ func (m *mscalendar) setStatusOrAskUser(user *store.User, currentStatus *model.S | |
|
||
if !isFree { | ||
toSet = model.StatusDnd | ||
if user.Settings.UpdateStatusFromOptions == AwayStatusOption { | ||
if user.Settings.UpdateStatusFromOptions == store.AwayStatusOption { | ||
toSet = model.StatusAway | ||
} | ||
if !user.Settings.GetConfirmation { | ||
|
@@ -660,27 +645,32 @@ func (m *mscalendar) notifyUpcomingEvents(mattermostUserID string, events []*rem | |
} | ||
} | ||
|
||
func filterBusyEvents(events []*remote.Event) []*remote.Event { | ||
func filterBusyAndAttendeeEvents(events []*remote.Event) []*remote.Event { | ||
result := []*remote.Event{} | ||
for _, e := range events { | ||
if e.ShowAs == "busy" && !e.IsCancelled { | ||
// Not setting custom status for events without attendees since those are unlikely to be meetings. | ||
if e.ShowAs == "busy" && !e.IsCancelled && len(e.Attendees) >= 1 { | ||
result = append(result, e) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
// Function to check for overlapping events. | ||
func checkOverlappingEvents(events []*remote.Event) bool { | ||
// getMergedEvents accepts a sorted array of events, and returns events after merging them, if overlapping or if the meeting duration is less than StatusSyncJobInterval. | ||
func getMergedEvents(events []*remote.Event) []*remote.Event { | ||
if len(events) <= 1 { | ||
return false | ||
return events | ||
} | ||
|
||
idx := 0 | ||
for i := 1; i < len(events); i++ { | ||
if events[i-1].End.Time().UnixMicro() > events[i].Start.Time().UnixMicro() { | ||
return true | ||
if (events[idx].End.Time().UnixMicro() >= events[i].Start.Time().UnixMicro()) || (events[idx].End.Time().Sub(events[idx].Start.Time()) <= StatusSyncJobInterval && events[i].Start.Time().Sub(events[idx].End.Time()) <= StatusSyncJobInterval) { | ||
events[idx].End = events[i].End | ||
} else { | ||
idx++ | ||
events[idx] = events[i] | ||
} | ||
} | ||
|
||
return false | ||
return events[0 : idx+1] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to put the body of this loop in its own function, and have it unit tested to show/document how it works There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mickmister Added a comment to it. I don't think we need to separately test the function as it is already covered by its parent function. |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would expect these methods to be defined on
user.Settings
, though I don't think it matters. This current way allows for less typing throughout the usages of the method