From 3454935b3bfb295bf363fe3fc48f331a6224af25 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sun, 24 Aug 2025 10:24:00 +0100 Subject: [PATCH] core: pre- and post-start chat hooks for CLI-based bots (#6217) --- src/Simplex/Chat/Controller.hs | 10 ++++++++-- src/Simplex/Chat/Core.hs | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index eb7ed53283..998d7542b3 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -168,7 +168,13 @@ data RandomAgentServers = RandomAgentServers -- The hooks can be used to extend or customize chat core in mobile or CLI clients. data ChatHooks = ChatHooks - { -- preCmdHook can be used to process or modify the commands before they are processed. + { -- preStartHook can be used to verify some data, + -- It is called before chat controller is started, unless the core is started in maintenance mode. + preStartHook :: Maybe (ChatController -> IO ()), + -- postStartHook can be used to update some data after start (e.g. commands in bot or group profiles), + -- It is called after chat controller is started. + postStartHook :: Maybe (ChatController -> IO ()), + -- preCmdHook can be used to process or modify the commands before they are processed. -- This hook should be used to process CustomChatCommand. -- if this hook returns ChatResponse, the command processing will be skipped. preCmdHook :: Maybe (ChatController -> ChatCommand -> IO (Either (Either ChatError ChatResponse) ChatCommand)), @@ -180,7 +186,7 @@ data ChatHooks = ChatHooks } defaultChatHooks :: ChatHooks -defaultChatHooks = ChatHooks Nothing Nothing Nothing +defaultChatHooks = ChatHooks Nothing Nothing Nothing Nothing Nothing data PresetServers = PresetServers { operators :: NonEmpty PresetOperator, diff --git a/src/Simplex/Chat/Core.hs b/src/Simplex/Chat/Core.hs index 7ad822da91..fabc45a04c 100644 --- a/src/Simplex/Chat/Core.hs +++ b/src/Simplex/Chat/Core.hs @@ -38,7 +38,7 @@ import Text.Read (readMaybe) import UnliftIO.Async simplexChatCore :: ChatConfig -> ChatOpts -> (User -> ChatController -> IO ()) -> IO () -simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {coreOptions = CoreChatOpts {dbOptions, logAgent, yesToUpMigrations}, createBot, maintenance} chat = +simplexChatCore cfg@ChatConfig {confirmMigrations, testView, chatHooks} opts@ChatOpts {coreOptions = CoreChatOpts {dbOptions, logAgent, yesToUpMigrations}, createBot, maintenance} chat = case logAgent of Just level -> do setLogLevel level @@ -56,13 +56,15 @@ simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {core cc <- newChatController db u_ cfg opts backgroundMode u <- maybe (createActiveUser cc createBot) pure u_ unless testView $ putStrLn $ "Current user: " <> userStr u + unless maintenance $ forM_ (preStartHook chatHooks) ($ cc) runSimplexChat opts u cc chat runSimplexChat :: ChatOpts -> User -> ChatController -> (User -> ChatController -> IO ()) -> IO () -runSimplexChat ChatOpts {maintenance} u cc chat +runSimplexChat ChatOpts {maintenance} u cc@ChatController {config = ChatConfig {chatHooks}} chat | maintenance = wait =<< async (chat u cc) | otherwise = do a1 <- runReaderT (startChatController True True) cc + forM_ (postStartHook chatHooks) ($ cc) a2 <- async $ chat u cc waitEither_ a1 a2