-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
58 lines (47 loc) · 1.9 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import System.Process (readProcess, runCommand)
import Data.List (find, stripPrefix, isPrefixOf)
import Data.Text (strip, pack, unpack)
import Text.Printf (printf)
import System.Process.Internals (ProcessHandle(ProcessHandle))
import Control.Monad.Trans.Maybe (MaybeT(MaybeT, runMaybeT))
import Control.Concurrent (threadDelay)
import Control.Monad (when)
import Control.Monad.Cont (void)
import Data.Char (toUpper)
strip' :: String -> String
strip' = unpack . strip . pack
readBatteryInfo :: IO String
readBatteryInfo = readProcess "system_profiler" ["SPPowerDataType"] []
readBatteryStat :: String -> IO (Maybe String)
readBatteryStat prefix = do
stats <- fmap strip' . lines <$> readBatteryInfo
return $ find (isPrefixOf prefix) stats >>= stripPrefix prefix
readBatteryLevel :: IO (Maybe Float)
readBatteryLevel = fmap read <$> readBatteryStat "State of Charge (%): "
readBatteryChargingStatus :: IO (Maybe Bool)
readBatteryChargingStatus = fmap (=="Yes") <$> readBatteryStat "Charging: "
notificationBody :: Float -> String -> String
notificationBody = printf "Battery level is at %.0f%%. Time to %s!"
notificationHeader :: String -> String
notificationHeader (head:tail) = printf "%s Computer" (toUpper head:tail)
notifyCommand :: Float -> String -> String
notifyCommand level =
printf "osascript -e 'display notification \"%s\" with title \"%s\"'" <$>
notificationBody level <*>
notificationHeader
notifyIfLow :: IO (Maybe ())
notifyIfLow = runMaybeT $ do
level <- MaybeT readBatteryLevel
isCharging <- MaybeT readBatteryChargingStatus
if level > 60 && isCharging then
notify level "unplug"
else when (level < 40 && not isCharging) $
notify level "plug in"
where notify level action = MaybeT $ void . Just <$> runCommand (notifyCommand level action)
sleepDuration :: Int
sleepDuration = 1000000 * 60 * 5
main :: IO ()
main = do
notifyIfLow
threadDelay sleepDuration
main