{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ViewPatterns #-}
module MatrixBot.Bot.EventsListener.Handlers.ReplyToMedia
( replyToMedia
) where
import qualified Control.Lens as Lens
import qualified Control.Monad.Logger as ML
import qualified Control.Monad.Trans.Except as Except
import qualified Data.Attoparsec.Text as AP
import Data.Text (pack, Text)
import qualified MatrixBot.Bot.BotConfig as BotConfig
import MatrixBot.Bot.BotM (BotM)
import qualified MatrixBot.Bot.EventsListener.Filters as Filters
import MatrixBot.Bot.Jobs.BotJob (BotJob (BotJobSendMessage))
import MatrixBot.Bot.Jobs.Queue (HasBotJobsWriter (botJobsWriter))
import qualified MatrixBot.Log as L
import qualified MatrixBot.MatrixApi as Api
import qualified MatrixBot.SharedTypes as T
import qualified UnliftIO.STM as STM
import Data.Functor ((<&>))
replyToMedia
∷ ∀r m. (BotM r m, HasBotJobsWriter r)
⇒ [BotConfig.BotConfigReplyToMedia]
→ T.RoomId
→ T.Mxid
→ T.EventId
→ Api.MRoomMessageClientEventContent
→ m ()
replyToMedia :: forall r (m :: * -> *).
(BotM r m, HasBotJobsWriter r) =>
[BotConfigReplyToMedia]
-> RoomId
-> Mxid
-> EventId
-> MRoomMessageClientEventContent
-> m ()
replyToMedia [] RoomId
_ Mxid
_ EventId
_ MRoomMessageClientEventContent
_ =
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
"There is no configuration entries for “reply to media” feature. "
, Text
"No replies/messages will be posted for the event."
]
replyToMedia [BotConfigReplyToMedia]
configEntries RoomId
roomId Mxid
userId EventId
eventId MRoomMessageClientEventContent
clientContent = do
case MRoomMessageClientEventContent
clientContent of
(MRoomMessageClientEventContent -> Maybe MediaEventData
mkMediaEventDataFromClientContent → Just MediaEventData
mediaData) →
MediaEventData -> (ExtractedMediaValues -> m ()) -> m ()
forall (m :: * -> *).
MonadLogger m =>
MediaEventData -> (ExtractedMediaValues -> m ()) -> m ()
withExtractedMediaValues MediaEventData
mediaData ((ExtractedMediaValues -> m ()) -> m ())
-> (ExtractedMediaValues -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \ExtractedMediaValues
extractMediaValues →
m ()
logProcessing m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (BotConfigReplyToMedia -> m ()) -> [BotConfigReplyToMedia] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (MediaEventData
-> ExtractedMediaValues -> BotConfigReplyToMedia -> m ()
handleEntry MediaEventData
mediaData ExtractedMediaValues
extractMediaValues) [BotConfigReplyToMedia]
configEntries
MRoomMessageClientEventContent
_ →
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
"This event type is not a detected media file one. "
, Text
"“Reply to media” handling is skipped for this event."
]
where
logProcessing :: m ()
logProcessing =
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Going through “reply to media” configuration to see if this event is matching…"
resolveFilter :: Either Text () -> m ()
resolveFilter =
((Text -> m ()) -> (() -> m ()) -> Either Text () -> m ())
-> (() -> m ()) -> (Text -> m ()) -> Either Text () -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Text -> m ()) -> (() -> m ()) -> Either Text () -> m ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Text -> m ()) -> Either Text () -> m ())
-> (Text -> m ()) -> Either Text () -> m ()
forall a b. (a -> b) -> a -> b
$
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> m ()) -> (Text -> Text) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"Event mismatched filter (skipping this replying to media config entry): " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)
handleEntry ∷ MediaEventData → ExtractedMediaValues → BotConfig.BotConfigReplyToMedia → m ()
handleEntry :: MediaEventData
-> ExtractedMediaValues -> BotConfigReplyToMedia -> m ()
handleEntry MediaEventData
mediaEventData ExtractedMediaValues
extractedMediaValues BotConfigReplyToMedia
entry = (Either Text () -> m ()
resolveFilter (Either Text () -> m ()) -> m (Either Text ()) -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) (m (Either Text ()) -> m ()) -> m (Either Text ()) -> m ()
forall a b. (a -> b) -> a -> b
$ ExceptT Text m () -> m (Either Text ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
Except.runExceptT (ExceptT Text m () -> m (Either Text ()))
-> ExceptT Text m () -> m (Either Text ())
forall a b. (a -> b) -> a -> b
$ do
Text -> ExceptT Text m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> ExceptT Text m ()) -> Text -> ExceptT Text m ()
forall a b. (a -> b) -> a -> b
$ Text
"Handling reply to media config entry: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (String -> Text
pack (String -> Text)
-> (BotConfigReplyToMedia -> String)
-> BotConfigReplyToMedia
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BotConfigReplyToMedia -> String
forall a. Show a => a -> String
show) BotConfigReplyToMedia
entry
Maybe UsersFilter -> Mxid -> ExceptT Text m ()
forall (m :: * -> *).
MonadLogger m =>
Maybe UsersFilter -> Mxid -> ExceptT Text m ()
Filters.filterByUser (BotConfigReplyToMedia -> Maybe UsersFilter
BotConfig.botConfigReplyToMediaUsersFilter BotConfigReplyToMedia
entry) Mxid
userId
Maybe RoomsFilter -> RoomId -> ExceptT Text m ()
forall (m :: * -> *).
MonadLogger m =>
Maybe RoomsFilter -> RoomId -> ExceptT Text m ()
Filters.filterByRoom (BotConfigReplyToMedia -> Maybe RoomsFilter
BotConfig.botConfigReplyToMediaRoomsFilter BotConfigReplyToMedia
entry) RoomId
roomId
Maybe MediaMsgtypeFilter
-> MRoomMessageClientEventContent -> ExceptT Text m ()
forall (m :: * -> *).
MonadLogger m =>
Maybe MediaMsgtypeFilter
-> MRoomMessageClientEventContent -> ExceptT Text m ()
Filters.filterByMediaMsgtype (BotConfigReplyToMedia -> Maybe MediaMsgtypeFilter
BotConfig.botConfigReplyToMediaMsgtypeFilter BotConfigReplyToMedia
entry) MRoomMessageClientEventContent
clientContent
let
replyMessage :: Text
replyMessage =
[BotConfigReplyToMedia_MessageTemplateEntry]
-> MediaEventData -> ExtractedMediaValues -> Text
renderTemplate
(BotConfigReplyToMedia
-> [BotConfigReplyToMedia_MessageTemplateEntry]
BotConfig.botConfigReplyToMediaMessageTemplate BotConfigReplyToMedia
entry)
MediaEventData
mediaEventData
ExtractedMediaValues
extractedMediaValues
htmlReplyMessage :: Maybe Text
htmlReplyMessage =
BotConfigReplyToMedia
-> Maybe [BotConfigReplyToMedia_MessageTemplateEntry]
BotConfig.botConfigReplyToMediaHtmlMessageTemplate BotConfigReplyToMedia
entry Maybe [BotConfigReplyToMedia_MessageTemplateEntry]
-> ([BotConfigReplyToMedia_MessageTemplateEntry] -> Text)
-> Maybe Text
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \[BotConfigReplyToMedia_MessageTemplateEntry]
x →
[BotConfigReplyToMedia_MessageTemplateEntry]
-> MediaEventData -> ExtractedMediaValues -> Text
renderTemplate [BotConfigReplyToMedia_MessageTemplateEntry]
x MediaEventData
mediaEventData ExtractedMediaValues
extractedMediaValues
Text -> ExceptT Text m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text -> ExceptT Text m ()) -> Text -> ExceptT Text m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Sending a reply message ", (String -> Text
pack (String -> Text) -> (Text -> String) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show) Text
replyMessage
, Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall a. Monoid a => a
mempty ((Text
"(html version: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> (Text -> String) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show) Maybe Text
htmlReplyMessage
, Text
" for event ", EventId -> Text
T.unEventId EventId
eventId
, Text
" in room ", RoomId -> Text
T.printRoomId RoomId
roomId
, Text
"…"
]
TransactionId
transactionId ← ExceptT Text m TransactionId
forall (m :: * -> *). MonadIO m => m TransactionId
T.genTransactionId
Getting (BotJob -> STM ()) r (BotJob -> STM ())
-> ExceptT Text m (BotJob -> STM ())
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
Lens.view Getting (BotJob -> STM ()) r (BotJob -> STM ())
forall r. HasBotJobsWriter r => Getter r (BotJob -> STM ())
Getter r (BotJob -> STM ())
botJobsWriter ExceptT Text m (BotJob -> STM ())
-> ((BotJob -> STM ()) -> ExceptT Text m ()) -> ExceptT Text m ()
forall a b.
ExceptT Text m a -> (a -> ExceptT Text m b) -> ExceptT Text m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \BotJob -> STM ()
sendJob →
STM () -> ExceptT Text m ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
STM.atomically (STM () -> ExceptT Text m ())
-> (BotJob -> STM ()) -> BotJob -> ExceptT Text m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BotJob -> STM ()
sendJob (BotJob -> ExceptT Text m ()) -> BotJob -> ExceptT Text m ()
forall a b. (a -> b) -> a -> b
$
TransactionId
-> RoomId -> Maybe EventId -> Maybe Text -> Text -> BotJob
BotJobSendMessage TransactionId
transactionId RoomId
roomId (EventId -> Maybe EventId
forall a. a -> Maybe a
Just EventId
eventId) Maybe Text
htmlReplyMessage Text
replyMessage
renderTemplate
∷ [BotConfig.BotConfigReplyToMedia_MessageTemplateEntry]
→ MediaEventData
→ ExtractedMediaValues
→ Text
renderTemplate :: [BotConfigReplyToMedia_MessageTemplateEntry]
-> MediaEventData -> ExtractedMediaValues -> Text
renderTemplate [BotConfigReplyToMedia_MessageTemplateEntry]
template MediaEventData
mediaEventData ExtractedMediaValues
extractedMediaValues =
((BotConfigReplyToMedia_MessageTemplateEntry -> Text)
-> [BotConfigReplyToMedia_MessageTemplateEntry] -> Text)
-> [BotConfigReplyToMedia_MessageTemplateEntry]
-> (BotConfigReplyToMedia_MessageTemplateEntry -> Text)
-> Text
forall a b c. (a -> b -> c) -> b -> a -> c
flip (BotConfigReplyToMedia_MessageTemplateEntry -> Text)
-> [BotConfigReplyToMedia_MessageTemplateEntry] -> Text
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap [BotConfigReplyToMedia_MessageTemplateEntry]
template ((BotConfigReplyToMedia_MessageTemplateEntry -> Text) -> Text)
-> (BotConfigReplyToMedia_MessageTemplateEntry -> Text) -> Text
forall a b. (a -> b) -> a -> b
$ \case
BotConfig.BotConfigReplyToMedia_MessageTemplateEntry_PlainString Text
x → Text
x
BotConfig.BotConfigReplyToMedia_MessageTemplateEntry_DynamicSubstitution_Field BotConfigReplyToMedia_DynamicFieldName
x →
case BotConfigReplyToMedia_DynamicFieldName
x of
BotConfigReplyToMedia_DynamicFieldName
BotConfig.BotConfigReplyToMedia_DynamicFieldName_MsgType → MediaEventData -> Text
msgtype MediaEventData
mediaEventData
BotConfigReplyToMedia_DynamicFieldName
BotConfig.BotConfigReplyToMedia_DynamicFieldName_Body → MediaEventData -> Text
body MediaEventData
mediaEventData
BotConfigReplyToMedia_DynamicFieldName
BotConfig.BotConfigReplyToMedia_DynamicFieldName_Url → MediaEventData -> Text
url MediaEventData
mediaEventData
BotConfig.BotConfigReplyToMedia_MessageTemplateEntry_DynamicSubstitution_ExtractedValue BotConfigReplyToMedia_DynamicExtractedValueName
x →
case BotConfigReplyToMedia_DynamicExtractedValueName
x of
BotConfigReplyToMedia_DynamicExtractedValueName
BotConfig.BotConfigReplyToMedia_DynamicExtractedValueName_MediaId →
ExtractedMediaValues -> Text
extractedMediaId ExtractedMediaValues
extractedMediaValues
data MediaEventData = MediaEventData
{ MediaEventData -> Text
msgtype ∷ Text
, MediaEventData -> Text
body ∷ Text
, MediaEventData -> Text
url ∷ Text
}
deriving stock (Int -> MediaEventData -> ShowS
[MediaEventData] -> ShowS
MediaEventData -> String
(Int -> MediaEventData -> ShowS)
-> (MediaEventData -> String)
-> ([MediaEventData] -> ShowS)
-> Show MediaEventData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MediaEventData -> ShowS
showsPrec :: Int -> MediaEventData -> ShowS
$cshow :: MediaEventData -> String
show :: MediaEventData -> String
$cshowList :: [MediaEventData] -> ShowS
showList :: [MediaEventData] -> ShowS
Show, MediaEventData -> MediaEventData -> Bool
(MediaEventData -> MediaEventData -> Bool)
-> (MediaEventData -> MediaEventData -> Bool) -> Eq MediaEventData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MediaEventData -> MediaEventData -> Bool
== :: MediaEventData -> MediaEventData -> Bool
$c/= :: MediaEventData -> MediaEventData -> Bool
/= :: MediaEventData -> MediaEventData -> Bool
Eq)
mkMediaEventDataFromClientContent ∷ Api.MRoomMessageClientEventContent → Maybe MediaEventData
mkMediaEventDataFromClientContent :: MRoomMessageClientEventContent -> Maybe MediaEventData
mkMediaEventDataFromClientContent = \case
Api.MRoomMessageClientEventContentMImage MRoomMessageMImageMsgtypeClientEventContent
x →
MediaEventData -> Maybe MediaEventData
forall a. a -> Maybe a
Just (MediaEventData -> Maybe MediaEventData)
-> MediaEventData -> Maybe MediaEventData
forall a b. (a -> b) -> a -> b
$ MediaEventData
{ msgtype :: Text
msgtype = (MImageType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString (MImageType -> Text)
-> (MRoomMessageMImageMsgtypeClientEventContent -> MImageType)
-> MRoomMessageMImageMsgtypeClientEventContent
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MRoomMessageMImageMsgtypeClientEventContent -> MImageType
Api.mRoomMessageMImageMsgtypeClientEventContentMsgtype) MRoomMessageMImageMsgtypeClientEventContent
x
, body :: Text
body = MRoomMessageMImageMsgtypeClientEventContent -> Text
Api.mRoomMessageMImageMsgtypeClientEventContentBody MRoomMessageMImageMsgtypeClientEventContent
x
, url :: Text
url = MRoomMessageMImageMsgtypeClientEventContent -> Text
Api.mRoomMessageMImageMsgtypeClientEventContentUrl MRoomMessageMImageMsgtypeClientEventContent
x
}
Api.MRoomMessageClientEventContentMVideo MRoomMessageMVideoMsgtypeClientEventContent
x →
MediaEventData -> Maybe MediaEventData
forall a. a -> Maybe a
Just (MediaEventData -> Maybe MediaEventData)
-> MediaEventData -> Maybe MediaEventData
forall a b. (a -> b) -> a -> b
$ MediaEventData
{ msgtype :: Text
msgtype = (MVideoType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString (MVideoType -> Text)
-> (MRoomMessageMVideoMsgtypeClientEventContent -> MVideoType)
-> MRoomMessageMVideoMsgtypeClientEventContent
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MRoomMessageMVideoMsgtypeClientEventContent -> MVideoType
Api.mRoomMessageMVideoMsgtypeClientEventContentMsgtype) MRoomMessageMVideoMsgtypeClientEventContent
x
, body :: Text
body = MRoomMessageMVideoMsgtypeClientEventContent -> Text
Api.mRoomMessageMVideoMsgtypeClientEventContentBody MRoomMessageMVideoMsgtypeClientEventContent
x
, url :: Text
url = MRoomMessageMVideoMsgtypeClientEventContent -> Text
Api.mRoomMessageMVideoMsgtypeClientEventContentUrl MRoomMessageMVideoMsgtypeClientEventContent
x
}
Api.MRoomMessageClientEventContentMAudio MRoomMessageMAudioMsgtypeClientEventContent
x →
MediaEventData -> Maybe MediaEventData
forall a. a -> Maybe a
Just (MediaEventData -> Maybe MediaEventData)
-> MediaEventData -> Maybe MediaEventData
forall a b. (a -> b) -> a -> b
$ MediaEventData
{ msgtype :: Text
msgtype = (MAudioType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString (MAudioType -> Text)
-> (MRoomMessageMAudioMsgtypeClientEventContent -> MAudioType)
-> MRoomMessageMAudioMsgtypeClientEventContent
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MRoomMessageMAudioMsgtypeClientEventContent -> MAudioType
Api.mRoomMessageMAudioMsgtypeClientEventContentMsgtype) MRoomMessageMAudioMsgtypeClientEventContent
x
, body :: Text
body = MRoomMessageMAudioMsgtypeClientEventContent -> Text
Api.mRoomMessageMAudioMsgtypeClientEventContentBody MRoomMessageMAudioMsgtypeClientEventContent
x
, url :: Text
url = MRoomMessageMAudioMsgtypeClientEventContent -> Text
Api.mRoomMessageMAudioMsgtypeClientEventContentUrl MRoomMessageMAudioMsgtypeClientEventContent
x
}
Api.MRoomMessageClientEventContentMFile MRoomMessageMFileMsgtypeClientEventContent
x →
MediaEventData -> Maybe MediaEventData
forall a. a -> Maybe a
Just (MediaEventData -> Maybe MediaEventData)
-> MediaEventData -> Maybe MediaEventData
forall a b. (a -> b) -> a -> b
$ MediaEventData
{ msgtype :: Text
msgtype = (MFileType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString (MFileType -> Text)
-> (MRoomMessageMFileMsgtypeClientEventContent -> MFileType)
-> MRoomMessageMFileMsgtypeClientEventContent
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MRoomMessageMFileMsgtypeClientEventContent -> MFileType
Api.mRoomMessageMFileMsgtypeClientEventContentMsgtype) MRoomMessageMFileMsgtypeClientEventContent
x
, body :: Text
body = MRoomMessageMFileMsgtypeClientEventContent -> Text
Api.mRoomMessageMFileMsgtypeClientEventContentBody MRoomMessageMFileMsgtypeClientEventContent
x
, url :: Text
url = MRoomMessageMFileMsgtypeClientEventContent -> Text
Api.mRoomMessageMFileMsgtypeClientEventContentUrl MRoomMessageMFileMsgtypeClientEventContent
x
}
Api.MRoomMessageClientEventContentMText MRoomMessageMTextMsgtypeClientEventContent
_ → Maybe MediaEventData
forall a. Maybe a
Nothing
Api.MRoomMessageClientEventContentOther Object
_ → Maybe MediaEventData
forall a. Maybe a
Nothing
newtype =
{ ∷ Text
}
deriving stock (Int -> ExtractedMediaValues -> ShowS
[ExtractedMediaValues] -> ShowS
ExtractedMediaValues -> String
(Int -> ExtractedMediaValues -> ShowS)
-> (ExtractedMediaValues -> String)
-> ([ExtractedMediaValues] -> ShowS)
-> Show ExtractedMediaValues
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExtractedMediaValues -> ShowS
showsPrec :: Int -> ExtractedMediaValues -> ShowS
$cshow :: ExtractedMediaValues -> String
show :: ExtractedMediaValues -> String
$cshowList :: [ExtractedMediaValues] -> ShowS
showList :: [ExtractedMediaValues] -> ShowS
Show, ExtractedMediaValues -> ExtractedMediaValues -> Bool
(ExtractedMediaValues -> ExtractedMediaValues -> Bool)
-> (ExtractedMediaValues -> ExtractedMediaValues -> Bool)
-> Eq ExtractedMediaValues
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExtractedMediaValues -> ExtractedMediaValues -> Bool
== :: ExtractedMediaValues -> ExtractedMediaValues -> Bool
$c/= :: ExtractedMediaValues -> ExtractedMediaValues -> Bool
/= :: ExtractedMediaValues -> ExtractedMediaValues -> Bool
Eq)
withExtractedMediaValues
∷ ML.MonadLogger m
⇒ MediaEventData
→ (ExtractedMediaValues → m ())
→ m ()
MediaEventData
mediaEventData ExtractedMediaValues -> m ()
m = do
case Text -> Either String Text
extractMediaIdFromUrl (Text -> Either String Text) -> Text -> Either String Text
forall a b. (a -> b) -> a -> b
$ MediaEventData -> Text
url MediaEventData
mediaEventData of
Right Text
x →
ExtractedMediaValues -> m ()
m ExtractedMediaValues
{ extractedMediaId :: Text
extractedMediaId = Text
x
}
Left String
e →
Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logError (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Failed to extract “media_id” out from “url”: ", (String -> Text
pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. Show a => a -> String
show) String
e
, Text
" (skipping the event for “reply to media” handling)"
]
extractMediaIdFromUrl ∷ Text → Either String Text
= Parser Text -> Text -> Either String Text
forall a. Parser a -> Text -> Either String a
AP.parseOnly Parser Text
parser
where
parser ∷ AP.Parser Text
parser :: Parser Text
parser
= Text -> Parser Text
AP.string Text
"mxc://"
Parser Text -> Parser Text String -> Parser Text String
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
AP.many1 (Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
AP.many1 ((Char -> Bool) -> Parser Text Char
AP.satisfy (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/')) Parser Text String -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Char -> Parser Text Char
AP.char Char
'/')
Parser Text String -> Parser Text -> Parser Text
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text
AP.takeText
Parser Text -> Parser Text () -> Parser Text
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
AP.endOfInput