module Network.PushNotify.Apns.Types
(
APNSConfig(..)
, APNSManager(..)
, DeviceToken
, Env(..)
, APNSmessage(..)
, AlertDictionary(..)
, APNSresult(..)
, APNSFeedBackresult(..)
) where
import Network.PushNotify.Apns.Constants
import Network.TLS (PrivateKey)
import Control.Concurrent
import Control.Concurrent.STM.TChan
import Control.Monad.Writer
import Control.Retry
import Data.Aeson.Types
import Data.Certificate.X509 (X509)
import Data.Default
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as HS
import Data.IORef
import Data.Text
import Data.Time.Clock
data Env = Development
| Production
| Local
deriving Show
data APNSConfig = APNSConfig
{ apnsCertificate :: X509
, apnsPrivateKey :: PrivateKey
, environment :: Env
, timeoutLimit :: Int
, apnsRetrySettings :: RetrySettings
}
instance Default APNSConfig where
def = APNSConfig {
apnsCertificate = undefined
, apnsPrivateKey = undefined
, environment = Development
, timeoutLimit = 200000
, apnsRetrySettings = RetrySettings {
backoff = True
, baseDelay = 200
, numRetries = limitedRetries 5
}
}
data APNSManager = APNSManager
{ mState :: IORef (Maybe ())
, mApnsChannel :: TChan ( MVar (Maybe (Chan Int,Int)) , APNSmessage)
, mWorkerID :: ThreadId
, mTimeoutLimit :: Int
}
type DeviceToken = Text
data APNSmessage = APNSmessage
{ deviceTokens :: HS.HashSet DeviceToken
, expiry :: Maybe UTCTime
, alert :: Either Text AlertDictionary
, badge :: Maybe Int
, sound :: Text
, rest :: Maybe Object
} deriving Show
instance Default APNSmessage where
def = APNSmessage {
deviceTokens = HS.empty
, expiry = Nothing
, alert = Left empty
, badge = Nothing
, sound = empty
, rest = Nothing
}
data AlertDictionary = AlertDictionary
{ body :: Text
, action_loc_key :: Text
, loc_key :: Text
, loc_args :: [Text]
, launch_image :: Text
} deriving Show
instance Default AlertDictionary where
def = AlertDictionary{
body = empty
, action_loc_key = empty
, loc_key = empty
, loc_args = []
, launch_image = empty
}
data APNSresult = APNSresult
{ successfulTokens :: HS.HashSet DeviceToken
, toReSendTokens :: HS.HashSet DeviceToken
} deriving Show
instance Default APNSresult where
def = APNSresult HS.empty HS.empty
data APNSFeedBackresult = APNSFeedBackresult
{ unRegisteredTokens :: HM.HashMap DeviceToken UTCTime
} deriving Show
instance Default APNSFeedBackresult where
def = APNSFeedBackresult HM.empty
ifNotDef :: (ToJSON a,MonadWriter [Pair] m,Eq a,Default b)
=> Text
-> (b -> a)
-> b
-> m ()
ifNotDef label f msg = if f def /= f msg
then tell [(label .= (f msg))]
else tell []
instance ToJSON APNSmessage where
toJSON msg = case rest msg of
Nothing -> object [(cAPPS .= toJSONapps msg)]
Just (map) -> Object $ HM.insert cAPPS (toJSONapps msg) map
toJSONapps msg = object $ execWriter $ do
case alert msg of
Left xs -> if xs == empty
then tell []
else tell [(cALERT .= xs)]
Right m -> tell [(cALERT .= (toJSON m))]
ifNotDef cBADGE badge msg
ifNotDef cSOUND sound msg
instance ToJSON AlertDictionary where
toJSON msg = object $ execWriter $ do
ifNotDef cBODY body msg
ifNotDef cACTION_LOC_KEY action_loc_key msg
ifNotDef cLOC_KEY loc_key msg
if loc_key def /= loc_key msg
then ifNotDef cLOC_ARGS loc_args msg
else tell []
ifNotDef cLAUNCH_IMAGE launch_image msg