@@ -69,7 +69,7 @@ import Data.Time.Format.Internal (buildTime)
69
69
import Data.Typeable (Typeable )
70
70
import Distribution.Text (display )
71
71
import Network.Mail.Mime
72
- import Network.URI (uriAuthority , uriRegName , uriToString )
72
+ import Network.URI (uriAuthority , uriPath , uriRegName )
73
73
import Text.CSV (CSV , Record )
74
74
import Text.PrettyPrint hiding ((<>) )
75
75
import Text.XHtml hiding (base , text , (</>) )
@@ -683,19 +683,19 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
683
683
684
684
revisionsAndUploads <- collectRevisionsAndUploads trimLastTime now
685
685
revisionUploadNotifications <- foldM (genRevUploadList notifyPrefs) Map. empty revisionsAndUploads
686
- let revisionUploadEmails = map (describeRevision users trimLastTime now) <$> revisionUploadNotifications
686
+ let revisionUploadEmails = foldMap (describeRevision users trimLastTime now) <$> revisionUploadNotifications
687
687
688
688
groupActions <- collectAdminActions trimLastTime now
689
689
groupActionNotifications <- foldM (genGroupUploadList notifyPrefs) Map. empty groupActions
690
- let groupActionEmails = mapMaybe (describeGroupAction users) <$> groupActionNotifications
690
+ let groupActionEmails = mconcat . mapMaybe (describeGroupAction users) <$> groupActionNotifications
691
691
692
692
docReports <- collectDocReport trimLastTime now
693
693
docReportNotifications <- foldM (genDocReportList notifyPrefs) Map. empty docReports
694
- let docReportEmails = map describeDocReport <$> docReportNotifications
694
+ let docReportEmails = foldMap describeDocReport <$> docReportNotifications
695
695
696
696
tagProposals <- collectTagProposals
697
697
tagProposalNotifications <- foldM (genTagProposalList notifyPrefs) Map. empty tagProposals
698
- let tagProposalEmails = map describeTagProposal <$> tagProposalNotifications
698
+ let tagProposalEmails = foldMap describeTagProposal <$> tagProposalNotifications
699
699
700
700
idx <- queryGetPackageIndex
701
701
revIdx <- liftIO queryReverseIndex
@@ -704,7 +704,7 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
704
704
705
705
-- Concat the constituent email parts such that only one email is sent per user
706
706
mapM_ (sendNotifyEmailAndDelay users) . Map. toList $
707
- fmap (" Maintainer Notifications" ,) . foldr1 (Map. unionWith (++ ) ) $
707
+ fmap (" Maintainer Notifications" ,) . foldr1 (Map. unionWith (<> ) ) $
708
708
[ revisionUploadEmails
709
709
, groupActionEmails
710
710
, docReportEmails
@@ -719,6 +719,13 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
719
719
720
720
updateState notifyState (SetNotifyTime now)
721
721
722
+ renderPkgLink pkg =
723
+ EmailContentLink
724
+ (T. pack $ display pkg)
725
+ serverBaseURI
726
+ { uriPath = " /package/" <> display (packageName pkg) <> " -" <> display (packageVersion pkg)
727
+ }
728
+
722
729
formatTimeUser users t u =
723
730
EmailContentText . T. pack $
724
731
display (Users. userIdToName users u) ++ " [" ++
@@ -810,21 +817,24 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
810
817
811
818
describeRevision users earlier now pkg
812
819
| pkgNumRevisions pkg <= 1 =
813
- " Package upload, " <> emailContentDisplay (packageName pkg) <> " , by " <>
820
+ EmailContentParagraph $
821
+ " Package upload, " <> renderPkgLink (pkgInfoId pkg) <> " , by " <>
814
822
formatTimeUser users (pkgLatestUploadTime pkg) (pkgLatestUploadUser pkg)
815
823
| otherwise =
816
- " Package metadata revision(s), " <> emailContentDisplay (packageName pkg) <> " :" <> EmailContentSoftBreak
817
- <> foldMap ( <> EmailContentSoftBreak ) (map (uncurry (formatTimeUser users) . snd ) recentRevs)
824
+ EmailContentParagraph ( " Package metadata revision(s), " <> renderPkgLink (pkgInfoId pkg) <> " :" )
825
+ <> EmailContentList (map (uncurry (formatTimeUser users) . snd ) recentRevs)
818
826
where
819
827
revs = reverse $ Vec. toList (pkgMetadataRevisions pkg)
820
828
recentRevs = filter ((\ x -> x > earlier && x <= now) . fst . snd ) revs
821
829
822
830
describeGroupAction users (time, uid, act, reason) =
823
831
fmap
824
832
( \ message ->
825
- " Group modified by " <> formatTimeUser users time uid <> " :" <> EmailContentSoftBreak
826
- <> message <> EmailContentSoftBreak
827
- <> " Reason: " <> emailContentLBS reason
833
+ EmailContentParagraph (" Group modified by " <> formatTimeUser users time uid <> " :" )
834
+ <> EmailContentList
835
+ [ message
836
+ , " Reason: " <> emailContentLBS reason
837
+ ]
828
838
)
829
839
$ case act of
830
840
(Admin_GroupAddUser tn (MaintainerGroup pkg)) ->
@@ -840,28 +850,32 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
840
850
_ -> Nothing
841
851
842
852
describeDocReport (pkg, success) =
843
- " Package doc build for " <> emailContentDisplay (packageName pkg) <> " :" <> EmailContentSoftBreak <>
844
- if success
845
- then " Build successful."
846
- else " Build failed."
853
+ EmailContentParagraph $
854
+ " Package doc build for " <> emailContentDisplay (packageName pkg) <> " :" <> EmailContentSoftBreak <>
855
+ if success
856
+ then " Build successful."
857
+ else " Build failed."
847
858
848
859
describeTagProposal (pkgName, (addTags, delTags)) =
849
- " Pending tag proposal for " <> emailContentDisplay pkgName <> " :" <> EmailContentSoftBreak
850
- <> " Additions: " <> showTags addTags <> EmailContentSoftBreak
851
- <> " Deletions: " <> showTags delTags
860
+ EmailContentParagraph (" Pending tag proposal for " <> emailContentDisplay pkgName <> " :" )
861
+ <> EmailContentList
862
+ [ " Additions: " <> showTags addTags
863
+ , " Deletions: " <> showTags delTags
864
+ ]
852
865
where
853
866
showTags = emailContentIntercalate " , " . map emailContentDisplay . Set. toList
854
867
855
868
describeDependencyUpdate (uId, dep) revDeps = do
856
869
mPrefs <- queryGetUserNotifyPref uId
857
870
pure $
858
871
case mPrefs of
859
- Nothing -> []
872
+ Nothing -> mempty
860
873
Just NotifyPref {notifyDependencyTriggerBounds} ->
861
874
let depName = emailContentDisplay (packageName dep)
862
875
depVersion = emailContentDisplay (packageVersion dep)
863
876
in
864
- [ " The dependency " <> emailContentDisplay dep <> " has been uploaded or revised."
877
+ foldMap EmailContentParagraph
878
+ [ " The dependency " <> renderPkgLink dep <> " has been uploaded or revised."
865
879
, case notifyDependencyTriggerBounds of
866
880
Always ->
867
881
" You have requested to be notified for each upload or revision \
@@ -880,9 +894,9 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
880
894
<> " but don't accept " <> depVersion
881
895
<> " (they do accept the second-highest version):"
882
896
]
883
- ++ map emailContentDisplay revDeps
897
+ <> EmailContentList ( map renderPkgLink revDeps)
884
898
885
- sendNotifyEmailAndDelay :: Users. Users -> (UserId , (T. Text , [ EmailContent ] )) -> IO ()
899
+ sendNotifyEmailAndDelay :: Users. Users -> (UserId , (T. Text , EmailContent )) -> IO ()
886
900
sendNotifyEmailAndDelay users (uid, (subject, emailContent)) = do
887
901
mudetails <- queryUserDetails uid
888
902
case mudetails of
@@ -894,9 +908,7 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
894
908
mailTo = [Address (Just aname) eml],
895
909
mailHeaders = [(BSS. pack " Subject" , " [Hackage] " <> subject)],
896
910
mailParts =
897
- [ fromEmailContent $
898
- foldMap EmailContentParagraph $
899
- emailContent <> [updatePreferencesText]
911
+ [ fromEmailContent $ emailContent <> updatePreferencesText
900
912
]
901
913
}
902
914
Just ourHost = uriAuthority serverBaseURI
@@ -906,10 +918,14 @@ userNotifyFeature ServerEnv{serverBaseURI, serverCron}
906
918
threadDelay 250000
907
919
where
908
920
updatePreferencesText =
921
+ EmailContentParagraph $
909
922
" You can adjust your notification preferences at" <> EmailContentSoftBreak
910
- <> (EmailContentText . T. pack)
911
- ( uriToString id serverBaseURI " "
912
- <> " /user/"
913
- <> display (Users. userIdToName users uid)
914
- <> " /notify"
915
- )
923
+ <> emailContentUrl
924
+ serverBaseURI
925
+ { uriPath =
926
+ concatMap (" /" <> )
927
+ [ " user"
928
+ , display $ Users. userIdToName users uid
929
+ , " notify"
930
+ ]
931
+ }
0 commit comments