Add RoomInvite type

pull/1/head
Bram van den Heuvel 2023-03-15 15:31:29 +01:00
parent 45142509d3
commit 1d90d300da
7 changed files with 314 additions and 14 deletions

View File

@ -0,0 +1,40 @@
module Internal.Api.Leave.Api exposing (..)
import Internal.Api.Request as R
import Internal.Tools.Context exposing (Context)
import Internal.Tools.Exceptions as X
import Json.Decode as D
import Task exposing (Task)
type alias LeaveInputV1 =
{ roomId : String }
type alias LeaveInputV2 =
{ roomId : String, reason : Maybe String }
type alias LeaveOutputV1 =
()
leaveV1 : LeaveInputV1 -> Context { a | accessToken : (), baseUrl : () } -> Task X.Error LeaveOutputV1
leaveV1 { roomId } =
R.callApi "POST" "/_matrix/client/r0/rooms/{roomId}/leave"
>> R.withAttributes
[ R.accessToken
, R.replaceInUrl "roomId" roomId
]
>> R.toTask (D.map (always ()) D.value)
leaveV2 : LeaveInputV2 -> Context { a | accessToken : (), baseUrl : () } -> Task X.Error LeaveOutputV1
leaveV2 { roomId, reason } =
R.callApi "POST" "/_matrix/client/r0/rooms/{roomId}/leave"
>> R.withAttributes
[ R.accessToken
, R.replaceInUrl "roomId" roomId
, R.bodyOpString "reason" reason
]
>> R.toTask (D.map (always ()) D.value)

View File

@ -0,0 +1,48 @@
module Internal.Api.Leave.Main exposing (..)
import Internal.Api.Leave.Api as Api
import Internal.Tools.Context as Context exposing (Context, VBA)
import Internal.Tools.Exceptions as X
import Internal.Tools.VersionControl as VC
import Task exposing (Task)
leave : Context (VBA a) -> LeaveInput -> Task X.Error LeaveOutput
leave context input =
VC.withBottomLayer
{ current = Api.leaveV1
, version = "r0.0.0"
}
|> VC.sameForVersion "r0.0.1"
|> VC.sameForVersion "r0.1.0"
|> VC.sameForVersion "r0.2.0"
|> VC.sameForVersion "r0.3.0"
|> VC.sameForVersion "r0.4.0"
|> VC.sameForVersion "r0.5.0"
|> VC.sameForVersion "r0.6.0"
|> VC.sameForVersion "r0.6.1"
|> VC.addMiddleLayer
{ downcast =
\data ->
{ roomId = data.roomId
}
, current = Api.leaveV2
, upcast = identity
, version = "v1.1"
}
|> VC.sameForVersion "v1.2"
|> VC.sameForVersion "v1.3"
|> VC.sameForVersion "v1.4"
|> VC.sameForVersion "v1.5"
|> VC.mostRecentFromVersionList (Context.getVersions context)
|> Maybe.withDefault (always <| always <| Task.fail X.UnsupportedSpecVersion)
|> (|>) input
|> (|>) context
type alias LeaveInput =
Api.LeaveInputV2
type alias LeaveOutput =
Api.LeaveOutputV1

View File

@ -10,6 +10,7 @@ import Internal.Api.GetEvent.Main exposing (EventInput)
import Internal.Api.Invite.Main exposing (InviteInput) import Internal.Api.Invite.Main exposing (InviteInput)
import Internal.Api.JoinRoomById.Main exposing (JoinRoomByIdInput) import Internal.Api.JoinRoomById.Main exposing (JoinRoomByIdInput)
import Internal.Api.JoinedMembers.Main exposing (JoinedMembersInput) import Internal.Api.JoinedMembers.Main exposing (JoinedMembersInput)
import Internal.Api.Leave.Main exposing (LeaveInput)
import Internal.Api.SendStateKey.Main exposing (SendStateKeyInput) import Internal.Api.SendStateKey.Main exposing (SendStateKeyInput)
import Internal.Api.Sync.Main exposing (SyncInput) import Internal.Api.Sync.Main exposing (SyncInput)
import Internal.Api.VaultUpdate as C import Internal.Api.VaultUpdate as C
@ -55,6 +56,13 @@ joinRoomById data cred =
|> C.toTask |> C.toTask
leave : LeaveInput -> Credentials -> FutureTask
leave data cred =
C.makeVBA cred
|> Chain.andThen (C.leave data)
|> C.toTask
type alias RedactInput = type alias RedactInput =
{ eventId : String { eventId : String
, extraTransactionNoise : String , extraTransactionNoise : String

View File

@ -6,6 +6,7 @@ import Internal.Api.GetEvent.Main as GetEvent
import Internal.Api.Invite.Main as Invite import Internal.Api.Invite.Main as Invite
import Internal.Api.JoinRoomById.Main as JoinRoomById import Internal.Api.JoinRoomById.Main as JoinRoomById
import Internal.Api.JoinedMembers.Main as JoinedMembers import Internal.Api.JoinedMembers.Main as JoinedMembers
import Internal.Api.Leave.Main as Leave
import Internal.Api.LoginWithUsernameAndPassword.Main as LoginWithUsernameAndPassword import Internal.Api.LoginWithUsernameAndPassword.Main as LoginWithUsernameAndPassword
import Internal.Api.Redact.Main as Redact import Internal.Api.Redact.Main as Redact
import Internal.Api.SendMessageEvent.Main as SendMessageEvent import Internal.Api.SendMessageEvent.Main as SendMessageEvent
@ -27,6 +28,7 @@ type VaultUpdate
| InviteSent Invite.InviteInput Invite.InviteOutput | InviteSent Invite.InviteInput Invite.InviteOutput
| JoinedMembersToRoom JoinedMembers.JoinedMembersInput JoinedMembers.JoinedMembersOutput | JoinedMembersToRoom JoinedMembers.JoinedMembersInput JoinedMembers.JoinedMembersOutput
| JoinedRoom JoinRoomById.JoinRoomByIdInput JoinRoomById.JoinRoomByIdOutput | JoinedRoom JoinRoomById.JoinRoomByIdInput JoinRoomById.JoinRoomByIdOutput
| LeftRoom Leave.LeaveInput Leave.LeaveOutput
| LoggedInWithUsernameAndPassword LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordInput LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordOutput | LoggedInWithUsernameAndPassword LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordInput LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordOutput
| MessageEventSent SendMessageEvent.SendMessageEventInput SendMessageEvent.SendMessageEventOutput | MessageEventSent SendMessageEvent.SendMessageEventInput SendMessageEvent.SendMessageEventOutput
| RedactedEvent Redact.RedactInput Redact.RedactOutput | RedactedEvent Redact.RedactInput Redact.RedactOutput
@ -165,6 +167,19 @@ joinRoomById input =
input input
leave : Leave.LeaveInput -> IdemChain VaultUpdate (VBA a)
leave input =
toChain
(\output ->
Chain.TaskChainPiece
{ contextChange = identity
, messages = [ LeftRoom input output ]
}
)
Leave.leave
input
loginWithUsernameAndPassword : LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordInput -> TaskChain VaultUpdate (VB a) (VBA a) loginWithUsernameAndPassword : LoginWithUsernameAndPassword.LoginWithUsernameAndPasswordInput -> TaskChain VaultUpdate (VB a) (VBA a)
loginWithUsernameAndPassword input = loginWithUsernameAndPassword input =
toChain toChain

75
src/Internal/Invite.elm Normal file
View File

@ -0,0 +1,75 @@
module Internal.Invite exposing (..)
{-| An invite is an Elm type that informs the user they've been invited to a room.
-}
import Internal.Api.Credentials exposing (Credentials)
import Internal.Api.Sync.V2.SpecObjects exposing (StrippedStateEvent)
import Internal.Api.Task as Api
import Internal.Api.VaultUpdate exposing (VaultUpdate(..))
import Internal.Tools.Exceptions as X
import Internal.Values.RoomInvite as Internal
import Task exposing (Task)
type RoomInvite
= RoomInvite
{ invite : Internal.IRoomInvite
, context : Credentials
}
getRoomId : RoomInvite -> String
getRoomId =
withoutCredentials >> Internal.roomId
initFromStrippedStateEvent : { roomId : String, events : List StrippedStateEvent } -> Internal.IRoomInvite
initFromStrippedStateEvent =
Internal.init
withCredentials : Credentials -> Internal.IRoomInvite -> RoomInvite
withCredentials context invite =
RoomInvite { context = context, invite = invite }
withoutCredentials : RoomInvite -> Internal.IRoomInvite
withoutCredentials (RoomInvite { invite }) =
invite
getEvent : { contentType : String, stateKey : String } -> RoomInvite -> Maybe Internal.RoomInviteEvent
getEvent data =
withoutCredentials >> Internal.getEvent data
getAllEvents : RoomInvite -> List Internal.RoomInviteEvent
getAllEvents =
withoutCredentials >> Internal.getAllEvents
{-| Accept an invite and join the room.
-}
accept : { invite : RoomInvite, reason : Maybe String } -> Task X.Error VaultUpdate
accept { invite, reason } =
case invite of
RoomInvite data ->
Api.joinRoomById
{ roomId = Internal.roomId data.invite
, reason = reason
}
data.context
{-| Reject the invite and do not join the room.
-}
reject : { invite : RoomInvite, reason : Maybe String } -> Task X.Error VaultUpdate
reject { invite, reason } =
case invite of
RoomInvite data ->
Api.leave
{ roomId = Internal.roomId data.invite
, reason = reason
}
data.context

View File

@ -0,0 +1,70 @@
module Internal.Values.RoomInvite exposing (..)
{-| This module contains the internal version of the `RoomInvite` type.
-}
import Dict exposing (Dict)
import Internal.Values.Room exposing (IRoom)
import Json.Encode as E
type IRoomInvite
= IRoomInvite
{ roomId : String
, events : Dict ( String, String ) RoomInviteEvent
}
type RoomInviteEvent
= RoomInviteEvent
{ content : E.Value
, sender : String
, stateKey : String
, contentType : String
}
init : { roomId : String, events : List { content : E.Value, sender : String, stateKey : String, contentType : String } } -> IRoomInvite
init data =
data.events
|> List.map
(\event ->
( ( event.contentType, event.stateKey ), RoomInviteEvent event )
)
|> Dict.fromList
|> (\e -> IRoomInvite { roomId = data.roomId, events = e })
getEvent : { contentType : String, stateKey : String } -> IRoomInvite -> Maybe RoomInviteEvent
getEvent data (IRoomInvite { events }) =
Dict.get ( data.contentType, data.stateKey ) events
getAllEvents : IRoomInvite -> List RoomInviteEvent
getAllEvents (IRoomInvite { events }) =
Dict.values events
roomId : IRoomInvite -> String
roomId (IRoomInvite data) =
data.roomId
content : RoomInviteEvent -> E.Value
content (RoomInviteEvent data) =
data.content
sender : RoomInviteEvent -> String
sender (RoomInviteEvent data) =
data.sender
stateKey : RoomInviteEvent -> String
stateKey (RoomInviteEvent data) =
data.stateKey
contentType : RoomInviteEvent -> String
contentType (RoomInviteEvent data) =
data.contentType

View File

@ -13,9 +13,11 @@ import Internal.Api.Sync.Main exposing (SyncInput)
import Internal.Api.Task as Api import Internal.Api.Task as Api
import Internal.Api.VaultUpdate exposing (VaultUpdate(..)) import Internal.Api.VaultUpdate exposing (VaultUpdate(..))
import Internal.Event as Event import Internal.Event as Event
import Internal.Invite as Invite
import Internal.Room as Room import Internal.Room as Room
import Internal.Tools.Exceptions as X import Internal.Tools.Exceptions as X
import Internal.Values.Room as IRoom import Internal.Values.Room as IRoom
import Internal.Values.RoomInvite exposing (IRoomInvite)
import Internal.Values.StateManager as StateManager import Internal.Values.StateManager as StateManager
import Internal.Values.Vault as Internal import Internal.Values.Vault as Internal
import Task exposing (Task) import Task exposing (Task)
@ -64,6 +66,14 @@ fromLoginVault { username, password, baseUrl } =
|> Vault |> Vault
{-| Get a user's invited rooms.
-}
getInvites : Vault -> List Invite.RoomInvite
getInvites (Vault { cred, context }) =
Internal.getInvites cred
|> List.map (Invite.withCredentials context)
{-| Get a room based on its id. {-| Get a room based on its id.
-} -}
getRoomById : String -> Vault -> Maybe Room.Room getRoomById : String -> Vault -> Maybe Room.Room
@ -86,50 +96,67 @@ insertRoom =
Room.withoutCredentials >> insertInternalRoom Room.withoutCredentials >> insertInternalRoom
{-| Join a Matrix room by its id.
-}
joinRoomById : String -> Vault -> Task X.Error VaultUpdate
joinRoomById roomId (Vault { context }) =
Api.joinRoomById { roomId = roomId, reason = Nothing } context
{-| Update the Vault type with new values {-| Update the Vault type with new values
-} -}
updateWith : VaultUpdate -> Vault -> Vault updateWith : VaultUpdate -> Vault -> Vault
updateWith vaultUpdate ((Vault ({ cred, context } as data)) as credentials) = updateWith vaultUpdate ((Vault ({ cred, context } as data)) as vault) =
case vaultUpdate of case vaultUpdate of
MultipleUpdates updates -> MultipleUpdates updates ->
List.foldl updateWith credentials updates List.foldl updateWith vault updates
GetEvent input output -> GetEvent input output ->
case getRoomById input.roomId credentials of case getRoomById input.roomId vault of
Just room -> Just room ->
output output
|> Event.initFromGetEvent |> Event.initFromGetEvent
|> Room.addInternalEvent |> Room.addInternalEvent
|> (|>) room |> (|>) room
|> insertRoom |> insertRoom
|> (|>) credentials |> (|>) vault
Nothing -> Nothing ->
credentials vault
-- TODO -- TODO
InviteSent _ _ -> InviteSent _ _ ->
credentials vault
-- TODO -- TODO
JoinedMembersToRoom _ _ -> JoinedMembersToRoom _ _ ->
credentials vault
-- TODO -- TODO
JoinedRoom _ _ -> JoinedRoom input _ ->
credentials cred
|> Internal.removeInvite input.roomId
|> (\x -> { cred = x, context = context })
|> Vault
-- TODO
LeftRoom input _ ->
cred
|> Internal.removeInvite input.roomId
|> (\x -> { cred = x, context = context })
|> Vault
-- TODO -- TODO
MessageEventSent _ _ -> MessageEventSent _ _ ->
credentials vault
-- TODO -- TODO
RedactedEvent _ _ -> RedactedEvent _ _ ->
credentials vault
-- TODO -- TODO
StateEventSent _ _ -> StateEventSent _ _ ->
credentials vault
SyncUpdate input output -> SyncUpdate input output ->
let let
@ -141,7 +168,7 @@ updateWith vaultUpdate ((Vault ({ cred, context } as data)) as credentials) =
|> Dict.toList |> Dict.toList
|> List.map |> List.map
(\( roomId, jroom ) -> (\( roomId, jroom ) ->
case getRoomById roomId credentials of case getRoomById roomId vault of
-- Update existing room -- Update existing room
Just room -> Just room ->
case jroom.timeline of case jroom.timeline of
@ -176,11 +203,28 @@ updateWith vaultUpdate ((Vault ({ cred, context } as data)) as credentials) =
jroom jroom
|> Room.initFromJoinedRoom { nextBatch = output.nextBatch, roomId = roomId } |> Room.initFromJoinedRoom { nextBatch = output.nextBatch, roomId = roomId }
) )
invites : List IRoomInvite
invites =
output.rooms
|> Maybe.map .invite
|> Maybe.withDefault Dict.empty
|> Dict.toList
|> List.map (Tuple.mapSecond .inviteState)
|> List.map (Tuple.mapSecond (Maybe.map .events))
|> List.map (Tuple.mapSecond (Maybe.withDefault []))
|> List.map (\( roomId, events ) -> { roomId = roomId, events = events })
|> List.map Invite.initFromStrippedStateEvent
in in
cred cred
-- Add new since token
|> Internal.addSince output.nextBatch |> Internal.addSince output.nextBatch
-- Add joined rooms
|> List.foldl Internal.insertRoom |> List.foldl Internal.insertRoom
|> (|>) jRooms |> (|>) jRooms
-- Add invites
|> List.foldl Internal.addInvite
|> (|>) invites
|> (\x -> { cred = x, context = context }) |> (\x -> { cred = x, context = context })
|> Vault |> Vault
@ -195,7 +239,7 @@ updateWith vaultUpdate ((Vault ({ cred, context } as data)) as credentials) =
Vault { data | context = Credentials.addToken output.accessToken context } Vault { data | context = Credentials.addToken output.accessToken context }
{-| Synchronize credentials {-| Synchronize vault
-} -}
sync : Vault -> Task X.Error VaultUpdate sync : Vault -> Task X.Error VaultUpdate
sync (Vault { cred, context }) = sync (Vault { cred, context }) =