Broadcasting works
This commit is contained in:
parent
7c8394f0fd
commit
b0ebeda23a
|
@ -1,8 +1,3 @@
|
||||||
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
|
||||||
|
|
||||||
{-# HLINT ignore "Redundant <$>" #-}
|
|
||||||
{-# HLINT ignore "Redundant $" #-}
|
|
||||||
{-# HLINT ignore "Redundant bracket" #-}
|
|
||||||
module BroadcastUserData
|
module BroadcastUserData
|
||||||
( broadcastUserData,
|
( broadcastUserData,
|
||||||
)
|
)
|
||||||
|
@ -10,11 +5,11 @@ where
|
||||||
|
|
||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
import Data.Aeson (encode)
|
import Data.Aeson (encode)
|
||||||
|
import Network.WebSockets qualified as WS
|
||||||
import Types.AppTypes (HasConnectedClientState (..))
|
import Types.AppTypes (HasConnectedClientState (..))
|
||||||
import Types.ConnectionState (Client (..))
|
import Types.ConnectionState (Client (..), ConnectedClients)
|
||||||
import Types.RoomsState (HasRoomsState (..))
|
import Types.RoomsState (HasRoomsState (..))
|
||||||
import Types.UsersData (UsersData (..))
|
import Types.UsersData (UsersData (..))
|
||||||
import WebSocket (broadCastToClients)
|
|
||||||
|
|
||||||
broadcastUserData ::
|
broadcastUserData ::
|
||||||
( MonadIO m,
|
( MonadIO m,
|
||||||
|
@ -24,9 +19,10 @@ broadcastUserData ::
|
||||||
) =>
|
) =>
|
||||||
m ()
|
m ()
|
||||||
broadcastUserData = do
|
broadcastUserData = do
|
||||||
|
putStrLn "broadcasting"
|
||||||
userWithOutRoom <- getUsersWithoutRoom
|
userWithOutRoom <- getUsersWithoutRoom
|
||||||
roomsData <- (getRoomsState <$> ask) >>= readMVar
|
roomsData <- ask >>= readMVar . getRoomsState
|
||||||
let usersData = UsersData {userWithOutRoom = userWithOutRoom, roomsData = roomsData}
|
let usersData = UsersData {usersWithOutRoom = userWithOutRoom, roomsData = roomsData}
|
||||||
broadCastToClients $ (decodeUtf8 . toStrict . encode) usersData
|
broadCastToClients $ (decodeUtf8 . toStrict . encode) usersData
|
||||||
|
|
||||||
getUsersWithoutRoom ::
|
getUsersWithoutRoom ::
|
||||||
|
@ -36,5 +32,21 @@ getUsersWithoutRoom ::
|
||||||
) =>
|
) =>
|
||||||
m [Text]
|
m [Text]
|
||||||
getUsersWithoutRoom = do
|
getUsersWithoutRoom = do
|
||||||
state <- (getConnectedClientState <$> ask) >>= readMVar
|
state <- ask >>= readMVar . getConnectedClientState
|
||||||
return $ map name $ filter (not . joinedRoom) state
|
return $ map name $ filter (not . joinedRoom) state
|
||||||
|
|
||||||
|
broadcast :: Text -> ConnectedClients -> IO ()
|
||||||
|
broadcast message clients = do
|
||||||
|
putStrLn message
|
||||||
|
forM_ clients $ \client -> WS.sendTextData (conn client) message
|
||||||
|
|
||||||
|
broadCastToClients ::
|
||||||
|
( MonadIO m,
|
||||||
|
HasConnectedClientState env,
|
||||||
|
MonadReader env m
|
||||||
|
) =>
|
||||||
|
Text ->
|
||||||
|
m ()
|
||||||
|
broadCastToClients message = do
|
||||||
|
state <- getConnectedClientState <$> ask
|
||||||
|
liftIO $ withMVar state $ \currenState -> broadcast message currenState
|
||||||
|
|
|
@ -75,6 +75,7 @@ badRequest ::
|
||||||
m ResponseReceived
|
m ResponseReceived
|
||||||
badRequest errorMessage = do
|
badRequest errorMessage = do
|
||||||
respond' <- getRespond <$> ask
|
respond' <- getRespond <$> ask
|
||||||
|
liftIO $ print errorMessage
|
||||||
liftIO $
|
liftIO $
|
||||||
respond' $
|
respond' $
|
||||||
responseLBS
|
responseLBS
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Types.RoomData (RoomsData)
|
||||||
|
|
||||||
data UsersData = UsersData
|
data UsersData = UsersData
|
||||||
{ roomsData :: RoomsData,
|
{ roomsData :: RoomsData,
|
||||||
userWithOutRoom :: UsersWithoutRoom
|
usersWithOutRoom :: UsersWithoutRoom
|
||||||
}
|
}
|
||||||
deriving (Generic, Show)
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import Types.RoomsState
|
||||||
updateRoomState,
|
updateRoomState,
|
||||||
)
|
)
|
||||||
import Types.WebEnv
|
import Types.WebEnv
|
||||||
import WebSocket (broadCastToClients)
|
|
||||||
|
|
||||||
newtype ExceptTApp e a = E {unExceptTApp :: IO (Either e a)}
|
newtype ExceptTApp e a = E {unExceptTApp :: IO (Either e a)}
|
||||||
deriving
|
deriving
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
|
||||||
|
module WebSocket (runWebSocketServer) where
|
||||||
|
|
||||||
module WebSocket (broadCastToClients, runWebSocketServer) where
|
import BroadcastUserData (broadcastUserData)
|
||||||
|
|
||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
import Data.UUID (UUID)
|
import Data.UUID (UUID)
|
||||||
import Data.UUID.V4 (nextRandom)
|
import Data.UUID.V4 (nextRandom)
|
||||||
import qualified Network.WebSockets as WS
|
import Network.WebSockets qualified as WS
|
||||||
import Types.AppTypes (Env (connectedClientsState),
|
import Types.AppTypes
|
||||||
HasConnectedClientState (getConnectedClientState))
|
( Env (..),
|
||||||
|
HasConnectedClientState (getConnectedClientState),
|
||||||
|
)
|
||||||
import Types.ConnectionState (Client (..), ConnectedClients)
|
import Types.ConnectionState (Client (..), ConnectedClients)
|
||||||
|
import Types.RoomsState (HasRoomsState (..))
|
||||||
|
|
||||||
data WSEnv = WSEnv
|
data WSEnv = WSEnv
|
||||||
{ appEnv :: Env,
|
{ appEnv :: Env,
|
||||||
|
@ -22,6 +25,9 @@ data WSEnv = WSEnv
|
||||||
instance HasConnectedClientState WSEnv where
|
instance HasConnectedClientState WSEnv where
|
||||||
getConnectedClientState = connectedClientsState . appEnv
|
getConnectedClientState = connectedClientsState . appEnv
|
||||||
|
|
||||||
|
instance HasRoomsState WSEnv where
|
||||||
|
getRoomsState = roomsState . appEnv
|
||||||
|
|
||||||
class HasWSEnv a where
|
class HasWSEnv a where
|
||||||
getConn :: a -> WS.Connection
|
getConn :: a -> WS.Connection
|
||||||
getClientId :: a -> UUID
|
getClientId :: a -> UUID
|
||||||
|
@ -70,6 +76,7 @@ joinRoom ::
|
||||||
joinRoom = do
|
joinRoom = do
|
||||||
clientId <- getClientId <$> ask
|
clientId <- getClientId <$> ask
|
||||||
state <- getConnectedClientState <$> ask
|
state <- getConnectedClientState <$> ask
|
||||||
|
liftIO $ putStrLn "joinedRoom"
|
||||||
modifyMVar_ state $ \s ->
|
modifyMVar_ state $ \s ->
|
||||||
let s' = updateClient clientId (\c -> c {joinedRoom = True}) s
|
let s' = updateClient clientId (\c -> c {joinedRoom = True}) s
|
||||||
in return s'
|
in return s'
|
||||||
|
@ -80,15 +87,10 @@ removeClient toRemove = filter ((/= toRemove) . uuid)
|
||||||
updateClient :: UUID -> (Client -> Client) -> ConnectedClients -> ConnectedClients
|
updateClient :: UUID -> (Client -> Client) -> ConnectedClients -> ConnectedClients
|
||||||
updateClient toUpdate f allClients = do
|
updateClient toUpdate f allClients = do
|
||||||
client <- allClients
|
client <- allClients
|
||||||
if (toUpdate == uuid client)
|
if toUpdate == uuid client
|
||||||
then (return $ f client)
|
then return $ f client
|
||||||
else return client
|
else return client
|
||||||
|
|
||||||
broadcast :: Text -> ConnectedClients -> IO ()
|
|
||||||
broadcast message clients = do
|
|
||||||
putStrLn message
|
|
||||||
forM_ clients $ \client -> WS.sendTextData (conn client) message
|
|
||||||
|
|
||||||
runWebSocketServer ::
|
runWebSocketServer ::
|
||||||
( MonadIO m,
|
( MonadIO m,
|
||||||
MonadReader Env m
|
MonadReader Env m
|
||||||
|
@ -111,8 +113,7 @@ runWSApp = do
|
||||||
conn <- WS.acceptRequest pending
|
conn <- WS.acceptRequest pending
|
||||||
uuid <- nextRandom
|
uuid <- nextRandom
|
||||||
let wsEnv = WSEnv {appEnv = env, connection = conn, clientId = uuid}
|
let wsEnv = WSEnv {appEnv = env, connection = conn, clientId = uuid}
|
||||||
WS.withPingThread conn 30 (return ()) $ do
|
WS.withPingThread conn 30 (return ()) $ unWSApp wsApp wsEnv
|
||||||
unWSApp wsApp wsEnv
|
|
||||||
)
|
)
|
||||||
|
|
||||||
newClient ::
|
newClient ::
|
||||||
|
@ -140,6 +141,7 @@ newtype WSApp env a = WSApp {unWSApp :: env -> IO a}
|
||||||
wsApp ::
|
wsApp ::
|
||||||
( HasWSEnv env,
|
( HasWSEnv env,
|
||||||
HasConnectedClientState env,
|
HasConnectedClientState env,
|
||||||
|
HasRoomsState env,
|
||||||
MonadReader env m,
|
MonadReader env m,
|
||||||
MonadUnliftIO m
|
MonadUnliftIO m
|
||||||
) =>
|
) =>
|
||||||
|
@ -149,10 +151,11 @@ wsApp = do
|
||||||
putStrLn msg
|
putStrLn msg
|
||||||
client <- newClient msg
|
client <- newClient msg
|
||||||
addWSClient client
|
addWSClient client
|
||||||
flip finally disconnectWsClient $ do
|
broadcastUserData
|
||||||
forever $ do
|
flip finally disconnectWsClient $ forever $ do
|
||||||
currentMsg <- getMessage
|
currentMsg <- getMessage
|
||||||
joinRoom
|
joinRoom
|
||||||
|
broadcastUserData
|
||||||
putStrLn currentMsg
|
putStrLn currentMsg
|
||||||
|
|
||||||
getMessage ::
|
getMessage ::
|
||||||
|
@ -164,14 +167,3 @@ getMessage ::
|
||||||
getMessage = do
|
getMessage = do
|
||||||
conn' <- getConn <$> ask
|
conn' <- getConn <$> ask
|
||||||
liftIO $ WS.receiveData conn'
|
liftIO $ WS.receiveData conn'
|
||||||
|
|
||||||
broadCastToClients ::
|
|
||||||
( MonadIO m,
|
|
||||||
HasConnectedClientState env,
|
|
||||||
MonadReader env m
|
|
||||||
) =>
|
|
||||||
Text ->
|
|
||||||
m ()
|
|
||||||
broadCastToClients message = do
|
|
||||||
state <- getConnectedClientState <$> ask
|
|
||||||
liftIO $ withMVar state $ \currenState -> broadcast message currenState
|
|
||||||
|
|
Loading…
Reference in New Issue