Add lenses to listing and use them in the example bot
This commit is contained in:
parent
9a476d9371
commit
822bb9efad
2 changed files with 70 additions and 41 deletions
|
|
@ -1,7 +1,13 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
-- | This module contains an example implementation of a small bot. It is a good
|
||||
-- starting point if you want to create your own bot.
|
||||
--
|
||||
-- The example bot uses lenses for its state because they vastly reduce the
|
||||
-- amount of code required to update the 'Listing' inside the state. It is
|
||||
-- entirely possible to use haboli without lenses though, should you want to do
|
||||
-- that.
|
||||
|
||||
module Haboli.Euphoria.ExampleBot
|
||||
( exampleBot
|
||||
|
|
@ -14,15 +20,19 @@ import Data.List
|
|||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
import Data.Time
|
||||
import Lens.Micro
|
||||
import Lens.Micro.TH
|
||||
|
||||
import Haboli.Euphoria
|
||||
import Haboli.Euphoria.Botrulez
|
||||
|
||||
data BotState = BotState
|
||||
{ botStartTime :: UTCTime
|
||||
, botListing :: Listing
|
||||
{ _botStartTime :: UTCTime
|
||||
, _botListing :: Listing
|
||||
} deriving (Show)
|
||||
|
||||
makeLenses ''BotState
|
||||
|
||||
-- | A small example bot. Takes a room password as its first argument. You can
|
||||
-- run this bot in [&test](https://euphoria.io/room/test) like this:
|
||||
--
|
||||
|
|
@ -33,27 +43,27 @@ exampleBot mPasswd = do
|
|||
initialEvents <- untilConnected $
|
||||
respondingToBounce mPasswd $
|
||||
respondingToPing nextEvent
|
||||
listing <- preferNick "ExampleBot" $ newListing initialEvents
|
||||
stateVar <- liftIO $ newMVar $ BotState startTime listing
|
||||
let initialState = BotState startTime $ newListing initialEvents
|
||||
stateVar <- liftIO $ newMVar initialState
|
||||
preferNickVia botListing stateVar "ExampleBot"
|
||||
botMain stateVar
|
||||
|
||||
botMain :: MVar BotState -> Client T.Text ()
|
||||
botMain stateVar = forever $ do
|
||||
event <- respondingToCommands (getCommands stateVar) $
|
||||
respondingToPing nextEvent
|
||||
-- Update the listing
|
||||
liftIO $ modifyMVar_ stateVar $ \state ->
|
||||
pure state{botListing = updateFromEvent event $ botListing state}
|
||||
updateFromEventVia botListing stateVar event
|
||||
|
||||
getCommands :: MVar BotState -> Client e [Command T.Text]
|
||||
getCommands stateVar = do
|
||||
state <- liftIO $ readMVar stateVar
|
||||
let name = svNick $ self $ botListing state
|
||||
let name = state ^. botListing . lsSelfL . svNickL
|
||||
pure
|
||||
[ botrulezPingGeneral
|
||||
, botrulezPingSpecific name
|
||||
, botrulezHelpSpecific name "I am an example bot for https://github.com/Garmelon/haboli/."
|
||||
, botrulezUptimeSpecific name $ botStartTime state
|
||||
, botrulezHelpSpecific name
|
||||
"I am an example bot for https://github.com/Garmelon/haboli/."
|
||||
, botrulezUptimeSpecific name $ state ^. botStartTime
|
||||
, botrulezKillSpecific name
|
||||
, cmdSpecific "hug" name $ \msg -> void $ reply msg "/me hugs back"
|
||||
, cmdHello
|
||||
|
|
@ -68,15 +78,12 @@ cmdHello = cmdGeneral "hello" $ \msg -> do
|
|||
|
||||
cmdNick :: MVar BotState -> T.Text -> Command e
|
||||
cmdNick stateVar name = cmdSpecificArgs "nick" name $ \msg args -> do
|
||||
-- Update the listing while updating the nick
|
||||
state <- liftIO $ takeMVar stateVar
|
||||
listing' <- preferNick args $ botListing state
|
||||
liftIO $ putMVar stateVar state{botListing = listing'}
|
||||
preferNickVia botListing stateVar args
|
||||
void $ reply msg "Is this better?"
|
||||
|
||||
cmdWho :: MVar BotState -> Command e
|
||||
cmdWho stateVar = cmdGeneral "who" $ \msg -> do
|
||||
state <- liftIO $ readMVar stateVar
|
||||
let people = others $ botListing state
|
||||
let people = state ^. botListing . lsOthersL
|
||||
nicks = sort $ map svNick $ Map.elems people
|
||||
void $ reply msg $ T.intercalate "\n" nicks
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue