All Chat Backend
This commit is contained in:
parent
b01b637a22
commit
cf1c7625be
|
@ -1,6 +1,6 @@
|
||||||
cabal-version: 1.12
|
cabal-version: 1.12
|
||||||
|
|
||||||
-- This file has been generated from package.yaml by hpack version 0.35.1.
|
-- This file has been generated from package.yaml by hpack version 0.35.0.
|
||||||
--
|
--
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
|
@ -35,10 +35,12 @@ library
|
||||||
Types.Participant
|
Types.Participant
|
||||||
Types.RoomData
|
Types.RoomData
|
||||||
Types.RoomsState
|
Types.RoomsState
|
||||||
|
Types.User
|
||||||
Types.UsersData
|
Types.UsersData
|
||||||
Types.WebEnv
|
Types.WebEnv
|
||||||
Types.WebSocketMessages.WebSocketMessages
|
Types.WebSocketMessages.WebSocketMessages
|
||||||
WebServer
|
WebServer
|
||||||
|
WebSocket.AllChat
|
||||||
WebSocket.Messages
|
WebSocket.Messages
|
||||||
WebSocket.MonadWebSocketSession
|
WebSocket.MonadWebSocketSession
|
||||||
WebSocket.Server
|
WebSocket.Server
|
||||||
|
@ -90,4 +92,3 @@ executable jitsi-rooms-exe
|
||||||
, warp
|
, warp
|
||||||
, websockets
|
, websockets
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
|
|
@ -58,14 +58,4 @@ executables:
|
||||||
dependencies:
|
dependencies:
|
||||||
- jitsi-rooms
|
- jitsi-rooms
|
||||||
|
|
||||||
tests:
|
|
||||||
jitsi-rooms-test:
|
|
||||||
main: Spec.hs
|
|
||||||
source-dirs: test
|
|
||||||
ghc-options:
|
|
||||||
- -threaded
|
|
||||||
- -rtsopts
|
|
||||||
- -with-rtsopts=-N
|
|
||||||
dependencies:
|
|
||||||
- jitsi-rooms
|
|
||||||
default-extensions: NoImplicitPrelude,OverloadedStrings,ImportQualifiedPost
|
default-extensions: NoImplicitPrelude,OverloadedStrings,ImportQualifiedPost
|
||||||
|
|
|
@ -7,12 +7,11 @@ where
|
||||||
|
|
||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
import Data.Aeson (encode)
|
import Data.Aeson (encode)
|
||||||
import qualified Network.WebSockets as WS
|
import Network.WebSockets qualified as WS
|
||||||
import State.ConnectedClientsState (MonadConnectedClientsRead (getConnctedClients))
|
import State.ConnectedClientsState (MonadConnectedClientsRead (getConnctedClients))
|
||||||
import State.RoomDataState (MonadRoomDataStateRead (getRoomDataState))
|
import State.RoomDataState (MonadRoomDataStateRead (getRoomDataState))
|
||||||
import Types.AppTypes (HasConnectedClientState (..))
|
|
||||||
import Types.ConnectionState (Client (..), ConnectedClients)
|
import Types.ConnectionState (Client (..), ConnectedClients)
|
||||||
import Types.RoomsState (HasRoomsState (..))
|
import Types.User (User, clientToUser)
|
||||||
import Types.UsersData (UsersData (..))
|
import Types.UsersData (UsersData (..))
|
||||||
|
|
||||||
class (Monad m, MonadConnectedClientsRead m) => MonadBroadcast m where
|
class (Monad m, MonadConnectedClientsRead m) => MonadBroadcast m where
|
||||||
|
@ -32,8 +31,8 @@ broadcastUserData = do
|
||||||
getUsersWithoutRoom ::
|
getUsersWithoutRoom ::
|
||||||
( MonadConnectedClientsRead m
|
( MonadConnectedClientsRead m
|
||||||
) =>
|
) =>
|
||||||
m [Text]
|
m [User]
|
||||||
getUsersWithoutRoom = map name . filter (not . joinedRoom) <$> getConnctedClients
|
getUsersWithoutRoom = map clientToUser . filter (not . joinedRoom) <$> getConnctedClients
|
||||||
|
|
||||||
broadCastToClientsGeneric ::
|
broadCastToClientsGeneric ::
|
||||||
( MonadIO m,
|
( MonadIO m,
|
||||||
|
|
21
backend/src/Types/User.hs
Normal file
21
backend/src/Types/User.hs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
|
||||||
|
module Types.User (User, clientToUser) where
|
||||||
|
|
||||||
|
import ClassyPrelude
|
||||||
|
import Data.Aeson (FromJSON, ToJSON)
|
||||||
|
import Data.UUID (UUID)
|
||||||
|
import Types.ConnectionState qualified as C
|
||||||
|
|
||||||
|
data User = User
|
||||||
|
{ uuid :: UUID,
|
||||||
|
name :: Text
|
||||||
|
}
|
||||||
|
deriving (Generic, Show, Eq)
|
||||||
|
|
||||||
|
clientToUser :: C.Client -> User
|
||||||
|
clientToUser C.Client {C.uuid = userUuid, C.name = userName, C.joinedRoom = _, C.conn = _} = User userUuid userName
|
||||||
|
|
||||||
|
instance ToJSON User
|
||||||
|
|
||||||
|
instance FromJSON User
|
|
@ -8,6 +8,7 @@ where
|
||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
import Data.Aeson (ToJSON)
|
import Data.Aeson (ToJSON)
|
||||||
import Types.RoomData (RoomsData)
|
import Types.RoomData (RoomsData)
|
||||||
|
import Types.User (User)
|
||||||
|
|
||||||
data UsersData = UsersData
|
data UsersData = UsersData
|
||||||
{ roomsData :: RoomsData,
|
{ roomsData :: RoomsData,
|
||||||
|
@ -17,4 +18,4 @@ data UsersData = UsersData
|
||||||
|
|
||||||
instance ToJSON UsersData
|
instance ToJSON UsersData
|
||||||
|
|
||||||
type UsersWithoutRoom = [Text]
|
type UsersWithoutRoom = [User]
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
|
||||||
module Types.WebSocketMessages.WebSocketMessages
|
module Types.WebSocketMessages.WebSocketMessages
|
||||||
( WebSocketMessage (..),
|
( WebSocketMessage (..),
|
||||||
SetClientInfo (..),
|
SetClientInfo (..),
|
||||||
JoinRoom (..),
|
JoinRoom (..),
|
||||||
|
AllChatMessageIncoming (..),
|
||||||
|
AllChatMessageOutgoing (..),
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -12,14 +15,13 @@ import Data.Aeson
|
||||||
( FromJSON (parseJSON),
|
( FromJSON (parseJSON),
|
||||||
Options (sumEncoding),
|
Options (sumEncoding),
|
||||||
SumEncoding (..),
|
SumEncoding (..),
|
||||||
decode,
|
ToJSON,
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
genericParseJSON,
|
genericParseJSON,
|
||||||
withObject,
|
|
||||||
(.:),
|
|
||||||
)
|
)
|
||||||
|
import Types.User (User)
|
||||||
|
|
||||||
data WebSocketMessage = ClientInfoMessage SetClientInfo | JoinRoomMessage JoinRoom
|
data WebSocketMessage = ClientInfoMessage SetClientInfo | JoinRoomMessage JoinRoom | AllChatMessageIncomingMessage AllChatMessageIncoming
|
||||||
deriving (Generic)
|
deriving (Generic)
|
||||||
|
|
||||||
instance FromJSON WebSocketMessage where
|
instance FromJSON WebSocketMessage where
|
||||||
|
@ -38,3 +40,18 @@ data JoinRoom = JoinRoom
|
||||||
deriving (Generic, Show)
|
deriving (Generic, Show)
|
||||||
|
|
||||||
instance FromJSON JoinRoom
|
instance FromJSON JoinRoom
|
||||||
|
|
||||||
|
data AllChatMessageIncoming = AllChatMessageIncoming
|
||||||
|
{ content :: Text
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance FromJSON AllChatMessageIncoming
|
||||||
|
|
||||||
|
data AllChatMessageOutgoing = AllChatMessageOutgoing
|
||||||
|
{ content :: Text,
|
||||||
|
sender :: User
|
||||||
|
}
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
instance ToJSON AllChatMessageOutgoing
|
||||||
|
|
18
backend/src/WebSocket/AllChat.hs
Normal file
18
backend/src/WebSocket/AllChat.hs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
|
||||||
|
module WebSocket.AllChat (broadCastAllChatMessage) where
|
||||||
|
|
||||||
|
import BroadcastUserData (MonadBroadcast (..))
|
||||||
|
import ClassyPrelude
|
||||||
|
import Data.Aeson (encode)
|
||||||
|
import Types.User (clientToUser)
|
||||||
|
import Types.WebSocketMessages.WebSocketMessages (AllChatMessageIncoming (..), AllChatMessageOutgoing (AllChatMessageOutgoing))
|
||||||
|
import WebSocket.MonadWebSocketSession (MonadWebSocketSession (getClient))
|
||||||
|
|
||||||
|
broadCastAllChatMessage :: (MonadBroadcast m, MonadWebSocketSession m) => AllChatMessageIncoming -> m ()
|
||||||
|
broadCastAllChatMessage AllChatMessageIncoming {content = message} = do
|
||||||
|
getClient >>= \case
|
||||||
|
Nothing -> return ()
|
||||||
|
Just client -> do
|
||||||
|
let broadCastValue = AllChatMessageOutgoing message (clientToUser client)
|
||||||
|
broadCastToClients $ (decodeUtf8 . toStrict . encode) broadCastValue
|
|
@ -15,6 +15,7 @@ import Data.Aeson
|
||||||
import Data.UUID (UUID)
|
import Data.UUID (UUID)
|
||||||
import State.ConnectedClientsState
|
import State.ConnectedClientsState
|
||||||
( MonadConnectedClientsModify,
|
( MonadConnectedClientsModify,
|
||||||
|
MonadConnectedClientsRead (getConnctedClients),
|
||||||
removeWSClient,
|
removeWSClient,
|
||||||
)
|
)
|
||||||
import State.RoomDataState (MonadRoomDataStateRead)
|
import State.RoomDataState (MonadRoomDataStateRead)
|
||||||
|
@ -23,9 +24,10 @@ import Types.WebSocketMessages.WebSocketMessages (SetClientInfo (..))
|
||||||
import WebSocket.Messages
|
import WebSocket.Messages
|
||||||
import WebSocket.WSReaderTApp
|
import WebSocket.WSReaderTApp
|
||||||
|
|
||||||
class Monad m => MonadWebSocketSession m where
|
class MonadConnectedClientsRead m => MonadWebSocketSession m where
|
||||||
getTypedWSMessage :: FromJSON a => m a
|
getTypedWSMessage :: FromJSON a => m a
|
||||||
getSesssionId :: m UUID
|
getSesssionId :: m UUID
|
||||||
|
getClient :: m (Maybe Client)
|
||||||
|
|
||||||
instance MonadWebSocketSession (WSApp WSEnv) where
|
instance MonadWebSocketSession (WSApp WSEnv) where
|
||||||
getTypedWSMessage = do
|
getTypedWSMessage = do
|
||||||
|
@ -36,6 +38,9 @@ instance MonadWebSocketSession (WSApp WSEnv) where
|
||||||
sendMessage $ "Bad message: " <> pack err
|
sendMessage $ "Bad message: " <> pack err
|
||||||
getTypedWSMessage
|
getTypedWSMessage
|
||||||
getSesssionId = getClientId <$> ask
|
getSesssionId = getClientId <$> ask
|
||||||
|
getClient = do
|
||||||
|
id' <- getSesssionId
|
||||||
|
find ((== id') . uuid) <$> getConnctedClients
|
||||||
|
|
||||||
class (Monad m) => MonadWebSocketSessionInit m where
|
class (Monad m) => MonadWebSocketSessionInit m where
|
||||||
newClient :: SetClientInfo -> m Client
|
newClient :: SetClientInfo -> m Client
|
||||||
|
|
|
@ -13,6 +13,7 @@ import Types.WebSocketMessages.WebSocketMessages
|
||||||
( SetClientInfo (displayName),
|
( SetClientInfo (displayName),
|
||||||
WebSocketMessage (..),
|
WebSocketMessage (..),
|
||||||
)
|
)
|
||||||
|
import WebSocket.AllChat (broadCastAllChatMessage)
|
||||||
import WebSocket.MonadWebSocketSession
|
import WebSocket.MonadWebSocketSession
|
||||||
import WebSocket.WSReaderTApp
|
import WebSocket.WSReaderTApp
|
||||||
|
|
||||||
|
@ -35,7 +36,8 @@ wsApp = do
|
||||||
|
|
||||||
handleWSAction ::
|
handleWSAction ::
|
||||||
( MonadWebSocketSession m,
|
( MonadWebSocketSession m,
|
||||||
MonadConnectedClientsModify m
|
MonadConnectedClientsModify m,
|
||||||
|
MonadBroadcast m
|
||||||
) =>
|
) =>
|
||||||
m ()
|
m ()
|
||||||
handleWSAction = do
|
handleWSAction = do
|
||||||
|
@ -45,6 +47,8 @@ handleWSAction = do
|
||||||
joinRoom
|
joinRoom
|
||||||
ClientInfoMessage clientInfo -> do
|
ClientInfoMessage clientInfo -> do
|
||||||
updateClientName clientInfo
|
updateClientName clientInfo
|
||||||
|
AllChatMessageIncomingMessage incomingMessage -> do
|
||||||
|
broadCastAllChatMessage incomingMessage
|
||||||
|
|
||||||
joinRoom ::
|
joinRoom ::
|
||||||
( MonadConnectedClientsModify m,
|
( MonadConnectedClientsModify m,
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
main :: IO ()
|
|
||||||
main = putStrLn "Test suite not yet implemented"
|
|
Loading…
Reference in a new issue