From bd73b97e93a115902a4c4633fee302e86689dd35 Mon Sep 17 00:00:00 2001 From: Bram van den Heuvel Date: Tue, 7 Mar 2023 14:10:47 +0100 Subject: [PATCH] Add invite sending --- src/Internal/Api/All.elm | 40 +++++++++++++++++++ src/Internal/Api/Invite/Api.elm | 60 ++++++++++++++++++++++++++++ src/Internal/Api/Invite/Main.elm | 47 ++++++++++++++++++++++ src/Internal/Api/README.md | 22 +++++++++- src/Internal/Credentials.elm | 8 ++++ src/Internal/Values/Room.elm | 8 +++- src/Internal/Values/StateManager.elm | 4 +- 7 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 src/Internal/Api/Invite/Api.elm create mode 100644 src/Internal/Api/Invite/Main.elm diff --git a/src/Internal/Api/All.elm b/src/Internal/Api/All.elm index 5470748..22a3536 100644 --- a/src/Internal/Api/All.elm +++ b/src/Internal/Api/All.elm @@ -2,6 +2,7 @@ module Internal.Api.All exposing (..) import Hash import Internal.Api.GetEvent.Main as GetEvent +import Internal.Api.Invite.Main as Invite import Internal.Api.JoinedMembers.Main as JoinedMembers import Internal.Api.PreApi.Main as PreApi import Internal.Api.PreApi.Objects.Versions as V @@ -21,6 +22,7 @@ type CredUpdate = MultipleUpdates (List CredUpdate) -- Updates as a result of API calls | GetEvent GetEvent.EventInput GetEvent.EventOutput + | InviteSent Invite.InviteInput Invite.InviteOutput | JoinedMembersToRoom JoinedMembers.JoinedMembersInput JoinedMembers.JoinedMembersOutput | MessageEventSent SendMessageEvent.SendMessageEventInput SendMessageEvent.SendMessageEventOutput | RedactedEvent Redact.RedactInput Redact.RedactOutput @@ -72,6 +74,44 @@ getEvent data = (PreApi.accessToken data.baseUrl data.accessToken) (PreApi.versions data.baseUrl data.versions) +type alias InviteInput = + { accessToken : AccessToken + , baseUrl : String + , reason : Maybe String + , roomId : String + , userId : String + , versions : Maybe V.Versions + } + +{-| Send an invite to join a room. +-} +invite : InviteInput -> Future CredUpdate +invite data = + VG.withInfo2 + (\accessToken versions -> + let + input : Invite.InviteInput + input = + { accessToken = accessToken + , baseUrl = data.baseUrl + , reason = data.reason + , roomId = data.roomId + , userId = data.userId + } + in + Invite.invite versions.versions input + |> Task.map + (\output -> + MultipleUpdates + [ InviteSent input output + , UpdateAccessToken accessToken + , UpdateVersions versions + ] + ) + ) + (PreApi.accessToken data.baseUrl data.accessToken) + (PreApi.versions data.baseUrl data.versions) + type alias JoinedMembersInput = { accessToken : AccessToken diff --git a/src/Internal/Api/Invite/Api.elm b/src/Internal/Api/Invite/Api.elm new file mode 100644 index 0000000..c410d95 --- /dev/null +++ b/src/Internal/Api/Invite/Api.elm @@ -0,0 +1,60 @@ +module Internal.Api.Invite.Api exposing (..) + +import Internal.Api.Request as R +import Internal.Tools.Exceptions as X +import Json.Decode as D +import Task exposing (Task) + +type alias InviteInputV1 = + { accessToken : String + , baseUrl : String + , roomId : String + , userId : String + } + +type alias InviteInputV2 = + { accessToken : String + , baseUrl : String + , reason : Maybe String + , roomId : String + , userId : String + } + +type alias InviteOutputV1 = () + +inviteV1 : InviteInputV1 -> Task X.Error InviteOutputV1 +inviteV1 data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "POST" + , baseUrl = data.baseUrl + , path = "/_matrix/client/r0/rooms/{roomId}/invite" + , pathParams = + [ ( "roomId", data.roomId ) + ] + , queryParams = [] + , bodyParams = + [ R.RequiredString "user_id" data.userId + ] + , timeout = Nothing + , decoder = always (D.map (always ()) D.value) + } + +inviteV2 : InviteInputV2 -> Task X.Error InviteOutputV1 +inviteV2 data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "POST" + , baseUrl = data.baseUrl + , path = "/_matrix/client/r0/rooms/{roomId}/invite" + , pathParams = + [ ( "roomId", data.roomId ) + ] + , queryParams = [] + , bodyParams = + [ R.RequiredString "user_id" data.userId + , R.OptionalString "reason" data.reason + ] + , timeout = Nothing + , decoder = always (D.map (always ()) D.value) + } \ No newline at end of file diff --git a/src/Internal/Api/Invite/Main.elm b/src/Internal/Api/Invite/Main.elm new file mode 100644 index 0000000..983cee7 --- /dev/null +++ b/src/Internal/Api/Invite/Main.elm @@ -0,0 +1,47 @@ +module Internal.Api.Invite.Main exposing (..) + +import Internal.Api.Invite.Api as Api +import Internal.Tools.Exceptions as X +import Internal.Tools.VersionControl as VC +import Task exposing (Task) + + +invite : List String -> InviteInput -> Task X.Error InviteOutput +invite versions = + VC.withBottomLayer + { current = Api.inviteV1 + , 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 -> + { accessToken = data.accessToken + , baseUrl = data.baseUrl + , roomId = data.roomId + , userId = data.userId + } + ) + , current = Api.inviteV2 + , upcast = identity + , version = "v1.1" + } + |> VC.sameForVersion "v1.2" + |> VC.sameForVersion "v1.3" + |> VC.sameForVersion "v1.4" + |> VC.sameForVersion "v1.5" + |> VC.mostRecentFromVersionList versions + |> Maybe.withDefault (always <| Task.fail X.UnsupportedSpecVersion) + +type alias InviteInput = + Api.InviteInputV2 + +type alias InviteOutput = + Api.InviteOutputV1 diff --git a/src/Internal/Api/README.md b/src/Internal/Api/README.md index c430eba..ef644e3 100644 --- a/src/Internal/Api/README.md +++ b/src/Internal/Api/README.md @@ -36,9 +36,29 @@ Note that **under development** doesn't always mean that it _will be_ supported. | r0.0.1 || ❌ | ✔️ | | r0.0.0 || ❌ | ✔️ | +## Changing room member status + +| **Spec version** | | Inviting | Joining room id | +| ---------------- | - | -------- | --------------- | +| v1.6 || ⚠️ | ⚠️ | +| v1.5 || ✔️ | ⚠️ | +| v1.4 || ✔️ | ⚠️ | +| v1.3 || ✔️ | ⚠️ | +| v1.2 || ✔️ | ⚠️ | +| v1.1 || ✔️ | ⚠️ | +| r0.6.1 || ✔️ | ⚠️ | +| r0.6.0 || ✔️ | ⚠️ | +| r0.5.0 || ✔️ | ⚠️ | +| r0.4.0 || ✔️ | ⚠️ | +| r0.3.0 || ✔️ | ⚠️ | +| r0.2.0 || ✔️ | ⚠️ | +| r0.1.0 || ✔️ | ⚠️ | +| r0.0.1 || ✔️ | ⚠️ | +| r0.0.0 || ✔️ | ⚠️ | + ## Getting events for a room -| **Spec version** | | Event | Joined members | Members | Curren state | State event | Event at timestamp | +| **Spec version** | | Event | Joined members | Members | Current state | State event | Event at timestamp | | ---------------- | - | ----- | -------------- | ------- | ------------ | ----------- | ------------------ | | v1.6 || ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | | v1.5 || ✔️ | ✔️ | ⚡ | ⚡ | ⚡ | ⛔ | diff --git a/src/Internal/Credentials.elm b/src/Internal/Credentials.elm index 7c25ab0..cc3a718 100644 --- a/src/Internal/Credentials.elm +++ b/src/Internal/Credentials.elm @@ -106,12 +106,20 @@ updateWith credUpdate ((Credentials ({ cred, context } as data)) as credentials) Nothing -> credentials + -- TODO + Api.InviteSent _ _ -> + credentials + Api.JoinedMembersToRoom _ _ -> credentials -- TODO Api.MessageEventSent _ _ -> credentials + + -- TODO + Api.RedactedEvent _ _ -> + credentials -- TODO Api.StateEventSent _ _ -> diff --git a/src/Internal/Values/Room.elm b/src/Internal/Values/Room.elm index b95aab4..d16dc0e 100644 --- a/src/Internal/Values/Room.elm +++ b/src/Internal/Values/Room.elm @@ -4,7 +4,7 @@ import Dict exposing (Dict) import Internal.Tools.Hashdict as Hashdict exposing (Hashdict) import Internal.Tools.SpecEnums exposing (SessionDescriptionType(..)) import Internal.Values.Event exposing (BlindEvent, IEvent) -import Internal.Values.StateManager exposing (StateManager) +import Internal.Values.StateManager as StateManager exposing (StateManager) import Internal.Values.Timeline as Timeline exposing (Timeline) import Json.Encode as E @@ -51,6 +51,12 @@ getEventById : String -> IRoom -> Maybe IEvent getEventById eventId (IRoom room) = Hashdict.get eventId room.events +getStateEvent : { eventType : String, stateKey : String } -> IRoom -> Maybe IEvent +getStateEvent data (IRoom room) = + room.timeline + |> Timeline.mostRecentState + |> StateManager.getStateEvent data + {-| Get the room's id. -} diff --git a/src/Internal/Values/StateManager.elm b/src/Internal/Values/StateManager.elm index d496613..d83aad3 100644 --- a/src/Internal/Values/StateManager.elm +++ b/src/Internal/Values/StateManager.elm @@ -18,8 +18,8 @@ addEvent event oldManager = oldManager -getStateEvent : String -> String -> StateManager -> Maybe IEvent -getStateEvent eventType stateKey = +getStateEvent : { eventType : String, stateKey : String } -> StateManager -> Maybe IEvent +getStateEvent { eventType, stateKey } = Dict.get ( eventType, stateKey )