module TeaCleaner.Filter ( FilterResult(..) , UserFilter(..) , filterByActivities , filterByUserProperties ) where import qualified Data.Text as Text import Data.Time (LocalTime(..), ZonedTime(..), UTCTime(..), addUTCTime) import qualified Data.Vector as Vector import TeaCleaner.Client (Activity(..), User(..), getActivities) import TeaCleaner.Configuration (Settings(..)) import GHC.Records (HasField(..)) data UserFilter = PassFilter | SuspiciousFilter | FailedFilter deriving (Eq, Show) data FilterResult = FilterResult User UserFilter deriving (Show) filterByUserProperties :: Settings -> User -> FilterResult filterByUserProperties settings user@User{ created, lastLogin } | noLoginSinceRegistration = FilterResult user FailedFilter | containsSpamWords = FilterResult user FailedFilter | percentEncodedWebsite = FilterResult user FailedFilter | hasFullDescription = FilterResult user SuspiciousFilter | unusualMailDomains = FilterResult user SuspiciousFilter | otherwise = FilterResult user PassFilter where percentEncodedWebsite = Text.elem '%' $ getField @"website" user unusualMailDomains = let predicate = (`Text.isSuffixOf` getField @"email" user) in any predicate (getField @"mailDomains" settings) containsSpamWords = let lowerCaseDescription = Text.toLower $ getField @"description" user lowerCaseWebsite = Text.toLower $ getField @"website" user predicate word = Text.isInfixOf word lowerCaseWebsite || Text.isInfixOf word lowerCaseDescription in any predicate (getField @"spamWords" settings) hasFullDescription = not (Text.null $ getField @"description" user) && not (Text.null $ getField @"website" user) noLoginSinceRegistration = let monthAgo = utctDay $ addUTCTime (-2592000) $ getField @"now" settings in zonedDay created < monthAgo && zonedDay created == zonedDay lastLogin zonedDay = localDay . zonedTimeToLocalTime filterByActivities :: Settings -> User -> IO FilterResult filterByActivities settings user = getActivities settings user >>= evalActivities where evalActivities activities | Just (Activity{ opType }, rest) <- Vector.uncons activities , Vector.null rest , opType == "create_repo" = pure $ FilterResult user FailedFilter evalActivities _ = pure $ FilterResult user PassFilter