mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-03-31 05:25:47 +00:00
133 lines
4.4 KiB
Haskell
133 lines
4.4 KiB
Haskell
{-# LANGUAGE DataKinds #-}
|
|
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
module Simplex.Chat.Operators where
|
|
|
|
import Data.Aeson (FromJSON (..), ToJSON (..))
|
|
import qualified Data.Aeson as J
|
|
import qualified Data.Aeson.Encoding as JE
|
|
import qualified Data.Aeson.TH as JQ
|
|
import Data.FileEmbed
|
|
import Data.Int (Int64)
|
|
import Data.Map.Strict (Map)
|
|
import qualified Data.Map.Strict as M
|
|
import Data.Maybe (fromMaybe)
|
|
import Data.Text (Text)
|
|
import Data.Time.Clock (UTCTime)
|
|
import Database.SQLite.Simple.FromField (FromField (..))
|
|
import Database.SQLite.Simple.ToField (ToField (..))
|
|
import Language.Haskell.TH.Syntax (lift)
|
|
import Simplex.Chat.Operators.Conditions
|
|
import Simplex.Chat.Types.Util (textParseJSON)
|
|
import Simplex.Messaging.Agent.Env.SQLite (OperatorId, ServerCfg (..), ServerRoles)
|
|
import Simplex.Messaging.Encoding.String
|
|
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, fromTextField_, sumTypeJSON)
|
|
import Simplex.Messaging.Protocol (ProtocolType (..))
|
|
import Simplex.Messaging.Util (safeDecodeUtf8)
|
|
|
|
usageConditionsCommit :: Text
|
|
usageConditionsCommit = "165143a1112308c035ac00ed669b96b60599aa1c"
|
|
|
|
usageConditionsText :: Text
|
|
usageConditionsText =
|
|
$( let s = $(embedFile =<< makeRelativeToProject "PRIVACY.md")
|
|
in [|stripFrontMatter (safeDecodeUtf8 $(lift s))|]
|
|
)
|
|
|
|
data OperatorTag = OTSimplex | OTXyz
|
|
deriving (Show)
|
|
|
|
instance FromField OperatorTag where fromField = fromTextField_ textDecode
|
|
|
|
instance ToField OperatorTag where toField = toField . textEncode
|
|
|
|
instance FromJSON OperatorTag where
|
|
parseJSON = textParseJSON "OperatorTag"
|
|
|
|
instance ToJSON OperatorTag where
|
|
toJSON = J.String . textEncode
|
|
toEncoding = JE.text . textEncode
|
|
|
|
instance TextEncoding OperatorTag where
|
|
textDecode = \case
|
|
"simplex" -> Just OTSimplex
|
|
"xyz" -> Just OTXyz
|
|
_ -> Nothing
|
|
textEncode = \case
|
|
OTSimplex -> "simplex"
|
|
OTXyz -> "xyz"
|
|
|
|
data UsageConditions = UsageConditions
|
|
{ conditionsId :: Int64,
|
|
conditionsCommit :: Text,
|
|
notifiedAt :: Maybe UTCTime,
|
|
createdAt :: UTCTime
|
|
}
|
|
deriving (Show)
|
|
|
|
data UsageConditionsAction
|
|
= UCAReview {operators :: [ServerOperator], deadline :: Maybe UTCTime, showNotice :: Bool}
|
|
| UCAAccepted {operators :: [ServerOperator]}
|
|
deriving (Show)
|
|
|
|
-- TODO UI logic
|
|
usageConditionsAction :: [ServerOperator] -> UsageConditionsAction
|
|
usageConditionsAction _operators = UCAAccepted []
|
|
|
|
data ConditionsAcceptance
|
|
= CAAccepted {acceptedAt :: UTCTime}
|
|
| CARequired {deadline :: Maybe UTCTime}
|
|
deriving (Show)
|
|
|
|
data ServerOperator = ServerOperator
|
|
{ operatorId :: OperatorId,
|
|
operatorTag :: Maybe OperatorTag,
|
|
tradeName :: Text,
|
|
legalName :: Maybe Text,
|
|
serverDomains :: [Text],
|
|
acceptedConditions :: ConditionsAcceptance,
|
|
enabled :: Bool,
|
|
roles :: ServerRoles
|
|
}
|
|
deriving (Show)
|
|
|
|
data UserServers = UserServers
|
|
{ operator :: Maybe ServerOperator,
|
|
smpServers :: [ServerCfg 'PSMP],
|
|
xftpServers :: [ServerCfg 'PXFTP]
|
|
}
|
|
deriving (Show)
|
|
|
|
groupByOperator :: [ServerOperator] -> [ServerCfg 'PSMP] -> [ServerCfg 'PXFTP] -> [UserServers]
|
|
groupByOperator srvOperators smpSrvs xftpSrvs =
|
|
map createOperatorServers (M.toList combinedMap)
|
|
where
|
|
srvOperatorId :: ServerCfg p -> Maybe Int64
|
|
srvOperatorId ServerCfg {operator} = operator
|
|
operatorMap :: Map (Maybe Int64) (Maybe ServerOperator)
|
|
operatorMap = M.fromList [(Just (operatorId op), Just op) | op <- srvOperators] `M.union` M.singleton Nothing Nothing
|
|
initialMap :: Map (Maybe Int64) ([ServerCfg 'PSMP], [ServerCfg 'PXFTP])
|
|
initialMap = M.fromList [(key, ([], [])) | key <- M.keys operatorMap]
|
|
smpsMap = foldr (\server acc -> M.adjust (\(smps, xftps) -> (server : smps, xftps)) (srvOperatorId server) acc) initialMap smpSrvs
|
|
combinedMap = foldr (\server acc -> M.adjust (\(smps, xftps) -> (smps, server : xftps)) (srvOperatorId server) acc) smpsMap xftpSrvs
|
|
createOperatorServers (key, (groupedSmps, groupedXftps)) =
|
|
UserServers
|
|
{ operator = fromMaybe Nothing (M.lookup key operatorMap),
|
|
smpServers = groupedSmps,
|
|
xftpServers = groupedXftps
|
|
}
|
|
|
|
$(JQ.deriveJSON defaultJSON ''UsageConditions)
|
|
|
|
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CA") ''ConditionsAcceptance)
|
|
|
|
$(JQ.deriveJSON defaultJSON ''ServerOperator)
|
|
|
|
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "UCA") ''UsageConditionsAction)
|
|
|
|
$(JQ.deriveJSON defaultJSON ''UserServers)
|