All Chat Backend

This commit is contained in:
qvalentin 2023-04-08 15:57:33 +02:00
parent b01b637a22
commit cf1c7625be
10 changed files with 90 additions and 36 deletions

View File

@ -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

View File

@ -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

View File

@ -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
View 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

View File

@ -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]

View File

@ -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

View 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

View File

@ -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

View File

@ -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,

View File

@ -1,2 +0,0 @@
main :: IO ()
main = putStrLn "Test suite not yet implemented"