Add WegaBorad bot
I'm just committing all unstaged files so they don't get lost when I delete this repo.
This commit is contained in:
parent
b93f7f38ec
commit
133152286e
1 changed files with 111 additions and 0 deletions
111
WegaBorad.hs
Normal file
111
WegaBorad.hs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module Haboli.Euphoria.WegaBorad where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import Control.Monad.Trans.Class
|
||||||
|
import Control.Monad.Trans.State
|
||||||
|
import Data.Char
|
||||||
|
import Data.Foldable
|
||||||
|
import Data.List
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Haboli.Euphoria.Api
|
||||||
|
import Haboli.Euphoria.Client
|
||||||
|
|
||||||
|
{- Range stuff -}
|
||||||
|
|
||||||
|
data Range = Range Char Char
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance Show Range where
|
||||||
|
show (Range a b)
|
||||||
|
| a == b = [a]
|
||||||
|
| otherwise = "[" ++ [a] ++ ".." ++ [b] ++ "]"
|
||||||
|
|
||||||
|
letterRange :: Char -> Char -> Range
|
||||||
|
letterRange a b =
|
||||||
|
let realA = chr $ max (ord 'a') $ min (ord 'z') $ ord a
|
||||||
|
realB = chr $ max (ord 'a') $ min (ord 'z') $ ord b
|
||||||
|
in Range realA realB
|
||||||
|
|
||||||
|
fullRange :: Range
|
||||||
|
fullRange = Range 'a' 'z'
|
||||||
|
|
||||||
|
getRangeChar :: Range -> Maybe Char
|
||||||
|
getRangeChar (Range a b)
|
||||||
|
| a == b = Just a
|
||||||
|
| otherwise = Nothing
|
||||||
|
|
||||||
|
splitRange :: Int -> Range -> [Range]
|
||||||
|
splitRange steps (Range a b) =
|
||||||
|
let amount = ord b - ord a + 1
|
||||||
|
width = amount `div` steps
|
||||||
|
leftover = amount `mod` steps
|
||||||
|
widths = zipWith (+) (replicate steps width) (replicate leftover 1 ++ repeat 0)
|
||||||
|
skips = scanl (+) 0 (init widths)
|
||||||
|
in nub $ zipWith (\s w -> letterRange (chr $ ord a + s) (chr $ ord a + s + w - 1)) skips widths
|
||||||
|
|
||||||
|
{- Bot logic -}
|
||||||
|
|
||||||
|
data Search = Search
|
||||||
|
{ searchStartMsg :: Message
|
||||||
|
, searchOptions :: Map.Map Snowflake Range
|
||||||
|
} deriving (Show)
|
||||||
|
|
||||||
|
data MyState = MyState
|
||||||
|
{ msSplitInto :: Int
|
||||||
|
, msCurrentSearch :: Maybe Search
|
||||||
|
} deriving (Show)
|
||||||
|
|
||||||
|
defaultState :: MyState
|
||||||
|
defaultState = MyState 3 Nothing
|
||||||
|
|
||||||
|
type MyClient a = StateT MyState (Client ()) a
|
||||||
|
|
||||||
|
wegaBot :: MyClient ()
|
||||||
|
wegaBot = forever $ do
|
||||||
|
event <- lift $ respondingToPing nextEvent
|
||||||
|
case event of
|
||||||
|
EventSnapshot _ -> void $ lift $ nick "WegaBot"
|
||||||
|
EventSend e -> onMessage (sendMessage e)
|
||||||
|
_ -> pure ()
|
||||||
|
|
||||||
|
runWegaBot :: MyState -> MyClient a -> Client () a
|
||||||
|
runWegaBot start bot = fst <$> runStateT bot start
|
||||||
|
|
||||||
|
onMessage :: Message -> MyClient ()
|
||||||
|
onMessage msg
|
||||||
|
| msgContent msg == "!wega" = startNewWega msg
|
||||||
|
| otherwise = do
|
||||||
|
s <- get
|
||||||
|
for_ (msCurrentSearch s) $ \search -> do
|
||||||
|
let maybeRange = do
|
||||||
|
parent <- msgParent msg
|
||||||
|
searchOptions search Map.!? parent
|
||||||
|
for_ maybeRange $ closeInOn search msg
|
||||||
|
|
||||||
|
startNewWega :: Message -> MyClient ()
|
||||||
|
startNewWega msg = do
|
||||||
|
startMsg <- lift $ reply msg "New character!"
|
||||||
|
closeInOn (Search msg Map.empty) startMsg fullRange
|
||||||
|
|
||||||
|
-- | @'closeInOn' search msg range@ closes in on the currently running @search@,
|
||||||
|
-- where @msg@ has just selected @range@.
|
||||||
|
closeInOn :: Search -> Message -> Range -> MyClient ()
|
||||||
|
closeInOn search msg range =
|
||||||
|
case getRangeChar range of
|
||||||
|
Just char -> do
|
||||||
|
void $ lift $ reply msg $ "You've selected " <> T.pack (show char)
|
||||||
|
startNewWega $ searchStartMsg search
|
||||||
|
Nothing -> do
|
||||||
|
s <- get
|
||||||
|
let possibleRanges = splitRange (msSplitInto s) range
|
||||||
|
rangesWithMessageIds <- mapM (sendRange msg) possibleRanges
|
||||||
|
let options = Map.fromList rangesWithMessageIds
|
||||||
|
put s{msCurrentSearch = Just search{searchOptions = options}}
|
||||||
|
|
||||||
|
sendRange :: Message -> Range -> MyClient (Snowflake, Range)
|
||||||
|
sendRange msg range = do
|
||||||
|
msg' <- lift $ reply msg $ "Reply to this message to choose " <> T.pack (show range) <> "."
|
||||||
|
pure (msgId msg', range)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue