module Network.Pusher.Data (
AppID
, AppKey
, AppSecret
, Pusher(..)
, Credentials(..)
, getPusher
, getPusherWithHost
, getPusherWithConnManager
, Channel(..)
, ChannelName
, ChannelType(..)
, renderChannel
, renderChannelPrefix
, parseChannel
, Event
, EventData
, SocketID
) where
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Aeson ((.:))
import Data.Foldable (asum)
import Data.Hashable (Hashable)
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Data.Text.Encoding (encodeUtf8)
import GHC.Generics (Generic)
import Network.HTTP.Client (Manager, defaultManagerSettings, newManager)
import qualified Data.Aeson as A
import qualified Data.ByteString as B
import qualified Data.Text as T
import Network.Pusher.Internal.Util (failExpectObj, show')
type AppID = Integer
type AppKey = B.ByteString
type AppSecret = B.ByteString
data Pusher = Pusher
{ pusherHost :: T.Text
, pusherPath :: T.Text
, pusherCredentials :: Credentials
, pusherConnectionManager :: Manager
}
data Credentials = Credentials
{ credentialsAppID :: AppID
, credentialsAppKey :: AppKey
, credentialsAppSecret :: AppSecret
}
instance A.FromJSON Credentials where
parseJSON (A.Object v) = Credentials
<$> v .: "app-id"
<*> (encodeUtf8 <$> v .: "app-key")
<*> (encodeUtf8 <$> v .: "app-secret")
parseJSON v2 = failExpectObj v2
getPusher :: MonadIO m => Credentials -> m Pusher
getPusher cred = do
connManager <- getConnManager
return $ getPusherWithConnManager connManager Nothing cred
getPusherWithHost :: MonadIO m => T.Text -> Credentials -> m Pusher
getPusherWithHost apiHost cred = do
connManager <- getConnManager
return $ getPusherWithConnManager connManager (Just apiHost) cred
getPusherWithConnManager :: Manager -> Maybe T.Text -> Credentials -> Pusher
getPusherWithConnManager connManager apiHost cred =
let path = "/apps/" <> show' (credentialsAppID cred) <> "/" in
Pusher
{ pusherHost = fromMaybe "http://api.pusherapp.com" apiHost
, pusherPath = path
, pusherCredentials = cred
, pusherConnectionManager = connManager
}
getConnManager :: MonadIO m => m Manager
getConnManager = liftIO $ newManager defaultManagerSettings
type ChannelName = T.Text
data ChannelType = Public | Private | Presence deriving (Eq, Generic, Show)
instance Hashable ChannelType
renderChannelPrefix :: ChannelType -> T.Text
renderChannelPrefix Public = ""
renderChannelPrefix Private = "private-"
renderChannelPrefix Presence = "presence-"
data Channel = Channel
{ channelType :: ChannelType
, channelName :: ChannelName
} deriving (Eq, Generic, Show)
instance Hashable Channel
renderChannel :: Channel -> T.Text
renderChannel (Channel cType cName) = renderChannelPrefix cType <> cName
parseChannel :: T.Text -> Channel
parseChannel chan =
fromMaybe
(Channel Public chan)
(asum [parseChanAs Private, parseChanAs Presence])
where
parseChanAs chanType =
let split = T.splitOn (renderChannelPrefix chanType) chan in
if length split > 1 && T.null (head split) then
Just $ Channel chanType (T.concat $ tail split)
else
Nothing
type Event = T.Text
type EventData = T.Text
type SocketID = T.Text