|
1 | 1 | {-# LANGUAGE OverloadedRecordDot #-} |
2 | 2 | {-# LANGUAGE OverloadedStrings #-} |
3 | 3 |
|
4 | | -module WriteiCal (saveICal) where |
| 4 | +module WriteiCal (saveMultipleICals) where |
5 | 5 |
|
6 | 6 | import Data.ByteString.Lazy.Char8 qualified as BSL |
7 | 7 | import Data.Default |
| 8 | +import Data.Foldable (traverse_) |
8 | 9 | import Data.Function ((&)) |
9 | 10 | import Data.Map.Strict as M |
10 | 11 | import Data.Text qualified as TS |
@@ -54,49 +55,65 @@ emptyVEvent = |
54 | 55 | veOther = def |
55 | 56 | } |
56 | 57 |
|
57 | | -toVCal :: Day -> [IDandSubj] -> VCalendar |
58 | | -toVCal weekStartDay subjects = |
59 | | - emptyVCalendar |
60 | | - { vcEvents = vEventMap |
61 | | - } |
| 58 | +toVCal :: Day -> [IDandSubj] -> IO VCalendar |
| 59 | +toVCal weekStartDay subjects = do |
| 60 | + emap <- vEventMap |
| 61 | + pure $ |
| 62 | + emptyVCalendar |
| 63 | + { vcEvents = emap |
| 64 | + } |
62 | 65 | where |
63 | | - vEventMap :: Map (TL.Text, Maybe (Either Date DateTime)) VEvent |
64 | | - vEventMap = ((\(txt, ev) -> ((txt, Nothing), ev)) <$> vEventList) & M.fromList |
| 66 | + vEventMap :: IO (Map (TL.Text, Maybe (Either Date DateTime)) VEvent) |
| 67 | + vEventMap = do |
| 68 | + elist <- vEventList |
| 69 | + pure $ ((\(txt, ev) -> ((txt, Nothing), ev)) <$> elist) & M.fromList |
65 | 70 |
|
66 | | - vEventList :: [(TL.Text, VEvent)] |
67 | | - vEventList = concatMap idandsubjToVEvents subjects |
| 71 | + vEventList :: IO [(TL.Text, VEvent)] |
| 72 | + vEventList = concat <$> traverse idandsubjToVEvents subjects |
68 | 73 |
|
69 | | - idandsubjToVEvents :: IDandSubj -> [(TL.Text, VEvent)] |
70 | | - idandsubjToVEvents (IDandSubj (subId, subj)) = fmap (classToEvent subId subj.subjName subj.subjProfessor) subj.subjclasses |
| 74 | + idandsubjToVEvents :: IDandSubj -> IO [(TL.Text, VEvent)] |
| 75 | + idandsubjToVEvents (IDandSubj (subId, subj)) = traverse (classToEvent subId subj.subjName subj.subjProfessor) subj.subjclasses |
71 | 76 |
|
72 | | - classToEvent :: TS.Text -> TS.Text -> TS.Text -> Class -> (TL.Text, VEvent) -- T.Text: UID value |
73 | | - classToEvent subId name teacher individualClass = |
74 | | - ( uidText, |
75 | | - emptyVEvent |
76 | | - { veSummary = |
77 | | - Just $ |
78 | | - Summary |
79 | | - { summaryValue = TL.fromStrict (name <> "(" <> subId <> ")"), |
80 | | - summaryLanguage = def, |
81 | | - summaryAltRep = def, |
82 | | - summaryOther = def |
83 | | - }, |
84 | | - veUID = UID uidText def, |
85 | | - veDTStart = Just startDatetime, |
86 | | - veDTEndDuration = Just $ Left endDatetime, |
87 | | - veDescription = |
88 | | - Just $ |
89 | | - Description |
90 | | - { descriptionValue = TL.fromStrict teacher, |
91 | | - descriptionLanguage = def, |
92 | | - descriptionAltRep = def, |
93 | | - descriptionOther = def |
94 | | - } |
95 | | - } |
96 | | - ) |
| 77 | + classToEvent :: TS.Text -> TS.Text -> TS.Text -> Class -> IO (TL.Text, VEvent) -- T.Text: UID value |
| 78 | + classToEvent subId name teacher individualClass = do |
| 79 | + uidText <- getUidText |
| 80 | + pure $ |
| 81 | + ( uidText, |
| 82 | + emptyVEvent |
| 83 | + { veSummary = |
| 84 | + Just $ |
| 85 | + Summary |
| 86 | + { summaryValue = TL.fromStrict (name <> "(" <> subId <> ")"), |
| 87 | + summaryLanguage = def, |
| 88 | + summaryAltRep = def, |
| 89 | + summaryOther = def |
| 90 | + }, |
| 91 | + veUID = UID uidText def, |
| 92 | + veDTStart = Just startDatetime, |
| 93 | + veDTEndDuration = Just $ Left endDatetime, |
| 94 | + veDescription = |
| 95 | + Just $ |
| 96 | + Description |
| 97 | + { descriptionValue = TL.fromStrict teacher, |
| 98 | + descriptionLanguage = def, |
| 99 | + descriptionAltRep = def, |
| 100 | + descriptionOther = def |
| 101 | + } |
| 102 | + } |
| 103 | + ) |
97 | 104 | where |
98 | | - uidText :: TL.Text |
99 | | - uidText = TL.fromStrict subId <> TL.pack (show $ getClassDayOffset individualClass) |
| 105 | + getUidText :: IO TL.Text |
| 106 | + getUidText = do |
| 107 | + time <- TL.pack . show <$> getSystemTime |
| 108 | + let res = |
| 109 | + TL.fromStrict subId |
| 110 | + <> "-" |
| 111 | + <> TL.replace " " "_" (TL.fromStrict name) |
| 112 | + <> "-" |
| 113 | + <> TL.pack (show $ getClassDayOffset individualClass) |
| 114 | + <> "-" |
| 115 | + <> time |
| 116 | + pure res |
100 | 117 |
|
101 | 118 | dayOfClass :: Day |
102 | 119 | dayOfClass = addDays (getClassDayOffset individualClass) weekStartDay |
@@ -136,11 +153,19 @@ renderICal :: [IDandSubj] -> IO BSL.ByteString |
136 | 153 | renderICal idAndSubj = do |
137 | 154 | (LocalTime today _) <- getLocalTime |
138 | 155 | let nextMonday = addDays 1 $ sundayAfter today |
139 | | - let vcal = toVCal nextMonday idAndSubj |
| 156 | + vcal <- toVCal nextMonday idAndSubj |
140 | 157 | pure $ printICalendar def vcal |
141 | 158 |
|
142 | | - |
143 | 159 | saveICal :: [IDandSubj] -> FilePath -> IO () |
144 | 160 | saveICal idAndSubj filepath = do |
145 | 161 | renderedICal <- renderICal idAndSubj |
146 | 162 | BSL.writeFile filepath renderedICal |
| 163 | + |
| 164 | +saveMultipleICals :: [[IDandSubj]] -> IO () |
| 165 | +saveMultipleICals schedules = traverse_ (uncurry saveICal) schedulesWithNames |
| 166 | + where |
| 167 | + joinLists :: [IDandSubj] -> Int -> ([IDandSubj], FilePath) |
| 168 | + joinLists singleSchedule scheduleNumber = (singleSchedule, "schedule" <> show scheduleNumber <> ".ics") |
| 169 | + |
| 170 | + schedulesWithNames :: [([IDandSubj], FilePath)] |
| 171 | + schedulesWithNames = zipWith joinLists schedules [1 ..] |
0 commit comments