diff --git a/src/Internal/Api/Main.elm b/src/Internal/Api/Main.elm index bf9b1ea..c0d3f2b 100644 --- a/src/Internal/Api/Main.elm +++ b/src/Internal/Api/Main.elm @@ -1,6 +1,6 @@ module Internal.Api.Main exposing ( Msg - , sendMessageEvent, sync + , sendMessageEvent, sendStateEvent, sync ) {-| @@ -18,7 +18,7 @@ This module is used as reference for getting ## Actions -@docs sendMessageEvent, sync +@docs sendMessageEvent, sendStateEvent, sync -} @@ -59,6 +59,31 @@ sendMessageEvent env data = (Context.apiFormat env.context) +{-| Send a state event to a room. +-} +sendStateEvent : + E.Envelope a + -> + { content : Json.Value + , eventType : String + , roomId : String + , stateKey : String + , toMsg : Msg -> msg + } + -> Cmd msg +sendStateEvent env data = + ITask.run + data.toMsg + (ITask.sendStateEvent + { content = data.content + , eventType = data.eventType + , roomId = data.roomId + , stateKey = data.stateKey + } + ) + (Context.apiFormat env.context) + + {-| Sync with the Matrix API to stay up-to-date. -} sync : diff --git a/src/Internal/Api/SendStateEvent/Api.elm b/src/Internal/Api/SendStateEvent/Api.elm new file mode 100644 index 0000000..f69e377 --- /dev/null +++ b/src/Internal/Api/SendStateEvent/Api.elm @@ -0,0 +1,177 @@ +module Internal.Api.SendStateEvent.Api exposing (..) + +{-| + + +# Send state event + +This module sends state events to Matrix rooms. + +@docs Phantom, sendStateEvent + +-} + +import Internal.Api.Api as A +import Internal.Api.Invite.Api exposing (Phantom) +import Internal.Api.Request as R +import Internal.Config.Log exposing (log) +import Internal.Config.Text as Text +import Internal.Tools.Json as Json +import Internal.Values.Envelope as E + + +{-| Send a state event to a Matrix room. +-} +sendStateEvent : SendStateEventInput -> A.TaskChain (Phantom a) (Phantom a) +sendStateEvent = + A.startWithVersion "r0.0.0" sendStateEventV1 + |> A.sameForVersion "r0.0.1" + |> A.sameForVersion "r0.1.0" + |> A.sameForVersion "r0.2.0" + |> A.sameForVersion "r0.3.0" + |> A.sameForVersion "r0.4.0" + |> A.sameForVersion "r0.5.0" + |> A.sameForVersion "r0.6.0" + |> A.forVersion "r0.6.1" sendStateEventV2 + |> A.forVersion "v1.1" sendStateEventV3 + |> A.sameForVersion "v1.2" + |> A.sameForVersion "v1.3" + |> A.sameForVersion "v1.4" + |> A.sameForVersion "v1.5" + |> A.sameForVersion "v1.6" + |> A.sameForVersion "v1.7" + |> A.sameForVersion "v1.8" + |> A.sameForVersion "v1.9" + |> A.sameForVersion "v1.10" + |> A.sameForVersion "v1.11" + |> A.versionChain + + +{-| Context needed for sending a state event +-} +type alias Phantom a = + { a | accessToken : (), baseUrl : (), versions : () } + + +type alias PhantomV1 a = + { a | accessToken : (), baseUrl : () } + + +type alias SendStateEventInput = + { content : Json.Value + , eventType : String + , roomId : String + , stateKey : String + } + + +type alias SendStateEventInputV1 a = + { a + | content : Json.Value + , eventType : String + , roomId : String + , stateKey : String + } + + +type alias SendStateEventOutputV1 = + { eventId : Maybe String } + + +type alias SendStateEventOutputV2 = + { eventId : String } + + +sendStateEventV1 : SendStateEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a) +sendStateEventV1 { content, eventType, roomId, stateKey } = + A.request + { attributes = [ R.accessToken, R.fullBody content ] + , coder = coderV1 + , contextChange = always identity + , method = "PUT" + , path = [ "_matrix", "client", "r0", "rooms", roomId, "state", eventType, stateKey ] + , toUpdate = + \out -> + ( E.More [] + , out.eventId + |> Text.logs.sendEvent + |> log.debug + |> List.singleton + ) + } + + +sendStateEventV2 : SendStateEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a) +sendStateEventV2 { content, eventType, roomId, stateKey } = + A.request + { attributes = [ R.accessToken, R.fullBody content ] + , coder = coderV2 + , contextChange = always identity + , method = "PUT" + , path = [ "_matrix", "client", "r0", "rooms", roomId, "state", eventType, stateKey ] + , toUpdate = + \out -> + ( E.More [] + , out.eventId + |> Maybe.Just + |> Text.logs.sendEvent + |> log.debug + |> List.singleton + ) + } + + +sendStateEventV3 : SendStateEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a) +sendStateEventV3 { content, eventType, roomId, stateKey } = + A.request + { attributes = [ R.accessToken, R.fullBody content ] + , coder = coderV2 + , contextChange = always identity + , method = "PUT" + , path = [ "_matrix", "client", "v3", "rooms", roomId, "state", eventType, stateKey ] + , toUpdate = + \out -> + ( E.More [] + , out.eventId + |> Maybe.Just + |> Text.logs.sendEvent + |> log.debug + |> List.singleton + ) + } + + +coderV1 : Json.Coder SendStateEventOutputV1 +coderV1 = + Json.object1 + { name = "EventResponse" + , description = + [ "This object is returned after a state event has been sent." + ] + , init = SendStateEventOutputV1 + } + (Json.field.optional.value + { fieldName = "event_id" + , toField = .eventId + , description = [ "A unique identifier for the event." ] + , coder = Json.string + } + ) + + +coderV2 : Json.Coder SendStateEventOutputV2 +coderV2 = + Json.object1 + { name = "EventResponse" + , description = + [ "This object is returned after a state event has been sent." + ] + , init = SendStateEventOutputV2 + } + (Json.field.required + { fieldName = "event_id" + , toField = .eventId + , description = [ "A unique identifier for the event." ] + , coder = Json.string + } + ) diff --git a/src/Internal/Api/Task.elm b/src/Internal/Api/Task.elm index 43d3845..8d4c741 100644 --- a/src/Internal/Api/Task.elm +++ b/src/Internal/Api/Task.elm @@ -1,6 +1,6 @@ module Internal.Api.Task exposing ( Task, run, Backpack - , sendMessageEvent, sync + , sendMessageEvent, sendStateEvent, sync ) {-| @@ -23,7 +23,7 @@ up-to-date. ## Tasks -@docs sendMessageEvent, sync +@docs sendMessageEvent, sendStateEvent, sync -} @@ -33,6 +33,7 @@ import Internal.Api.LoginWithUsernameAndPassword.Api import Internal.Api.Now.Api import Internal.Api.Request as Request import Internal.Api.SendMessageEvent.Api +import Internal.Api.SendStateEvent.Api import Internal.Api.Sync.Api import Internal.Api.Versions.Api import Internal.Config.Log exposing (Log, log) @@ -232,6 +233,15 @@ sendMessageEvent input = |> finishTask +{-| Send a state event to a room. +-} +sendStateEvent : { content : Json.Value, eventType : String, roomId : String, stateKey : String } -> Task +sendStateEvent input = + makeVBA + |> C.andThen (Internal.Api.SendStateEvent.Api.sendStateEvent input) + |> finishTask + + {-| Sync with the Matrix API to stay up-to-date. -} sync : { fullState : Maybe Bool, presence : Maybe String, since : Maybe String, timeout : Maybe Int } -> Task diff --git a/src/Matrix/Room.elm b/src/Matrix/Room.elm index 5909c70..8feff52 100644 --- a/src/Matrix/Room.elm +++ b/src/Matrix/Room.elm @@ -1,7 +1,7 @@ module Matrix.Room exposing ( Room, mostRecentEvents, roomId , getAccountData - , sendMessageEvent + , sendMessageEvent, sendStateEvent ) {-| @@ -44,7 +44,7 @@ room. These events are JSON objects that can be shaped in any way or form that you like. To help other users with decoding your JSON objects, you pass an `eventType` string which helps them figure out the nature of your JSON object. -@docs sendMessageEvent +@docs sendMessageEvent, sendStateEvent -} @@ -104,3 +104,25 @@ sendMessageEvent data = , toMsg = Types.VaultUpdate >> data.toMsg , transactionId = data.transactionId } + + +{-| Send a state event to a given room. +-} +sendStateEvent : + { content : E.Value + , eventType : String + , room : Room + , stateKey : String + , toMsg : Types.VaultUpdate -> msg + } + -> Cmd msg +sendStateEvent data = + case data.room of + Room room -> + Api.sendStateEvent room + { content = data.content + , eventType = data.eventType + , roomId = roomId data.room + , stateKey = data.stateKey + , toMsg = Types.VaultUpdate >> data.toMsg + }