diff --git a/server/channels/app/email/email_batching.go b/server/channels/app/email/email_batching.go index 5a0585b2ef..3d9fac3cc7 100644 --- a/server/channels/app/email/email_batching.go +++ b/server/channels/app/email/email_batching.go @@ -17,6 +17,7 @@ import ( "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/i18n" "github.com/mattermost/mattermost/server/public/shared/mlog" + "github.com/mattermost/mattermost/server/v8/channels/utils" ) const ( @@ -278,6 +279,13 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []* } } + var useMilitaryTime bool + if data, err := es.store.Preference().Get(user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameUseMilitaryTime); err != nil { + useMilitaryTime = false + } else { + useMilitaryTime = data.Value == "true" + } + if emailNotificationContentsType == model.EmailNotificationContentsFull { for i, notification := range notifications { sender, errSender := es.userService.GetUser(notification.post.UserId) @@ -300,17 +308,9 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []* embeddedFiles[senderPhoto] = bytes.NewReader(senderProfileImage) } - tm := time.Unix(notification.post.CreateAt/1000, 0) - timezone, _ := tm.Zone() + formattedTime := utils.GetFormattedPostTime(user, notification.post, useMilitaryTime, translateFunc) - t := translateFunc("api.email_batching.send_batched_email_notification.time", map[string]any{ - "Hour": tm.Hour(), - "Minute": fmt.Sprintf("%02d", tm.Minute()), - "Month": translateFunc(tm.Month().String()), - "Day": tm.Day(), - "Year": tm.Year(), - "TimeZone": timezone, - }) + t := translateFunc("api.email_batching.send_batched_email_notification.time", formattedTime) MessageURL := siteURL + "/" + notification.teamName + "/pl/" + notification.post.Id @@ -346,13 +346,13 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []* } } - tm := time.Unix(notifications[0].post.CreateAt/1000, 0) + formattedTime := utils.GetFormattedPostTime(user, notifications[0].post, useMilitaryTime, translateFunc) subject := translateFunc("api.email_batching.send_batched_email_notification.subject", len(notifications), map[string]any{ "SiteName": es.config().TeamSettings.SiteName, - "Year": tm.Year(), - "Month": translateFunc(tm.Month().String()), - "Day": tm.Day(), + "Year": formattedTime.Year, + "Month": formattedTime.Month, + "Day": formattedTime.Day, }) data := es.NewEmailTemplateData(user.Locale) diff --git a/server/channels/app/notification_email.go b/server/channels/app/notification_email.go index afd67ab2bd..a7ad3e3cf7 100644 --- a/server/channels/app/notification_email.go +++ b/server/channels/app/notification_email.go @@ -9,9 +9,7 @@ import ( "html" "html/template" "io" - "strconv" "strings" - "time" "github.com/pkg/errors" @@ -148,7 +146,7 @@ func (a *App) sendNotificationEmail(c request.CTX, notification *PostNotificatio * Computes the subject line for direct notification email messages */ func getDirectMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, senderName string, useMilitaryTime bool) string { - t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc) + t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc) var subjectParameters = map[string]any{ "SiteName": siteName, "SenderDisplayName": senderName, @@ -163,7 +161,7 @@ func getDirectMessageNotificationEmailSubject(user *model.User, post *model.Post * Computes the subject line for group, public, and private email messages */ func getNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, teamName string, useMilitaryTime bool) string { - t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc) + t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc) var subjectParameters = map[string]any{ "SiteName": siteName, "TeamName": teamName, @@ -178,7 +176,7 @@ func getNotificationEmailSubject(user *model.User, post *model.Post, translateFu * Computes the subject line for group email messages */ func getGroupMessageNotificationEmailSubject(user *model.User, post *model.Post, translateFunc i18n.TranslateFunc, siteName string, channelName string, emailNotificationContentsType string, useMilitaryTime bool) string { - t := getFormattedPostTime(user, post, useMilitaryTime, translateFunc) + t := utils.GetFormattedPostTime(user, post, useMilitaryTime, translateFunc) var subjectParameters = map[string]any{ "SiteName": siteName, "Month": t.Month, @@ -226,7 +224,7 @@ func (a *App) getNotificationEmailBody(c request.CTX, recipient *model.User, pos SenderPhoto: senderPhoto, } - t := getFormattedPostTime(recipient, post, useMilitaryTime, translateFunc) + t := utils.GetFormattedPostTime(recipient, post, useMilitaryTime, translateFunc) messageTime := map[string]any{ "Hour": t.Hour, "Minute": t.Minute, @@ -311,48 +309,6 @@ func (a *App) getNotificationEmailBody(c request.CTX, recipient *model.User, pos return a.Srv().TemplatesContainer().RenderToString("messages_notification", data) } -type formattedPostTime struct { - Time time.Time - Year string - Month string - Day string - Hour string - Minute string - TimeZone string -} - -func getFormattedPostTime(user *model.User, post *model.Post, useMilitaryTime bool, translateFunc i18n.TranslateFunc) formattedPostTime { - preferredTimezone := user.GetPreferredTimezone() - postTime := time.Unix(post.CreateAt/1000, 0) - zone, _ := postTime.Zone() - - localTime := postTime - if preferredTimezone != "" { - loc, _ := time.LoadLocation(preferredTimezone) - if loc != nil { - localTime = postTime.In(loc) - zone, _ = localTime.Zone() - } - } - - hour := localTime.Format("15") - period := "" - if !useMilitaryTime { - hour = localTime.Format("3") - period = " " + localTime.Format("PM") - } - - return formattedPostTime{ - Time: localTime, - Year: strconv.Itoa(localTime.Year()), - Month: translateFunc(localTime.Month().String()), - Day: strconv.Itoa(localTime.Day()), - Hour: hour, - Minute: fmt.Sprintf("%02d"+period, localTime.Minute()), - TimeZone: zone, - } -} - func (a *App) generateHyperlinkForChannels(c request.CTX, postMessage, teamName, teamURL string) (string, *model.AppError) { team, err := a.GetTeamByName(teamName) if err != nil { diff --git a/server/channels/app/notification_email_test.go b/server/channels/app/notification_email_test.go index ce6f376e7b..ea983d0c3d 100644 --- a/server/channels/app/notification_email_test.go +++ b/server/channels/app/notification_email_test.go @@ -18,6 +18,7 @@ import ( "github.com/mattermost/mattermost/server/public/shared/i18n" "github.com/mattermost/mattermost/server/public/shared/timezones" "github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks" + "github.com/mattermost/mattermost/server/v8/channels/utils" ) func TestGetDirectMessageNotificationEmailSubject(t *testing.T) { @@ -255,7 +256,7 @@ func TestGetNotificationEmailBodyFullNotificationLocaleTimeNoTimezone(t *testing tm := time.Unix(post.CreateAt/1000, 0) zone, _ := tm.Zone() - formattedTime := formattedPostTime{ + formattedTime := utils.FormattedPostTime{ Hour: fmt.Sprintf("%02d", tm.Hour()), Minute: fmt.Sprintf("%02d", tm.Minute()), TimeZone: zone, diff --git a/server/channels/utils/time.go b/server/channels/utils/time.go index 7843fe4977..1768b7fe81 100644 --- a/server/channels/utils/time.go +++ b/server/channels/utils/time.go @@ -4,7 +4,12 @@ package utils import ( + "fmt" + "strconv" "time" + + "github.com/mattermost/mattermost/server/public/model" + "github.com/mattermost/mattermost/server/public/shared/i18n" ) func MillisFromTime(t time.Time) int64 { @@ -28,3 +33,45 @@ func EndOfDay(t time.Time) time.Time { func Yesterday() time.Time { return time.Now().AddDate(0, 0, -1) } + +type FormattedPostTime struct { + Time time.Time + Year string + Month string + Day string + Hour string + Minute string + TimeZone string +} + +func GetFormattedPostTime(user *model.User, post *model.Post, useMilitaryTime bool, translateFunc i18n.TranslateFunc) FormattedPostTime { + preferredTimezone := user.GetPreferredTimezone() + postTime := time.Unix(post.CreateAt/1000, 0) + zone, _ := postTime.Zone() + + localTime := postTime + if preferredTimezone != "" { + loc, _ := time.LoadLocation(preferredTimezone) + if loc != nil { + localTime = postTime.In(loc) + zone, _ = localTime.Zone() + } + } + + hour := localTime.Format("15") + period := "" + if !useMilitaryTime { + hour = localTime.Format("3") + period = " " + localTime.Format("PM") + } + + return FormattedPostTime{ + Time: localTime, + Year: strconv.Itoa(localTime.Year()), + Month: translateFunc(localTime.Month().String()), + Day: strconv.Itoa(localTime.Day()), + Hour: hour, + Minute: fmt.Sprintf("%02d"+period, localTime.Minute()), + TimeZone: zone, + } +}