{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Use camelCase" #-}
module MatrixBot.Bot.EventsListener.Filters
( UsersFilter
, filterByUser
, RoomsFilter
, filterByRoom
, MediaMsgtypeFilter
, MediaMsgtype (..)
, filterByMediaMsgtype
) where
import qualified Control.Monad.Trans.Except as Except
import Data.Text (Text, pack)
import qualified MatrixBot.SharedTypes as T
import qualified Data.List.NonEmpty as NE
import qualified MatrixBot.Log as L
import qualified Control.Monad.Logger as ML
import qualified MatrixBot.MatrixApi as Api
import GHC.Generics (Generic)
import qualified Data.Aeson as J
import Data.List (find)
type UsersFilter = NE.NonEmpty T.Mxid
filterByUser
∷ ML.MonadLogger m
⇒ Maybe UsersFilter
→ T.Mxid
→ Except.ExceptT Text m ()
filterByUser :: forall (m :: * -> *).
MonadLogger m =>
Maybe UsersFilter -> Mxid -> ExceptT Text m ()
filterByUser Maybe UsersFilter
usersFilter Mxid
userId =
case Maybe UsersFilter
usersFilter of
Maybe UsersFilter
Nothing →
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
"There is no user filter"
, Text
" (filter passed)"
]
Just UsersFilter
x | Mxid
userId Mxid -> UsersFilter -> Bool
forall a. Eq a => a -> NonEmpty a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` UsersFilter
x →
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
"User ", Mxid -> Text
T.printMxid Mxid
userId
, Text
" is one of these: ", (String -> Text
pack (String -> Text) -> (UsersFilter -> String) -> UsersFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsersFilter -> String
forall a. Show a => a -> String
show) UsersFilter
x
, Text
" (filter passed)"
]
Just UsersFilter
x →
Text -> ExceptT Text m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
Except.throwE (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
"User ", Mxid -> Text
T.printMxid Mxid
userId
, Text
" is not one of these: ", (String -> Text
pack (String -> Text) -> (UsersFilter -> String) -> UsersFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsersFilter -> String
forall a. Show a => a -> String
show) UsersFilter
x
, Text
" (filter not passed)"
]
type RoomsFilter = NE.NonEmpty T.RoomId
filterByRoom
∷ ML.MonadLogger m
⇒ Maybe RoomsFilter
→ T.RoomId
→ Except.ExceptT Text m ()
filterByRoom :: forall (m :: * -> *).
MonadLogger m =>
Maybe RoomsFilter -> RoomId -> ExceptT Text m ()
filterByRoom Maybe RoomsFilter
roomsFilter RoomId
roomId =
case Maybe RoomsFilter
roomsFilter of
Maybe RoomsFilter
Nothing →
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
"There is no room filter"
, Text
" (filter passed)"
]
Just RoomsFilter
x | RoomId
roomId RoomId -> RoomsFilter -> Bool
forall a. Eq a => a -> NonEmpty a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` RoomsFilter
x →
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
"Room ", RoomId -> Text
T.printRoomId RoomId
roomId
, Text
" is one of these: ", (String -> Text
pack (String -> Text) -> (RoomsFilter -> String) -> RoomsFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomsFilter -> String
forall a. Show a => a -> String
show) RoomsFilter
x
, Text
" (filter passed)"
]
Just RoomsFilter
x →
Text -> ExceptT Text m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
Except.throwE (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
"Room ", RoomId -> Text
T.printRoomId RoomId
roomId
, Text
" is not one of these: ", (String -> Text
pack (String -> Text) -> (RoomsFilter -> String) -> RoomsFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoomsFilter -> String
forall a. Show a => a -> String
show) RoomsFilter
x
, Text
" (filter not passed)"
]
type MediaMsgtypeFilter = NE.NonEmpty MediaMsgtype
data MediaMsgtype
= MediaMsgtype_File
| MediaMsgtype_Image
| MediaMsgtype_Video
| MediaMsgtype_Audio
deriving stock ((forall x. MediaMsgtype -> Rep MediaMsgtype x)
-> (forall x. Rep MediaMsgtype x -> MediaMsgtype)
-> Generic MediaMsgtype
forall x. Rep MediaMsgtype x -> MediaMsgtype
forall x. MediaMsgtype -> Rep MediaMsgtype x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. MediaMsgtype -> Rep MediaMsgtype x
from :: forall x. MediaMsgtype -> Rep MediaMsgtype x
$cto :: forall x. Rep MediaMsgtype x -> MediaMsgtype
to :: forall x. Rep MediaMsgtype x -> MediaMsgtype
Generic, MediaMsgtype -> MediaMsgtype -> Bool
(MediaMsgtype -> MediaMsgtype -> Bool)
-> (MediaMsgtype -> MediaMsgtype -> Bool) -> Eq MediaMsgtype
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MediaMsgtype -> MediaMsgtype -> Bool
== :: MediaMsgtype -> MediaMsgtype -> Bool
$c/= :: MediaMsgtype -> MediaMsgtype -> Bool
/= :: MediaMsgtype -> MediaMsgtype -> Bool
Eq, Int -> MediaMsgtype -> ShowS
[MediaMsgtype] -> ShowS
MediaMsgtype -> String
(Int -> MediaMsgtype -> ShowS)
-> (MediaMsgtype -> String)
-> ([MediaMsgtype] -> ShowS)
-> Show MediaMsgtype
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MediaMsgtype -> ShowS
showsPrec :: Int -> MediaMsgtype -> ShowS
$cshow :: MediaMsgtype -> String
show :: MediaMsgtype -> String
$cshowList :: [MediaMsgtype] -> ShowS
showList :: [MediaMsgtype] -> ShowS
Show, MediaMsgtype
MediaMsgtype -> MediaMsgtype -> Bounded MediaMsgtype
forall a. a -> a -> Bounded a
$cminBound :: MediaMsgtype
minBound :: MediaMsgtype
$cmaxBound :: MediaMsgtype
maxBound :: MediaMsgtype
Bounded, Int -> MediaMsgtype
MediaMsgtype -> Int
MediaMsgtype -> [MediaMsgtype]
MediaMsgtype -> MediaMsgtype
MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
MediaMsgtype -> MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
(MediaMsgtype -> MediaMsgtype)
-> (MediaMsgtype -> MediaMsgtype)
-> (Int -> MediaMsgtype)
-> (MediaMsgtype -> Int)
-> (MediaMsgtype -> [MediaMsgtype])
-> (MediaMsgtype -> MediaMsgtype -> [MediaMsgtype])
-> (MediaMsgtype -> MediaMsgtype -> [MediaMsgtype])
-> (MediaMsgtype -> MediaMsgtype -> MediaMsgtype -> [MediaMsgtype])
-> Enum MediaMsgtype
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: MediaMsgtype -> MediaMsgtype
succ :: MediaMsgtype -> MediaMsgtype
$cpred :: MediaMsgtype -> MediaMsgtype
pred :: MediaMsgtype -> MediaMsgtype
$ctoEnum :: Int -> MediaMsgtype
toEnum :: Int -> MediaMsgtype
$cfromEnum :: MediaMsgtype -> Int
fromEnum :: MediaMsgtype -> Int
$cenumFrom :: MediaMsgtype -> [MediaMsgtype]
enumFrom :: MediaMsgtype -> [MediaMsgtype]
$cenumFromThen :: MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
enumFromThen :: MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
$cenumFromTo :: MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
enumFromTo :: MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
$cenumFromThenTo :: MediaMsgtype -> MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
enumFromThenTo :: MediaMsgtype -> MediaMsgtype -> MediaMsgtype -> [MediaMsgtype]
Enum)
instance J.ToJSON MediaMsgtype where
toJSON :: MediaMsgtype -> Value
toJSON MediaMsgtype
x = Text -> Value
J.String (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ case MediaMsgtype
x of
MediaMsgtype
MediaMsgtype_File → MFileType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString MFileType
Api.MFileType
MediaMsgtype
MediaMsgtype_Image → MImageType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString MImageType
Api.MImageType
MediaMsgtype
MediaMsgtype_Video → MVideoType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString MVideoType
Api.MVideoType
MediaMsgtype
MediaMsgtype_Audio → MAudioType -> Text
forall a. MsgtypeString a => a -> Text
Api.msgtypeString MAudioType
Api.MAudioType
instance J.FromJSON MediaMsgtype where
parseJSON :: Value -> Parser MediaMsgtype
parseJSON Value
jsonValue =
Parser MediaMsgtype
-> (MediaMsgtype -> Parser MediaMsgtype)
-> Maybe MediaMsgtype
-> Parser MediaMsgtype
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
(String -> Parser MediaMsgtype
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser MediaMsgtype) -> String -> Parser MediaMsgtype
forall a b. (a -> b) -> a -> b
$ String
"Failed to parse MediaMsgtype from " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
jsonValue)
MediaMsgtype -> Parser MediaMsgtype
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
((MediaMsgtype -> Bool) -> [MediaMsgtype] -> Maybe MediaMsgtype
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Value
jsonValue Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
==) (Value -> Bool) -> (MediaMsgtype -> Value) -> MediaMsgtype -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaMsgtype -> Value
forall a. ToJSON a => a -> Value
J.toJSON) [MediaMsgtype
forall a. Bounded a => a
minBound .. MediaMsgtype
forall a. Bounded a => a
maxBound ∷ MediaMsgtype])
clientEventContentToMediaMsgtype
∷ Api.MRoomMessageClientEventContent
→ Maybe MediaMsgtype
clientEventContentToMediaMsgtype :: MRoomMessageClientEventContent -> Maybe MediaMsgtype
clientEventContentToMediaMsgtype = \case
Api.MRoomMessageClientEventContentMImage MRoomMessageMImageMsgtypeClientEventContent
_ → MediaMsgtype -> Maybe MediaMsgtype
forall a. a -> Maybe a
Just MediaMsgtype
MediaMsgtype_Image
Api.MRoomMessageClientEventContentMVideo MRoomMessageMVideoMsgtypeClientEventContent
_ → MediaMsgtype -> Maybe MediaMsgtype
forall a. a -> Maybe a
Just MediaMsgtype
MediaMsgtype_Video
Api.MRoomMessageClientEventContentMAudio MRoomMessageMAudioMsgtypeClientEventContent
_ → MediaMsgtype -> Maybe MediaMsgtype
forall a. a -> Maybe a
Just MediaMsgtype
MediaMsgtype_Audio
Api.MRoomMessageClientEventContentMFile MRoomMessageMFileMsgtypeClientEventContent
_ → MediaMsgtype -> Maybe MediaMsgtype
forall a. a -> Maybe a
Just MediaMsgtype
MediaMsgtype_File
Api.MRoomMessageClientEventContentMText MRoomMessageMTextMsgtypeClientEventContent
_ → Maybe MediaMsgtype
forall a. Maybe a
Nothing
Api.MRoomMessageClientEventContentOther Object
_ → Maybe MediaMsgtype
forall a. Maybe a
Nothing
filterByMediaMsgtype
∷ ML.MonadLogger m
⇒ Maybe MediaMsgtypeFilter
→ Api.MRoomMessageClientEventContent
→ Except.ExceptT Text m ()
filterByMediaMsgtype :: forall (m :: * -> *).
MonadLogger m =>
Maybe MediaMsgtypeFilter
-> MRoomMessageClientEventContent -> ExceptT Text m ()
filterByMediaMsgtype Maybe MediaMsgtypeFilter
filterList (MRoomMessageClientEventContent -> Maybe MediaMsgtype
clientEventContentToMediaMsgtype → Maybe MediaMsgtype
mediaMsgType) =
case (Maybe MediaMsgtypeFilter
filterList, Maybe MediaMsgtype
mediaMsgType) of
(Maybe MediaMsgtypeFilter
Nothing, Maybe MediaMsgtype
_) →
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
"There is no “msgtype” media filter"
, Text
" (filter passed)"
]
(Just MediaMsgtypeFilter
x, Just MediaMsgtype
y) | MediaMsgtype
y MediaMsgtype -> MediaMsgtypeFilter -> Bool
forall a. Eq a => a -> NonEmpty a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` MediaMsgtypeFilter
x →
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
"Media “msgtype” ", (String -> Text
pack (String -> Text)
-> (MediaMsgtype -> String) -> MediaMsgtype -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaMsgtype -> String
forall a. Show a => a -> String
show) MediaMsgtype
y
, Text
" is one of these: ", (String -> Text
pack (String -> Text)
-> (MediaMsgtypeFilter -> String) -> MediaMsgtypeFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaMsgtypeFilter -> String
forall a. Show a => a -> String
show) MediaMsgtypeFilter
x
, Text
" (filter passed)"
]
(Just MediaMsgtypeFilter
_, Maybe MediaMsgtype
Nothing) →
Text -> ExceptT Text m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
Except.throwE (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
"“msgtype” is not one of the media types"
, Text
" (filter not passed)"
]
(Just MediaMsgtypeFilter
x, Just MediaMsgtype
y) →
Text -> ExceptT Text m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
Except.throwE (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
"Media “msgtype” ", (String -> Text
pack (String -> Text)
-> (MediaMsgtype -> String) -> MediaMsgtype -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaMsgtype -> String
forall a. Show a => a -> String
show) MediaMsgtype
y
, Text
" is not one of these: ", (String -> Text
pack (String -> Text)
-> (MediaMsgtypeFilter -> String) -> MediaMsgtypeFilter -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaMsgtypeFilter -> String
forall a. Show a => a -> String
show) MediaMsgtypeFilter
x
, Text
" (filter not passed)"
]