{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Redundant <&>" #-}
module MatrixBot.Bot.EventsListener
( eventsListener
) where
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Aeson (eitherDecodeStrict, encodeFile)
import qualified Data.ByteString as BS
import Data.Data (Proxy(Proxy))
import Data.Function (fix)
import Data.Functor ((<&>))
import Data.Functor.Identity (Identity(runIdentity))
import Data.Text (pack)
import qualified MatrixBot.Bot.BotConfig as BotConfig
import MatrixBot.Bot.BotM (BotM)
import MatrixBot.Bot.EventsListener.Handlers.ReactToUsers (reactToUsers)
import MatrixBot.Bot.Retry (retryOnClientError)
import qualified MatrixBot.Log as L
import qualified MatrixBot.MatrixApi as Api
import qualified MatrixBot.MatrixApi.Client as Api
import qualified MatrixBot.MatrixApi.Types.MEventTypes as Api
import qualified MatrixBot.SharedTypes as T
import Servant.API (AuthProtect)
import Servant.Client.Core (AuthenticatedRequest)
import System.Directory (doesFileExist)
import MatrixBot.Bot.Jobs.Queue (HasBotJobsWriter)
import Data.Maybe (fromMaybe)
import MatrixBot.Bot.EventsListener.Handlers.ReplyToMedia (replyToMedia)
eventsListener
∷ ∀ r m
. (BotM r m, HasBotJobsWriter r)
⇒ Maybe FilePath
→ T.EventsTimeout
→ BotConfig.BotConfig
→ Api.MatrixApiClient
→ AuthenticatedRequest (AuthProtect "access-token")
→ m ()
eventsListener :: forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
Maybe FilePath
-> EventsTimeout
-> BotConfig
-> MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> m ()
eventsListener Maybe FilePath
eventTokenFile EventsTimeout
eventsTimeout BotConfig
botConfig MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth = do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Starting Matrix rooms events listener…"
Maybe EventToken
initialEventToken ←
case Maybe FilePath
eventTokenFile of
Maybe FilePath
Nothing → do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logWarn Text
"No event token file provided, listening starting from next following events…"
Maybe EventToken -> m (Maybe EventToken)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe EventToken
forall a. Maybe a
Nothing
Just FilePath
file → do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Checking if ", FilePath -> Text
pack (FilePath -> Text)
-> (Maybe FilePath -> FilePath) -> Maybe FilePath -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe FilePath -> FilePath
forall a. Show a => a -> FilePath
show (Maybe FilePath -> Text) -> Maybe FilePath -> Text
forall a b. (a -> b) -> a -> b
$ Maybe FilePath
eventTokenFile
, Text
" token file exists to read initial event token from…"
]
Bool
exists ← IO Bool -> m Bool
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
doesFileExist FilePath
file)
if Bool -> Bool
not Bool
exists
then
(Maybe EventToken
forall a. Maybe a
Nothing Maybe EventToken -> m () -> m (Maybe EventToken)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe EventToken))
-> (Text -> m ()) -> Text -> m (Maybe EventToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m (Maybe EventToken)) -> Text -> m (Maybe EventToken)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Event token file ", FilePath -> Text
pack (FilePath -> Text)
-> (Maybe FilePath -> FilePath) -> Maybe FilePath -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe FilePath -> FilePath
forall a. Show a => a -> FilePath
show (Maybe FilePath -> Text) -> Maybe FilePath -> Text
forall a b. (a -> b) -> a -> b
$ Maybe FilePath
eventTokenFile
, Text
" does not exist, listening starting from next following events…"
]
else
IO ByteString -> m ByteString
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO ByteString
BS.readFile FilePath
file) m ByteString
-> (ByteString -> Either FilePath EventToken)
-> m (Either FilePath EventToken)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> ByteString -> Either FilePath EventToken
forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict m (Either FilePath EventToken)
-> (Either FilePath EventToken -> m (Maybe EventToken))
-> m (Maybe EventToken)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Right EventToken
x →
(EventToken -> Maybe EventToken
forall a. a -> Maybe a
Just EventToken
x Maybe EventToken -> m () -> m (Maybe EventToken)
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (m () -> m (Maybe EventToken))
-> (Text -> m ()) -> Text -> m (Maybe EventToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m (Maybe EventToken)) -> Text -> m (Maybe EventToken)
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Read and parsed last event token from ", FilePath -> Text
pack (FilePath -> Text) -> (FilePath -> FilePath) -> FilePath -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
forall a. Show a => a -> FilePath
show (FilePath -> Text) -> FilePath -> Text
forall a b. (a -> b) -> a -> b
$ FilePath
file
, Text
" file, listening for next events starting from: ", FilePath -> Text
pack (FilePath -> Text)
-> (EventToken -> FilePath) -> EventToken -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath)
-> (EventToken -> Text) -> EventToken -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventToken -> Text
T.unEventToken (EventToken -> Text) -> EventToken -> Text
forall a b. (a -> b) -> a -> b
$ EventToken
x
]
Left FilePath
e →
FilePath -> m (Maybe EventToken)
forall a. FilePath -> m a
forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail (FilePath -> m (Maybe EventToken))
-> FilePath -> m (Maybe EventToken)
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
forall a. Monoid a => [a] -> a
mconcat
[ FilePath
"Failed to read event token from ", FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
file
, FilePath
" event token file: ", FilePath
e
]
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Listening for events from all rooms filtering them accordingly to the bot config…"
((Maybe EventToken -> m ()) -> Maybe EventToken -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe EventToken
initialEventToken) ((Maybe EventToken -> m ()) -> m ())
-> (((Maybe EventToken -> m ()) -> Maybe EventToken -> m ())
-> Maybe EventToken -> m ())
-> ((Maybe EventToken -> m ()) -> Maybe EventToken -> m ())
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe EventToken -> m ()) -> Maybe EventToken -> m ())
-> Maybe EventToken -> m ()
forall a. (a -> a) -> a
fix (((Maybe EventToken -> m ()) -> Maybe EventToken -> m ()) -> m ())
-> ((Maybe EventToken -> m ()) -> Maybe EventToken -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \Maybe EventToken -> m ()
again Maybe EventToken
eventToken → do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Waiting for next room events chunk…"
EventsResponse
eventsReponse ← m EventsResponse -> m EventsResponse
forall (m :: * -> *) r a.
(MonadMask m, MonadLogger m, MonadIO m, MonadReader r m,
HasRetryParams r) =>
m a -> m a
retryOnClientError (m EventsResponse -> m EventsResponse)
-> m EventsResponse -> m EventsResponse
forall a b. (a -> b) -> a -> b
$ Maybe EventToken -> m EventsResponse
getNextEvents' Maybe EventToken
eventToken
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Received next events chunk: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (FilePath -> Text
pack (FilePath -> Text)
-> (EventsResponse -> FilePath) -> EventsResponse -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventsResponse -> FilePath
forall a. Show a => a -> FilePath
show) EventsResponse
eventsReponse
let events :: [ClientEvent]
events = EventsResponse -> [ClientEvent]
Api.eventsResponseChunk EventsResponse
eventsReponse
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Handling " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (FilePath -> Text
pack (FilePath -> Text)
-> ([ClientEvent] -> FilePath) -> [ClientEvent] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> FilePath
forall a. Show a => a -> FilePath
show (Int -> FilePath)
-> ([ClientEvent] -> Int) -> [ClientEvent] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ClientEvent] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) [ClientEvent]
events Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" events…"
(ClientEvent -> m ()) -> [ClientEvent] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (BotConfig -> ClientEvent -> m ()
forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
BotConfig -> ClientEvent -> m ()
handleEvent BotConfig
botConfig) [ClientEvent]
events
let nextEventToken :: EventToken
nextEventToken = EventsResponse -> EventToken
Api.eventsResponseEnd EventsResponse
eventsReponse
case Maybe FilePath
eventTokenFile of
Maybe FilePath
Nothing → () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just FilePath
_ | Maybe EventToken
eventToken Maybe EventToken -> Maybe EventToken -> Bool
forall a. Eq a => a -> a -> Bool
== EventToken -> Maybe EventToken
forall a. a -> Maybe a
Just EventToken
nextEventToken →
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Received event token ", FilePath -> Text
pack (FilePath -> Text)
-> (EventToken -> FilePath) -> EventToken -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath)
-> (EventToken -> Text) -> EventToken -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventToken -> Text
T.unEventToken (EventToken -> Text) -> EventToken -> Text
forall a b. (a -> b) -> a -> b
$ EventToken
nextEventToken
, Text
"didn’t change since the last time, no need to save it again, skipping save…"
]
Just FilePath
_ | [ClientEvent] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ClientEvent]
events →
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug
Text
"Received list of events is empty, skipping save of event token to event token file…"
Just FilePath
file → do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Saving received event token ", FilePath -> Text
pack (FilePath -> Text)
-> (EventToken -> FilePath) -> EventToken -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath)
-> (EventToken -> Text) -> EventToken -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventToken -> Text
T.unEventToken (EventToken -> Text) -> EventToken -> Text
forall a b. (a -> b) -> a -> b
$ EventToken
nextEventToken
, Text
" to ", FilePath -> Text
pack (FilePath -> Text)
-> (Maybe FilePath -> FilePath) -> Maybe FilePath -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe FilePath -> FilePath
forall a. Show a => a -> FilePath
show (Maybe FilePath -> Text) -> Maybe FilePath -> Text
forall a b. (a -> b) -> a -> b
$ Maybe FilePath
eventTokenFile, Text
" event token file…"
]
IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> EventToken -> IO ()
forall a. ToJSON a => FilePath -> a -> IO ()
encodeFile FilePath
file EventToken
nextEventToken
Maybe EventToken -> m ()
again (Maybe EventToken -> m ())
-> (EventToken -> Maybe EventToken) -> EventToken -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventToken -> Maybe EventToken
forall a. a -> Maybe a
Just (EventToken -> m ()) -> EventToken -> m ()
forall a b. (a -> b) -> a -> b
$ EventToken
nextEventToken
where
getNextEvents' ∷ Maybe T.EventToken → m Api.EventsResponse
getNextEvents' :: Maybe EventToken -> m EventsResponse
getNextEvents' = EventsTimeout
-> MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> Maybe EventToken
-> m EventsResponse
forall r (m :: * -> *).
BotM r m =>
EventsTimeout
-> MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> Maybe EventToken
-> m EventsResponse
getNextEvents EventsTimeout
eventsTimeout MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth
getNextEvents
∷ BotM r m
⇒ T.EventsTimeout
→ Api.MatrixApiClient
→ AuthenticatedRequest (AuthProtect "access-token")
→ Maybe T.EventToken
→ m Api.EventsResponse
getNextEvents :: forall r (m :: * -> *).
BotM r m =>
EventsTimeout
-> MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> Maybe EventToken
-> m EventsResponse
getNextEvents EventsTimeout
eventsTimeout MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth Maybe EventToken
eventToken =
MatrixApiClient
-> forall api (m :: * -> *) a.
(MonadIO m, MonadFail m, Show a, MonadThrow m, MonadLogger m,
HasClient (Free ClientF) api, HasClient ClientM api) =>
Proxy api
-> (forall (clientM :: * -> *).
HasClient clientM api =>
Client clientM api -> clientM a)
-> m a
Api.runMatrixApiClient' MatrixApiClient
req (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Api.EventsApi) ((forall {clientM :: * -> *}.
HasClient clientM EventsApi =>
Client clientM EventsApi -> clientM EventsResponse)
-> m EventsResponse)
-> (forall {clientM :: * -> *}.
HasClient clientM EventsApi =>
Client clientM EventsApi -> clientM EventsResponse)
-> m EventsResponse
forall a b. (a -> b) -> a -> b
$ \Client clientM EventsApi
f → Client clientM EventsApi
AuthenticatedRequest (AuthProtect "access-token")
-> Maybe EventToken
-> Maybe RoomId
-> Maybe Milliseconds
-> clientM EventsResponse
f
AuthenticatedRequest (AuthProtect "access-token")
auth
Maybe EventToken
eventToken
Maybe RoomId
forall a. Maybe a
Nothing
(Milliseconds -> Maybe Milliseconds
forall a. a -> Maybe a
Just (Milliseconds -> Maybe Milliseconds)
-> (EventsTimeout -> Milliseconds)
-> EventsTimeout
-> Maybe Milliseconds
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seconds -> Milliseconds
T.secondsToMilliseconds (Seconds -> Milliseconds)
-> (EventsTimeout -> Seconds) -> EventsTimeout -> Milliseconds
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventsTimeout -> Seconds
T.unEventsTimeout (EventsTimeout -> Maybe Milliseconds)
-> EventsTimeout -> Maybe Milliseconds
forall a b. (a -> b) -> a -> b
$ EventsTimeout
eventsTimeout)
handleEvent ∷ (BotM r m, HasBotJobsWriter r) ⇒ BotConfig.BotConfig → Api.ClientEvent → m ()
handleEvent :: forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
BotConfig -> ClientEvent -> m ()
handleEvent BotConfig
botConfig ClientEvent
ev = do
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Handling event: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (FilePath -> Text
pack (FilePath -> Text)
-> (ClientEvent -> FilePath) -> ClientEvent -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientEvent -> FilePath
forall a. Show a => a -> FilePath
show) ClientEvent
ev
case ClientEvent
ev of
Api.ClientEventMRoomMessage ClientEventGeneric Identity
g MRoomMessageClientEvent
m → do
let
roomId :: RoomId
roomId = Identity RoomId -> RoomId
forall a. Identity a -> a
runIdentity (Identity RoomId -> RoomId)
-> (ClientEventGeneric Identity -> Identity RoomId)
-> ClientEventGeneric Identity
-> RoomId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientEventGeneric Identity -> Identity RoomId
forall (f :: * -> *). ClientEventGeneric f -> f RoomId
Api.clientEventGenericRoomId (ClientEventGeneric Identity -> RoomId)
-> ClientEventGeneric Identity -> RoomId
forall a b. (a -> b) -> a -> b
$ ClientEventGeneric Identity
g
userId :: Mxid
userId = Identity Mxid -> Mxid
forall a. Identity a -> a
runIdentity (Identity Mxid -> Mxid)
-> (ClientEventGeneric Identity -> Identity Mxid)
-> ClientEventGeneric Identity
-> Mxid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientEventGeneric Identity -> Identity Mxid
forall (f :: * -> *). ClientEventGeneric f -> f Mxid
Api.clientEventGenericSender (ClientEventGeneric Identity -> Mxid)
-> ClientEventGeneric Identity -> Mxid
forall a b. (a -> b) -> a -> b
$ ClientEventGeneric Identity
g
eventId :: EventId
eventId = Identity EventId -> EventId
forall a. Identity a -> a
runIdentity (Identity EventId -> EventId)
-> (ClientEventGeneric Identity -> Identity EventId)
-> ClientEventGeneric Identity
-> EventId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientEventGeneric Identity -> Identity EventId
forall (f :: * -> *). ClientEventGeneric f -> f EventId
Api.clientEventGenericEventId (ClientEventGeneric Identity -> EventId)
-> ClientEventGeneric Identity -> EventId
forall a b. (a -> b) -> a -> b
$ ClientEventGeneric Identity
g
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Received "
, MEventType -> Text
forall s. IsString s => MEventType -> s
Api.mEventTypeToString (MEventType -> Text)
-> (MRoomMessageClientEvent -> MEventType)
-> MRoomMessageClientEvent
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MEventTypeOneOf '[ 'MRoomMessageType] -> MEventType
forall (t :: MEventType) (ts :: [MEventType]).
MEventTypeOneOf (t : ts) -> MEventType
Api.mEventTypeOneOfToMEventType (MEventTypeOneOf '[ 'MRoomMessageType] -> MEventType)
-> (MRoomMessageClientEvent
-> MEventTypeOneOf '[ 'MRoomMessageType])
-> MRoomMessageClientEvent
-> MEventType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MRoomMessageClientEvent -> MEventTypeOneOf '[ 'MRoomMessageType]
Api.mRoomMessageClientEventType (MRoomMessageClientEvent -> Text)
-> MRoomMessageClientEvent -> Text
forall a b. (a -> b) -> a -> b
$ MRoomMessageClientEvent
m
, Text
" event type from room ", RoomId -> Text
T.printRoomId RoomId
roomId
, Text
" from user ", Mxid -> Text
T.printMxid Mxid
userId
, Text
" (event ID: ", EventId -> Text
T.unEventId EventId
eventId, Text
")"
]
[BotConfigReactToUsers] -> RoomId -> Mxid -> EventId -> m ()
forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
[BotConfigReactToUsers] -> RoomId -> Mxid -> EventId -> m ()
reactToUsers
([BotConfigReactToUsers]
-> Maybe [BotConfigReactToUsers] -> [BotConfigReactToUsers]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [BotConfigReactToUsers] -> [BotConfigReactToUsers])
-> Maybe [BotConfigReactToUsers] -> [BotConfigReactToUsers]
forall a b. (a -> b) -> a -> b
$ BotConfig -> Maybe [BotConfigReactToUsers]
BotConfig.botConfigReactToUsers BotConfig
botConfig)
RoomId
roomId
Mxid
userId
EventId
eventId
[BotConfigReplyToMedia]
-> RoomId
-> Mxid
-> EventId
-> MRoomMessageClientEventContent
-> m ()
forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
[BotConfigReplyToMedia]
-> RoomId
-> Mxid
-> EventId
-> MRoomMessageClientEventContent
-> m ()
replyToMedia
([BotConfigReplyToMedia]
-> Maybe [BotConfigReplyToMedia] -> [BotConfigReplyToMedia]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [BotConfigReplyToMedia] -> [BotConfigReplyToMedia])
-> Maybe [BotConfigReplyToMedia] -> [BotConfigReplyToMedia]
forall a b. (a -> b) -> a -> b
$ BotConfig -> Maybe [BotConfigReplyToMedia]
BotConfig.botConfigReplyToMedia BotConfig
botConfig)
RoomId
roomId
Mxid
userId
EventId
eventId
(MRoomMessageClientEvent -> MRoomMessageClientEventContent
Api.mRoomMessageClientEventContent MRoomMessageClientEvent
m)
Api.ClientEventOther ClientEventGeneric Maybe
g Object
_ →
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"No need to handle " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ClientEventGeneric Maybe -> Text
forall (f :: * -> *). ClientEventGeneric f -> Text
Api.clientEventGenericType ClientEventGeneric Maybe
g Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" event type (skipped)"