{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Proof.Assistant.Bot where

import Control.Concurrent
import Control.Concurrent.Async
import Control.Monad (forever, void)
import Control.Monad.IO.Class (liftIO)
import Data.Coerce (coerce)
import Data.Maybe (isJust)

import Telegram.Bot.API
import Telegram.Bot.Simple
import Telegram.Bot.Simple.UpdateParser

import qualified Data.HashMap.Strict as HashMap

import Proof.Assistant.Helpers
import Proof.Assistant.Interpreter
import Proof.Assistant.Request
import Proof.Assistant.Response
import Proof.Assistant.Settings
import Agda.Interaction.State
import Proof.Assistant.Transport
import Proof.Assistant.Version

-- | Telegram Model.
type Model = BotState

-- | Supported actions by bot.
data Action
  = Call Backend InterpreterRequest  -- ^ Call backend and send request to it.
  | SendBack InterpreterResponse  -- ^ Send response back as reply.
  | Help InterpreterRequest  -- ^ Reply with help message.
  | Version InterpreterRequest  -- ^ Reply with version message.
  | Debug String  -- ^ Write in STDOUT unknown input.

-- | Supported backends.
data Backend = Agda | Arend | Idris | Coq | Lean | Rzk

-- | Initiate bot app based on a 'Model'.
proofAssistantBot :: Model -> BotApp Model Action
proofAssistantBot :: Model -> BotApp Model Action
proofAssistantBot Model
state = BotApp :: forall model action.
model
-> (Update -> model -> Maybe action)
-> (action -> model -> Eff action model)
-> [BotJob model action]
-> BotApp model action
BotApp
  { botInitialModel :: Model
botInitialModel = Model
state
  , botAction :: Update -> Model -> Maybe Action
botAction = (Model -> Update -> Maybe Action)
-> Update -> Model -> Maybe Action
forall a b c. (a -> b -> c) -> b -> a -> c
flip Model -> Update -> Maybe Action
updateToAction
  , botHandler :: Action -> Model -> Eff Action Model
botHandler = Action -> Model -> Eff Action Model
handleAction
  , botJobs :: [BotJob Model Action]
botJobs = []
  }

-- | How to handle updates from Telegram.
updateToAction :: Model -> Update -> Maybe Action
updateToAction :: Model -> Update -> Maybe Action
updateToAction BotState{TBQueue InterpreterResponse
Settings
Interpreters
interpreters :: Model -> Interpreters
botSettings :: Model -> Settings
output :: Model -> TBQueue InterpreterResponse
interpreters :: Interpreters
botSettings :: Settings
output :: TBQueue InterpreterResponse
..} Update
update
  -- interpreters
  | Text -> Update -> Bool
isCommand Text
"coq" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Coq Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"agda" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Agda Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"idris2" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Idris Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"lean" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Lean Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"arend" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Arend Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"rzk" Update
update = Backend -> InterpreterRequest -> Action
Call (Backend -> InterpreterRequest -> Action)
-> Maybe Backend -> Maybe (InterpreterRequest -> Action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Backend -> Maybe Backend
forall a. a -> Maybe a
Just Backend
Rzk Maybe (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  -- other
  | Text -> Update -> Bool
isCommand Text
"help" Update
update = InterpreterRequest -> Action
Help (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Text -> Update -> Bool
isCommand Text
"version" Update
update = InterpreterRequest -> Action
Version (InterpreterRequest -> Action)
-> Maybe InterpreterRequest -> Maybe Action
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Update -> Maybe InterpreterRequest
updateToRequest Update
update
  | Bool
otherwise = Action -> Maybe Action
forall a. a -> Maybe a
Just (Action -> Maybe Action) -> Action -> Maybe Action
forall a b. (a -> b) -> a -> b
$ String -> Action
Debug (String -> Action) -> String -> Action
forall a b. (a -> b) -> a -> b
$ Update -> String
forall a. Show a => a -> String
show Update
update
  where
    Settings{Natural
Text
HashMap Text Text
InterpretersSettings
$sel:interpretersSettings:Settings :: Settings -> InterpretersSettings
$sel:version:Settings :: Settings -> Text
$sel:helpMessages:Settings :: Settings -> HashMap Text Text
$sel:help:Settings :: Settings -> Text
$sel:outputSize:Settings :: Settings -> Natural
$sel:botToken:Settings :: Settings -> Text
$sel:botName:Settings :: Settings -> Text
interpretersSettings :: InterpretersSettings
version :: Text
helpMessages :: HashMap Text Text
help :: Text
outputSize :: Natural
botToken :: Text
botName :: Text
..} = Settings
botSettings
    isCommand :: Text -> Update -> Bool
isCommand Text
cmd = Maybe Text -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Text -> Bool) -> (Update -> Maybe Text) -> Update -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UpdateParser Text -> Update -> Maybe Text
forall a. UpdateParser a -> Update -> Maybe a
parseUpdate (Text -> Text -> UpdateParser Text
commandWithBotName Text
botName Text
cmd)

-- | How to handle actions after parsing updates.
handleAction :: Action -> Model -> Eff Action Model
handleAction :: Action -> Model -> Eff Action Model
handleAction (Call Backend
backend InterpreterRequest
request) Model
model = Model
model Model -> BotM () -> Eff Action Model
forall a action model.
GetAction a action =>
model -> BotM a -> Eff action model
<# do
  IO () -> BotM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> BotM ()) -> IO () -> BotM ()
forall a b. (a -> b) -> a -> b
$ do
    let BotState{TBQueue InterpreterResponse
Settings
Interpreters
interpreters :: Interpreters
botSettings :: Settings
output :: TBQueue InterpreterResponse
interpreters :: Model -> Interpreters
botSettings :: Model -> Settings
output :: Model -> TBQueue InterpreterResponse
..} = Model
model
        Interpreters{InterpreterState IdrisSettings
InterpreterState ArendSettings
InterpreterState LeanSettings
InternalState
ExternalState
AgdaState
rzk :: Interpreters -> InternalState
lean :: Interpreters -> InterpreterState LeanSettings
coq :: Interpreters -> ExternalState
idris :: Interpreters -> InterpreterState IdrisSettings
arend :: Interpreters -> InterpreterState ArendSettings
agda :: Interpreters -> AgdaState
rzk :: InternalState
lean :: InterpreterState LeanSettings
coq :: ExternalState
idris :: InterpreterState IdrisSettings
arend :: InterpreterState ArendSettings
agda :: AgdaState
..} = Interpreters
interpreters
        handle :: InterpreterState settings -> IO ()
handle = InterpreterRequest -> InterpreterState settings -> IO ()
forall settings.
InterpreterRequest -> InterpreterState settings -> IO ()
writeInput InterpreterRequest
request
        handleAgda :: AgdaState -> IO ()
handleAgda = InterpreterState AgdaSettings -> IO ()
forall settings. InterpreterState settings -> IO ()
handle (InterpreterState AgdaSettings -> IO ())
-> (AgdaState -> InterpreterState AgdaSettings)
-> AgdaState
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AgdaState -> InterpreterState AgdaSettings
interpreterState
    case Backend
backend of
      Backend
Agda -> AgdaState -> IO ()
handleAgda AgdaState
agda
      Backend
Arend -> InterpreterState ArendSettings -> IO ()
forall settings. InterpreterState settings -> IO ()
handle InterpreterState ArendSettings
arend
      Backend
Coq -> ExternalState -> IO ()
forall settings. InterpreterState settings -> IO ()
handle ExternalState
coq
      Backend
Idris -> InterpreterState IdrisSettings -> IO ()
forall settings. InterpreterState settings -> IO ()
handle InterpreterState IdrisSettings
idris
      Backend
Lean -> InterpreterState LeanSettings -> IO ()
forall settings. InterpreterState settings -> IO ()
handle InterpreterState LeanSettings
lean
      Backend
Rzk -> InternalState -> IO ()
forall settings. InterpreterState settings -> IO ()
handle InternalState
rzk
handleAction (SendBack InterpreterResponse
response) Model
model = Model
model Model -> BotM () -> Eff Action Model
forall a action model.
GetAction a action =>
model -> BotM a -> Eff action model
<# Bool -> InterpreterResponse -> BotM ()
sendResponseBack Bool
True InterpreterResponse
response
handleAction (Help InterpreterRequest
req) Model
model = Model
model Model -> BotM () -> Eff Action Model
forall a action model.
GetAction a action =>
model -> BotM a -> Eff action model
<# do
  let BotState {TBQueue InterpreterResponse
Settings
Interpreters
interpreters :: Interpreters
botSettings :: Settings
output :: TBQueue InterpreterResponse
interpreters :: Model -> Interpreters
botSettings :: Model -> Settings
output :: Model -> TBQueue InterpreterResponse
..} = Model
model
      Settings{Natural
Text
HashMap Text Text
InterpretersSettings
interpretersSettings :: InterpretersSettings
version :: Text
helpMessages :: HashMap Text Text
help :: Text
outputSize :: Natural
botToken :: Text
botName :: Text
$sel:interpretersSettings:Settings :: Settings -> InterpretersSettings
$sel:version:Settings :: Settings -> Text
$sel:helpMessages:Settings :: Settings -> HashMap Text Text
$sel:help:Settings :: Settings -> Text
$sel:outputSize:Settings :: Settings -> Natural
$sel:botToken:Settings :: Settings -> Text
$sel:botName:Settings :: Settings -> Text
..} = Settings
botSettings
  case Text -> HashMap Text Text -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup (ByteString -> Text
bsToText (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ InterpreterRequest -> ByteString
interpreterRequestMessage InterpreterRequest
req) HashMap Text Text
helpMessages of
    Maybe Text
Nothing -> Bool -> InterpreterResponse -> BotM ()
sendResponseBack Bool
False (InterpreterResponse -> BotM ()) -> InterpreterResponse -> BotM ()
forall a b. (a -> b) -> a -> b
$ InterpreterRequest -> ByteString -> InterpreterResponse
makeTelegramResponse InterpreterRequest
req (Text -> ByteString
textToBS Text
help) 
    Just Text
helpMessage -> Bool -> InterpreterResponse -> BotM ()
sendResponseBack Bool
False
      (InterpreterResponse -> BotM ()) -> InterpreterResponse -> BotM ()
forall a b. (a -> b) -> a -> b
$ InterpreterRequest -> ByteString -> InterpreterResponse
makeTelegramResponse InterpreterRequest
req (Text -> ByteString
textToBS Text
helpMessage)
handleAction (Version InterpreterRequest
req) Model
model = Model
model Model -> BotM () -> Eff Action Model
forall a action model.
GetAction a action =>
model -> BotM a -> Eff action model
<# do
  let BotState {TBQueue InterpreterResponse
Settings
Interpreters
interpreters :: Interpreters
botSettings :: Settings
output :: TBQueue InterpreterResponse
interpreters :: Model -> Interpreters
botSettings :: Model -> Settings
output :: Model -> TBQueue InterpreterResponse
..} = Model
model
      Settings{Natural
Text
HashMap Text Text
InterpretersSettings
interpretersSettings :: InterpretersSettings
version :: Text
helpMessages :: HashMap Text Text
help :: Text
outputSize :: Natural
botToken :: Text
botName :: Text
$sel:interpretersSettings:Settings :: Settings -> InterpretersSettings
$sel:version:Settings :: Settings -> Text
$sel:helpMessages:Settings :: Settings -> HashMap Text Text
$sel:help:Settings :: Settings -> Text
$sel:outputSize:Settings :: Settings -> Natural
$sel:botToken:Settings :: Settings -> Text
$sel:botName:Settings :: Settings -> Text
..} = Settings
botSettings
  Bool -> InterpreterResponse -> BotM ()
sendResponseBack Bool
False (InterpreterResponse -> BotM ()) -> InterpreterResponse -> BotM ()
forall a b. (a -> b) -> a -> b
$ InterpreterRequest -> ByteString -> InterpreterResponse
makeTelegramResponse InterpreterRequest
req (Text -> ByteString
textToBS (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ Text -> Text
makeVersion Text
version)
handleAction (Debug String
str) Model
model = Model
model Model -> BotM () -> Eff Action Model
forall a action model.
GetAction a action =>
model -> BotM a -> Eff action model
<# (IO () -> BotM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> BotM ()) -> IO () -> BotM ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
str)

-- | Helper that will try to deliver message even when Telegram failed to send it.
sendResponseBack :: Bool -> InterpreterResponse -> BotM ()
sendResponseBack :: Bool -> InterpreterResponse -> BotM ()
sendResponseBack Bool
isMonospace InterpreterResponse
response =
  let req :: SendMessageRequest
req = Bool -> InterpreterResponse -> SendMessageRequest
toSendMessageRequest Bool
isMonospace InterpreterResponse
response
      waitAndRetry :: Response a -> ClientM ()
waitAndRetry Response a
result = if Response a -> Bool
forall a. Response a -> Bool
responseOk Response a
result
        then () -> ClientM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        else case Response a -> Maybe ResponseParameters
forall a. Response a -> Maybe ResponseParameters
responseParameters Response a
result Maybe ResponseParameters
-> (ResponseParameters -> Maybe Seconds) -> Maybe Seconds
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ResponseParameters -> Maybe Seconds
responseParametersRetryAfter of
               Maybe Seconds
Nothing -> () -> ClientM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
               Just Seconds
sec -> do
                 IO () -> ClientM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ClientM ()) -> (Int -> IO ()) -> Int -> ClientM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO ()
threadDelay (Int -> ClientM ()) -> Int -> ClientM ()
forall a b. (a -> b) -> a -> b
$ Seconds -> Int
coerce Seconds
sec Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1000000
                 ClientM (Response Message) -> ClientM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (SendMessageRequest -> ClientM (Response Message)
sendMessage SendMessageRequest
req)
  in ClientM () -> BotM ()
forall a. ClientM a -> BotM a
liftClientM (ClientM () -> BotM ()) -> ClientM () -> BotM ()
forall a b. (a -> b) -> a -> b
$ do
    Response Message
result <- SendMessageRequest -> ClientM (Response Message)
sendMessage SendMessageRequest
req
    Response Message -> ClientM ()
forall a. Response a -> ClientM ()
waitAndRetry Response Message
result

-- | Initiate Telegram Env, 'Model', start Bot, start backends concurrently.
runTelegramBot :: Model -> IO ()
runTelegramBot :: Model -> IO ()
runTelegramBot state :: Model
state@BotState{TBQueue InterpreterResponse
Settings
Interpreters
interpreters :: Interpreters
botSettings :: Settings
output :: TBQueue InterpreterResponse
interpreters :: Model -> Interpreters
botSettings :: Model -> Settings
output :: Model -> TBQueue InterpreterResponse
..} = do
  ClientEnv
env <- Token -> IO ClientEnv
defaultTelegramClientEnv (Text -> Token
Token (Text -> Token) -> Text -> Token
forall a b. (a -> b) -> a -> b
$ Settings -> Text
botToken Settings
botSettings)
  Action -> IO ()
botActionFun <- BotApp Model Action -> ClientEnv -> IO (Action -> IO ())
forall model action.
BotApp model action -> ClientEnv -> IO (action -> IO ())
startBotAsync (Model -> BotApp Model Action
proofAssistantBot Model
state) ClientEnv
env
  IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Concurrently () -> IO ()
forall a. Concurrently a -> IO a
runConcurrently (Concurrently () -> IO ()) -> Concurrently () -> IO ()
forall a b. (a -> b) -> a -> b
$ 
    IO Any -> Concurrently Any
forall a. IO a -> Concurrently a
Concurrently ((Action -> IO ()) -> IO Any
forall a b. (Action -> IO a) -> IO b
botResponseHandlerJob Action -> IO ()
botActionFun) Concurrently Any -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
    IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Interpreters -> IO ()
interpreterJobs Interpreters
interpreters)
  where
    botResponseHandlerJob :: (Action -> IO a) -> IO b
botResponseHandlerJob Action -> IO a
fun = IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (IO a -> IO b) -> IO a -> IO b
forall a b. (a -> b) -> a -> b
$ do
      InterpreterResponse
interpreterResponse <- Model -> IO InterpreterResponse
readOutput Model
state
      Action -> IO a
fun (InterpreterResponse -> Action
SendBack InterpreterResponse
interpreterResponse)
    interpreterJobs :: Interpreters -> IO ()
interpreterJobs Interpreters{InterpreterState IdrisSettings
InterpreterState ArendSettings
InterpreterState LeanSettings
InternalState
ExternalState
AgdaState
rzk :: InternalState
lean :: InterpreterState LeanSettings
coq :: ExternalState
idris :: InterpreterState IdrisSettings
arend :: InterpreterState ArendSettings
agda :: AgdaState
rzk :: Interpreters -> InternalState
lean :: Interpreters -> InterpreterState LeanSettings
coq :: Interpreters -> ExternalState
idris :: Interpreters -> InterpreterState IdrisSettings
arend :: Interpreters -> InterpreterState ArendSettings
agda :: Interpreters -> AgdaState
..} = IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Concurrently () -> IO ()
forall a. Concurrently a -> IO a
runConcurrently (Concurrently () -> IO ()) -> Concurrently () -> IO ()
forall a b. (a -> b) -> a -> b
$
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> AgdaState -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state AgdaState
agda) Concurrently () -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> InterpreterState ArendSettings -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state InterpreterState ArendSettings
arend) Concurrently () -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> ExternalState -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state ExternalState
coq) Concurrently () -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> InterpreterState IdrisSettings -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state InterpreterState IdrisSettings
idris) Concurrently () -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> InterpreterState LeanSettings -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state InterpreterState LeanSettings
lean) Concurrently () -> Concurrently () -> Concurrently ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      IO () -> Concurrently ()
forall a. IO a -> Concurrently a
Concurrently (Model -> InternalState -> IO ()
forall state settings.
Interpreter state settings =>
Model -> state -> IO ()
runInterpreter Model
state InternalState
rzk)

-- | Main function.
run :: IO ()
run :: IO ()
run = Model -> IO ()
runTelegramBot (Model -> IO ()) -> IO Model -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Settings -> IO Model
newBotState (Settings -> IO Model) -> IO Settings -> IO Model
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO Settings
loadDefaultSettings