servant-pushbullet-client 0.0.3.0 → 0.1.0.0
raw patch · 14 files changed
+24/−920 lines, 14 filesdep +pushbullet-typesdep ~http-client
Dependencies added: pushbullet-types
Dependency ranges changed: http-client
Files
- ChangeLog.md +10/−0
- servant-pushbullet-client.cabal +14/−16
- src/Network/Pushbullet/Reflection.hs +0/−17
- src/Network/Pushbullet/Types.hs +0/−114
- src/Network/Pushbullet/Types/Device.hs +0/−167
- src/Network/Pushbullet/Types/Ephemeral.hs +0/−51
- src/Network/Pushbullet/Types/Misc.hs +0/−46
- src/Network/Pushbullet/Types/Pagination.hs +0/−29
- src/Network/Pushbullet/Types/Permanent.hs +0/−25
- src/Network/Pushbullet/Types/Push.hs +0/−239
- src/Network/Pushbullet/Types/SMS.hs +0/−119
- src/Network/Pushbullet/Types/Status.hs +0/−30
- src/Network/Pushbullet/Types/Time.hs +0/−26
- src/Network/Pushbullet/Types/User.hs +0/−41
ChangeLog.md view
@@ -1,5 +1,15 @@ # Revision history for servant-pushbullet-client +## 0.1.0.0 -- 2017-02-20++The bulk of the library has been moved into a separate library+[pushbullet-types](https://github.com/tsani/pushbullet-types).++This library now just defines the Pushbullet API-as-a-type and applies+servant-client's `client` function to produce the functions for querying the+Pushbullet API. Also included in this library proper is a utility function for+consuming paginated data returned from Pushbullet.+ ## 0.0.3.0 -- 2017-02-10 Forgot to export all those lenses.
servant-pushbullet-client.cabal view
@@ -2,7 +2,7 @@ -- further documentation, see http://haskell.org/cabal/users-guide/ name: servant-pushbullet-client-version: 0.0.3.0+version: 0.1.0.0 synopsis: Bindings to the Pushbullet API using servant-client description: This library describes the Pushbullet API as a type, and uses servant-client@@ -18,24 +18,20 @@ extra-source-files: ChangeLog.md cabal-version: >=1.10 +source-repository head+ type: git+ location: https://github.com/tsani/servant-pushbullet-client++source-repository this+ type: git+ location: https://github.com/tsani/servant-pushbullet-client/releases/tag/v0.1.0.0+ tag: v0.1.0.0+ library exposed-modules: Network.Pushbullet.Api, Network.Pushbullet.Client,- Network.Pushbullet.Misc,- Network.Pushbullet.Types- other-modules:- Network.Pushbullet.Reflection- Network.Pushbullet.Types.Device,- Network.Pushbullet.Types.Ephemeral,- Network.Pushbullet.Types.Misc,- Network.Pushbullet.Types.Pagination,- Network.Pushbullet.Types.Permanent,- Network.Pushbullet.Types.Push,- Network.Pushbullet.Types.SMS,- Network.Pushbullet.Types.Status,- Network.Pushbullet.Types.Time,- Network.Pushbullet.Types.User+ Network.Pushbullet.Misc hs-source-dirs: src default-language: Haskell2010 ghc-options:@@ -52,11 +48,13 @@ TypeFamilies TypeApplications build-depends:+ pushbullet-types >=0.1 && <0.2,+ aeson >=0.11 && <1.1, base >=4.9 && <4.10, http-api-data >=0.3 && <0.4, http-client-tls >=0.3 && <0.4,- http-client,+ http-client >=0.5 && <0.6, microlens >=0.4 && <0.5, microlens-th >=0.4 && <0.5, scientific >=0.3 && <0.4,
− src/Network/Pushbullet/Reflection.hs
@@ -1,17 +0,0 @@-module Network.Pushbullet.Reflection-( Demote'-, Demote-, Reflected-, Reflect(..)-, KProxy(..)-) where--import Data.Proxy--type family Demote' (p :: KProxy k) :: k -> *--type Demote (a :: k) = Demote' ('KProxy :: KProxy k)-type Reflected a = Demote a a--class Reflect a where- reflect :: proxy a -> Reflected a
− src/Network/Pushbullet/Types.hs
@@ -1,114 +0,0 @@-module Network.Pushbullet.Types-( -- * Pagination- Paginated(..)-, Cursor- -- * Pushes-, Push(..)-, PushData(..)-, PushTarget(..)-, simpleNewPush-, ExistingPushes(..)- -- * Ephemerals-, Ephemeral(..)- -- * Devices-, Device(..)-, DeviceId(..)-, Nickname(..)-, DeviceIcon(..)-, HasSms(..)-, ExistingDevices(..)-, newDevice- -- * Users-, User(..)-, UserId(..)- -- * Permanents-, Permanent(..)-, PermanentK(..)- -- ** SMS-, SmsThreads(..)-, SmsThread(..)-, SmsThreadId(..)-, SmsThreadRecipient(..)-, SmsMessages(..)-, SmsMessage(..)-, SmsId(..)-, SmsDirection(..)-, SmsMessageType(..)- -- * Misc- --- -- ** Data-, EmailAddress(..)-, ChannelTag(..)-, ClientId(..)-, MimeType(..)-, Url(..)-, Guid(..)-, TrivialObject(..)-, Status(..)-, PushbulletTime(..)-, PhoneNumber(..)-, Name(..)-- -- ** Type-level stuff-, EqT-- -- * Lenses- -- ** Device-, deviceId-, deviceActive-, deviceCreated-, deviceModified-, deviceIcon-, deviceNickname-, deviceGeneratedNickname-, deviceManufacturer-, deviceModel-, deviceAppVersion-, deviceFingerprint-, deviceKeyFingerprint- -- ** User-, userCreated-, userEmail-, userEmailNormalized-, userId-, userImageUrl-, userMaxUploadSize-, userModified-, userName- -- ** SMS-, smsDirection-, smsTime-, smsBody-, smsId-, smsSent-, smsType-, recipientName-, recipientAddress-, recipientNumber-, threadId-, threadRecipients-, threadLatest- -- ** Ephemerals-, ephSmsSourceUser-, ephSmsTargetDevice-, ephSmsConversation-, ephSmsMessage- -- ** Clipboard-, ephClipBody-, ephClipSourceUser-, ephClipSourceDevice- -- ** Pagination-, pageData-, pageCursor-) where--import Network.Pushbullet.Types.Device-import Network.Pushbullet.Types.Ephemeral-import Network.Pushbullet.Types.Misc-import Network.Pushbullet.Types.Pagination-import Network.Pushbullet.Types.Permanent-import Network.Pushbullet.Types.Push-import Network.Pushbullet.Types.SMS-import Network.Pushbullet.Types.Status-import Network.Pushbullet.Types.Time-import Network.Pushbullet.Types.User
− src/Network/Pushbullet/Types/Device.hs
@@ -1,167 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--module Network.Pushbullet.Types.Device where--import Network.Pushbullet.Types.Status-import Network.Pushbullet.Types.Time--import Data.Aeson-import Data.Text ( Text )-import Lens.Micro.TH-import Web.HttpApiData ( ToHttpApiData(..) )--newtype DeviceId = DeviceId Text- deriving (Eq, FromJSON, Show, ToJSON, ToHttpApiData)--newtype DeviceIcon = DeviceIcon Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype Nickname = Nickname Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype PushToken = PushToken Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype Manufacturer = Manufacturer Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype Fingerprint = Fingerprint Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype Model = Model Text- deriving (Eq, ToJSON, Show, FromJSON)--newtype AppVersion = AppVersion Int- deriving (Eq, ToJSON, Show, FromJSON)--newtype KeyFingerprint = KeyFingerprint Text- deriving (Eq, ToJSON, Show, FromJSON)---- | Whether the device has SMS capabilities.-data HasSms = NoSms | HasSms- deriving (Eq, Ord, Show)---- | A device attached to a Pushbullet account.-data Device (s :: Status)- = Device- { _deviceId :: !(EqT 'Existing s DeviceId)- , _deviceActive :: !(EqT 'Existing s Bool)- , _deviceCreated :: !(EqT 'Existing s PushbulletTime)- , _deviceModified :: !(EqT 'Existing s PushbulletTime)- , _deviceIcon :: !DeviceIcon- , _deviceNickname :: !(Maybe Nickname)- , _deviceGeneratedNickname :: !(EqT 'Existing s Bool)- , _deviceManufacturer :: !(Maybe Manufacturer)- , _deviceModel :: !(Maybe Model)- , _deviceAppVersion :: !(Maybe AppVersion)- , _deviceFingerprint :: !(EqT 'Existing s (Maybe Fingerprint))- , _deviceKeyFingerprint :: !(EqT 'Existing s (Maybe KeyFingerprint))- , _deviceHasSms :: !HasSms- , _devicePushToken :: !(Maybe PushToken)- }--makeLenses ''Device---- | Smart constructor for a new device that fills in the ignored fields.-newDevice- :: HasSms- -> DeviceIcon- -> Nickname- -> Maybe Manufacturer- -> Maybe Model- -> Maybe AppVersion- -> Device 'New-newDevice sms icon nick man m ver = Device- { _deviceId = ()- , _deviceActive = ()- , _deviceCreated = ()- , _deviceModified = ()- , _deviceIcon = icon- , _deviceNickname = Just nick- , _deviceGeneratedNickname = ()- , _deviceManufacturer = man- , _deviceModel = m- , _deviceAppVersion = ver- , _deviceFingerprint = ()- , _deviceKeyFingerprint = ()- , _deviceHasSms = sms- , _devicePushToken = Nothing- }---- | A newtype wrapper for a list of existing devices. We need this to get a--- nonstandard 'FromJSON' instance for the list, because Pushbullet gives us--- the list wrapped in a trivial object with one key.-newtype ExistingDevices- = ExistingDevices- { unExistingDevices :: [Device 'Existing]- }- deriving (Eq, Show)--instance ToJSON HasSms where- toJSON NoSms = Bool False- toJSON HasSms = Bool True--instance FromJSON HasSms where- parseJSON (Bool True) = pure HasSms- parseJSON (Bool False) = pure NoSms- parseJSON _ = fail "cannot parse SMS ability from non-boolean"--deriving instance Eq (Device 'New)-deriving instance Eq (Device 'Existing)-deriving instance Show (Device 'New)-deriving instance Show (Device 'Existing)--instance ToJSON (Device 'Existing) where- toJSON Device{..} = object- [ "iden" .= _deviceId- , "active" .= _deviceActive- , "created" .= _deviceCreated- , "modified" .= _deviceModified- , "icon" .= _deviceIcon- , "nickname" .= _deviceNickname- , "generated_nickname" .= _deviceGeneratedNickname- , "manufacturer" .= _deviceManufacturer- , "model" .= _deviceModel- , "app_version" .= _deviceAppVersion- , "fingerprint" .= _deviceFingerprint- , "key_fingerprint" .= _deviceKeyFingerprint- , "has_sms" .= _deviceHasSms- , "push_token" .= _devicePushToken- ]--instance FromJSON (Device 'Existing) where- parseJSON (Object o) = pure Device- <*> o .: "iden"- <*> o .: "active"- <*> o .: "created"- <*> o .: "modified"- <*> o .: "icon"- <*> o .:? "nickname"- <*> o .:? "generated_nickname" .!= False- <*> o .:? "manufacturer"- <*> o .:? "model"- <*> o .:? "app_version"- <*> o .:? "fingerprint"- <*> o .:? "key_fingerprint"- <*> o .:? "has_sms" .!= NoSms- <*> o .:? "push_token"- parseJSON _ = fail "cannot parse existing device from non-object"--instance ToJSON (Device 'New) where- toJSON Device{..} = object- [ "nickname" .= _deviceNickname- , "model" .= _deviceModel- , "manufacturer" .= _deviceManufacturer- , "push_token" .= _devicePushToken- , "app_version" .= _deviceAppVersion- , "icon" .= _deviceIcon- , "has_sms" .= _deviceHasSms- ]--instance FromJSON ExistingDevices where- parseJSON (Object o) = ExistingDevices <$> o .: "devices"- parseJSON _ = fail "cannot parse devices object from non-object"--instance ToJSON ExistingDevices where- toJSON (ExistingDevices ds) = object [ "devices" .= ds ]
− src/Network/Pushbullet/Types/Ephemeral.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--module Network.Pushbullet.Types.Ephemeral where--import Network.Pushbullet.Types.Device-import Network.Pushbullet.Types.Misc-import Network.Pushbullet.Types.User--import Data.Aeson-import Data.Text ( Text )-import Lens.Micro.TH--data Ephemeral- = Sms- { _ephSmsSourceUser :: !UserId- , _ephSmsTargetDevice :: !DeviceId- , _ephSmsConversation :: !PhoneNumber- , _ephSmsMessage :: !Text- }- | Clipboard- { _ephClipBody :: !Text- , _ephClipSourceUser :: !UserId- , _ephClipSourceDevice :: !DeviceId- }- deriving (Eq, Show)--makeLenses ''Ephemeral--instance ToJSON Ephemeral where- toJSON o = case o of- Sms{..} -> object- [ "type" .= id @Text "push"- , "push" .= object- [ "type" .= id @Text "messaging_extension_reply"- , "package_name" .= id @Text "com.pushbullet.android"- , "source_user_iden" .= _ephSmsSourceUser- , "target_device_iden" .= _ephSmsTargetDevice- , "conversation_iden" .= _ephSmsConversation- , "message" .= _ephSmsMessage- ]- ]- Clipboard{..} -> object- [ "type" .= id @Text "push"- , "push" .= object- [ "type" .= id @Text "clip"- , "body" .= _ephClipBody- , "source_user_iden" .= _ephClipSourceUser- , "source_device_iden" .= _ephClipSourceDevice- ]- ]
− src/Network/Pushbullet/Types/Misc.hs
@@ -1,46 +0,0 @@-module Network.Pushbullet.Types.Misc where--import Data.Aeson-import qualified Data.HashMap.Lazy as H-import Data.Text ( Text )--newtype EmailAddress = EmailAddress Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype ChannelTag = ChannelTag Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype ChannelId = ChannelId Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype ClientId = ClientId Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype MimeType = MimeType Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype Url = Url Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype Guid = Guid Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype PhoneNumber = PhoneNumber Text- deriving (Eq, FromJSON, Show, ToJSON)--newtype TrivialObject = TrivialObject ()- deriving (Eq, Ord, Monoid, Show)--newtype Name = Name- { unName :: Text- }- deriving (Eq, FromJSON, Show, ToJSON)--instance ToJSON TrivialObject where- toJSON _ = object []--instance FromJSON TrivialObject where- parseJSON (Object o)- | H.null o = pure mempty- | otherwise = fail "trivial object has no keys"- parseJSON _ = fail "cannot parse non-object to trivial object"
− src/Network/Pushbullet/Types/Pagination.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--module Network.Pushbullet.Types.Pagination where--import Data.Aeson-import Data.Text ( Text )-import Lens.Micro.TH-import Web.HttpApiData ( ToHttpApiData(..) )---- | Cursors are opaque.-newtype Cursor = Cursor Text- deriving (Eq, FromJSON, Show, ToJSON, ToHttpApiData)---- | A single page of data, possibly with a cursor attached to it.--- The cursor may be used in routes that return paginated data to produce the--- next page of data.-data Paginated a- = Page- { _pageData :: !a- , _pageCursor :: !(Maybe Cursor)- }- deriving (Eq, Functor, Show)--makeLenses ''Paginated--instance FromJSON a => FromJSON (Paginated a) where- parseJSON j@(Object o) = Page <$> parseJSON j <*> o .:? "cursor"- parseJSON _ = fail "cannot parse paginated data from non-object"
− src/Network/Pushbullet/Types/Permanent.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Network.Pushbullet.Types.Permanent where--import Network.Pushbullet.Types.Device-import Network.Pushbullet.Types.SMS--import Data.Monoid ( (<>) )-import Web.HttpApiData ( ToHttpApiData(..) )--data PermanentK- = ThreadList- | MessageList--data Permanent (p :: PermanentK) where- ThreadsOf :: !DeviceId -> Permanent 'ThreadList- MessagesIn :: !DeviceId -> !SmsThreadId -> Permanent 'MessageList--instance ToHttpApiData (Permanent 'ThreadList) where- toUrlPiece p = case p of- ThreadsOf (DeviceId d) -> d <> "_threads"--instance ToHttpApiData (Permanent 'MessageList) where- toUrlPiece p = case p of- MessagesIn (DeviceId d) (SmsThreadId t) -> d <> "_thread_" <> t
− src/Network/Pushbullet/Types/Push.hs
@@ -1,239 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Network.Pushbullet.Types.Push-( Push(..)-, PushId(..)-, PushDirection(..)-, PushTarget(..)-, PushData(..)-, PushOrigin(..)-, ExistingPushes(..)-, simpleNewPush-) where--import Network.Pushbullet.Types.Device-import Network.Pushbullet.Types.Misc-import Network.Pushbullet.Types.Status-import Network.Pushbullet.Types.Time-import Network.Pushbullet.Types.User--import Control.Applicative ( (<|>) )-import Data.Aeson-import Data.Text ( Text )---- | A push. We reuse the same datatype for representing new pushes and--- existing pushes. The 'EqT' type family is used to enable fields selectively--- according to whether we're making a new push or representing an existing--- one.-data Push (s :: Status)- = Push- { pushData :: !(PushData s)- , pushSourceDevice :: !(Maybe DeviceId)- , pushTarget :: !(PushTarget s)- , pushGuid :: !(Maybe Guid)- , pushId :: !(EqT 'Existing s PushId)- , pushActive :: !(EqT 'Existing s Bool)- , pushCreated :: !(EqT 'Existing s PushbulletTime)- , pushModified :: !(EqT 'Existing s PushbulletTime)- , pushDismissed :: !(EqT 'Existing s Bool)- , pushDirection :: !(EqT 'Existing s PushDirection)- , pushSender :: !(EqT 'Existing s UserId)- , pushSenderEmail :: !(EqT 'Existing s EmailAddress)- , pushSenderEmailNormalized :: !(EqT 'Existing s EmailAddress)- , pushSenderName :: !(EqT 'Existing s Name)- , pushReceiver :: !(EqT 'Existing s UserId)- , pushReceiverEmail :: !(EqT 'Existing s EmailAddress)- , pushReceiverEmailNormalized :: !(EqT 'Existing s EmailAddress)- , pushOrigin :: !(EqT 'Existing s (Maybe PushOrigin))- }---- | Unique identifier for a push.-newtype PushId = PushId Text- deriving (Eq, FromJSON, Show, ToJSON)---- | The direction of a push.-data PushDirection- = SelfPush- | OutgoingPush- | IncomingPush- deriving (Eq, Ord, Show)---- | The target of a push.-data PushTarget (s :: Status) where- ToAll :: PushTarget 'New- ToDevice :: !DeviceId -> PushTarget 'New- ToEmail :: !EmailAddress -> PushTarget 'New- ToChannel :: !ChannelTag -> PushTarget 'New- ToClient :: !ClientId -> PushTarget 'New- SentBroadcast :: PushTarget 'Existing- SentToDevice :: !DeviceId -> PushTarget 'Existing---- | The actual contents of a push.-data PushData (s :: Status)- = NotePush- { pushTitle :: !Text- , pushBody :: !Text- }- | LinkPush- { pushTitle :: !Text- , pushBody :: !Text- , pushUrl :: !Url- }- | FilePush- { pushBody :: !Text- , pushFileName :: !Text- , pushFileType :: !MimeType- , pushFileUrl :: !Url- , pushFileTitle :: !(EqT 'Existing s Text)- , pushImageUrl :: !(EqT 'Existing s (Maybe Url))- , pushImageWidth :: !(EqT 'Existing s (Maybe Int))- , pushImageHeight :: !(EqT 'Existing s (Maybe Int))- }---- | The origin of a push.-data PushOrigin- = FromClient !ClientId- | FromChannel !ChannelId- deriving (Eq, Show)---- | A newtype wrapper for a list of existing pushes. We need this to get a--- nonstandard 'FromJSON' instance for the list, because Pushbullet gives us--- the list wrapped in a trivial object with one key.-newtype ExistingPushes = ExistingPushes [Push 'Existing]- deriving (Eq, Show)---- | Constructs a new @Push@ with the source device and guid set to @Nothing@.-simpleNewPush :: PushTarget 'New -> PushData 'New -> Push 'New-simpleNewPush t d = Push- { pushData = d- , pushSourceDevice = Nothing- , pushTarget = t- , pushGuid = Nothing- , pushId = ()- , pushActive = ()- , pushCreated = ()- , pushModified = ()- , pushDismissed = ()- , pushDirection = ()- , pushSender = ()- , pushSenderEmail = ()- , pushSenderEmailNormalized = ()- , pushSenderName = ()- , pushReceiver = ()- , pushReceiverEmail = ()- , pushReceiverEmailNormalized = ()- , pushOrigin = ()- }--instance ToJSON PushDirection where- toJSON SelfPush = String "self"- toJSON OutgoingPush = String "outgoing"- toJSON IncomingPush = String "incoming"--instance FromJSON PushDirection where- parseJSON (String s) = case s of- "self" -> pure SelfPush- "outgoing" -> pure OutgoingPush- "incoming" -> pure IncomingPush- _ -> fail "invalid direction string"- parseJSON _ = fail "cannot parse push direction from non-string"--deriving instance Eq (PushTarget s)-deriving instance Show (PushTarget s)--deriving instance Eq (PushData 'New)-deriving instance Eq (PushData 'Existing)-deriving instance Show (PushData 'New)-deriving instance Show (PushData 'Existing)--deriving instance Eq (Push 'New)-deriving instance Eq (Push 'Existing)-deriving instance Show (Push 'New)-deriving instance Show (Push 'Existing)--instance FromJSON (Push 'Existing) where- parseJSON (Object o) = do- pushType <- o .: "type"- d <- case id @Text pushType of- "note" -> pure NotePush- <*> o .: "title"- <*> o .: "body"- "file" -> pure FilePush- <*> o .: "body"- <*> o .: "file_name"- <*> o .: "file_type"- <*> o .: "file_url"- <*> o .: "file_title"- <*> o .:? "image_url"- <*> o .:? "image_width"- <*> o .:? "image_height"- "link" -> pure LinkPush- <*> o .: "title"- <*> o .: "body"- <*> o .: "url"- _ -> fail "unrecognized push type"- client <- o .:? "client_iden"- channel <- o .:? "channel_iden"- let origin = (FromClient <$> client) <|> (FromChannel <$> channel)-- pure Push- <*> pure d- <*> o .:? "source_device_iden"- <*> (maybe SentBroadcast SentToDevice <$> o .:? "target_device_iden")- <*> o .:? "guid"- <*> o .: "iden"- <*> o .: "active"- <*> o .: "created"- <*> o .: "modified"- <*> o .: "dismissed"- <*> o .: "direction"- <*> o .: "sender_iden"- <*> o .: "sender_email"- <*> o .: "sender_email_normalized"- <*> o .: "sender_name"- <*> o .: "receiver_iden"- <*> o .: "receiver_email"- <*> o .: "receiver_email_normalized"- <*> pure origin- parseJSON _ = fail "cannot parse push from non-object"--instance FromJSON ExistingPushes where- parseJSON (Object o) = ExistingPushes <$> o .: "pushes"- parseJSON _ = fail "cannot parse existing pushes from non-object"--instance ToJSON (Push 'New) where- toJSON Push{..} = object (concat pieces) where- pieces =- [ [ "source_device_iden" .= pushSourceDevice- , "guid" .= pushGuid- ]- , target- , thePushData- ]-- target = case pushTarget of- ToAll -> []- ToDevice d -> [ "device_iden" .= d ]- ToEmail email -> [ "email" .= email ]- ToChannel tag -> [ "channel_tag" .= tag ]- ToClient client -> [ "client_iden" .= client ]-- thePushData = case pushData of- NotePush{..} ->- [ "type" .= id @Text "note"- , "title" .= pushTitle- , "body" .= pushBody- ]- LinkPush{..} ->- [ "type" .= id @Text "link"- , "title" .= pushTitle- , "body" .= pushBody- , "url" .= pushUrl- ]- FilePush{..} ->- [ "type" .= id @Text "file"- , "body" .= pushBody- , "file_name" .= pushFileName- , "file_type" .= pushFileType- , "file_url" .= pushFileUrl- ]
− src/Network/Pushbullet/Types/SMS.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--module Network.Pushbullet.Types.SMS where--import Data.Aeson-import Data.Text ( Text )-import Data.List.NonEmpty ( NonEmpty )-import Lens.Micro.TH--import Network.Pushbullet.Types.Misc-import Network.Pushbullet.Types.Time--data SmsDirection- = IncomingSms- | OutgoingSms- deriving (Eq, Show)--newtype SmsId = SmsId Text- deriving (Eq, FromJSON, Show, ToJSON)--data SmsMessageType- = SMS- | MMS- deriving (Eq, Show)--data SmsMessage- = SmsMessage- { _smsDirection :: !SmsDirection- , _smsTime :: !PushbulletTime- , _smsBody :: !Text- , _smsId :: !SmsId- , _smsSent :: !(Maybe Bool)- , _smsType :: !SmsMessageType- }- deriving (Eq, Show)--makeLenses ''SmsMessage--newtype SmsMessages- = SmsMessages- { unSmsMessages :: [SmsMessage]- }- deriving (Eq, Show)--data SmsThreadRecipient- = SmsThreadRecipient- { _recipientName :: !Name- , _recipientAddress :: !PhoneNumber- , _recipientNumber :: !PhoneNumber- }- deriving (Eq, Show)--makeLenses ''SmsThreadRecipient--newtype SmsThreadId = SmsThreadId Text- deriving (Eq, FromJSON, Show, ToJSON)--data SmsThread- = SmsThread- { _threadId :: SmsThreadId- , _threadRecipients :: NonEmpty SmsThreadRecipient- , _threadLatest :: SmsMessage- }- deriving (Eq, Show)--makeLenses ''SmsThread--newtype SmsThreads- = SmsThreads- { unSmsThreads :: [SmsThread]- }- deriving (Eq, Show)--instance FromJSON SmsDirection where- parseJSON (String s) = case s of- "incoming" -> pure IncomingSms- "outgoing" -> pure OutgoingSms- _ -> fail "invalid SMS direction string"- parseJSON _ = fail "cannot parse SMS direction from non-string"--instance FromJSON SmsMessageType where- parseJSON (String s)- | "sms" <- s = pure SMS- | "mms" <- s = pure MMS- | otherwise = fail "invalid SMS type"- parseJSON _ = fail "cannot parse SMS type from non-string"--instance FromJSON SmsMessage where- parseJSON (Object o) = pure SmsMessage- <*> o .: "direction"- <*> o .: "timestamp"- <*> o .: "body"- <*> o .: "id"- <*> o .:? "sent"- <*> o .: "type"- parseJSON _ = fail "cannot parse sms message from non-object"--instance FromJSON SmsMessages where- parseJSON (Object o) = SmsMessages <$> o .: "thread"- parseJSON _ = fail "cannot parse sms messages from non-object"--instance FromJSON SmsThreads where- parseJSON (Object o) = SmsThreads <$> o .: "threads"- parseJSON _ = fail "cannot parse sms threads from non-object"--instance FromJSON SmsThreadRecipient where- parseJSON (Object o) = pure SmsThreadRecipient- <*> o .: "name"- <*> o .: "address"- <*> o .: "number"- parseJSON _ = fail "cannot parse sms thread recipient from non-object"--instance FromJSON SmsThread where- parseJSON (Object o) = pure SmsThread- <*> o .: "id"- <*> o .: "recipients"- <*> o .: "latest"- parseJSON _ = fail "cannot parse sms thread from non-object"
− src/Network/Pushbullet/Types/Status.hs
@@ -1,30 +0,0 @@-module Network.Pushbullet.Types.Status-( Status(..)-, EqT-) where--import Network.Pushbullet.Reflection--data Status- = New- | Existing--data Status' :: Status -> * where- New' :: Status' 'New- Existing' :: Status' 'Existing--type instance Demote' ('KProxy :: KProxy Status) = Status'--instance Reflect 'New where- reflect _ = New'--instance Reflect 'Existing where- reflect _ = Existing'---- | If the first two types are the same, return the third; else, return unit.------ This type family is used to disable certain fields according to the 'Status'--- datakind.-type family EqT (s :: k) (s' :: k) (a :: *) :: * where- EqT s s a = a- EqT _ _ _ = ()
− src/Network/Pushbullet/Types/Time.hs
@@ -1,26 +0,0 @@-module Network.Pushbullet.Types.Time where--import Data.Aeson-import Data.String ( fromString )-import Data.Scientific ( toRealFloat )-import Data.Time.Clock ( NominalDiffTime, UTCTime )-import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds, posixSecondsToUTCTime )-import Web.HttpApiData ( ToHttpApiData(..) )--newtype PushbulletTime = PushbulletTime UTCTime- deriving (Eq, Ord, Show)--instance ToHttpApiData PushbulletTime where- toUrlPiece (PushbulletTime utc) = fromString (show d) where- d = fromRational r :: Double- r = toRational $ utcTimeToPOSIXSeconds utc--instance FromJSON PushbulletTime where- parseJSON (Number n) = pure (PushbulletTime (posixSecondsToUTCTime p)) where- p = fromRational (toRational d) :: NominalDiffTime- d = toRealFloat n :: Double- parseJSON _ = fail "cannot parse pushbullet time from non-number"--instance ToJSON PushbulletTime where- toJSON (PushbulletTime utcTime)- = Number $ fromRational (toRational $ utcTimeToPOSIXSeconds utcTime)
− src/Network/Pushbullet/Types/User.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}--module Network.Pushbullet.Types.User where--import Network.Pushbullet.Types.Misc-import Network.Pushbullet.Types.Time--import Data.Aeson-import Data.Text ( Text )-import Lens.Micro.TH--newtype UserId = UserId Text- deriving (Eq, FromJSON, Show, ToJSON)--data User- = User- { _userCreated :: PushbulletTime- , _userEmail :: EmailAddress- , _userEmailNormalized :: EmailAddress- , _userId :: UserId- , _userImageUrl :: Url- , _userMaxUploadSize :: Double- , _userModified :: PushbulletTime- , _userName :: Name- }- deriving (Eq, Show)--makeLenses ''User--instance FromJSON User where- parseJSON (Object o) = pure User- <*> o .: "created"- <*> o .: "email"- <*> o .: "email_normalized"- <*> o .: "iden"- <*> o .: "image_url"- <*> o .: "max_upload_size"- <*> o .: "modified"- <*> o .: "name"- parseJSON _ = fail "cannot parse user from non-object"