aboutsummaryrefslogtreecommitdiff
path: root/tea-cleaner/TeaCleaner/Filter.hs
blob: 658606dd0f3b3f35e3968b55860b5847cce5e5a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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