summaryrefslogtreecommitdiff
path: root/deps/discord-haskell/examples/state-counter.hs
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2023-11-16 19:06:43 -0500
committerLLLL Colonq <llll@colonq>2023-11-16 19:06:43 -0500
commitdcef0b65069fb38fd0f6c4382353167f603ebff1 (patch)
tree45954ffe308c3dd056e6af4f734e6d2af89e5856 /deps/discord-haskell/examples/state-counter.hs
Initial commit
Diffstat (limited to 'deps/discord-haskell/examples/state-counter.hs')
-rw-r--r--deps/discord-haskell/examples/state-counter.hs75
1 files changed, 75 insertions, 0 deletions
diff --git a/deps/discord-haskell/examples/state-counter.hs b/deps/discord-haskell/examples/state-counter.hs
new file mode 100644
index 0000000..f017d9c
--- /dev/null
+++ b/deps/discord-haskell/examples/state-counter.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+import Control.Monad (when, void, forever)
+import UnliftIO (try, IOException) -- liftIO
+import UnliftIO.MVar
+import UnliftIO.Chan
+import UnliftIO.Concurrent (forkIO, killThread)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Discord
+import Discord.Types
+import qualified Discord.Requests as R
+
+import ExampleUtils (getToken)
+
+main :: IO ()
+main = stateExample
+
+data State = State { pingCount :: Integer }
+ deriving (Show, Read, Eq, Ord)
+
+-- | Counts how many pings we've seen across sessions
+stateExample :: IO ()
+stateExample = do
+ tok <- getToken
+
+ -- eventHandler is called concurrently, need to sync stdout
+ printQueue <- newChan :: IO (Chan T.Text)
+ threadId <- forkIO $ forever $ readChan printQueue >>= TIO.putStrLn
+
+ -- try to read previous state, otherwise use 0
+ state :: MVar (State) <- do
+ mfile <- try $ read . T.unpack <$> TIO.readFile "./cachedState"
+ s <- case mfile of
+ Right file -> do
+ writeChan printQueue "loaded state from file"
+ pure file
+ Left (_ :: IOException) -> do
+ writeChan printQueue "created new state"
+ pure $ State { pingCount = 0 }
+ newMVar s
+
+ t <- runDiscord $ def { discordToken = tok
+ , discordOnStart = writeChan printQueue "starting ping loop"
+ , discordOnEvent = eventHandler state printQueue
+ , discordOnEnd = do killThread threadId
+ --
+ s <- readMVar state
+ TIO.writeFile "./cachedState" (T.pack (show s))
+ }
+ TIO.putStrLn t
+
+
+eventHandler :: MVar State -> Chan T.Text -> Event -> DiscordHandler ()
+eventHandler state printQueue event = case event of
+ -- respond to message, and modify state
+ MessageCreate m -> when (not (fromBot m) && isPing m) $ do
+ writeChan printQueue "got a ping!"
+
+ s <- takeMVar state
+
+ void $ restCall (R.CreateMessage (messageChannelId m) (T.pack ("Pong #" <> show (pingCount s))))
+
+ putMVar state $ State { pingCount = pingCount s + 1 }
+
+ _ -> pure ()
+
+
+fromBot :: Message -> Bool
+fromBot = userIsBot . messageAuthor
+
+isPing :: Message -> Bool
+isPing = ("ping" `T.isPrefixOf`) . T.toLower . messageContent