module Network.Nylas.Types where
import Control.Applicative (empty, pure, (<*>))
import Control.Lens (makeLenses, makePrisms, (^.))
import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON),
Value (String, Object, Bool), object,
(.:), (.:?))
import Data.Aeson.Types (Parser)
import Data.Bool (Bool (True, False))
import qualified Data.ByteString.Char8 as B
import Data.Eq (Eq)
import Data.Functor (fmap, (<$>))
import Data.Int (Int)
import Data.Maybe (Maybe (Nothing, Just))
import Data.Monoid ((<>))
import Data.String (String)
import Data.Text (Text)
import Data.Time.Clock (UTCTime)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import GHC.Base (($), (.))
import GHC.Generics (Generic)
import GHC.Real (fromIntegral)
import Pipes (Producer)
import Pipes.Aeson (DecodingError)
import Prelude (Show)
import System.IO (IO)
type Url = String
newtype AccessToken = AccessToken Text deriving (Eq, Show)
newtype NylasId = NylasId { _nylasId :: Text } deriving (Eq, Show, Generic)
data Mailbox
= Mailbox
{ _mailboxName :: Maybe Text
, _mailboxEmail :: Text
} deriving (Eq, Show)
data File
= File
{ _fileId :: NylasId
, _fileContentType :: Text
, _fileName :: Text
, _fileSize :: Int
, _fileContentId :: Maybe Text
} deriving (Eq, Show)
newtype MessageTime = MessageTime { _utcTime :: UTCTime }
deriving (Eq, Show, Generic)
data ReadStatus = MessageRead
| MessageUnread
deriving (Eq, Show)
data StarStatus = Starred
| Unstarred
deriving (Eq, Show)
data Label
= Label
{ _labelId :: NylasId
, _labelName :: Text
, _labelDisplayName :: Text
} deriving (Eq, Show)
data Folder
= Folder
{ _folderId :: NylasId
, _folderName :: Text
, _folderDisplayName :: Text
} deriving (Eq, Show)
data Message
= Message
{ _messageId :: NylasId
, _messageSubject :: Text
, _messageSenders :: [Mailbox]
, _messageToRecipients :: [Mailbox]
, _messageCcRecipients :: [Mailbox]
, _messageBccRecipients :: [Mailbox]
, _messageTime :: MessageTime
, _messageThreadId :: NylasId
, _messageFiles :: [File]
, _messageSnippet :: Text
, _messageLabels :: Maybe [Label]
, _messageFolder :: Maybe Folder
, _messageBody :: Text
, _messageRead :: ReadStatus
, _messageStarred :: StarStatus
} deriving (Eq, Show)
data AttachmentsStatus = HasAttachments
| NoAttachments
deriving (Eq, Show)
data Thread
= Thread
{ _threadId :: NylasId
, _threadSubject :: Text
, _threadFirstTimestamp :: MessageTime
, _threadLastTimestamp :: MessageTime
, _threadParticipants :: [Mailbox]
, _threadSnippet :: Text
, _threadLabels :: Maybe [Label]
, _threadFolders :: Maybe [Folder]
, _threadMessageIds :: [NylasId]
, _threadDraftIds :: [NylasId]
, _threadVersion :: Int
, _threadStarred :: StarStatus
, _threadAttachments :: AttachmentsStatus
} deriving (Eq, Show)
newtype Cursor = Cursor { _cursorId :: Text } deriving (Eq, Show, Generic)
data StreamingError = ParsingError DecodingError (Producer B.ByteString IO ())
| ConsumerError Text
data Change a
= Create a
| Modify a
| Delete
deriving (Eq, Show)
data DeltaChange
= CalendarChange
| ContactChange
| EventChange
| FileChange
| MessageChange (Change Message)
| DraftChange
| ThreadChange (Change Thread)
| LabelChange
| FolderChange
deriving (Eq, Show)
data Delta
= Delta
{ _deltaCursor :: Cursor
, _deltaObjectId :: NylasId
, _deltaChange :: DeltaChange
} deriving (Eq, Show)
makeLenses ''NylasId
makeLenses ''Mailbox
makeLenses ''File
makeLenses ''MessageTime
makePrisms ''ReadStatus
makePrisms ''StarStatus
makeLenses ''Label
makeLenses ''Folder
makeLenses ''Message
makePrisms ''AttachmentsStatus
makeLenses ''Thread
makeLenses ''Cursor
makePrisms ''Change
makePrisms ''DeltaChange
makeLenses ''Delta
recipients :: Message -> [Mailbox]
recipients m = m ^. messageToRecipients
<> m ^. messageCcRecipients
<> m ^. messageBccRecipients
instance FromJSON Mailbox where
parseJSON (Object v) =
Mailbox <$> fmap nonEmpty (v .: "name")
<*> v .: "email"
where
nonEmpty "" = Nothing
nonEmpty str = Just str
parseJSON _ = empty
instance FromJSON File where
parseJSON (Object v) =
File <$> v .: "id"
<*> v .: "content_type"
<*> v .: "filename"
<*> v .: "size"
<*> v .:? "content_id"
parseJSON _ = empty
instance FromJSON MessageTime where
parseJSON n = (MessageTime . posixSecondsToUTCTime . fromIntegral)
<$> (parseJSON n :: Parser Int)
instance FromJSON StarStatus where
parseJSON (Bool True) = pure Starred
parseJSON (Bool False) = pure Unstarred
parseJSON _ = empty
instance FromJSON Label where
parseJSON (Object v) =
Label <$> v .: "id"
<*> v .: "name"
<*> v .: "display_name"
parseJSON _ = empty
instance FromJSON Folder where
parseJSON (Object v) =
Folder <$> v .: "id"
<*> v .: "name"
<*> v .: "display_name"
parseJSON _ = empty
instance FromJSON Message where
parseJSON (Object v) =
Message <$> v .: "id"
<*> v .: "subject"
<*> v .: "from"
<*> v .: "to"
<*> v .: "cc"
<*> v .: "bcc"
<*> v .: "date"
<*> v .: "thread_id"
<*> v .: "files"
<*> v .: "snippet"
<*> v .:? "labels"
<*> v .:? "folder"
<*> v .: "body"
<*> fmap fromUnread (v .: "unread")
<*> v .: "starred"
where
fromUnread :: Bool -> ReadStatus
fromUnread True = MessageUnread
fromUnread False = MessageRead
parseJSON _ = empty
instance FromJSON AttachmentsStatus where
parseJSON (Bool True) = pure HasAttachments
parseJSON (Bool False) = pure NoAttachments
parseJSON _ = empty
instance FromJSON Thread where
parseJSON (Object v) =
Thread <$> v .: "id"
<*> v .: "subject"
<*> v .: "first_message_timestamp"
<*> v .: "last_message_timestamp"
<*> v .: "participants"
<*> v .: "snippet"
<*> v .:? "labels"
<*> v .:? "folders"
<*> v .: "message_ids"
<*> v .: "draft_ids"
<*> v .: "version"
<*> v .: "starred"
<*> v .: "has_attachments"
parseJSON _ = empty
instance FromJSON Cursor where
parseJSON (String s) = pure $ Cursor s
parseJSON _ = empty
instance FromJSON NylasId where
parseJSON (String s) = pure $ NylasId s
parseJSON _ = empty
instance FromJSON Delta where
parseJSON (Object deltaV) = do
cursor <- deltaV .: "cursor"
nyId <- deltaV .: "id"
(String event) <- deltaV .: "event"
(String objectType) <- deltaV .: "object"
mObjV <- deltaV .:? "attributes"
dc <- case objectType of
"calendar" -> pure CalendarChange
"contact" -> pure ContactChange
"event" -> pure EventChange
"file" -> pure FileChange
"message" -> MessageChange <$> parseChange event mObjV
"draft" -> pure DraftChange
"thread" -> ThreadChange <$> parseChange event mObjV
"label" -> pure LabelChange
"folder" -> pure FolderChange
_ -> empty
pure $ Delta cursor nyId dc
where
parseChange :: FromJSON a => Text -> Maybe Value -> Parser (Change a)
parseChange "create" (Just objV) = Create <$> parseJSON objV
parseChange "modify" (Just objV) = Modify <$> parseJSON objV
parseChange "delete" Nothing = pure Delete
parseChange _ _ = empty
parseJSON _ = empty
instance ToJSON Delta where
toJSON _ = object []