{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE OverloadedRecordDot #-}

-- | Application startup module
module MatrixBot.App
     ( runApp
     ) where

import GHC.Generics (Generic)
import Data.Aeson (ToJSON (..), FromJSON (..), eitherDecodeFileStrict)
import Data.Aeson.Text (encodeToLazyText)
import Data.String (IsString)
import Data.Text (Text, pack)
import Data.Text.Lazy (toStrict)
import qualified Data.Text.IO as TextIO
import Control.Lens.Lens (lens)
import Control.Monad.IO.Class
import Control.Monad.IO.Unlift (MonadUnliftIO)
import qualified Control.Exception.Safe as E
import qualified Control.Monad.Logger as ML
import qualified Control.Monad.Reader as MR
import System.Exit (ExitCode (..))
import System.IO
import MatrixBot.AesonUtils (myGenericToJSON, myGenericParseJSON)
import MatrixBot.Log
import MatrixBot.MatrixApi (EventResponse)
import qualified MatrixBot.Auth as Auth
import qualified MatrixBot.Bot as Bot
import qualified MatrixBot.Options as O
import qualified MatrixBot.SharedTypes as T
import MatrixBot.Bot.Jobs.Handlers.SendMessage (sendMessage, MessageEdit (..))
import qualified MatrixBot.Bot.Jobs.Queue as BotJobsQueue
import qualified Control.Lens as Lens
import qualified UnliftIO as UIO


type AppM m =
  ( MonadIO m
  , MonadUnliftIO m
  , MonadFail m
  , E.MonadMask m
  )


runApp  AppM m  m ()
runApp :: forall (m :: * -> *). AppM m => m ()
runApp = m ()
forall {m :: * -> *}.
(MonadUnliftIO m, MonadFail m, MonadMask m) =>
m ()
go where
  go :: m ()
go = do
    LogStateHandle
logStateHandle  m LogStateHandle
forall (m :: * -> *). MonadIO m => m LogStateHandle
createLogState
    LogStateHandle -> (Logger -> m ()) -> m ()
forall (m :: * -> *) a.
MonadUnliftIO m =>
LogStateHandle -> (Logger -> m a) -> m a
withLogger LogStateHandle
logStateHandle ((Logger -> m ()) -> m ())
-> (ReaderT Logger m () -> Logger -> m ())
-> ReaderT Logger m ()
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReaderT Logger m () -> Logger -> m ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
MR.runReaderT (ReaderT Logger m () -> m ()) -> ReaderT Logger m () -> m ()
forall a b. (a -> b) -> a -> b
$
      ReaderT Logger m ()
-> (SomeException -> ReaderT Logger m ()) -> ReaderT Logger m ()
forall (m :: * -> *) e a.
(HasCallStack, MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
E.catch (LogStateHandle -> ReaderT Logger m ()
forall (m :: * -> *).
(AppM m, MonadLogger m) =>
LogStateHandle -> m ()
startApp LogStateHandle
logStateHandle) (LogStateHandle -> SomeException -> ReaderT Logger m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadThrow m, MonadLogger m) =>
LogStateHandle -> SomeException -> m ()
exceptionHandler LogStateHandle
logStateHandle)

  exceptionHandler
     (UIO.MonadUnliftIO m, E.MonadThrow m, ML.MonadLogger m)
     LogStateHandle
     E.SomeException
     m ()
  exceptionHandler :: forall (m :: * -> *).
(MonadUnliftIO m, MonadThrow m, MonadLogger m) =>
LogStateHandle -> SomeException -> m ()
exceptionHandler LogStateHandle
logStateHandle SomeException
e = do
    LogStateHandle -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
LogStateHandle -> m ()
forceLogInitialization LogStateHandle
logStateHandle
    case forall e. Exception e => SomeException -> Maybe e
E.fromException @ExitCode SomeException
e of
      Just ExitCode
ExitSuccess  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> (SomeException -> Text) -> SomeException -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text)
-> (SomeException -> String) -> SomeException -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Application exits with: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<>) (String -> String)
-> (SomeException -> String) -> SomeException -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> String
forall e. Exception e => e -> String
E.displayException (SomeException -> m ()) -> SomeException -> m ()
forall a b. (a -> b) -> a -> b
$ SomeException
e
        SomeException -> m ()
forall (m :: * -> *) e a.
(HasCallStack, MonadThrow m, Exception e) =>
e -> m a
E.throwM SomeException
e
      Maybe ExitCode
_  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logError (Text -> m ()) -> (SomeException -> Text) -> SomeException -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text)
-> (SomeException -> String) -> SomeException -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Application failed with: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<>) (String -> String)
-> (SomeException -> String) -> SomeException -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> String
forall e. Exception e => e -> String
E.displayException (SomeException -> m ()) -> SomeException -> m ()
forall a b. (a -> b) -> a -> b
$ SomeException
e
        SomeException -> m ()
forall (m :: * -> *) e a.
(HasCallStack, MonadThrow m, Exception e) =>
e -> m a
E.throwM SomeException
e

  startApp  (AppM m, ML.MonadLogger m)  LogStateHandle  m ()
  startApp :: forall (m :: * -> *).
(AppM m, MonadLogger m) =>
LogStateHandle -> m ()
startApp LogStateHandle
logStateHandle = do
    Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug Text
"Starting the application…"

    Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug Text
"Parsing the command-line arguments…"
    m AppCommand
forall (m :: * -> *). MonadIO m => m AppCommand
O.parseAppCommand m AppCommand -> (AppCommand -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      O.AppCommandAuth AuthOptions
opts  do
        LogStateHandle -> Maybe LogLevel -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
LogStateHandle -> Maybe LogLevel -> m ()
setLogLevel LogStateHandle
logStateHandle AuthOptions
opts.authOptionsLogLevel
        AuthOptions -> m ()
forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
AuthOptions -> m ()
runAuth AuthOptions
opts
      O.AppCommandStart StartOptions
opts  do
        LogStateHandle -> Maybe LogLevel -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
LogStateHandle -> Maybe LogLevel -> m ()
setLogLevel LogStateHandle
logStateHandle StartOptions
opts.startOptionsLogLevel
        StartOptions -> m ()
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m,
 MonadLogger m) =>
StartOptions -> m ()
runStart StartOptions
opts
      O.AppCommandSendMessage SendMessageOptions
opts  do
        LogStateHandle -> Maybe LogLevel -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
LogStateHandle -> Maybe LogLevel -> m ()
setLogLevel LogStateHandle
logStateHandle SendMessageOptions
opts.sendMessageOptionsLogLevel
        SendMessageOptions -> m ()
forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
SendMessageOptions -> m ()
runSendMessage SendMessageOptions
opts
      O.AppCommandEditMessage EditMessageOptions
opts  do
        LogStateHandle -> Maybe LogLevel -> m ()
forall (m :: * -> *).
(MonadUnliftIO m, MonadLogger m) =>
LogStateHandle -> Maybe LogLevel -> m ()
setLogLevel LogStateHandle
logStateHandle EditMessageOptions
opts.editMessageOptionsLogLevel
        EditMessageOptions -> m ()
forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
EditMessageOptions -> m ()
runEditMessage EditMessageOptions
opts


runAuth
   (MonadIO m, MonadUnliftIO m, MonadFail m, E.MonadThrow m, ML.MonadLogger m)
   O.AuthOptions
   m ()
runAuth :: forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
AuthOptions -> m ()
runAuth AuthOptions
opts = do
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Running authentication…"
  let quotedMxid :: Text
quotedMxid = Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (AuthOptions -> Text) -> AuthOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mxid -> Text
T.printMxid (Mxid -> Text) -> (AuthOptions -> Mxid) -> AuthOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AuthOptions -> Mxid
O.authOptionsMxid (AuthOptions -> Text) -> AuthOptions -> Text
forall a b. (a -> b) -> a -> b
$ AuthOptions
opts
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"MXID: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
quotedMxid

  Password
password 
    case AuthOptions -> Either Password String
O.authOptionsPassword AuthOptions
opts of
      Left Password
x 
        Password
x Password -> m () -> m Password
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text
"Password for " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
quotedMxid Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" was provided as an option argument")
      Right String
file  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Reading password for " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
quotedMxid Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" from " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted String
file Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"…"
        Handle
handle  IO Handle -> m Handle
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ String -> IOMode -> IO Handle
openFile String
file IOMode
ReadMode
        IO Password -> m Password
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Password -> m Password) -> IO Password -> m Password
forall a b. (a -> b) -> a -> b
$ Text -> Password
T.Password (Text -> Password) -> IO Text -> IO Password
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Handle -> IO Text
TextIO.hGetLine Handle
handle

  Credentials
credentials  Mxid -> Password -> m Credentials
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadUnliftIO m, MonadThrow m,
 MonadLogger m) =>
Mxid -> Password -> m Credentials
Auth.authenticate (AuthOptions -> Mxid
O.authOptionsMxid AuthOptions
opts) Password
password
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug Text
"Received credentials"

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Saving credentials to " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (String -> Text) -> (AuthOptions -> String) -> AuthOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AuthOptions -> String
O.authOptionsOutputFile) AuthOptions
opts Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"…"
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (Credentials -> IO ()) -> Credentials -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text -> IO ()
TextIO.writeFile (AuthOptions -> String
O.authOptionsOutputFile AuthOptions
opts) (Text -> IO ()) -> (Credentials -> Text) -> Credentials -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> Text
toStrict (LazyText -> Text)
-> (Credentials -> LazyText) -> Credentials -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Credentials -> LazyText
forall a. ToJSON a => a -> LazyText
encodeToLazyText (Credentials -> m ()) -> Credentials -> m ()
forall a b. (a -> b) -> a -> b
$ Credentials
credentials

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Success!"


runStart
   (MonadIO m, MonadFail m, E.MonadMask m, MonadUnliftIO m, ML.MonadLogger m)
   O.StartOptions
   m ()
runStart :: forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m,
 MonadLogger m) =>
StartOptions -> m ()
runStart StartOptions
opts = do
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Initializing the bot…"

  let
    retryLimit :: RetryLimit
retryLimit = StartOptions -> RetryLimit
O.startOptionsRetryLimit StartOptions
opts
    retryDelay :: RetryDelay
retryDelay = StartOptions -> RetryDelay
O.startOptionsRetryDelay StartOptions
opts
    eventTokenFile :: Maybe String
eventTokenFile = StartOptions -> Maybe String
O.startOptionsEventTokenFile StartOptions
opts
    eventsTimeout :: EventsTimeout
eventsTimeout = StartOptions -> EventsTimeout
O.startOptionsEventsTimeout StartOptions
opts

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
    [ Text
"Failed Matrix API call retry limit: "
    , String -> Text
pack (String -> Text) -> (RetryLimit -> String) -> RetryLimit -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> String
forall a. Show a => a -> String
show (Natural -> String)
-> (RetryLimit -> Natural) -> RetryLimit -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetryLimit -> Natural
T.unRetryLimit (RetryLimit -> Text) -> RetryLimit -> Text
forall a b. (a -> b) -> a -> b
$ RetryLimit
retryLimit
    , Text
" (amount of retries before bot fails completely)"
    ]

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
    [ Text
"Failed Matrix API call retry interval: "
    , RetryDelay -> Text
forall s. IsString s => RetryDelay -> s
T.printRetryDelaySeconds RetryDelay
retryDelay
    ]

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
    [ Text
"Matrix events listening timeout: "
    , String -> Text
pack (String -> Text)
-> (EventsTimeout -> String) -> EventsTimeout -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> String
forall a. Show a => a -> String
show (Integer -> String)
-> (EventsTimeout -> Integer) -> EventsTimeout -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seconds -> Integer
T.unSeconds (Seconds -> Integer)
-> (EventsTimeout -> Seconds) -> EventsTimeout -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventsTimeout -> Seconds
T.unEventsTimeout (EventsTimeout -> Text) -> EventsTimeout -> Text
forall a b. (a -> b) -> a -> b
$ EventsTimeout
eventsTimeout
    , Text
" second(s)"
    ]

  case Maybe String
eventTokenFile of
    Maybe String
Nothing 
      Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logWarn (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
        [ Text
"There’s no event token file provided, "
        , Text
"will start listening from next following events"
        ]
    Just String
x 
      Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
        [ Text
"Event token file where to read from and save to last event token that is used "
        , Text
"as a starting point to get next events from: ", String -> Text
pack (String -> Text) -> (String -> String) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. Show a => a -> String
show (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
x
        ]

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
    [ Text
"Reading and parsing credentials "
    , String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (String -> Text)
-> (StartOptions -> String) -> StartOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StartOptions -> String
O.startOptionsCredentialsFile (StartOptions -> Text) -> StartOptions -> Text
forall a b. (a -> b) -> a -> b
$ StartOptions
opts
    , Text
" file…"
    ]

  Credentials
credentials 
    (String -> m Credentials)
-> (Credentials -> m Credentials)
-> Either String Credentials
-> m Credentials
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m Credentials
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Credentials -> m Credentials
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Credentials -> m Credentials)
-> m (Either String Credentials) -> m Credentials
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Either String Credentials) -> m (Either String Credentials)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Either String Credentials)
forall a. FromJSON a => String -> IO (Either String a)
eitherDecodeFileStrict (String -> IO (Either String Credentials))
-> (StartOptions -> String)
-> StartOptions
-> IO (Either String Credentials)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StartOptions -> String
O.startOptionsCredentialsFile (StartOptions -> IO (Either String Credentials))
-> StartOptions -> IO (Either String Credentials)
forall a b. (a -> b) -> a -> b
$ StartOptions
opts)

  let
    quotedMxid :: Text
quotedMxid
      = Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (Mxid -> Text) -> Mxid -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mxid -> Text
T.printMxid
      (Mxid -> Text) -> Mxid -> Text
forall a b. (a -> b) -> a -> b
$ Username -> HomeServer -> Mxid
T.Mxid (Credentials -> Username
Auth.credentialsUsername Credentials
credentials) (Credentials -> HomeServer
Auth.credentialsHomeServer Credentials
credentials)

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"MXID: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
quotedMxid

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
    [ Text
"Reading and parsing bot configuration from "
    , String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (String -> Text)
-> (StartOptions -> String) -> StartOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StartOptions -> String
O.startOptionsBotConfigFile (StartOptions -> Text) -> StartOptions -> Text
forall a b. (a -> b) -> a -> b
$ StartOptions
opts
    , Text
" file…"
    ]

  BotConfig
botConfig 
    (String -> m BotConfig)
-> (BotConfig -> m BotConfig)
-> Either String BotConfig
-> m BotConfig
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m BotConfig
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail BotConfig -> m BotConfig
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String BotConfig -> m BotConfig)
-> m (Either String BotConfig) -> m BotConfig
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Either String BotConfig) -> m (Either String BotConfig)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Either String BotConfig)
forall a. FromJSON a => String -> IO (Either String a)
eitherDecodeFileStrict (String -> IO (Either String BotConfig))
-> (StartOptions -> String)
-> StartOptions
-> IO (Either String BotConfig)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StartOptions -> String
O.startOptionsBotConfigFile (StartOptions -> IO (Either String BotConfig))
-> StartOptions -> IO (Either String BotConfig)
forall a b. (a -> b) -> a -> b
$ StartOptions
opts)

  BotJobsQueue
botJobsQueue  m BotJobsQueue
forall (m :: * -> *). MonadIO m => m BotJobsQueue
BotJobsQueue.mkBotJobsQueue

  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Listening to events…"
  Maybe String -> EventsTimeout -> BotConfig -> ReaderT BotEnv m ()
forall r (m :: * -> *).
(BotM r m, HasBotJobsReader r, HasBotJobsWriter r) =>
Maybe String -> EventsTimeout -> BotConfig -> m ()
Bot.startTheBot Maybe String
eventTokenFile EventsTimeout
eventsTimeout BotConfig
botConfig
    ReaderT BotEnv m () -> BotEnv -> m ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
`MR.runReaderT` Credentials -> RetryLimit -> RetryDelay -> BotJobsQueue -> BotEnv
BotEnv Credentials
credentials RetryLimit
retryLimit RetryDelay
retryDelay BotJobsQueue
botJobsQueue


runSendMessage
   (MonadIO m, MonadUnliftIO m, MonadFail m, E.MonadThrow m, ML.MonadLogger m)
   O.SendMessageOptions
   m ()
runSendMessage :: forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
SendMessageOptions -> m ()
runSendMessage SendMessageOptions
opts = do
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Running send message command…"

  let roomId :: RoomId
roomId = SendMessageOptions -> RoomId
O.sendMessageOptionsRoomId SendMessageOptions
opts

  Credentials
credentials  Auth.Credentials  do
    Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
      [ Text
"Reading and parsing credentials "
      , String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (String -> Text)
-> (SendMessageOptions -> String) -> SendMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SendMessageOptions -> String
O.sendMessageOptionsCredentialsFile (SendMessageOptions -> Text) -> SendMessageOptions -> Text
forall a b. (a -> b) -> a -> b
$ SendMessageOptions
opts
      , Text
" file…"
      ]

    (String -> m Credentials)
-> (Credentials -> m Credentials)
-> Either String Credentials
-> m Credentials
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m Credentials
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Credentials -> m Credentials
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Credentials -> m Credentials)
-> m (Either String Credentials) -> m Credentials
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Either String Credentials) -> m (Either String Credentials)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Either String Credentials)
forall a. FromJSON a => String -> IO (Either String a)
eitherDecodeFileStrict (String -> IO (Either String Credentials))
-> (SendMessageOptions -> String)
-> SendMessageOptions
-> IO (Either String Credentials)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SendMessageOptions -> String
O.sendMessageOptionsCredentialsFile (SendMessageOptions -> IO (Either String Credentials))
-> SendMessageOptions -> IO (Either String Credentials)
forall a b. (a -> b) -> a -> b
$ SendMessageOptions
opts)

  Text
message 
    case SendMessageOptions -> Either Text String
O.sendMessageOptionsMessage SendMessageOptions
opts of
      Left Text
x 
        (Text
x Text -> m () -> m Text
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m Text) -> (Text -> m ()) -> Text -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Message to send to ", String -> Text
pack (String -> Text) -> (RoomId -> String) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (RoomId -> Text) -> RoomId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId (RoomId -> Text) -> RoomId -> Text
forall a b. (a -> b) -> a -> b
$ RoomId
roomId
          , Text
" room was provided as an option argument"
          ]
      Right String
file  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading message to send to ", String -> Text
pack (String -> Text) -> (RoomId -> String) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (RoomId -> Text) -> RoomId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId (RoomId -> Text) -> RoomId -> Text
forall a b. (a -> b) -> a -> b
$ RoomId
roomId
          , Text
" room from ", String -> Text
pack (String -> Text) -> (String -> String) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. Show a => a -> String
show (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
file, Text
" file…"
          ]
        IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Maybe Text
htmlMessage 
    case SendMessageOptions -> Maybe (Either Text String)
O.sendMessageOptionsHtmlMessage SendMessageOptions
opts of
      Maybe (Either Text String)
Nothing  Maybe Text -> m (Maybe Text)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Text
forall a. Maybe a
Nothing
      Just (Left Text
x) 
        (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
x Maybe Text -> m () -> m (Maybe Text)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe Text))
-> (Text -> m ()) -> Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m (Maybe Text)) -> Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"HTML-formatted message to send to "
          , (String -> Text
pack (String -> Text) -> (RoomId -> String) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (RoomId -> Text) -> RoomId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" room was provided as an option argument"
          ]
      Just (Right String
file)  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading HTML-formatted message to send to "
          , (String -> Text
pack (String -> Text) -> (RoomId -> String) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (RoomId -> Text) -> RoomId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" room from "
          , (String -> Text
pack (String -> Text) -> (String -> String) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. Show a => a -> String
show) String
file
          , Text
" file…"
          ]
        (Text -> Maybe Text) -> m Text -> m (Maybe Text)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Maybe Text
forall a. a -> Maybe a
Just (m Text -> m (Maybe Text))
-> (IO Text -> m Text) -> IO Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m (Maybe Text)) -> IO Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Maybe EventId
replyTo 
    case SendMessageOptions -> Maybe EventId
O.sendMessageOptionsReplyTo SendMessageOptions
opts of
      Maybe EventId
Nothing  Maybe EventId -> m (Maybe EventId)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe EventId
forall a. Maybe a
Nothing
      Just EventId
x  (EventId -> Maybe EventId
forall a. a -> Maybe a
Just EventId
x Maybe EventId -> m () -> m (Maybe EventId)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe EventId)) -> m () -> m (Maybe EventId)
forall a b. (a -> b) -> a -> b
$ Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [Text
"Replying to ", (String -> Text
pack (String -> Text) -> (EventId -> String) -> EventId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show) EventId
x]

  (ReaderT Credentials m () -> Credentials -> m ())
-> Credentials -> ReaderT Credentials m () -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT Credentials m () -> Credentials -> m ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
MR.runReaderT Credentials
credentials (ReaderT Credentials m () -> m ())
-> ReaderT Credentials m () -> m ()
forall a b. (a -> b) -> a -> b
$
    EventsTimeout
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token")
    -> ReaderT Credentials m ())
-> ReaderT Credentials m ()
forall (m :: * -> *) r a.
(MonadIO m, MonadUnliftIO m, MonadThrow m, MonadLogger m,
 MonadReader r m, HasCredentials r) =>
EventsTimeout
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token") -> m a)
-> m a
Bot.withReqAndAuth (Seconds -> EventsTimeout
T.EventsTimeout (Seconds -> EventsTimeout)
-> (Integer -> Seconds) -> Integer -> EventsTimeout
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Seconds
T.Seconds (Integer -> EventsTimeout) -> Integer -> EventsTimeout
forall a b. (a -> b) -> a -> b
$ Integer
30) ((MatrixApiClient
  -> AuthenticatedRequest (AuthProtect "access-token")
  -> ReaderT Credentials m ())
 -> ReaderT Credentials m ())
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token")
    -> ReaderT Credentials m ())
-> ReaderT Credentials m ()
forall a b. (a -> b) -> a -> b
$ \MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth  do
      TransactionId
transactionId 
        case SendMessageOptions -> Maybe TransactionId
O.sendMessageOptionsTransactionId SendMessageOptions
opts of
          Maybe TransactionId
Nothing  do
            TransactionId
txid  ReaderT Credentials m TransactionId
forall (m :: * -> *). MonadIO m => m TransactionId
T.genTransactionId
            (TransactionId
txid TransactionId
-> ReaderT Credentials m () -> ReaderT Credentials m TransactionId
forall a b. a -> ReaderT Credentials m b -> ReaderT Credentials m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (ReaderT Credentials m () -> ReaderT Credentials m TransactionId)
-> (Text -> ReaderT Credentials m ())
-> Text
-> ReaderT Credentials m TransactionId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> ReaderT Credentials m TransactionId)
-> Text -> ReaderT Credentials m TransactionId
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
              [ Text
"No transaction ID was provided in the command-line options, generated new one: "
              , String -> Text
pack (String -> Text)
-> (TransactionId -> String) -> TransactionId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UUID -> String
forall a. Show a => a -> String
show (UUID -> String)
-> (TransactionId -> UUID) -> TransactionId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransactionId -> UUID
T.unTransactionId (TransactionId -> Text) -> TransactionId -> Text
forall a b. (a -> b) -> a -> b
$ TransactionId
txid
              ]
          Just TransactionId
txid  do
            (TransactionId
txid TransactionId
-> ReaderT Credentials m () -> ReaderT Credentials m TransactionId
forall a b. a -> ReaderT Credentials m b -> ReaderT Credentials m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (ReaderT Credentials m () -> ReaderT Credentials m TransactionId)
-> (Text -> ReaderT Credentials m ())
-> Text
-> ReaderT Credentials m TransactionId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> ReaderT Credentials m TransactionId)
-> Text -> ReaderT Credentials m TransactionId
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
              [ Text
"Using transaction ID provided in the command-line options: "
              , String -> Text
pack (String -> Text)
-> (TransactionId -> String) -> TransactionId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UUID -> String
forall a. Show a => a -> String
show (UUID -> String)
-> (TransactionId -> UUID) -> TransactionId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransactionId -> UUID
T.unTransactionId (TransactionId -> Text) -> TransactionId -> Text
forall a b. (a -> b) -> a -> b
$ TransactionId
txid
              ]

      EventResponse
response  MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> ReaderT Credentials m EventResponse
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadThrow m, MonadLogger m) =>
MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> m EventResponse
sendMessage MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth TransactionId
transactionId RoomId
roomId Maybe EventId
replyTo Maybe Text
htmlMessage Text
message Maybe MessageEdit
forall a. Maybe a
Nothing

      Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug Text
"Printing response and transaction ID to stdout…"

      IO () -> ReaderT Credentials m ()
forall a. IO a -> ReaderT Credentials m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Credentials m ())
-> (SendMessageResponse -> IO ())
-> SendMessageResponse
-> ReaderT Credentials m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> IO ()
TextIO.putStrLn (Text -> IO ())
-> (SendMessageResponse -> Text) -> SendMessageResponse -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> Text
toStrict (LazyText -> Text)
-> (SendMessageResponse -> LazyText) -> SendMessageResponse -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SendMessageResponse -> LazyText
forall a. ToJSON a => a -> LazyText
encodeToLazyText (SendMessageResponse -> ReaderT Credentials m ())
-> SendMessageResponse -> ReaderT Credentials m ()
forall a b. (a -> b) -> a -> b
$ SendMessageResponse
        { sendMessageResponseTransactionId :: TransactionId
sendMessageResponseTransactionId = TransactionId
transactionId
        , sendMessageResponseResponse :: EventResponse
sendMessageResponseResponse = EventResponse
response
        }

      Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Success!"


runEditMessage
   (MonadIO m, MonadUnliftIO m, MonadFail m, E.MonadThrow m, ML.MonadLogger m)
   O.EditMessageOptions
   m ()
runEditMessage :: forall (m :: * -> *).
(MonadIO m, MonadUnliftIO m, MonadFail m, MonadThrow m,
 MonadLogger m) =>
EditMessageOptions -> m ()
runEditMessage EditMessageOptions
opts = do
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Running edit message command…"

  let roomId :: RoomId
roomId = EditMessageOptions -> RoomId
O.editMessageOptionsRoomId EditMessageOptions
opts

  Credentials
credentials  Auth.Credentials  do
    Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
      [ Text
"Reading and parsing credentials "
      , (String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> String
O.editMessageOptionsCredentialsFile) EditMessageOptions
opts
      , Text
" file…"
      ]

    (String -> m Credentials)
-> (Credentials -> m Credentials)
-> Either String Credentials
-> m Credentials
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m Credentials
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Credentials -> m Credentials
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Credentials -> m Credentials)
-> m (Either String Credentials) -> m Credentials
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Either String Credentials) -> m (Either String Credentials)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Either String Credentials)
forall a. FromJSON a => String -> IO (Either String a)
eitherDecodeFileStrict (String -> IO (Either String Credentials))
-> (EditMessageOptions -> String)
-> EditMessageOptions
-> IO (Either String Credentials)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> String
O.editMessageOptionsCredentialsFile (EditMessageOptions -> IO (Either String Credentials))
-> EditMessageOptions -> IO (Either String Credentials)
forall a b. (a -> b) -> a -> b
$ EditMessageOptions
opts)

  Text
message 
    case EditMessageOptions -> Either Text String
O.editMessageOptionsMessage EditMessageOptions
opts of
      Left Text
x 
        (Text
x Text -> m () -> m Text
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m Text) -> (Text -> m ()) -> Text -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"New message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" was provided as an option argument"
          ]
      Right String
file  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading new message message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" from ", String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted String
file, Text
" file…"
          ]
        IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Maybe Text
htmlMessage 
    case EditMessageOptions -> Maybe (Either Text String)
O.editMessageOptionsHtmlMessage EditMessageOptions
opts of
      Maybe (Either Text String)
Nothing  Maybe Text -> m (Maybe Text)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Text
forall a. Maybe a
Nothing
      Just (Left Text
x) 
        (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
x Maybe Text -> m () -> m (Maybe Text)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe Text))
-> (Text -> m ()) -> Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m (Maybe Text)) -> Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"New HTML-formatted message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" was provided as an option argument"
          ]
      Just (Right String
file)  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading new HTML-formatted message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" from ", String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted String
file, Text
" file…"
          ]
        (Text -> Maybe Text) -> m Text -> m (Maybe Text)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Maybe Text
forall a. a -> Maybe a
Just (m Text -> m (Maybe Text))
-> (IO Text -> m Text) -> IO Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m (Maybe Text)) -> IO Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Text
compatMessage 
    case EditMessageOptions -> Maybe (Either Text String)
O.editMessageOptionsMessageCompat EditMessageOptions
opts of
      Maybe (Either Text String)
Nothing  Text -> m Text
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Text
forall {a}. (Semigroup a, IsString a) => a -> a
compatTextDefaultTemplate Text
message)
      Just (Left Text
x) 
        (Text
x Text -> m () -> m Text
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m Text) -> (Text -> m ()) -> Text -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"New old API-compatible message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" was provided as an option argument"
          ]
      Just (Right String
file)  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading new old API-compatible message message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" from ", String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted String
file, Text
" file…"
          ]
        IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Maybe Text
compatHtmlMessage 
    case (EditMessageOptions -> Maybe (Either Text String)
O.editMessageOptionsHtmlMessageCompat EditMessageOptions
opts, Maybe Text
htmlMessage) of
      (Maybe (Either Text String)
Nothing, Maybe Text
Nothing)  Maybe Text -> m (Maybe Text)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Text
forall a. Maybe a
Nothing
      (Maybe (Either Text String)
Nothing, Just Text
newHtmlBody)  (Maybe Text -> m (Maybe Text)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> m (Maybe Text))
-> (Text -> Maybe Text) -> Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> (Text -> Text) -> Text -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
forall {a}. (Semigroup a, IsString a) => a -> a
compatHtmlDefaultTemplate) Text
newHtmlBody
      (Just (Left Text
x), Maybe Text
_) 
        (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
x Maybe Text -> m () -> m (Maybe Text)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe Text))
-> (Text -> m ()) -> Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m (Maybe Text)) -> Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"New old API-compatible HTML-formatted message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" was provided as an option argument"
          ]
      (Just (Right String
file), Maybe Text
_)  do
        Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
          [ Text
"Reading new old API-compatible HTML-formatted message body for the message "
          , (String -> Text
pack (String -> Text)
-> (EditMessageOptions -> String) -> EditMessageOptions -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show (EventId -> String)
-> (EditMessageOptions -> EventId) -> EditMessageOptions -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EditMessageOptions -> EventId
O.editMessageOptionsMessageId) EditMessageOptions
opts
          , Text
" in the room "
          , (Text -> Text
forall s. (IsString s, Show s) => s -> Text
quoted (Text -> Text) -> (RoomId -> Text) -> RoomId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomId -> Text
T.printRoomId) RoomId
roomId
          , Text
" from ", String -> Text
forall s. (IsString s, Show s) => s -> Text
quoted String
file, Text
" file…"
          ]
        (Text -> Maybe Text) -> m Text -> m (Maybe Text)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Maybe Text
forall a. a -> Maybe a
Just (m Text -> m (Maybe Text))
-> (IO Text -> m Text) -> IO Text -> m (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m (Maybe Text)) -> IO Text -> m (Maybe Text)
forall a b. (a -> b) -> a -> b
$ String -> IO Text
TextIO.readFile String
file

  Maybe EventId
replyTo 
    case EditMessageOptions -> Maybe EventId
O.editMessageOptionsReplyTo EditMessageOptions
opts of
      Maybe EventId
Nothing  Maybe EventId -> m (Maybe EventId)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe EventId
forall a. Maybe a
Nothing
      Just EventId
x  (EventId -> Maybe EventId
forall a. a -> Maybe a
Just EventId
x Maybe EventId -> m () -> m (Maybe EventId)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe EventId)) -> m () -> m (Maybe EventId)
forall a b. (a -> b) -> a -> b
$ Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [Text
"Replying to ", (String -> Text
pack (String -> Text) -> (EventId -> String) -> EventId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventId -> String
forall a. Show a => a -> String
show) EventId
x]

  (ReaderT Credentials m () -> Credentials -> m ())
-> Credentials -> ReaderT Credentials m () -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT Credentials m () -> Credentials -> m ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
MR.runReaderT Credentials
credentials (ReaderT Credentials m () -> m ())
-> ReaderT Credentials m () -> m ()
forall a b. (a -> b) -> a -> b
$
    EventsTimeout
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token")
    -> ReaderT Credentials m ())
-> ReaderT Credentials m ()
forall (m :: * -> *) r a.
(MonadIO m, MonadUnliftIO m, MonadThrow m, MonadLogger m,
 MonadReader r m, HasCredentials r) =>
EventsTimeout
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token") -> m a)
-> m a
Bot.withReqAndAuth (Seconds -> EventsTimeout
T.EventsTimeout (Seconds -> EventsTimeout)
-> (Integer -> Seconds) -> Integer -> EventsTimeout
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Seconds
T.Seconds (Integer -> EventsTimeout) -> Integer -> EventsTimeout
forall a b. (a -> b) -> a -> b
$ Integer
30) ((MatrixApiClient
  -> AuthenticatedRequest (AuthProtect "access-token")
  -> ReaderT Credentials m ())
 -> ReaderT Credentials m ())
-> (MatrixApiClient
    -> AuthenticatedRequest (AuthProtect "access-token")
    -> ReaderT Credentials m ())
-> ReaderT Credentials m ()
forall a b. (a -> b) -> a -> b
$ \MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth  do
      TransactionId
transactionId 
        case EditMessageOptions -> Maybe TransactionId
O.editMessageOptionsTransactionId EditMessageOptions
opts of
          Maybe TransactionId
Nothing  do
            TransactionId
txid  ReaderT Credentials m TransactionId
forall (m :: * -> *). MonadIO m => m TransactionId
T.genTransactionId
            (TransactionId
txid TransactionId
-> ReaderT Credentials m () -> ReaderT Credentials m TransactionId
forall a b. a -> ReaderT Credentials m b -> ReaderT Credentials m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (ReaderT Credentials m () -> ReaderT Credentials m TransactionId)
-> (Text -> ReaderT Credentials m ())
-> Text
-> ReaderT Credentials m TransactionId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> ReaderT Credentials m TransactionId)
-> Text -> ReaderT Credentials m TransactionId
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
              [ Text
"No transaction ID was provided in the command-line options, generated new one: "
              , (String -> Text
pack (String -> Text)
-> (TransactionId -> String) -> TransactionId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UUID -> String
forall a. Show a => a -> String
show (UUID -> String)
-> (TransactionId -> UUID) -> TransactionId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransactionId -> UUID
T.unTransactionId) TransactionId
txid
              ]
          Just TransactionId
txid  do
            (TransactionId
txid TransactionId
-> ReaderT Credentials m () -> ReaderT Credentials m TransactionId
forall a b. a -> ReaderT Credentials m b -> ReaderT Credentials m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (ReaderT Credentials m () -> ReaderT Credentials m TransactionId)
-> (Text -> ReaderT Credentials m ())
-> Text
-> ReaderT Credentials m TransactionId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug (Text -> ReaderT Credentials m TransactionId)
-> Text -> ReaderT Credentials m TransactionId
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
              [ Text
"Using transaction ID provided in the command-line options: "
              , (String -> Text
pack (String -> Text)
-> (TransactionId -> String) -> TransactionId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UUID -> String
forall a. Show a => a -> String
show (UUID -> String)
-> (TransactionId -> UUID) -> TransactionId -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransactionId -> UUID
T.unTransactionId) TransactionId
txid
              ]

      EventResponse
response 
        MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> ReaderT Credentials m EventResponse
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadThrow m, MonadLogger m) =>
MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> m EventResponse
sendMessage MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth TransactionId
transactionId RoomId
roomId Maybe EventId
replyTo Maybe Text
compatHtmlMessage Text
compatMessage (Maybe MessageEdit -> ReaderT Credentials m EventResponse)
-> Maybe MessageEdit -> ReaderT Credentials m EventResponse
forall a b. (a -> b) -> a -> b
$
          MessageEdit -> Maybe MessageEdit
forall a. a -> Maybe a
Just MessageEdit
            { messageEditMessageId :: EventId
messageEditMessageId = EditMessageOptions -> EventId
O.editMessageOptionsMessageId EditMessageOptions
opts
            , messageEditNewText :: Text
messageEditNewText = Text
message
            , messageEditNewHtml :: Maybe Text
messageEditNewHtml = Maybe Text
htmlMessage
            }

      Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logDebug Text
"Printing response and transaction ID to stdout…"

      IO () -> ReaderT Credentials m ()
forall a. IO a -> ReaderT Credentials m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Credentials m ())
-> (SendMessageResponse -> IO ())
-> SendMessageResponse
-> ReaderT Credentials m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> IO ()
TextIO.putStrLn (Text -> IO ())
-> (SendMessageResponse -> Text) -> SendMessageResponse -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> Text
toStrict (LazyText -> Text)
-> (SendMessageResponse -> LazyText) -> SendMessageResponse -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SendMessageResponse -> LazyText
forall a. ToJSON a => a -> LazyText
encodeToLazyText (SendMessageResponse -> ReaderT Credentials m ())
-> SendMessageResponse -> ReaderT Credentials m ()
forall a b. (a -> b) -> a -> b
$ SendMessageResponse
        { sendMessageResponseTransactionId :: TransactionId
sendMessageResponseTransactionId = TransactionId
transactionId
        , sendMessageResponseResponse :: EventResponse
sendMessageResponseResponse = EventResponse
response
        }

      Text -> ReaderT Credentials m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
logInfo Text
"Success!"
  where
    compatTextDefaultTemplate :: a -> a
compatTextDefaultTemplate = (a
"EDIT: " a -> a -> a
forall a. Semigroup a => a -> a -> a
<>)
    compatHtmlDefaultTemplate :: a -> a
compatHtmlDefaultTemplate = (a
"<b>EDIT:</b> " a -> a -> a
forall a. Semigroup a => a -> a -> a
<>)


-- * Types

data BotEnv = BotEnv
  { BotEnv -> Credentials
botEnvCredentials  Auth.Credentials
  , BotEnv -> RetryLimit
botEnvRetryLimit  T.RetryLimit
  , BotEnv -> RetryDelay
botEnvRetryDelay  T.RetryDelay
  , BotEnv -> BotJobsQueue
botEnvJobsQueue  BotJobsQueue.BotJobsQueue
  }

instance Auth.HasCredentials BotEnv where
  credentials :: Lens' BotEnv Credentials
credentials = (BotEnv -> Credentials)
-> (BotEnv -> Credentials -> BotEnv) -> Lens' BotEnv Credentials
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BotEnv -> Credentials
botEnvCredentials ((BotEnv -> Credentials -> BotEnv) -> Lens' BotEnv Credentials)
-> (BotEnv -> Credentials -> BotEnv) -> Lens' BotEnv Credentials
forall a b. (a -> b) -> a -> b
$ \BotEnv
x Credentials
v  BotEnv
x { botEnvCredentials = v }

instance T.HasRetryParams BotEnv where
  retryLimit :: Lens' BotEnv RetryLimit
retryLimit = (BotEnv -> RetryLimit)
-> (BotEnv -> RetryLimit -> BotEnv) -> Lens' BotEnv RetryLimit
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BotEnv -> RetryLimit
botEnvRetryLimit ((BotEnv -> RetryLimit -> BotEnv) -> Lens' BotEnv RetryLimit)
-> (BotEnv -> RetryLimit -> BotEnv) -> Lens' BotEnv RetryLimit
forall a b. (a -> b) -> a -> b
$ \BotEnv
x RetryLimit
v  BotEnv
x { botEnvRetryLimit = v }
  retryDelay :: Lens' BotEnv RetryDelay
retryDelay = (BotEnv -> RetryDelay)
-> (BotEnv -> RetryDelay -> BotEnv) -> Lens' BotEnv RetryDelay
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BotEnv -> RetryDelay
botEnvRetryDelay ((BotEnv -> RetryDelay -> BotEnv) -> Lens' BotEnv RetryDelay)
-> (BotEnv -> RetryDelay -> BotEnv) -> Lens' BotEnv RetryDelay
forall a b. (a -> b) -> a -> b
$ \BotEnv
x RetryDelay
v  BotEnv
x { botEnvRetryDelay = v }

instance BotJobsQueue.HasBotJobsReader BotEnv where
  botJobsReader :: Getter BotEnv (STM BotJob)
botJobsReader = (BotEnv -> BotJobsQueue)
-> (BotJobsQueue -> f BotJobsQueue) -> BotEnv -> f BotEnv
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
Lens.to BotEnv -> BotJobsQueue
botEnvJobsQueue ((BotJobsQueue -> f BotJobsQueue) -> BotEnv -> f BotEnv)
-> ((STM BotJob -> f (STM BotJob))
    -> BotJobsQueue -> f BotJobsQueue)
-> (STM BotJob -> f (STM BotJob))
-> BotEnv
-> f BotEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (STM BotJob -> f (STM BotJob)) -> BotJobsQueue -> f BotJobsQueue
forall r. HasBotJobsReader r => Getter r (STM BotJob)
Getter BotJobsQueue (STM BotJob)
BotJobsQueue.botJobsReader

instance BotJobsQueue.HasBotJobsWriter BotEnv where
  botJobsWriter :: Getter BotEnv (BotJob -> STM ())
botJobsWriter = (BotEnv -> BotJobsQueue)
-> (BotJobsQueue -> f BotJobsQueue) -> BotEnv -> f BotEnv
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
Lens.to BotEnv -> BotJobsQueue
botEnvJobsQueue ((BotJobsQueue -> f BotJobsQueue) -> BotEnv -> f BotEnv)
-> (((BotJob -> STM ()) -> f (BotJob -> STM ()))
    -> BotJobsQueue -> f BotJobsQueue)
-> ((BotJob -> STM ()) -> f (BotJob -> STM ()))
-> BotEnv
-> f BotEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((BotJob -> STM ()) -> f (BotJob -> STM ()))
-> BotJobsQueue -> f BotJobsQueue
forall r. HasBotJobsWriter r => Getter r (BotJob -> STM ())
Getter BotJobsQueue (BotJob -> STM ())
BotJobsQueue.botJobsWriter


data SendMessageResponse = SendMessageResponse
  { SendMessageResponse -> TransactionId
sendMessageResponseTransactionId  T.TransactionId
  , SendMessageResponse -> EventResponse
sendMessageResponseResponse  EventResponse
  }
  deriving stock ((forall x. SendMessageResponse -> Rep SendMessageResponse x)
-> (forall x. Rep SendMessageResponse x -> SendMessageResponse)
-> Generic SendMessageResponse
forall x. Rep SendMessageResponse x -> SendMessageResponse
forall x. SendMessageResponse -> Rep SendMessageResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SendMessageResponse -> Rep SendMessageResponse x
from :: forall x. SendMessageResponse -> Rep SendMessageResponse x
$cto :: forall x. Rep SendMessageResponse x -> SendMessageResponse
to :: forall x. Rep SendMessageResponse x -> SendMessageResponse
Generic, SendMessageResponse -> SendMessageResponse -> Bool
(SendMessageResponse -> SendMessageResponse -> Bool)
-> (SendMessageResponse -> SendMessageResponse -> Bool)
-> Eq SendMessageResponse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SendMessageResponse -> SendMessageResponse -> Bool
== :: SendMessageResponse -> SendMessageResponse -> Bool
$c/= :: SendMessageResponse -> SendMessageResponse -> Bool
/= :: SendMessageResponse -> SendMessageResponse -> Bool
Eq, Int -> SendMessageResponse -> String -> String
[SendMessageResponse] -> String -> String
SendMessageResponse -> String
(Int -> SendMessageResponse -> String -> String)
-> (SendMessageResponse -> String)
-> ([SendMessageResponse] -> String -> String)
-> Show SendMessageResponse
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> SendMessageResponse -> String -> String
showsPrec :: Int -> SendMessageResponse -> String -> String
$cshow :: SendMessageResponse -> String
show :: SendMessageResponse -> String
$cshowList :: [SendMessageResponse] -> String -> String
showList :: [SendMessageResponse] -> String -> String
Show)

instance ToJSON SendMessageResponse where toJSON :: SendMessageResponse -> Value
toJSON = SendMessageResponse -> Value
forall a.
(Generic a, Typeable a, GToJSON' Value Zero (Rep a)) =>
a -> Value
myGenericToJSON
instance FromJSON SendMessageResponse where parseJSON :: Value -> Parser SendMessageResponse
parseJSON = Value -> Parser SendMessageResponse
forall a.
(Generic a, Typeable a, GFromJSON Zero (Rep a)) =>
Value -> Parser a
myGenericParseJSON


-- * Helpers

-- | Wrap a string into quotes
quoted  (IsString s, Show s)  s  Text
quoted :: forall s. (IsString s, Show s) => s -> Text
quoted = String -> Text
pack (String -> Text) -> (s -> String) -> s -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> String
forall a. Show a => a -> String
show