diff --git a/src/Internal/Api/GetEvent/Api.elm b/src/Internal/Api/GetEvent/Api.elm new file mode 100644 index 0000000..171c2e1 --- /dev/null +++ b/src/Internal/Api/GetEvent/Api.elm @@ -0,0 +1,32 @@ +module Internal.Api.GetEvent.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 GetEventInputV1 = + { accessToken : String + , baseUrl : String + , eventId : String + , roomId : String + } + + +getEventInputV1 : D.Decoder a -> (a -> b) -> GetEventInputV1 -> Task X.Error b +getEventInputV1 decoder mapping data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "GET" + , baseUrl = data.baseUrl + , path = "/_matrix/client/v3/rooms/{roomId}/event/{eventId}" + , pathParams = + [ ( "eventId", data.eventId ) + , ( "roomId", data.roomId ) + ] + , queryParams = [] + , bodyParams = [] + , timeout = Nothing + , decoder = \_ -> D.map mapping decoder + } diff --git a/src/Internal/Api/GetEvent/Main.elm b/src/Internal/Api/GetEvent/Main.elm new file mode 100644 index 0000000..30d2dee --- /dev/null +++ b/src/Internal/Api/GetEvent/Main.elm @@ -0,0 +1,28 @@ +module Internal.Api.GetEvent.Main exposing (..) + +import Internal.Api.GetEvent.Api as Api +import Internal.Api.GetEvent.V1_2.Api as V1_2 +import Internal.Api.GetEvent.V1_3.Api as V1_3 +import Internal.Api.GetEvent.V1_4.Api as V1_4 +import Internal.Api.GetEvent.V1_5.Api as V1_5 +import Internal.Api.GetEvent.V1_5.Objects as O +import Internal.Api.VersionControl as V +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +getEvent : List String -> EventInput -> EventOutput +getEvent = + V.firstVersion V1_2.packet + |> V.updateWith V1_3.packet + |> V.updateWith V1_4.packet + |> V.updateWith V1_5.packet + |> V.toFunction + + +type alias EventOutput = + Task X.Error O.ClientEvent + + +type alias EventInput = + Api.GetEventInputV1 diff --git a/src/Internal/Api/GetEvent/V1_2/Api.elm b/src/Internal/Api/GetEvent/V1_2/Api.elm new file mode 100644 index 0000000..3b67d65 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.GetEvent.V1_2.Api exposing (..) + +import Internal.Api.GetEvent.Api as Api +import Internal.Api.GetEvent.V1_2.Convert as C +import Internal.Api.GetEvent.V1_2.Objects as O +import Internal.Api.GetEvent.V1_2.SpecObjects as SO +import Internal.Api.GetEvent.V1_2.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion () () Api.GetEventInputV1 O.ClientEvent +packet = + { version = "v1.2" + , downcast = \_ -> () + , current = Api.getEventInputV1 SO.clientEventDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/GetEvent/V1_2/Convert.elm b/src/Internal/Api/GetEvent/V1_2/Convert.elm new file mode 100644 index 0000000..7a99460 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/Convert.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_2.Convert exposing (..) + +import Internal.Api.GetEvent.V1_2.Objects as O +import Internal.Api.GetEvent.V1_2.SpecObjects as SO + + +convert : SO.ClientEvent -> O.ClientEvent +convert e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map convertUnsigned e.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map convert u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_2/Objects.elm b/src/Internal/Api/GetEvent/V1_2/Objects.elm new file mode 100644 index 0000000..bcf112a --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/Objects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_2.Objects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_2/Objects.yaml b/src/Internal/Api/GetEvent/V1_2/Objects.yaml new file mode 100644 index 0000000..eebe4b0 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/Objects.yaml @@ -0,0 +1,40 @@ +version: v1.2 +name: Objects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_2/SpecObjects.elm b/src/Internal/Api/GetEvent/V1_2/SpecObjects.elm new file mode 100644 index 0000000..2975564 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/SpecObjects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_2.SpecObjects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_2/SpecObjects.yaml b/src/Internal/Api/GetEvent/V1_2/SpecObjects.yaml new file mode 100644 index 0000000..8d8bb95 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/SpecObjects.yaml @@ -0,0 +1,40 @@ +version: v1.2 +name: SpecObjects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_2/Upcast.elm b/src/Internal/Api/GetEvent/V1_2/Upcast.elm new file mode 100644 index 0000000..e7db279 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_2/Upcast.elm @@ -0,0 +1,18 @@ +module Internal.Api.GetEvent.V1_2.Upcast exposing (..) + +import Internal.Api.GetEvent.V1_2.Objects as O +import Internal.Config.Leaking as L +import Json.Encode as E + + +upcast : () -> O.ClientEvent +upcast _ = + { content = E.object [] + , eventId = L.eventId + , originServerTs = L.originServerTs + , roomId = L.roomId + , sender = L.sender + , stateKey = Nothing + , contentType = L.eventType + , unsigned = Nothing + } diff --git a/src/Internal/Api/GetEvent/V1_3/Api.elm b/src/Internal/Api/GetEvent/V1_3/Api.elm new file mode 100644 index 0000000..cd824e4 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.GetEvent.V1_3.Api exposing (..) + +import Internal.Api.GetEvent.Api as Api +import Internal.Api.GetEvent.V1_2.Objects as PO +import Internal.Api.GetEvent.V1_3.Convert as C +import Internal.Api.GetEvent.V1_3.Objects as O +import Internal.Api.GetEvent.V1_3.SpecObjects as SO +import Internal.Api.GetEvent.V1_3.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.GetEventInputV1 PO.ClientEvent Api.GetEventInputV1 O.ClientEvent +packet = + { version = "v1.3" + , downcast = identity + , current = Api.getEventInputV1 SO.clientEventDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/GetEvent/V1_3/Convert.elm b/src/Internal/Api/GetEvent/V1_3/Convert.elm new file mode 100644 index 0000000..146b6d4 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/Convert.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_3.Convert exposing (..) + +import Internal.Api.GetEvent.V1_3.Objects as O +import Internal.Api.GetEvent.V1_3.SpecObjects as SO + + +convert : SO.ClientEvent -> O.ClientEvent +convert e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map convertUnsigned e.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map convert u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_3/Objects.elm b/src/Internal/Api/GetEvent/V1_3/Objects.elm new file mode 100644 index 0000000..dc61b95 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/Objects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_3.Objects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_3/Objects.yaml b/src/Internal/Api/GetEvent/V1_3/Objects.yaml new file mode 100644 index 0000000..e4a9d82 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/Objects.yaml @@ -0,0 +1,40 @@ +version: v1.3 +name: Objects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_3/SpecObjects.elm b/src/Internal/Api/GetEvent/V1_3/SpecObjects.elm new file mode 100644 index 0000000..1a873a3 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/SpecObjects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_3.SpecObjects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_3/SpecObjects.yaml b/src/Internal/Api/GetEvent/V1_3/SpecObjects.yaml new file mode 100644 index 0000000..aa903c7 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/SpecObjects.yaml @@ -0,0 +1,40 @@ +version: v1.3 +name: SpecObjects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_3/Upcast.elm b/src/Internal/Api/GetEvent/V1_3/Upcast.elm new file mode 100644 index 0000000..ebf6159 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_3/Upcast.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_3.Upcast exposing (..) + +import Internal.Api.GetEvent.V1_2.Objects as PO +import Internal.Api.GetEvent.V1_3.Objects as O + + +upcast : PO.ClientEvent -> O.ClientEvent +upcast e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map upcastUnsigned e.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map upcast u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_4/Api.elm b/src/Internal/Api/GetEvent/V1_4/Api.elm new file mode 100644 index 0000000..1c6a043 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.GetEvent.V1_4.Api exposing (..) + +import Internal.Api.GetEvent.Api as Api +import Internal.Api.GetEvent.V1_3.Objects as PO +import Internal.Api.GetEvent.V1_4.Convert as C +import Internal.Api.GetEvent.V1_4.Objects as O +import Internal.Api.GetEvent.V1_4.SpecObjects as SO +import Internal.Api.GetEvent.V1_4.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.GetEventInputV1 PO.ClientEvent Api.GetEventInputV1 O.ClientEvent +packet = + { version = "v1.4" + , downcast = identity + , current = Api.getEventInputV1 SO.clientEventDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/GetEvent/V1_4/Convert.elm b/src/Internal/Api/GetEvent/V1_4/Convert.elm new file mode 100644 index 0000000..8c65a32 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/Convert.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_4.Convert exposing (..) + +import Internal.Api.GetEvent.V1_4.Objects as O +import Internal.Api.GetEvent.V1_4.SpecObjects as SO + + +convert : SO.ClientEvent -> O.ClientEvent +convert e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map convertUnsigned e.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map convert u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_4/Objects.elm b/src/Internal/Api/GetEvent/V1_4/Objects.elm new file mode 100644 index 0000000..3c9f675 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/Objects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_4.Objects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_4/Objects.yaml b/src/Internal/Api/GetEvent/V1_4/Objects.yaml new file mode 100644 index 0000000..9c4f25c --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/Objects.yaml @@ -0,0 +1,40 @@ +version: v1.4 +name: Objects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_4/SpecObjects.elm b/src/Internal/Api/GetEvent/V1_4/SpecObjects.elm new file mode 100644 index 0000000..bc83a03 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/SpecObjects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_4.SpecObjects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_4/SpecObjects.yaml b/src/Internal/Api/GetEvent/V1_4/SpecObjects.yaml new file mode 100644 index 0000000..77270ef --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/SpecObjects.yaml @@ -0,0 +1,40 @@ +version: v1.4 +name: SpecObjects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_4/Upcast.elm b/src/Internal/Api/GetEvent/V1_4/Upcast.elm new file mode 100644 index 0000000..ac901d9 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_4/Upcast.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_4.Upcast exposing (..) + +import Internal.Api.GetEvent.V1_3.Objects as PO +import Internal.Api.GetEvent.V1_4.Objects as O + + +upcast : PO.ClientEvent -> O.ClientEvent +upcast e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map upcastUnsigned e.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map upcast u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_5/Api.elm b/src/Internal/Api/GetEvent/V1_5/Api.elm new file mode 100644 index 0000000..f139e90 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.GetEvent.V1_5.Api exposing (..) + +import Internal.Api.GetEvent.Api as Api +import Internal.Api.GetEvent.V1_4.Objects as PO +import Internal.Api.GetEvent.V1_5.Convert as C +import Internal.Api.GetEvent.V1_5.Objects as O +import Internal.Api.GetEvent.V1_5.SpecObjects as SO +import Internal.Api.GetEvent.V1_5.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.GetEventInputV1 PO.ClientEvent Api.GetEventInputV1 O.ClientEvent +packet = + { version = "v1.5" + , downcast = identity + , current = Api.getEventInputV1 SO.clientEventDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/GetEvent/V1_5/Convert.elm b/src/Internal/Api/GetEvent/V1_5/Convert.elm new file mode 100644 index 0000000..de1f972 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/Convert.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_5.Convert exposing (..) + +import Internal.Api.GetEvent.V1_5.Objects as O +import Internal.Api.GetEvent.V1_5.SpecObjects as SO + + +convert : SO.ClientEvent -> O.ClientEvent +convert e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map convertUnsigned e.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map convert u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/GetEvent/V1_5/Objects.elm b/src/Internal/Api/GetEvent/V1_5/Objects.elm new file mode 100644 index 0000000..3044dba --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/Objects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_5.Objects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_5/Objects.yaml b/src/Internal/Api/GetEvent/V1_5/Objects.yaml new file mode 100644 index 0000000..7fdb81f --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/Objects.yaml @@ -0,0 +1,40 @@ +version: v1.5 +name: Objects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_5/SpecObjects.elm b/src/Internal/Api/GetEvent/V1_5/SpecObjects.elm new file mode 100644 index 0000000..924c4ae --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/SpecObjects.elm @@ -0,0 +1,97 @@ +module Internal.Api.GetEvent.V1_5.SpecObjects exposing + ( ClientEvent + , UnsignedData(..) + , clientEventDecoder + , encodeClientEvent + , encodeUnsignedData + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| Client Event containing all data on an event. +-} +type alias ClientEvent = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , roomId : String + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEvent : ClientEvent -> E.Value +encodeClientEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "room_id", Just <| E.string data.roomId ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventDecoder : D.Decoder ClientEvent +clientEventDecoder = + D.map8 + (\a b c d e f g h -> + { content = a, eventId = b, originServerTs = c, roomId = d, sender = e, stateKey = f, contentType = g, unsigned = h } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "room_id" D.string) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Extra information about the event. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEvent + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEvent data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/GetEvent/V1_5/SpecObjects.yaml b/src/Internal/Api/GetEvent/V1_5/SpecObjects.yaml new file mode 100644 index 0000000..11145ee --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/SpecObjects.yaml @@ -0,0 +1,40 @@ +version: v1.5 +name: SpecObjects +objects: + ClientEvent: + description: Client Event containing all data on an event. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + room_id: + type: string + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Extra information about the event. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEvent + transaction_id: + type: string diff --git a/src/Internal/Api/GetEvent/V1_5/Upcast.elm b/src/Internal/Api/GetEvent/V1_5/Upcast.elm new file mode 100644 index 0000000..22db576 --- /dev/null +++ b/src/Internal/Api/GetEvent/V1_5/Upcast.elm @@ -0,0 +1,27 @@ +module Internal.Api.GetEvent.V1_5.Upcast exposing (..) + +import Internal.Api.GetEvent.V1_4.Objects as PO +import Internal.Api.GetEvent.V1_5.Objects as O + + +upcast : PO.ClientEvent -> O.ClientEvent +upcast e = + { content = e.content + , eventId = e.eventId + , originServerTs = e.originServerTs + , roomId = e.roomId + , sender = e.sender + , stateKey = e.stateKey + , contentType = e.contentType + , unsigned = Maybe.map upcastUnsigned e.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData u) = + O.UnsignedData + { age = u.age + , prevContent = u.prevContent + , redactedBecause = Maybe.map upcast u.redactedBecause + , transactionId = u.transactionId + } diff --git a/src/Internal/Api/JoinedMembers/Api.elm b/src/Internal/Api/JoinedMembers/Api.elm new file mode 100644 index 0000000..cf961aa --- /dev/null +++ b/src/Internal/Api/JoinedMembers/Api.elm @@ -0,0 +1,30 @@ +module Internal.Api.JoinedMembers.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 JoinedMembersInputV1 = + { accessToken : String + , baseUrl : String + , roomId : String + } + + +joinedMembersInputV1 : D.Decoder a -> (a -> b) -> JoinedMembersInputV1 -> Task X.Error b +joinedMembersInputV1 decoder mapping data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "GET" + , baseUrl = data.baseUrl + , path = "/_matrix/client/v3/rooms/{roomId}/joined_members" + , pathParams = + [ ( "roomId", data.roomId ) + ] + , queryParams = [] + , bodyParams = [] + , timeout = Nothing + , decoder = \_ -> D.map mapping decoder + } diff --git a/src/Internal/Api/JoinedMembers/Main.elm b/src/Internal/Api/JoinedMembers/Main.elm new file mode 100644 index 0000000..df68bea --- /dev/null +++ b/src/Internal/Api/JoinedMembers/Main.elm @@ -0,0 +1,28 @@ +module Internal.Api.JoinedMembers.Main exposing (..) + +import Internal.Api.JoinedMembers.Api as Api +import Internal.Api.JoinedMembers.V1_2.Api as V1_2 +import Internal.Api.JoinedMembers.V1_3.Api as V1_3 +import Internal.Api.JoinedMembers.V1_4.Api as V1_4 +import Internal.Api.JoinedMembers.V1_5.Api as V1_5 +import Internal.Api.JoinedMembers.V1_5.Objects as O +import Internal.Api.VersionControl as V +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +joinedMembers : List String -> JoinedMembersInput -> JoinedMembersOutput +joinedMembers = + V.firstVersion V1_2.packet + |> V.updateWith V1_3.packet + |> V.updateWith V1_4.packet + |> V.updateWith V1_5.packet + |> V.toFunction + + +type alias JoinedMembersInput = + Api.JoinedMembersInputV1 + + +type alias JoinedMembersOutput = + Task X.Error O.RoomMemberList diff --git a/src/Internal/Api/JoinedMembers/V1_2/Api.elm b/src/Internal/Api/JoinedMembers/V1_2/Api.elm new file mode 100644 index 0000000..e6477d9 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.JoinedMembers.V1_2.Api exposing (..) + +import Internal.Api.JoinedMembers.Api as Api +import Internal.Api.JoinedMembers.V1_2.Convert as C +import Internal.Api.JoinedMembers.V1_2.Objects as O +import Internal.Api.JoinedMembers.V1_2.SpecObjects as SO +import Internal.Api.JoinedMembers.V1_2.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion () () Api.JoinedMembersInputV1 O.RoomMemberList +packet = + { version = "v1.2" + , downcast = \_ -> () + , current = Api.joinedMembersInputV1 SO.roomMemberListDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/JoinedMembers/V1_2/Convert.elm b/src/Internal/Api/JoinedMembers/V1_2/Convert.elm new file mode 100644 index 0000000..248216e --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_2.Convert exposing (..) + +import Internal.Api.JoinedMembers.V1_2.Objects as O +import Internal.Api.JoinedMembers.V1_2.SpecObjects as SO + + +convert : SO.RoomMemberList -> O.RoomMemberList +convert = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_2/Objects.elm b/src/Internal/Api/JoinedMembers/V1_2/Objects.elm new file mode 100644 index 0000000..55d0b4c --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/Objects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_2.Objects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_2/Objects.yaml b/src/Internal/Api/JoinedMembers/V1_2/Objects.yaml new file mode 100644 index 0000000..61d6109 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/Objects.yaml @@ -0,0 +1,17 @@ +version: v1.2 +name: Objects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.elm b/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.elm new file mode 100644 index 0000000..5e339b5 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_2.SpecObjects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.yaml b/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.yaml new file mode 100644 index 0000000..cd9b3a4 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/SpecObjects.yaml @@ -0,0 +1,17 @@ +version: v1.2 +name: SpecObjects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_2/Upcast.elm b/src/Internal/Api/JoinedMembers/V1_2/Upcast.elm new file mode 100644 index 0000000..70d4eee --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_2/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_2.Upcast exposing (..) + +import Dict +import Internal.Api.JoinedMembers.V1_2.Objects as O + + +upcast : () -> O.RoomMemberList +upcast _ = + { joined = Dict.empty } diff --git a/src/Internal/Api/JoinedMembers/V1_3/Api.elm b/src/Internal/Api/JoinedMembers/V1_3/Api.elm new file mode 100644 index 0000000..bfe1ccb --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.JoinedMembers.V1_3.Api exposing (..) + +import Internal.Api.JoinedMembers.Api as Api +import Internal.Api.JoinedMembers.V1_2.Objects as PO +import Internal.Api.JoinedMembers.V1_3.Convert as C +import Internal.Api.JoinedMembers.V1_3.Objects as O +import Internal.Api.JoinedMembers.V1_3.SpecObjects as SO +import Internal.Api.JoinedMembers.V1_3.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.JoinedMembersInputV1 PO.RoomMemberList Api.JoinedMembersInputV1 O.RoomMemberList +packet = + { version = "v1.3" + , downcast = identity + , current = Api.joinedMembersInputV1 SO.roomMemberListDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/JoinedMembers/V1_3/Convert.elm b/src/Internal/Api/JoinedMembers/V1_3/Convert.elm new file mode 100644 index 0000000..7c86004 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_3.Convert exposing (..) + +import Internal.Api.JoinedMembers.V1_3.Objects as O +import Internal.Api.JoinedMembers.V1_3.SpecObjects as SO + + +convert : SO.RoomMemberList -> O.RoomMemberList +convert = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_3/Objects.elm b/src/Internal/Api/JoinedMembers/V1_3/Objects.elm new file mode 100644 index 0000000..cac7445 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/Objects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_3.Objects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_3/Objects.yaml b/src/Internal/Api/JoinedMembers/V1_3/Objects.yaml new file mode 100644 index 0000000..b6f839c --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/Objects.yaml @@ -0,0 +1,17 @@ +version: v1.3 +name: Objects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.elm b/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.elm new file mode 100644 index 0000000..3d2d5e9 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_3.SpecObjects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.yaml b/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.yaml new file mode 100644 index 0000000..01800ab --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/SpecObjects.yaml @@ -0,0 +1,17 @@ +version: v1.3 +name: SpecObjects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_3/Upcast.elm b/src/Internal/Api/JoinedMembers/V1_3/Upcast.elm new file mode 100644 index 0000000..153a236 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_3/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_3.Upcast exposing (..) + +import Internal.Api.JoinedMembers.V1_2.Objects as PO +import Internal.Api.JoinedMembers.V1_3.Objects as O + + +upcast : PO.RoomMemberList -> O.RoomMemberList +upcast = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_4/Api.elm b/src/Internal/Api/JoinedMembers/V1_4/Api.elm new file mode 100644 index 0000000..f999577 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.JoinedMembers.V1_4.Api exposing (..) + +import Internal.Api.JoinedMembers.Api as Api +import Internal.Api.JoinedMembers.V1_3.Objects as PO +import Internal.Api.JoinedMembers.V1_4.Convert as C +import Internal.Api.JoinedMembers.V1_4.Objects as O +import Internal.Api.JoinedMembers.V1_4.SpecObjects as SO +import Internal.Api.JoinedMembers.V1_4.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.JoinedMembersInputV1 PO.RoomMemberList Api.JoinedMembersInputV1 O.RoomMemberList +packet = + { version = "v1.4" + , downcast = identity + , current = Api.joinedMembersInputV1 SO.roomMemberListDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/JoinedMembers/V1_4/Convert.elm b/src/Internal/Api/JoinedMembers/V1_4/Convert.elm new file mode 100644 index 0000000..eb133ef --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_4.Convert exposing (..) + +import Internal.Api.JoinedMembers.V1_4.Objects as O +import Internal.Api.JoinedMembers.V1_4.SpecObjects as SO + + +convert : SO.RoomMemberList -> O.RoomMemberList +convert = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_4/Objects.elm b/src/Internal/Api/JoinedMembers/V1_4/Objects.elm new file mode 100644 index 0000000..8fd5b3d --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/Objects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_4.Objects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_4/Objects.yaml b/src/Internal/Api/JoinedMembers/V1_4/Objects.yaml new file mode 100644 index 0000000..cb0d543 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/Objects.yaml @@ -0,0 +1,17 @@ +version: v1.4 +name: Objects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.elm b/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.elm new file mode 100644 index 0000000..5a580c7 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_4.SpecObjects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.yaml b/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.yaml new file mode 100644 index 0000000..0f3c6a1 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/SpecObjects.yaml @@ -0,0 +1,17 @@ +version: v1.4 +name: SpecObjects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_4/Upcast.elm b/src/Internal/Api/JoinedMembers/V1_4/Upcast.elm new file mode 100644 index 0000000..f8690fe --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_4/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_4.Upcast exposing (..) + +import Internal.Api.JoinedMembers.V1_3.Objects as PO +import Internal.Api.JoinedMembers.V1_4.Objects as O + + +upcast : PO.RoomMemberList -> O.RoomMemberList +upcast = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_5/Api.elm b/src/Internal/Api/JoinedMembers/V1_5/Api.elm new file mode 100644 index 0000000..9a2237e --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.JoinedMembers.V1_5.Api exposing (..) + +import Internal.Api.JoinedMembers.Api as Api +import Internal.Api.JoinedMembers.V1_4.Objects as PO +import Internal.Api.JoinedMembers.V1_5.Convert as C +import Internal.Api.JoinedMembers.V1_5.Objects as O +import Internal.Api.JoinedMembers.V1_5.SpecObjects as SO +import Internal.Api.JoinedMembers.V1_5.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.JoinedMembersInputV1 PO.RoomMemberList Api.JoinedMembersInputV1 O.RoomMemberList +packet = + { version = "v1.5" + , downcast = identity + , current = Api.joinedMembersInputV1 SO.roomMemberListDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/JoinedMembers/V1_5/Convert.elm b/src/Internal/Api/JoinedMembers/V1_5/Convert.elm new file mode 100644 index 0000000..47792f9 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_5.Convert exposing (..) + +import Internal.Api.JoinedMembers.V1_5.Objects as O +import Internal.Api.JoinedMembers.V1_5.SpecObjects as SO + + +convert : SO.RoomMemberList -> O.RoomMemberList +convert = + identity diff --git a/src/Internal/Api/JoinedMembers/V1_5/Objects.elm b/src/Internal/Api/JoinedMembers/V1_5/Objects.elm new file mode 100644 index 0000000..4dbae53 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/Objects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_5.Objects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_5/Objects.yaml b/src/Internal/Api/JoinedMembers/V1_5/Objects.yaml new file mode 100644 index 0000000..bfac3f6 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/Objects.yaml @@ -0,0 +1,17 @@ +version: v1.5 +name: Objects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.elm b/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.elm new file mode 100644 index 0000000..a9b5697 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.elm @@ -0,0 +1,69 @@ +module Internal.Api.JoinedMembers.V1_5.SpecObjects exposing + ( RoomMember + , RoomMemberList + , encodeRoomMember + , encodeRoomMemberList + , roomMemberDecoder + , roomMemberListDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| User information of joined users. +-} +type alias RoomMember = + { avatarUrl : Maybe String + , displayName : Maybe String + } + + +encodeRoomMember : RoomMember -> E.Value +encodeRoomMember data = + maybeObject + [ ( "avatar_url", Maybe.map E.string data.avatarUrl ) + , ( "display_name", Maybe.map E.string data.displayName ) + ] + + +roomMemberDecoder : D.Decoder RoomMember +roomMemberDecoder = + D.map2 + (\a b -> + { avatarUrl = a, displayName = b } + ) + (opField "avatar_url" D.string) + (opField "display_name" D.string) + + +{-| The dictionary containing all room member data. +-} +type alias RoomMemberList = + { joined : Dict String RoomMember + } + + +encodeRoomMemberList : RoomMemberList -> E.Value +encodeRoomMemberList data = + maybeObject + [ ( "joined", Just <| E.dict identity encodeRoomMember data.joined ) + ] + + +roomMemberListDecoder : D.Decoder RoomMemberList +roomMemberListDecoder = + D.map + (\a -> + { joined = a } + ) + (opFieldWithDefault "joined" Dict.empty (D.dict roomMemberDecoder)) diff --git a/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.yaml b/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.yaml new file mode 100644 index 0000000..2e913eb --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/SpecObjects.yaml @@ -0,0 +1,17 @@ +version: v1.5 +name: SpecObjects +objects: + RoomMemberList: + description: The dictionary containing all room member data. + fields: + joined: + type: "{RoomMember}" + required: false + default: Dict.empty + RoomMember: + description: User information of joined users. + fields: + avatar_url: + type: string + display_name: + type: string diff --git a/src/Internal/Api/JoinedMembers/V1_5/Upcast.elm b/src/Internal/Api/JoinedMembers/V1_5/Upcast.elm new file mode 100644 index 0000000..ddfe1a0 --- /dev/null +++ b/src/Internal/Api/JoinedMembers/V1_5/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.JoinedMembers.V1_5.Upcast exposing (..) + +import Internal.Api.JoinedMembers.V1_4.Objects as PO +import Internal.Api.JoinedMembers.V1_5.Objects as O + + +upcast : PO.RoomMemberList -> O.RoomMemberList +upcast = + identity diff --git a/src/Internal/Api/Request.elm b/src/Internal/Api/Request.elm new file mode 100644 index 0000000..3f854f3 --- /dev/null +++ b/src/Internal/Api/Request.elm @@ -0,0 +1,284 @@ +module Internal.Api.Request exposing (..) + +import Http +import Internal.Tools.Exceptions as X +import Json.Decode as D +import Json.Encode as E +import Process +import Task exposing (Task) +import Time +import Url.Builder as UrlBuilder + + +{-| Make a raw API call to a Matrix API. +-} +rawApiCall : + { headers : Headers + , method : String + , baseUrl : String + , path : String + , pathParams : List ( String, String ) + , queryParams : List QueryParam + , bodyParams : List BodyParam + , timeout : Maybe Float + , decoder : Int -> D.Decoder a + } + -> Task X.Error a +rawApiCall data = + Http.task + { method = data.method + , headers = fromHeaders data.headers + , url = buildUrl data.baseUrl data.path data.pathParams data.queryParams + , body = toBody data.bodyParams + , resolver = rawApiCallResolver data.decoder + , timeout = data.timeout + } + + +withRateLimits : Int -> Task X.Error a -> Task X.Error a +withRateLimits timeout task = + Time.now + |> Task.onError + (\_ -> X.CouldntGetTimestamp |> X.SDKException |> Task.fail) + |> Task.andThen + (\now -> + task + |> Task.onError + (\err -> + case err of + X.ServerException (X.M_LIMIT_EXCEEDED data) -> + case data.retryAfterMs of + Just t -> + Process.sleep (toFloat t) + |> Task.andThen (\_ -> Time.now) + |> Task.andThen + (\newNow -> + let + diff : Int + diff = + timeout - (Time.posixToMillis newNow - Time.posixToMillis now) + in + if diff <= 0 then + Task.fail err + + else + withRateLimits diff task + ) + + Nothing -> + Task.fail err + + _ -> + Task.fail err + ) + ) + + +{-| Potential headers to go along with a Matrix API call. +-} +type Headers + = NoHeaders + | WithAccessToken String + | WithContentType String + | WithBoth { accessToken : String, contentType : String } + + +{-| Turn Headers into useful values +-} +fromHeaders : Headers -> List Http.Header +fromHeaders h = + (case h of + NoHeaders -> + [ ( "Content-Type", "application/json" ) ] + + WithAccessToken token -> + [ ( "Content-Type", "application/json" ), ( "Authorization", "Bearer " ++ token ) ] + + WithContentType contentType -> + [ ( "Content-Type", contentType ) ] + + WithBoth data -> + [ ( "Content-Type", data.contentType ), ( "Authorization", "Bearer " ++ data.accessToken ) ] + ) + |> List.map (\( a, b ) -> Http.header a b) + + +{-| -} +type QueryParam + = QueryParamString String String + | OpQueryParamString String (Maybe String) + | QueryParamInt String Int + | OpQueryParamInt String (Maybe Int) + | QueryParamBool String Bool + | OpQueryParamBool String (Maybe Bool) + + +fromQueryParam : QueryParam -> Maybe UrlBuilder.QueryParameter +fromQueryParam param = + case param of + QueryParamString key value -> + Just <| UrlBuilder.string key value + + OpQueryParamString key value -> + Maybe.map (UrlBuilder.string key) value + + QueryParamInt key value -> + Just <| UrlBuilder.int key value + + OpQueryParamInt key value -> + Maybe.map (UrlBuilder.int key) value + + QueryParamBool key value -> + if value then + Just <| UrlBuilder.string key "true" + + else + Just <| UrlBuilder.string key "false" + + OpQueryParamBool key value -> + Maybe.andThen (QueryParamBool key >> fromQueryParam) value + + +fromQueryParams : List QueryParam -> List UrlBuilder.QueryParameter +fromQueryParams = + List.map fromQueryParam + >> List.filterMap identity + + +buildUrl : String -> String -> List ( String, String ) -> List QueryParam -> String +buildUrl baseUrl path pathParams queryParams = + let + fullPath : String + fullPath = + List.foldl + (\( a, b ) -> String.replace ("{" ++ a ++ "}") b) + path + pathParams + |> (\s -> + if String.startsWith "/" s then + String.dropLeft 1 s + + else + s + ) + in + UrlBuilder.crossOrigin baseUrl [ fullPath ] (fromQueryParams queryParams) + + +{-| Type that gathers all parameters that go in the request body. +-} +type BodyParam + = OptionalString String (Maybe String) + | RequiredString String String + | OptionalInt String (Maybe Int) + | RequiredInt String Int + | OptionalValue String (Maybe E.Value) + | RequiredValue String E.Value + + +encodeBodyParam : BodyParam -> ( String, Maybe E.Value ) +encodeBodyParam b = + case b of + OptionalString h s -> + ( h, Maybe.map E.string s ) + + RequiredString h s -> + ( h, Just <| E.string s ) + + OptionalInt h i -> + ( h, Maybe.map E.int i ) + + RequiredInt h i -> + ( h, Just <| E.int i ) + + OptionalValue h v -> + ( h, v ) + + RequiredValue h v -> + ( h, Just v ) + + +toBody : List BodyParam -> Http.Body +toBody params = + case params of + (RequiredValue "*" v) :: [] -> + Http.jsonBody v + + _ -> + List.map encodeBodyParam params + |> maybeObject + |> Http.jsonBody + + +{-| Create a body object based on optionally provided values. +-} +maybeObject : List ( String, Maybe E.Value ) -> E.Value +maybeObject = + List.filterMap + (\( name, value ) -> + case value of + Just v -> + Just ( name, v ) + + _ -> + Nothing + ) + >> E.object + + +rawApiCallResolver : (Int -> D.Decoder a) -> Http.Resolver X.Error a +rawApiCallResolver decoder = + Http.stringResolver + (\response -> + case response of + Http.BadUrl_ s -> + Http.BadUrl s + |> X.InternetException + |> Err + + Http.Timeout_ -> + Http.Timeout + |> X.InternetException + |> Err + + Http.NetworkError_ -> + Http.NetworkError + |> X.InternetException + |> Err + + Http.BadStatus_ metadata body -> + decodeServerResponse (decoder metadata.statusCode) body + + Http.GoodStatus_ metadata body -> + decodeServerResponse (decoder metadata.statusCode) body + ) + + +decodeServerResponse : D.Decoder a -> String -> Result X.Error a +decodeServerResponse decoder body = + case D.decodeString D.value body of + Err e -> + e + |> D.errorToString + |> X.ServerReturnsBadJSON + |> X.SDKException + |> Err + + Ok _ -> + case D.decodeString decoder body of + Ok v -> + Ok v + + Err err -> + -- The response is not valid! + -- Check if it is a valid error type as defined in spec. + case D.decodeString X.errorCatches body of + Ok v -> + Err (X.ServerException v) + + Err _ -> + err + |> D.errorToString + |> X.ServerReturnsBadJSON + |> X.SDKException + |> Err diff --git a/src/Internal/Api/SendMessageEvent/Api.elm b/src/Internal/Api/SendMessageEvent/Api.elm new file mode 100644 index 0000000..7e22142 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/Api.elm @@ -0,0 +1,35 @@ +module Internal.Api.SendMessageEvent.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 SendMessageEventInputV1 = + { accessToken : String + , baseUrl : String + , content : D.Value + , eventType : String + , roomId : String + , transactionId : String + } + + +sendMessageEventV1 : D.Decoder a -> (a -> b) -> SendMessageEventInputV1 -> Task X.Error b +sendMessageEventV1 decoder mapping data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "PUT" + , baseUrl = data.baseUrl + , path = "/_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}" + , pathParams = + [ ( "eventType", data.eventType ) + , ( "roomId", data.roomId ) + , ( "txnId", data.transactionId ) + ] + , queryParams = [] + , bodyParams = [ R.RequiredValue "*" data.content ] + , timeout = Nothing + , decoder = \_ -> D.map mapping decoder + } diff --git a/src/Internal/Api/SendMessageEvent/Main.elm b/src/Internal/Api/SendMessageEvent/Main.elm new file mode 100644 index 0000000..6529755 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/Main.elm @@ -0,0 +1,28 @@ +module Internal.Api.SendMessageEvent.Main exposing (..) + +import Internal.Api.SendMessageEvent.Api as Api +import Internal.Api.SendMessageEvent.V1_2.Api as V1_2 +import Internal.Api.SendMessageEvent.V1_3.Api as V1_3 +import Internal.Api.SendMessageEvent.V1_4.Api as V1_4 +import Internal.Api.SendMessageEvent.V1_5.Api as V1_5 +import Internal.Api.SendMessageEvent.V1_5.Objects as O +import Internal.Api.VersionControl as V +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +sendMessageEvent : List String -> SendMessageEventInput -> SendMessageEventOutput +sendMessageEvent = + V.firstVersion V1_2.packet + |> V.updateWith V1_3.packet + |> V.updateWith V1_4.packet + |> V.updateWith V1_5.packet + |> V.toFunction + + +type alias SendMessageEventInput = + Api.SendMessageEventInputV1 + + +type alias SendMessageEventOutput = + Task X.Error O.EventResponse diff --git a/src/Internal/Api/SendMessageEvent/V1_2/Api.elm b/src/Internal/Api/SendMessageEvent/V1_2/Api.elm new file mode 100644 index 0000000..a407148 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/Api.elm @@ -0,0 +1,16 @@ +module Internal.Api.SendMessageEvent.V1_2.Api exposing (..) + +import Internal.Api.SendMessageEvent.Api as Api +import Internal.Api.SendMessageEvent.V1_2.Convert as C +import Internal.Api.SendMessageEvent.V1_2.Objects as O +import Internal.Api.SendMessageEvent.V1_2.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion () () Api.SendMessageEventInputV1 O.EventResponse +packet = + { version = "v1.2" + , downcast = \_ -> () + , current = Api.sendMessageEventV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendMessageEvent/V1_2/Convert.elm b/src/Internal/Api/SendMessageEvent/V1_2/Convert.elm new file mode 100644 index 0000000..04d6c2a --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_2.Convert exposing (..) + +import Internal.Api.SendMessageEvent.V1_2.Objects as O +import Internal.Api.SendMessageEvent.V1_2.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_2/Objects.elm b/src/Internal/Api/SendMessageEvent/V1_2/Objects.elm new file mode 100644 index 0000000..62bcd68 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_2.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_2/Objects.yaml b/src/Internal/Api/SendMessageEvent/V1_2/Objects.yaml new file mode 100644 index 0000000..0d30551 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.2 +name: Objects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.elm b/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.elm new file mode 100644 index 0000000..8e57da4 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_2.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.yaml b/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.yaml new file mode 100644 index 0000000..f5eaebe --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.2 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_2/Upcast.elm b/src/Internal/Api/SendMessageEvent/V1_2/Upcast.elm new file mode 100644 index 0000000..d4b15d0 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_2/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_2.Upcast exposing (..) + +import Internal.Api.SendMessageEvent.V1_2.Objects as O +import Internal.Config.Leaking as L + + +upcast : () -> O.EventResponse +upcast _ = + { eventId = L.eventId } diff --git a/src/Internal/Api/SendMessageEvent/V1_3/Api.elm b/src/Internal/Api/SendMessageEvent/V1_3/Api.elm new file mode 100644 index 0000000..41c93e0 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendMessageEvent.V1_3.Api exposing (..) + +import Internal.Api.SendMessageEvent.Api as Api +import Internal.Api.SendMessageEvent.V1_2.Objects as PO +import Internal.Api.SendMessageEvent.V1_3.Convert as C +import Internal.Api.SendMessageEvent.V1_3.Objects as O +import Internal.Api.SendMessageEvent.V1_3.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendMessageEventInputV1 PO.EventResponse Api.SendMessageEventInputV1 O.EventResponse +packet = + { version = "v1.3" + , downcast = identity + , current = Api.sendMessageEventV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendMessageEvent/V1_3/Convert.elm b/src/Internal/Api/SendMessageEvent/V1_3/Convert.elm new file mode 100644 index 0000000..80259a8 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_3.Convert exposing (..) + +import Internal.Api.SendMessageEvent.V1_3.Objects as O +import Internal.Api.SendMessageEvent.V1_3.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_3/Objects.elm b/src/Internal/Api/SendMessageEvent/V1_3/Objects.elm new file mode 100644 index 0000000..ba6a7c9 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_3.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_3/Objects.yaml b/src/Internal/Api/SendMessageEvent/V1_3/Objects.yaml new file mode 100644 index 0000000..d302712 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.3 +name: Objects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.elm b/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.elm new file mode 100644 index 0000000..e346914 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_3.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.yaml b/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.yaml new file mode 100644 index 0000000..e330263 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.3 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_3/Upcast.elm b/src/Internal/Api/SendMessageEvent/V1_3/Upcast.elm new file mode 100644 index 0000000..2ca1c35 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_3/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_3.Upcast exposing (..) + +import Internal.Api.SendMessageEvent.V1_2.Objects as PO +import Internal.Api.SendMessageEvent.V1_3.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_4/Api.elm b/src/Internal/Api/SendMessageEvent/V1_4/Api.elm new file mode 100644 index 0000000..37ad6fb --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendMessageEvent.V1_4.Api exposing (..) + +import Internal.Api.SendMessageEvent.Api as Api +import Internal.Api.SendMessageEvent.V1_3.Objects as PO +import Internal.Api.SendMessageEvent.V1_4.Convert as C +import Internal.Api.SendMessageEvent.V1_4.Objects as O +import Internal.Api.SendMessageEvent.V1_4.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendMessageEventInputV1 PO.EventResponse Api.SendMessageEventInputV1 O.EventResponse +packet = + { version = "v1.4" + , downcast = identity + , current = Api.sendMessageEventV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendMessageEvent/V1_4/Convert.elm b/src/Internal/Api/SendMessageEvent/V1_4/Convert.elm new file mode 100644 index 0000000..19a4da6 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_4.Convert exposing (..) + +import Internal.Api.SendMessageEvent.V1_4.Objects as O +import Internal.Api.SendMessageEvent.V1_4.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_4/Objects.elm b/src/Internal/Api/SendMessageEvent/V1_4/Objects.elm new file mode 100644 index 0000000..65321e3 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_4.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_4/Objects.yaml b/src/Internal/Api/SendMessageEvent/V1_4/Objects.yaml new file mode 100644 index 0000000..93126c6 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.4 +name: Objects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.elm b/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.elm new file mode 100644 index 0000000..36e4461 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_4.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.yaml b/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.yaml new file mode 100644 index 0000000..9ab5c91 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.4 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_4/Upcast.elm b/src/Internal/Api/SendMessageEvent/V1_4/Upcast.elm new file mode 100644 index 0000000..84e9080 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_4/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_4.Upcast exposing (..) + +import Internal.Api.SendMessageEvent.V1_3.Objects as PO +import Internal.Api.SendMessageEvent.V1_4.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_5/Api.elm b/src/Internal/Api/SendMessageEvent/V1_5/Api.elm new file mode 100644 index 0000000..7680445 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendMessageEvent.V1_5.Api exposing (..) + +import Internal.Api.SendMessageEvent.Api as Api +import Internal.Api.SendMessageEvent.V1_4.Objects as PO +import Internal.Api.SendMessageEvent.V1_5.Convert as C +import Internal.Api.SendMessageEvent.V1_5.Objects as O +import Internal.Api.SendMessageEvent.V1_5.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendMessageEventInputV1 PO.EventResponse Api.SendMessageEventInputV1 O.EventResponse +packet = + { version = "v1.5" + , downcast = identity + , current = Api.sendMessageEventV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendMessageEvent/V1_5/Convert.elm b/src/Internal/Api/SendMessageEvent/V1_5/Convert.elm new file mode 100644 index 0000000..0df53f0 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_5.Convert exposing (..) + +import Internal.Api.SendMessageEvent.V1_5.Objects as O +import Internal.Api.SendMessageEvent.V1_5.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendMessageEvent/V1_5/Objects.elm b/src/Internal/Api/SendMessageEvent/V1_5/Objects.elm new file mode 100644 index 0000000..1828555 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_5.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_5/Objects.yaml b/src/Internal/Api/SendMessageEvent/V1_5/Objects.yaml new file mode 100644 index 0000000..b2411ba --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.5 +name: Objects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.elm b/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.elm new file mode 100644 index 0000000..1534cb2 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendMessageEvent.V1_5.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.yaml b/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.yaml new file mode 100644 index 0000000..ee1cb6f --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.5 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendMessageEvent/V1_5/Upcast.elm b/src/Internal/Api/SendMessageEvent/V1_5/Upcast.elm new file mode 100644 index 0000000..cdf56d6 --- /dev/null +++ b/src/Internal/Api/SendMessageEvent/V1_5/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendMessageEvent.V1_5.Upcast exposing (..) + +import Internal.Api.SendMessageEvent.V1_4.Objects as PO +import Internal.Api.SendMessageEvent.V1_5.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/SendStateKey/Api.elm b/src/Internal/Api/SendStateKey/Api.elm new file mode 100644 index 0000000..7b8c70e --- /dev/null +++ b/src/Internal/Api/SendStateKey/Api.elm @@ -0,0 +1,35 @@ +module Internal.Api.SendStateKey.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 SendStateKeyInputV1 = + { accessToken : String + , baseUrl : String + , content : D.Value + , eventType : String + , roomId : String + , stateKey : String + } + + +sendStateKeyV1 : D.Decoder a -> (a -> b) -> SendStateKeyInputV1 -> Task X.Error b +sendStateKeyV1 decoder mapping data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "PUT" + , baseUrl = data.baseUrl + , path = "/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}" + , pathParams = + [ ( "eventType", data.eventType ) + , ( "roomId", data.roomId ) + , ( "stateKey", data.stateKey ) + ] + , queryParams = [] + , bodyParams = [ R.RequiredValue "*" data.content ] + , timeout = Nothing + , decoder = \_ -> D.map mapping decoder + } diff --git a/src/Internal/Api/SendStateKey/Main.elm b/src/Internal/Api/SendStateKey/Main.elm new file mode 100644 index 0000000..65b61ed --- /dev/null +++ b/src/Internal/Api/SendStateKey/Main.elm @@ -0,0 +1,28 @@ +module Internal.Api.SendStateKey.Main exposing (..) + +import Internal.Api.SendStateKey.Api as Api +import Internal.Api.SendStateKey.V1_2.Api as V1_2 +import Internal.Api.SendStateKey.V1_3.Api as V1_3 +import Internal.Api.SendStateKey.V1_4.Api as V1_4 +import Internal.Api.SendStateKey.V1_5.Api as V1_5 +import Internal.Api.SendStateKey.V1_5.Objects as O +import Internal.Api.VersionControl as V +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +sendStateKey : List String -> SendStateKeyInput -> SendStateKeyOutput +sendStateKey = + V.firstVersion V1_2.packet + |> V.updateWith V1_3.packet + |> V.updateWith V1_4.packet + |> V.updateWith V1_5.packet + |> V.toFunction + + +type alias SendStateKeyInput = + Api.SendStateKeyInputV1 + + +type alias SendStateKeyOutput = + Task X.Error O.EventResponse diff --git a/src/Internal/Api/SendStateKey/V1_2/Api.elm b/src/Internal/Api/SendStateKey/V1_2/Api.elm new file mode 100644 index 0000000..3456b95 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/Api.elm @@ -0,0 +1,16 @@ +module Internal.Api.SendStateKey.V1_2.Api exposing (..) + +import Internal.Api.SendStateKey.Api as Api +import Internal.Api.SendStateKey.V1_2.Convert as C +import Internal.Api.SendStateKey.V1_2.Objects as O +import Internal.Api.SendStateKey.V1_2.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion () () Api.SendStateKeyInputV1 O.EventResponse +packet = + { version = "v1.2" + , downcast = \_ -> () + , current = Api.sendStateKeyV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendStateKey/V1_2/Convert.elm b/src/Internal/Api/SendStateKey/V1_2/Convert.elm new file mode 100644 index 0000000..ef2ca42 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_2.Convert exposing (..) + +import Internal.Api.SendStateKey.V1_2.Objects as O +import Internal.Api.SendStateKey.V1_2.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendStateKey/V1_2/Objects.elm b/src/Internal/Api/SendStateKey/V1_2/Objects.elm new file mode 100644 index 0000000..f7c6e6b --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_2.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_2/Objects.yaml b/src/Internal/Api/SendStateKey/V1_2/Objects.yaml new file mode 100644 index 0000000..f5eaebe --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.2 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_2/SpecObjects.elm b/src/Internal/Api/SendStateKey/V1_2/SpecObjects.elm new file mode 100644 index 0000000..b9467bc --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_2.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_2/SpecObjects.yaml b/src/Internal/Api/SendStateKey/V1_2/SpecObjects.yaml new file mode 100644 index 0000000..f5eaebe --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.2 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_2/Upcast.elm b/src/Internal/Api/SendStateKey/V1_2/Upcast.elm new file mode 100644 index 0000000..9b887a4 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_2/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_2.Upcast exposing (..) + +import Internal.Api.SendStateKey.V1_2.Objects as O +import Internal.Config.Leaking as L + + +upcast : () -> O.EventResponse +upcast _ = + { eventId = L.eventId } diff --git a/src/Internal/Api/SendStateKey/V1_3/Api.elm b/src/Internal/Api/SendStateKey/V1_3/Api.elm new file mode 100644 index 0000000..b16ed28 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendStateKey.V1_3.Api exposing (..) + +import Internal.Api.SendStateKey.Api as Api +import Internal.Api.SendStateKey.V1_2.Objects as PO +import Internal.Api.SendStateKey.V1_3.Convert as C +import Internal.Api.SendStateKey.V1_3.Objects as O +import Internal.Api.SendStateKey.V1_3.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendStateKeyInputV1 PO.EventResponse Api.SendStateKeyInputV1 O.EventResponse +packet = + { version = "v1.3" + , downcast = identity + , current = Api.sendStateKeyV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendStateKey/V1_3/Convert.elm b/src/Internal/Api/SendStateKey/V1_3/Convert.elm new file mode 100644 index 0000000..287f75d --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_3.Convert exposing (..) + +import Internal.Api.SendStateKey.V1_3.Objects as O +import Internal.Api.SendStateKey.V1_3.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendStateKey/V1_3/Objects.elm b/src/Internal/Api/SendStateKey/V1_3/Objects.elm new file mode 100644 index 0000000..0feefbc --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_3.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_3/Objects.yaml b/src/Internal/Api/SendStateKey/V1_3/Objects.yaml new file mode 100644 index 0000000..e330263 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.3 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_3/SpecObjects.elm b/src/Internal/Api/SendStateKey/V1_3/SpecObjects.elm new file mode 100644 index 0000000..b00c428 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_3.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_3/SpecObjects.yaml b/src/Internal/Api/SendStateKey/V1_3/SpecObjects.yaml new file mode 100644 index 0000000..e330263 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.3 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_3/Upcast.elm b/src/Internal/Api/SendStateKey/V1_3/Upcast.elm new file mode 100644 index 0000000..59b36dc --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_3/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_3.Upcast exposing (..) + +import Internal.Api.SendStateKey.V1_2.Objects as PO +import Internal.Api.SendStateKey.V1_3.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/SendStateKey/V1_4/Api.elm b/src/Internal/Api/SendStateKey/V1_4/Api.elm new file mode 100644 index 0000000..1aa8eae --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendStateKey.V1_4.Api exposing (..) + +import Internal.Api.SendStateKey.Api as Api +import Internal.Api.SendStateKey.V1_3.Objects as PO +import Internal.Api.SendStateKey.V1_4.Convert as C +import Internal.Api.SendStateKey.V1_4.Objects as O +import Internal.Api.SendStateKey.V1_4.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendStateKeyInputV1 PO.EventResponse Api.SendStateKeyInputV1 O.EventResponse +packet = + { version = "v1.4" + , downcast = identity + , current = Api.sendStateKeyV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendStateKey/V1_4/Convert.elm b/src/Internal/Api/SendStateKey/V1_4/Convert.elm new file mode 100644 index 0000000..b942f33 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_4.Convert exposing (..) + +import Internal.Api.SendStateKey.V1_4.Objects as O +import Internal.Api.SendStateKey.V1_4.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendStateKey/V1_4/Objects.elm b/src/Internal/Api/SendStateKey/V1_4/Objects.elm new file mode 100644 index 0000000..c298ec0 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_4.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_4/Objects.yaml b/src/Internal/Api/SendStateKey/V1_4/Objects.yaml new file mode 100644 index 0000000..9ab5c91 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.4 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_4/SpecObjects.elm b/src/Internal/Api/SendStateKey/V1_4/SpecObjects.elm new file mode 100644 index 0000000..435f6de --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_4.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_4/SpecObjects.yaml b/src/Internal/Api/SendStateKey/V1_4/SpecObjects.yaml new file mode 100644 index 0000000..9ab5c91 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.4 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_4/Upcast.elm b/src/Internal/Api/SendStateKey/V1_4/Upcast.elm new file mode 100644 index 0000000..4e46468 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_4/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_4.Upcast exposing (..) + +import Internal.Api.SendStateKey.V1_3.Objects as PO +import Internal.Api.SendStateKey.V1_4.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/SendStateKey/V1_5/Api.elm b/src/Internal/Api/SendStateKey/V1_5/Api.elm new file mode 100644 index 0000000..33cc30b --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.SendStateKey.V1_5.Api exposing (..) + +import Internal.Api.SendStateKey.Api as Api +import Internal.Api.SendStateKey.V1_4.Objects as PO +import Internal.Api.SendStateKey.V1_5.Convert as C +import Internal.Api.SendStateKey.V1_5.Objects as O +import Internal.Api.SendStateKey.V1_5.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SendStateKeyInputV1 PO.EventResponse Api.SendStateKeyInputV1 O.EventResponse +packet = + { version = "v1.5" + , downcast = identity + , current = Api.sendStateKeyV1 O.eventResponseDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/SendStateKey/V1_5/Convert.elm b/src/Internal/Api/SendStateKey/V1_5/Convert.elm new file mode 100644 index 0000000..aaf010a --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/Convert.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_5.Convert exposing (..) + +import Internal.Api.SendStateKey.V1_5.Objects as O +import Internal.Api.SendStateKey.V1_5.SpecObjects as SO + + +convert : SO.EventResponse -> O.EventResponse +convert = + identity diff --git a/src/Internal/Api/SendStateKey/V1_5/Objects.elm b/src/Internal/Api/SendStateKey/V1_5/Objects.elm new file mode 100644 index 0000000..6303d95 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/Objects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_5.Objects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_5/Objects.yaml b/src/Internal/Api/SendStateKey/V1_5/Objects.yaml new file mode 100644 index 0000000..ee1cb6f --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/Objects.yaml @@ -0,0 +1,9 @@ +version: v1.5 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_5/SpecObjects.elm b/src/Internal/Api/SendStateKey/V1_5/SpecObjects.elm new file mode 100644 index 0000000..a5e4dc5 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/SpecObjects.elm @@ -0,0 +1,38 @@ +module Internal.Api.SendStateKey.V1_5.SpecObjects exposing + ( EventResponse + , encodeEventResponse + , eventResponseDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| A response confirming that an event has been sent. +-} +type alias EventResponse = + { eventId : String + } + + +encodeEventResponse : EventResponse -> E.Value +encodeEventResponse data = + maybeObject + [ ( "event_id", Just <| E.string data.eventId ) + ] + + +eventResponseDecoder : D.Decoder EventResponse +eventResponseDecoder = + D.map + (\a -> + { eventId = a } + ) + (D.field "event_id" D.string) diff --git a/src/Internal/Api/SendStateKey/V1_5/SpecObjects.yaml b/src/Internal/Api/SendStateKey/V1_5/SpecObjects.yaml new file mode 100644 index 0000000..ee1cb6f --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/SpecObjects.yaml @@ -0,0 +1,9 @@ +version: v1.5 +name: SpecObjects +objects: + EventResponse: + description: A response confirming that an event has been sent. + fields: + event_id: + type: string + required: true diff --git a/src/Internal/Api/SendStateKey/V1_5/Upcast.elm b/src/Internal/Api/SendStateKey/V1_5/Upcast.elm new file mode 100644 index 0000000..adc8e51 --- /dev/null +++ b/src/Internal/Api/SendStateKey/V1_5/Upcast.elm @@ -0,0 +1,9 @@ +module Internal.Api.SendStateKey.V1_5.Upcast exposing (..) + +import Internal.Api.SendStateKey.V1_4.Objects as PO +import Internal.Api.SendStateKey.V1_5.Objects as O + + +upcast : PO.EventResponse -> O.EventResponse +upcast = + identity diff --git a/src/Internal/Api/Sync/Api.elm b/src/Internal/Api/Sync/Api.elm new file mode 100644 index 0000000..6f20c8a --- /dev/null +++ b/src/Internal/Api/Sync/Api.elm @@ -0,0 +1,42 @@ +module Internal.Api.Sync.Api exposing (..) + +import Internal.Api.Request as R +import Internal.Tools.Exceptions as X +import Internal.Tools.SpecEnums as Enums +import Json.Decode as D +import Task exposing (Task) + + +type alias SyncInputV1 = + { accessToken : String + , baseUrl : String + , filter : Maybe String + , fullState : Maybe Bool + , setPresence : Maybe Enums.UserPresence + , since : Maybe String + , timeout : Maybe Int + } + + +syncV1 : D.Decoder a -> (a -> b) -> SyncInputV1 -> Task X.Error b +syncV1 decoder mapping data = + R.rawApiCall + { headers = R.WithAccessToken data.accessToken + , method = "GET" + , baseUrl = data.baseUrl + , path = "/_matrix/client/v3/sync" + , pathParams = [] + , queryParams = + [ R.OpQueryParamString "filter" data.filter + , R.OpQueryParamBool "full_state" data.fullState + , R.OpQueryParamString "set_presence" (Maybe.map Enums.fromUserPresence data.setPresence) + , R.OpQueryParamString "since" data.since + , R.OpQueryParamInt "timeout" data.timeout + ] + , bodyParams = [] + , timeout = + data.timeout + |> Maybe.map ((+) 10000) + |> Maybe.map toFloat + , decoder = \_ -> D.map mapping decoder + } diff --git a/src/Internal/Api/Sync/Main.elm b/src/Internal/Api/Sync/Main.elm new file mode 100644 index 0000000..4710696 --- /dev/null +++ b/src/Internal/Api/Sync/Main.elm @@ -0,0 +1,28 @@ +module Internal.Api.Sync.Main exposing (..) + +import Internal.Api.Sync.Api as Api +import Internal.Api.Sync.V1_2.Api as V1_2 +import Internal.Api.Sync.V1_3.Api as V1_3 +import Internal.Api.Sync.V1_4.Api as V1_4 +import Internal.Api.Sync.V1_5.Api as V1_5 +import Internal.Api.Sync.V1_5.Objects as O +import Internal.Api.VersionControl as V +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +sync : List String -> SyncInput -> SyncOutput +sync = + V.firstVersion V1_2.packet + |> V.updateWith V1_3.packet + |> V.updateWith V1_4.packet + |> V.updateWith V1_5.packet + |> V.toFunction + + +type alias SyncInput = + Api.SyncInputV1 + + +type alias SyncOutput = + Task X.Error O.Sync diff --git a/src/Internal/Api/Sync/V1_2/Api.elm b/src/Internal/Api/Sync/V1_2/Api.elm new file mode 100644 index 0000000..840c6d6 --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/Api.elm @@ -0,0 +1,17 @@ +module Internal.Api.Sync.V1_2.Api exposing (..) + +import Internal.Api.Sync.Api as Api +import Internal.Api.Sync.V1_2.Convert as C +import Internal.Api.Sync.V1_2.Objects as O +import Internal.Api.Sync.V1_2.SpecObjects as SO +import Internal.Api.Sync.V1_2.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion () () Api.SyncInputV1 O.Sync +packet = + { version = "v1.2" + , downcast = \_ -> () + , current = Api.syncV1 SO.syncDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/Sync/V1_2/Convert.elm b/src/Internal/Api/Sync/V1_2/Convert.elm new file mode 100644 index 0000000..92cf2bd --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/Convert.elm @@ -0,0 +1,83 @@ +module Internal.Api.Sync.V1_2.Convert exposing (..) + +import Dict +import Internal.Api.Sync.V1_2.Objects as O +import Internal.Api.Sync.V1_2.SpecObjects as SO + + +convert : SO.Sync -> O.Sync +convert sync = + { accountData = convertEventHolder sync.accountData + , nextBatch = sync.nextBatch + , presence = convertEventHolder sync.presence + , rooms = Maybe.map convertRooms sync.rooms + } + + +convertEventHolder : Maybe { a | events : List b } -> List b +convertEventHolder = + Maybe.map .events >> Maybe.withDefault [] + + +convertRooms : SO.Rooms -> O.Rooms +convertRooms rooms = + { invite = + Dict.map + (\_ -> .inviteState >> Maybe.map .events >> Maybe.withDefault []) + rooms.invite + , join = Dict.map (\_ -> convertJoinedRoom) rooms.join + , knock = + Dict.map + (\_ -> .knockState >> Maybe.map .events >> Maybe.withDefault []) + rooms.knock + , leave = Dict.map (\_ -> convertLeftRoom) rooms.leave + } + + +convertJoinedRoom : SO.JoinedRoom -> O.JoinedRoom +convertJoinedRoom room = + { accountData = convertEventHolder room.accountData + , ephemeral = convertEventHolder room.ephemeral + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , summary = room.summary + , timeline = Maybe.map convertTimeline room.timeline + , unreadNotifications = room.unreadNotifications + } + + +convertClientEventWithoutRoomId : SO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +convertClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map convertUnsigned event.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map convertClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +convertTimeline : SO.Timeline -> O.Timeline +convertTimeline timeline = + { events = List.map convertClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +convertLeftRoom : SO.LeftRoom -> O.LeftRoom +convertLeftRoom room = + { accountData = convertEventHolder room.accountData + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , timeline = Maybe.map convertTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_2/Objects.elm b/src/Internal/Api/Sync/V1_2/Objects.elm new file mode 100644 index 0000000..4f1c074 --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/Objects.elm @@ -0,0 +1,395 @@ +module Internal.Api.Sync.V1_2.Objects exposing + ( BlindEvent + , ClientEventWithoutRoomId + , JoinedRoom + , LeftRoom + , RoomSummary + , Rooms + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , blindEventDecoder + , clientEventWithoutRoomIdDecoder + , encodeBlindEvent + , encodeClientEventWithoutRoomId + , encodeJoinedRoom + , encodeLeftRoom + , encodeRoomSummary + , encodeRooms + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , joinedRoomDecoder + , leftRoomDecoder + , roomSummaryDecoder + , roomsDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| A blind event that does not give context about itself. +-} +type alias BlindEvent = + { content : E.Value + , contentType : String + } + + +encodeBlindEvent : BlindEvent -> E.Value +encodeBlindEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +blindEventDecoder : D.Decoder BlindEvent +blindEventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : List BlindEvent + , ephemeral : List BlindEvent + , state : List ClientEventWithoutRoomId + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "ephemeral", Just <| E.list encodeBlindEvent data.ephemeral ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map6 + (\a b c d e f -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "ephemeral" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : List BlindEvent + , state : List ClientEventWithoutRoomId + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "timeline" timelineDecoder) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String (List StrippedStateEvent) + , join : Dict String JoinedRoom + , knock : Dict String (List StrippedStateEvent) + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : List BlindEvent + , nextBatch : String + , presence : List BlindEvent + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Just <| E.list encodeBlindEvent data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "next_batch" D.string) + (D.field "presence" (D.list blindEventDecoder)) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_2/Objects.yaml b/src/Internal/Api/Sync/V1_2/Objects.yaml new file mode 100644 index 0000000..c2e5a7b --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/Objects.yaml @@ -0,0 +1,152 @@ +version: v1.2 +name: Objects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: "[BlindEvent]" + required: true + next_batch: + type: string + required: true + presence: + type: "[BlindEvent]" + required: true + rooms: + type: Rooms + BlindEvent: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: "[BlindEvent]" + required: true + ephemeral: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_2/SpecObjects.elm b/src/Internal/Api/Sync/V1_2/SpecObjects.elm new file mode 100644 index 0000000..dc6e3ab --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/SpecObjects.elm @@ -0,0 +1,603 @@ +module Internal.Api.Sync.V1_2.SpecObjects exposing + ( AccountData + , ClientEventWithoutRoomId + , Ephemeral + , Event + , InviteState + , InvitedRoom + , JoinedRoom + , KnockState + , KnockedRoom + , LeftRoom + , Presence + , RoomSummary + , Rooms + , State + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , accountDataDecoder + , clientEventWithoutRoomIdDecoder + , encodeAccountData + , encodeClientEventWithoutRoomId + , encodeEphemeral + , encodeEvent + , encodeInviteState + , encodeInvitedRoom + , encodeJoinedRoom + , encodeKnockState + , encodeKnockedRoom + , encodeLeftRoom + , encodePresence + , encodeRoomSummary + , encodeRooms + , encodeState + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , ephemeralDecoder + , eventDecoder + , inviteStateDecoder + , invitedRoomDecoder + , joinedRoomDecoder + , knockStateDecoder + , knockedRoomDecoder + , leftRoomDecoder + , presenceDecoder + , roomSummaryDecoder + , roomsDecoder + , stateDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| The private data created by this user in a given context. +-} +type alias AccountData = + { events : List Event + } + + +encodeAccountData : AccountData -> E.Value +encodeAccountData data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +accountDataDecoder : D.Decoder AccountData +accountDataDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Ephemeral events in a room that aren't recorded in the timeline or the room state. +-} +type alias Ephemeral = + { events : List Event + } + + +encodeEphemeral : Ephemeral -> E.Value +encodeEphemeral data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +ephemeralDecoder : D.Decoder Ephemeral +ephemeralDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| A blind event that does not give context about itself. +-} +type alias Event = + { content : E.Value + , contentType : String + } + + +encodeEvent : Event -> E.Value +encodeEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +eventDecoder : D.Decoder Event +eventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Room that the user has been invited to. +-} +type alias InvitedRoom = + { inviteState : Maybe InviteState + } + + +encodeInvitedRoom : InvitedRoom -> E.Value +encodeInvitedRoom data = + maybeObject + [ ( "invite_state", Maybe.map encodeInviteState data.inviteState ) + ] + + +invitedRoomDecoder : D.Decoder InvitedRoom +invitedRoomDecoder = + D.map + (\a -> + { inviteState = a } + ) + (opField "invite_state" inviteStateDecoder) + + +{-| The state of a room that the user has been invited to. +-} +type alias InviteState = + { events : List StrippedStateEvent + } + + +encodeInviteState : InviteState -> E.Value +encodeInviteState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +inviteStateDecoder : D.Decoder InviteState +inviteStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : Maybe AccountData + , ephemeral : Maybe Ephemeral + , state : Maybe State + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "ephemeral", Maybe.map encodeEphemeral data.ephemeral ) + , ( "state", Maybe.map encodeState data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map6 + (\a b c d e f -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f } + ) + (opField "account_data" accountDataDecoder) + (opField "ephemeral" ephemeralDecoder) + (opField "state" stateDecoder) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + + +{-| Room that the user has knocked upon. +-} +type alias KnockedRoom = + { knockState : Maybe KnockState + } + + +encodeKnockedRoom : KnockedRoom -> E.Value +encodeKnockedRoom data = + maybeObject + [ ( "knock_state", Maybe.map encodeKnockState data.knockState ) + ] + + +knockedRoomDecoder : D.Decoder KnockedRoom +knockedRoomDecoder = + D.map + (\a -> + { knockState = a } + ) + (opField "knock_state" knockStateDecoder) + + +{-| The state of a room that the user has knocked upon. +-} +type alias KnockState = + { events : List StrippedStateEvent + } + + +encodeKnockState : KnockState -> E.Value +encodeKnockState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +knockStateDecoder : D.Decoder KnockState +knockStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : Maybe AccountData + , state : Maybe State + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "state", Maybe.map encodeState data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (opField "account_data" accountDataDecoder) + (opField "state" stateDecoder) + (opField "timeline" timelineDecoder) + + +{-| The updates to the presence status of other users. +-} +type alias Presence = + { events : List Event + } + + +encodePresence : Presence -> E.Value +encodePresence data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +presenceDecoder : D.Decoder Presence +presenceDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String InvitedRoom + , join : Dict String JoinedRoom + , knock : Dict String KnockedRoom + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity encodeInvitedRoom data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity encodeKnockedRoom data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict invitedRoomDecoder)) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict knockedRoomDecoder)) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Updates to the state of a room. +-} +type alias State = + { events : List ClientEventWithoutRoomId + } + + +encodeState : State -> E.Value +encodeState data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + ] + + +stateDecoder : D.Decoder State +stateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : Maybe AccountData + , nextBatch : String + , presence : Maybe Presence + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Maybe.map encodePresence data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (opField "account_data" accountDataDecoder) + (D.field "next_batch" D.string) + (opField "presence" presenceDecoder) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_2/SpecObjects.yaml b/src/Internal/Api/Sync/V1_2/SpecObjects.yaml new file mode 100644 index 0000000..757ddc7 --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/SpecObjects.yaml @@ -0,0 +1,197 @@ +version: v1.2 +name: SpecObjects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: AccountData + next_batch: + type: string + required: true + presence: + type: Presence + rooms: + type: Rooms + AccountData: + description: The private data created by this user in a given context. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Event: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Presence: + description: The updates to the presence status of other users. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{InvitedRoom}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{KnockedRoom}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + InvitedRoom: + description: Room that the user has been invited to. + fields: + invite_state: + type: InviteState + InviteState: + description: The state of a room that the user has been invited to. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: AccountData + ephemeral: + type: Ephemeral + state: + type: State + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + Ephemeral: + description: Ephemeral events in a room that aren't recorded in the timeline or the room state. + fields: + events: + type: "[Event]" + required: false + default: "[]" + State: + description: Updates to the state of a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + KnockedRoom: + description: Room that the user has knocked upon. + fields: + knock_state: + type: KnockState + KnockState: + description: The state of a room that the user has knocked upon. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: AccountData + state: + type: State + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_2/Upcast.elm b/src/Internal/Api/Sync/V1_2/Upcast.elm new file mode 100644 index 0000000..b7e0658 --- /dev/null +++ b/src/Internal/Api/Sync/V1_2/Upcast.elm @@ -0,0 +1,13 @@ +module Internal.Api.Sync.V1_2.Upcast exposing (..) + +import Internal.Api.Sync.V1_2.Objects as O +import Internal.Config.Leaking as L + + +upcast : () -> O.Sync +upcast _ = + { accountData = [] + , nextBatch = L.nextBatch + , presence = [] + , rooms = Nothing + } diff --git a/src/Internal/Api/Sync/V1_3/Api.elm b/src/Internal/Api/Sync/V1_3/Api.elm new file mode 100644 index 0000000..3189f8d --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.Sync.V1_3.Api exposing (..) + +import Internal.Api.Sync.Api as Api +import Internal.Api.Sync.V1_2.Objects as PO +import Internal.Api.Sync.V1_3.Convert as C +import Internal.Api.Sync.V1_3.Objects as O +import Internal.Api.Sync.V1_3.SpecObjects as SO +import Internal.Api.Sync.V1_3.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SyncInputV1 PO.Sync Api.SyncInputV1 O.Sync +packet = + { version = "v1.3" + , downcast = identity + , current = Api.syncV1 SO.syncDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/Sync/V1_3/Convert.elm b/src/Internal/Api/Sync/V1_3/Convert.elm new file mode 100644 index 0000000..2256c32 --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/Convert.elm @@ -0,0 +1,95 @@ +module Internal.Api.Sync.V1_3.Convert exposing (..) + +import Dict +import Internal.Api.Sync.V1_3.Objects as O +import Internal.Api.Sync.V1_3.SpecObjects as SO + + +convert : SO.Sync -> O.Sync +convert sync = + { accountData = convertEventHolder sync.accountData + , nextBatch = sync.nextBatch + , presence = convertEventHolder sync.presence + , rooms = Maybe.map convertRooms sync.rooms + } + + +convertEventHolder : Maybe { a | events : List b } -> List b +convertEventHolder = + Maybe.map .events >> Maybe.withDefault [] + + +convertRooms : SO.Rooms -> O.Rooms +convertRooms rooms = + { invite = + Dict.map + (\_ -> .inviteState >> Maybe.map .events >> Maybe.withDefault []) + rooms.invite + , join = Dict.map (\_ -> convertJoinedRoom) rooms.join + , knock = + Dict.map + (\_ -> .knockState >> Maybe.map .events >> Maybe.withDefault []) + rooms.knock + , leave = Dict.map (\_ -> convertLeftRoom) rooms.leave + } + + +convertJoinedRoom : SO.JoinedRoom -> O.JoinedRoom +convertJoinedRoom room = + { accountData = convertEventHolder room.accountData + , ephemeral = convertEventHolder room.ephemeral + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , summary = room.summary + , timeline = Maybe.map convertTimeline room.timeline + , unreadNotifications = room.unreadNotifications + } + + +convertClientEventWithoutRoomId : SO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +convertClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map convertUnsigned event.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map convertToOldBlindEvent data.redactedBecause + , transactionId = data.transactionId + } + + +convertToOldBlindEvent : SO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +convertToOldBlindEvent event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map convertUnsigned event.unsigned + } + + +convertTimeline : SO.Timeline -> O.Timeline +convertTimeline timeline = + { events = List.map convertClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +convertLeftRoom : SO.LeftRoom -> O.LeftRoom +convertLeftRoom room = + { accountData = convertEventHolder room.accountData + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , timeline = Maybe.map convertTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_3/Objects.elm b/src/Internal/Api/Sync/V1_3/Objects.elm new file mode 100644 index 0000000..66be9cd --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/Objects.elm @@ -0,0 +1,395 @@ +module Internal.Api.Sync.V1_3.Objects exposing + ( BlindEvent + , ClientEventWithoutRoomId + , JoinedRoom + , LeftRoom + , RoomSummary + , Rooms + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , blindEventDecoder + , clientEventWithoutRoomIdDecoder + , encodeBlindEvent + , encodeClientEventWithoutRoomId + , encodeJoinedRoom + , encodeLeftRoom + , encodeRoomSummary + , encodeRooms + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , joinedRoomDecoder + , leftRoomDecoder + , roomSummaryDecoder + , roomsDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| A blind event that does not give context about itself. +-} +type alias BlindEvent = + { content : E.Value + , contentType : String + } + + +encodeBlindEvent : BlindEvent -> E.Value +encodeBlindEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +blindEventDecoder : D.Decoder BlindEvent +blindEventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : List BlindEvent + , ephemeral : List BlindEvent + , state : List ClientEventWithoutRoomId + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "ephemeral", Just <| E.list encodeBlindEvent data.ephemeral ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map6 + (\a b c d e f -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "ephemeral" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : List BlindEvent + , state : List ClientEventWithoutRoomId + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "timeline" timelineDecoder) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String (List StrippedStateEvent) + , join : Dict String JoinedRoom + , knock : Dict String (List StrippedStateEvent) + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : List BlindEvent + , nextBatch : String + , presence : List BlindEvent + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Just <| E.list encodeBlindEvent data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "next_batch" D.string) + (D.field "presence" (D.list blindEventDecoder)) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_3/Objects.yaml b/src/Internal/Api/Sync/V1_3/Objects.yaml new file mode 100644 index 0000000..d1cfae1 --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/Objects.yaml @@ -0,0 +1,152 @@ +version: v1.3 +name: Objects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: "[BlindEvent]" + required: true + next_batch: + type: string + required: true + presence: + type: "[BlindEvent]" + required: true + rooms: + type: Rooms + BlindEvent: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: "[BlindEvent]" + required: true + ephemeral: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_3/SpecObjects.elm b/src/Internal/Api/Sync/V1_3/SpecObjects.elm new file mode 100644 index 0000000..cc3a1f3 --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/SpecObjects.elm @@ -0,0 +1,603 @@ +module Internal.Api.Sync.V1_3.SpecObjects exposing + ( AccountData + , ClientEventWithoutRoomId + , Ephemeral + , Event + , InviteState + , InvitedRoom + , JoinedRoom + , KnockState + , KnockedRoom + , LeftRoom + , Presence + , RoomSummary + , Rooms + , State + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , accountDataDecoder + , clientEventWithoutRoomIdDecoder + , encodeAccountData + , encodeClientEventWithoutRoomId + , encodeEphemeral + , encodeEvent + , encodeInviteState + , encodeInvitedRoom + , encodeJoinedRoom + , encodeKnockState + , encodeKnockedRoom + , encodeLeftRoom + , encodePresence + , encodeRoomSummary + , encodeRooms + , encodeState + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , ephemeralDecoder + , eventDecoder + , inviteStateDecoder + , invitedRoomDecoder + , joinedRoomDecoder + , knockStateDecoder + , knockedRoomDecoder + , leftRoomDecoder + , presenceDecoder + , roomSummaryDecoder + , roomsDecoder + , stateDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| The private data created by this user in a given context. +-} +type alias AccountData = + { events : List Event + } + + +encodeAccountData : AccountData -> E.Value +encodeAccountData data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +accountDataDecoder : D.Decoder AccountData +accountDataDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Ephemeral events in a room that aren't recorded in the timeline or the room state. +-} +type alias Ephemeral = + { events : List Event + } + + +encodeEphemeral : Ephemeral -> E.Value +encodeEphemeral data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +ephemeralDecoder : D.Decoder Ephemeral +ephemeralDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| A blind event that does not give context about itself. +-} +type alias Event = + { content : E.Value + , contentType : String + } + + +encodeEvent : Event -> E.Value +encodeEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +eventDecoder : D.Decoder Event +eventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Room that the user has been invited to. +-} +type alias InvitedRoom = + { inviteState : Maybe InviteState + } + + +encodeInvitedRoom : InvitedRoom -> E.Value +encodeInvitedRoom data = + maybeObject + [ ( "invite_state", Maybe.map encodeInviteState data.inviteState ) + ] + + +invitedRoomDecoder : D.Decoder InvitedRoom +invitedRoomDecoder = + D.map + (\a -> + { inviteState = a } + ) + (opField "invite_state" inviteStateDecoder) + + +{-| The state of a room that the user has been invited to. +-} +type alias InviteState = + { events : List StrippedStateEvent + } + + +encodeInviteState : InviteState -> E.Value +encodeInviteState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +inviteStateDecoder : D.Decoder InviteState +inviteStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : Maybe AccountData + , ephemeral : Maybe Ephemeral + , state : Maybe State + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "ephemeral", Maybe.map encodeEphemeral data.ephemeral ) + , ( "state", Maybe.map encodeState data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map6 + (\a b c d e f -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f } + ) + (opField "account_data" accountDataDecoder) + (opField "ephemeral" ephemeralDecoder) + (opField "state" stateDecoder) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + + +{-| Room that the user has knocked upon. +-} +type alias KnockedRoom = + { knockState : Maybe KnockState + } + + +encodeKnockedRoom : KnockedRoom -> E.Value +encodeKnockedRoom data = + maybeObject + [ ( "knock_state", Maybe.map encodeKnockState data.knockState ) + ] + + +knockedRoomDecoder : D.Decoder KnockedRoom +knockedRoomDecoder = + D.map + (\a -> + { knockState = a } + ) + (opField "knock_state" knockStateDecoder) + + +{-| The state of a room that the user has knocked upon. +-} +type alias KnockState = + { events : List StrippedStateEvent + } + + +encodeKnockState : KnockState -> E.Value +encodeKnockState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +knockStateDecoder : D.Decoder KnockState +knockStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : Maybe AccountData + , state : Maybe State + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "state", Maybe.map encodeState data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (opField "account_data" accountDataDecoder) + (opField "state" stateDecoder) + (opField "timeline" timelineDecoder) + + +{-| The updates to the presence status of other users. +-} +type alias Presence = + { events : List Event + } + + +encodePresence : Presence -> E.Value +encodePresence data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +presenceDecoder : D.Decoder Presence +presenceDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String InvitedRoom + , join : Dict String JoinedRoom + , knock : Dict String KnockedRoom + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity encodeInvitedRoom data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity encodeKnockedRoom data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict invitedRoomDecoder)) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict knockedRoomDecoder)) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Updates to the state of a room. +-} +type alias State = + { events : List ClientEventWithoutRoomId + } + + +encodeState : State -> E.Value +encodeState data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + ] + + +stateDecoder : D.Decoder State +stateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : Maybe AccountData + , nextBatch : String + , presence : Maybe Presence + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Maybe.map encodePresence data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (opField "account_data" accountDataDecoder) + (D.field "next_batch" D.string) + (opField "presence" presenceDecoder) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_3/SpecObjects.yaml b/src/Internal/Api/Sync/V1_3/SpecObjects.yaml new file mode 100644 index 0000000..cfc6cd7 --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/SpecObjects.yaml @@ -0,0 +1,197 @@ +version: v1.3 +name: SpecObjects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: AccountData + next_batch: + type: string + required: true + presence: + type: Presence + rooms: + type: Rooms + AccountData: + description: The private data created by this user in a given context. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Event: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Presence: + description: The updates to the presence status of other users. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{InvitedRoom}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{KnockedRoom}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + InvitedRoom: + description: Room that the user has been invited to. + fields: + invite_state: + type: InviteState + InviteState: + description: The state of a room that the user has been invited to. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: AccountData + ephemeral: + type: Ephemeral + state: + type: State + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + Ephemeral: + description: Ephemeral events in a room that aren't recorded in the timeline or the room state. + fields: + events: + type: "[Event]" + required: false + default: "[]" + State: + description: Updates to the state of a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + KnockedRoom: + description: Room that the user has knocked upon. + fields: + knock_state: + type: KnockState + KnockState: + description: The state of a room that the user has knocked upon. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: AccountData + state: + type: State + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_3/Upcast.elm b/src/Internal/Api/Sync/V1_3/Upcast.elm new file mode 100644 index 0000000..fb2d23c --- /dev/null +++ b/src/Internal/Api/Sync/V1_3/Upcast.elm @@ -0,0 +1,72 @@ +module Internal.Api.Sync.V1_3.Upcast exposing (..) + +import Dict +import Internal.Api.Sync.V1_2.Objects as PO +import Internal.Api.Sync.V1_3.Objects as O + + +upcast : PO.Sync -> O.Sync +upcast sync = + { accountData = sync.accountData + , nextBatch = sync.nextBatch + , presence = sync.presence + , rooms = Maybe.map upcastRooms sync.rooms + } + + +upcastRooms : PO.Rooms -> O.Rooms +upcastRooms rooms = + { invite = rooms.invite + , join = Dict.map (\_ -> upcastJoinedRoom) rooms.join + , knock = rooms.knock + , leave = Dict.map (\_ -> upcastLeftRoom) rooms.leave + } + + +upcastJoinedRoom : PO.JoinedRoom -> O.JoinedRoom +upcastJoinedRoom room = + { accountData = room.accountData + , ephemeral = room.ephemeral + , state = List.map upcastClientEventWithoutRoomId room.state + , summary = room.summary + , timeline = Maybe.map upcastTimeline room.timeline + , unreadNotifications = room.unreadNotifications + } + + +upcastClientEventWithoutRoomId : PO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +upcastClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map upcastUnsigned event.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map upcastClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +upcastTimeline : PO.Timeline -> O.Timeline +upcastTimeline timeline = + { events = List.map upcastClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +upcastLeftRoom : PO.LeftRoom -> O.LeftRoom +upcastLeftRoom room = + { accountData = room.accountData + , state = List.map upcastClientEventWithoutRoomId room.state + , timeline = Maybe.map upcastTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_4/Api.elm b/src/Internal/Api/Sync/V1_4/Api.elm new file mode 100644 index 0000000..c3335c5 --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.Sync.V1_4.Api exposing (..) + +import Internal.Api.Sync.Api as Api +import Internal.Api.Sync.V1_3.Objects as PO +import Internal.Api.Sync.V1_4.Convert as C +import Internal.Api.Sync.V1_4.Objects as O +import Internal.Api.Sync.V1_4.SpecObjects as SO +import Internal.Api.Sync.V1_4.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SyncInputV1 PO.Sync Api.SyncInputV1 O.Sync +packet = + { version = "v1.4" + , downcast = identity + , current = Api.syncV1 SO.syncDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/Sync/V1_4/Convert.elm b/src/Internal/Api/Sync/V1_4/Convert.elm new file mode 100644 index 0000000..c94066b --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/Convert.elm @@ -0,0 +1,84 @@ +module Internal.Api.Sync.V1_4.Convert exposing (..) + +import Dict +import Internal.Api.Sync.V1_4.Objects as O +import Internal.Api.Sync.V1_4.SpecObjects as SO + + +convert : SO.Sync -> O.Sync +convert sync = + { accountData = convertEventHolder sync.accountData + , nextBatch = sync.nextBatch + , presence = convertEventHolder sync.presence + , rooms = Maybe.map convertRooms sync.rooms + } + + +convertEventHolder : Maybe { a | events : List b } -> List b +convertEventHolder = + Maybe.map .events >> Maybe.withDefault [] + + +convertRooms : SO.Rooms -> O.Rooms +convertRooms rooms = + { invite = + Dict.map + (\_ -> .inviteState >> Maybe.map .events >> Maybe.withDefault []) + rooms.invite + , join = Dict.map (\_ -> convertJoinedRoom) rooms.join + , knock = + Dict.map + (\_ -> .knockState >> Maybe.map .events >> Maybe.withDefault []) + rooms.knock + , leave = Dict.map (\_ -> convertLeftRoom) rooms.leave + } + + +convertJoinedRoom : SO.JoinedRoom -> O.JoinedRoom +convertJoinedRoom room = + { accountData = convertEventHolder room.accountData + , ephemeral = convertEventHolder room.ephemeral + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , summary = room.summary + , timeline = Maybe.map convertTimeline room.timeline + , unreadNotifications = room.unreadNotifications + , unreadThreadNotifications = room.unreadThreadNotifications + } + + +convertClientEventWithoutRoomId : SO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +convertClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map convertUnsigned event.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map convertClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +convertTimeline : SO.Timeline -> O.Timeline +convertTimeline timeline = + { events = List.map convertClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +convertLeftRoom : SO.LeftRoom -> O.LeftRoom +convertLeftRoom room = + { accountData = convertEventHolder room.accountData + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , timeline = Maybe.map convertTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_4/Objects.elm b/src/Internal/Api/Sync/V1_4/Objects.elm new file mode 100644 index 0000000..02cacdd --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/Objects.elm @@ -0,0 +1,398 @@ +module Internal.Api.Sync.V1_4.Objects exposing + ( BlindEvent + , ClientEventWithoutRoomId + , JoinedRoom + , LeftRoom + , RoomSummary + , Rooms + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , blindEventDecoder + , clientEventWithoutRoomIdDecoder + , encodeBlindEvent + , encodeClientEventWithoutRoomId + , encodeJoinedRoom + , encodeLeftRoom + , encodeRoomSummary + , encodeRooms + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , joinedRoomDecoder + , leftRoomDecoder + , roomSummaryDecoder + , roomsDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| A blind event that does not give context about itself. +-} +type alias BlindEvent = + { content : E.Value + , contentType : String + } + + +encodeBlindEvent : BlindEvent -> E.Value +encodeBlindEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +blindEventDecoder : D.Decoder BlindEvent +blindEventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : List BlindEvent + , ephemeral : List BlindEvent + , state : List ClientEventWithoutRoomId + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + , unreadThreadNotifications : Dict String UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "ephemeral", Just <| E.list encodeBlindEvent data.ephemeral ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + , ( "unread_thread_notifications", Just <| E.dict identity encodeUnreadNotificationCounts data.unreadThreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map7 + (\a b c d e f g -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f, unreadThreadNotifications = g } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "ephemeral" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + (D.field "unread_thread_notifications" (D.dict unreadNotificationCountsDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : List BlindEvent + , state : List ClientEventWithoutRoomId + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "timeline" timelineDecoder) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String (List StrippedStateEvent) + , join : Dict String JoinedRoom + , knock : Dict String (List StrippedStateEvent) + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : List BlindEvent + , nextBatch : String + , presence : List BlindEvent + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Just <| E.list encodeBlindEvent data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "next_batch" D.string) + (D.field "presence" (D.list blindEventDecoder)) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_4/Objects.yaml b/src/Internal/Api/Sync/V1_4/Objects.yaml new file mode 100644 index 0000000..91a160f --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/Objects.yaml @@ -0,0 +1,155 @@ +version: v1.4 +name: Objects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: "[BlindEvent]" + required: true + next_batch: + type: string + required: true + presence: + type: "[BlindEvent]" + required: true + rooms: + type: Rooms + BlindEvent: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: "[BlindEvent]" + required: true + ephemeral: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + unread_thread_notifications: + type: "{UnreadNotificationCounts}" + required: true + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_4/SpecObjects.elm b/src/Internal/Api/Sync/V1_4/SpecObjects.elm new file mode 100644 index 0000000..d64896d --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/SpecObjects.elm @@ -0,0 +1,635 @@ +module Internal.Api.Sync.V1_4.SpecObjects exposing + ( AccountData + , ClientEventWithoutRoomId + , Ephemeral + , Event + , InviteState + , InvitedRoom + , JoinedRoom + , KnockState + , KnockedRoom + , LeftRoom + , Presence + , RoomSummary + , Rooms + , State + , StrippedStateEvent + , Sync + , ThreadNotificationCounts + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , accountDataDecoder + , clientEventWithoutRoomIdDecoder + , encodeAccountData + , encodeClientEventWithoutRoomId + , encodeEphemeral + , encodeEvent + , encodeInviteState + , encodeInvitedRoom + , encodeJoinedRoom + , encodeKnockState + , encodeKnockedRoom + , encodeLeftRoom + , encodePresence + , encodeRoomSummary + , encodeRooms + , encodeState + , encodeStrippedStateEvent + , encodeSync + , encodeThreadNotificationCounts + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , ephemeralDecoder + , eventDecoder + , inviteStateDecoder + , invitedRoomDecoder + , joinedRoomDecoder + , knockStateDecoder + , knockedRoomDecoder + , leftRoomDecoder + , presenceDecoder + , roomSummaryDecoder + , roomsDecoder + , stateDecoder + , strippedStateEventDecoder + , syncDecoder + , threadNotificationCountsDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| The private data created by this user in a given context. +-} +type alias AccountData = + { events : List Event + } + + +encodeAccountData : AccountData -> E.Value +encodeAccountData data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +accountDataDecoder : D.Decoder AccountData +accountDataDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Ephemeral events in a room that aren't recorded in the timeline or the room state. +-} +type alias Ephemeral = + { events : List Event + } + + +encodeEphemeral : Ephemeral -> E.Value +encodeEphemeral data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +ephemeralDecoder : D.Decoder Ephemeral +ephemeralDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| A blind event that does not give context about itself. +-} +type alias Event = + { content : E.Value + , contentType : String + } + + +encodeEvent : Event -> E.Value +encodeEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +eventDecoder : D.Decoder Event +eventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Room that the user has been invited to. +-} +type alias InvitedRoom = + { inviteState : Maybe InviteState + } + + +encodeInvitedRoom : InvitedRoom -> E.Value +encodeInvitedRoom data = + maybeObject + [ ( "invite_state", Maybe.map encodeInviteState data.inviteState ) + ] + + +invitedRoomDecoder : D.Decoder InvitedRoom +invitedRoomDecoder = + D.map + (\a -> + { inviteState = a } + ) + (opField "invite_state" inviteStateDecoder) + + +{-| The state of a room that the user has been invited to. +-} +type alias InviteState = + { events : List StrippedStateEvent + } + + +encodeInviteState : InviteState -> E.Value +encodeInviteState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +inviteStateDecoder : D.Decoder InviteState +inviteStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : Maybe AccountData + , ephemeral : Maybe Ephemeral + , state : Maybe State + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + , unreadThreadNotifications : Dict String ThreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "ephemeral", Maybe.map encodeEphemeral data.ephemeral ) + , ( "state", Maybe.map encodeState data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + , ( "unread_thread_notifications", Just <| E.dict identity encodeThreadNotificationCounts data.unreadThreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map7 + (\a b c d e f g -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f, unreadThreadNotifications = g } + ) + (opField "account_data" accountDataDecoder) + (opField "ephemeral" ephemeralDecoder) + (opField "state" stateDecoder) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + (opFieldWithDefault "unread_thread_notifications" Dict.empty (D.dict threadNotificationCountsDecoder)) + + +{-| Room that the user has knocked upon. +-} +type alias KnockedRoom = + { knockState : Maybe KnockState + } + + +encodeKnockedRoom : KnockedRoom -> E.Value +encodeKnockedRoom data = + maybeObject + [ ( "knock_state", Maybe.map encodeKnockState data.knockState ) + ] + + +knockedRoomDecoder : D.Decoder KnockedRoom +knockedRoomDecoder = + D.map + (\a -> + { knockState = a } + ) + (opField "knock_state" knockStateDecoder) + + +{-| The state of a room that the user has knocked upon. +-} +type alias KnockState = + { events : List StrippedStateEvent + } + + +encodeKnockState : KnockState -> E.Value +encodeKnockState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +knockStateDecoder : D.Decoder KnockState +knockStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : Maybe AccountData + , state : Maybe State + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "state", Maybe.map encodeState data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (opField "account_data" accountDataDecoder) + (opField "state" stateDecoder) + (opField "timeline" timelineDecoder) + + +{-| The updates to the presence status of other users. +-} +type alias Presence = + { events : List Event + } + + +encodePresence : Presence -> E.Value +encodePresence data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +presenceDecoder : D.Decoder Presence +presenceDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String InvitedRoom + , join : Dict String JoinedRoom + , knock : Dict String KnockedRoom + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity encodeInvitedRoom data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity encodeKnockedRoom data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict invitedRoomDecoder)) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict knockedRoomDecoder)) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Updates to the state of a room. +-} +type alias State = + { events : List ClientEventWithoutRoomId + } + + +encodeState : State -> E.Value +encodeState data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + ] + + +stateDecoder : D.Decoder State +stateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : Maybe AccountData + , nextBatch : String + , presence : Maybe Presence + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Maybe.map encodePresence data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (opField "account_data" accountDataDecoder) + (D.field "next_batch" D.string) + (opField "presence" presenceDecoder) + (opField "rooms" roomsDecoder) + + +{-| Counts of unread notifications for a given thread. +-} +type alias ThreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeThreadNotificationCounts : ThreadNotificationCounts -> E.Value +encodeThreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +threadNotificationCountsDecoder : D.Decoder ThreadNotificationCounts +threadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_4/SpecObjects.yaml b/src/Internal/Api/Sync/V1_4/SpecObjects.yaml new file mode 100644 index 0000000..88c567e --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/SpecObjects.yaml @@ -0,0 +1,208 @@ +version: v1.4 +name: SpecObjects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: AccountData + next_batch: + type: string + required: true + presence: + type: Presence + rooms: + type: Rooms + AccountData: + description: The private data created by this user in a given context. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Event: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Presence: + description: The updates to the presence status of other users. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{InvitedRoom}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{KnockedRoom}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + InvitedRoom: + description: Room that the user has been invited to. + fields: + invite_state: + type: InviteState + InviteState: + description: The state of a room that the user has been invited to. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: AccountData + ephemeral: + type: Ephemeral + state: + type: State + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + unread_thread_notifications: + type: "{ThreadNotificationCounts}" + required: false + default: Dict.empty + Ephemeral: + description: Ephemeral events in a room that aren't recorded in the timeline or the room state. + fields: + events: + type: "[Event]" + required: false + default: "[]" + State: + description: Updates to the state of a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + ThreadNotificationCounts: + description: Counts of unread notifications for a given thread. + fields: + highlight_count: + type: int + notification_count: + type: int + KnockedRoom: + description: Room that the user has knocked upon. + fields: + knock_state: + type: KnockState + KnockState: + description: The state of a room that the user has knocked upon. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: AccountData + state: + type: State + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_4/Upcast.elm b/src/Internal/Api/Sync/V1_4/Upcast.elm new file mode 100644 index 0000000..82b29cb --- /dev/null +++ b/src/Internal/Api/Sync/V1_4/Upcast.elm @@ -0,0 +1,73 @@ +module Internal.Api.Sync.V1_4.Upcast exposing (..) + +import Dict +import Internal.Api.Sync.V1_3.Objects as PO +import Internal.Api.Sync.V1_4.Objects as O + + +upcast : PO.Sync -> O.Sync +upcast sync = + { accountData = sync.accountData + , nextBatch = sync.nextBatch + , presence = sync.presence + , rooms = Maybe.map upcastRooms sync.rooms + } + + +upcastRooms : PO.Rooms -> O.Rooms +upcastRooms rooms = + { invite = rooms.invite + , join = Dict.map (\_ -> upcastJoinedRoom) rooms.join + , knock = rooms.knock + , leave = Dict.map (\_ -> upcastLeftRoom) rooms.leave + } + + +upcastJoinedRoom : PO.JoinedRoom -> O.JoinedRoom +upcastJoinedRoom room = + { accountData = room.accountData + , ephemeral = room.ephemeral + , state = List.map upcastClientEventWithoutRoomId room.state + , summary = room.summary + , timeline = Maybe.map upcastTimeline room.timeline + , unreadNotifications = room.unreadNotifications + , unreadThreadNotifications = Dict.empty + } + + +upcastClientEventWithoutRoomId : PO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +upcastClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map upcastUnsigned event.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map upcastClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +upcastTimeline : PO.Timeline -> O.Timeline +upcastTimeline timeline = + { events = List.map upcastClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +upcastLeftRoom : PO.LeftRoom -> O.LeftRoom +upcastLeftRoom room = + { accountData = room.accountData + , state = List.map upcastClientEventWithoutRoomId room.state + , timeline = Maybe.map upcastTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_5/Api.elm b/src/Internal/Api/Sync/V1_5/Api.elm new file mode 100644 index 0000000..7cdb83b --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/Api.elm @@ -0,0 +1,18 @@ +module Internal.Api.Sync.V1_5.Api exposing (..) + +import Internal.Api.Sync.Api as Api +import Internal.Api.Sync.V1_4.Objects as PO +import Internal.Api.Sync.V1_5.Convert as C +import Internal.Api.Sync.V1_5.Objects as O +import Internal.Api.Sync.V1_5.SpecObjects as SO +import Internal.Api.Sync.V1_5.Upcast as U +import Internal.Api.VersionControl as V + + +packet : V.SingleVersion Api.SyncInputV1 PO.Sync Api.SyncInputV1 O.Sync +packet = + { version = "v1.5" + , downcast = identity + , current = Api.syncV1 SO.syncDecoder C.convert + , upcast = U.upcast + } diff --git a/src/Internal/Api/Sync/V1_5/Convert.elm b/src/Internal/Api/Sync/V1_5/Convert.elm new file mode 100644 index 0000000..bb35320 --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/Convert.elm @@ -0,0 +1,84 @@ +module Internal.Api.Sync.V1_5.Convert exposing (..) + +import Dict +import Internal.Api.Sync.V1_5.Objects as O +import Internal.Api.Sync.V1_5.SpecObjects as SO + + +convert : SO.Sync -> O.Sync +convert sync = + { accountData = convertEventHolder sync.accountData + , nextBatch = sync.nextBatch + , presence = convertEventHolder sync.presence + , rooms = Maybe.map convertRooms sync.rooms + } + + +convertEventHolder : Maybe { a | events : List b } -> List b +convertEventHolder = + Maybe.map .events >> Maybe.withDefault [] + + +convertRooms : SO.Rooms -> O.Rooms +convertRooms rooms = + { invite = + Dict.map + (\_ -> .inviteState >> Maybe.map .events >> Maybe.withDefault []) + rooms.invite + , join = Dict.map (\_ -> convertJoinedRoom) rooms.join + , knock = + Dict.map + (\_ -> .knockState >> Maybe.map .events >> Maybe.withDefault []) + rooms.knock + , leave = Dict.map (\_ -> convertLeftRoom) rooms.leave + } + + +convertJoinedRoom : SO.JoinedRoom -> O.JoinedRoom +convertJoinedRoom room = + { accountData = convertEventHolder room.accountData + , ephemeral = convertEventHolder room.ephemeral + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , summary = room.summary + , timeline = Maybe.map convertTimeline room.timeline + , unreadNotifications = room.unreadNotifications + , unreadThreadNotifications = room.unreadThreadNotifications + } + + +convertClientEventWithoutRoomId : SO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +convertClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map convertUnsigned event.unsigned + } + + +convertUnsigned : SO.UnsignedData -> O.UnsignedData +convertUnsigned (SO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map convertClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +convertTimeline : SO.Timeline -> O.Timeline +convertTimeline timeline = + { events = List.map convertClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +convertLeftRoom : SO.LeftRoom -> O.LeftRoom +convertLeftRoom room = + { accountData = convertEventHolder room.accountData + , state = convertEventHolder room.state |> List.map convertClientEventWithoutRoomId + , timeline = Maybe.map convertTimeline room.timeline + } diff --git a/src/Internal/Api/Sync/V1_5/Objects.elm b/src/Internal/Api/Sync/V1_5/Objects.elm new file mode 100644 index 0000000..18f6304 --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/Objects.elm @@ -0,0 +1,398 @@ +module Internal.Api.Sync.V1_5.Objects exposing + ( BlindEvent + , ClientEventWithoutRoomId + , JoinedRoom + , LeftRoom + , RoomSummary + , Rooms + , StrippedStateEvent + , Sync + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , blindEventDecoder + , clientEventWithoutRoomIdDecoder + , encodeBlindEvent + , encodeClientEventWithoutRoomId + , encodeJoinedRoom + , encodeLeftRoom + , encodeRoomSummary + , encodeRooms + , encodeStrippedStateEvent + , encodeSync + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , joinedRoomDecoder + , leftRoomDecoder + , roomSummaryDecoder + , roomsDecoder + , strippedStateEventDecoder + , syncDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'Objects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| A blind event that does not give context about itself. +-} +type alias BlindEvent = + { content : E.Value + , contentType : String + } + + +encodeBlindEvent : BlindEvent -> E.Value +encodeBlindEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +blindEventDecoder : D.Decoder BlindEvent +blindEventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : List BlindEvent + , ephemeral : List BlindEvent + , state : List ClientEventWithoutRoomId + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + , unreadThreadNotifications : Dict String UnreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "ephemeral", Just <| E.list encodeBlindEvent data.ephemeral ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + , ( "unread_thread_notifications", Just <| E.dict identity encodeUnreadNotificationCounts data.unreadThreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map7 + (\a b c d e f g -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f, unreadThreadNotifications = g } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "ephemeral" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + (D.field "unread_thread_notifications" (D.dict unreadNotificationCountsDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : List BlindEvent + , state : List ClientEventWithoutRoomId + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "state", Just <| E.list encodeClientEventWithoutRoomId data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "state" (D.list clientEventWithoutRoomIdDecoder)) + (opField "timeline" timelineDecoder) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String (List StrippedStateEvent) + , join : Dict String JoinedRoom + , knock : Dict String (List StrippedStateEvent) + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity (E.list encodeStrippedStateEvent) data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict (D.list strippedStateEventDecoder))) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : List BlindEvent + , nextBatch : String + , presence : List BlindEvent + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Just <| E.list encodeBlindEvent data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Just <| E.list encodeBlindEvent data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (D.field "account_data" (D.list blindEventDecoder)) + (D.field "next_batch" D.string) + (D.field "presence" (D.list blindEventDecoder)) + (opField "rooms" roomsDecoder) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_5/Objects.yaml b/src/Internal/Api/Sync/V1_5/Objects.yaml new file mode 100644 index 0000000..4ccd041 --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/Objects.yaml @@ -0,0 +1,155 @@ +version: v1.5 +name: Objects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: "[BlindEvent]" + required: true + next_batch: + type: string + required: true + presence: + type: "[BlindEvent]" + required: true + rooms: + type: Rooms + BlindEvent: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{[StrippedStateEvent]}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: "[BlindEvent]" + required: true + ephemeral: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + unread_thread_notifications: + type: "{UnreadNotificationCounts}" + required: true + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: "[BlindEvent]" + required: true + state: + type: "[ClientEventWithoutRoomId]" + required: true + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_5/SpecObjects.elm b/src/Internal/Api/Sync/V1_5/SpecObjects.elm new file mode 100644 index 0000000..b32df81 --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/SpecObjects.elm @@ -0,0 +1,635 @@ +module Internal.Api.Sync.V1_5.SpecObjects exposing + ( AccountData + , ClientEventWithoutRoomId + , Ephemeral + , Event + , InviteState + , InvitedRoom + , JoinedRoom + , KnockState + , KnockedRoom + , LeftRoom + , Presence + , RoomSummary + , Rooms + , State + , StrippedStateEvent + , Sync + , ThreadNotificationCounts + , Timeline + , UnreadNotificationCounts + , UnsignedData(..) + , accountDataDecoder + , clientEventWithoutRoomIdDecoder + , encodeAccountData + , encodeClientEventWithoutRoomId + , encodeEphemeral + , encodeEvent + , encodeInviteState + , encodeInvitedRoom + , encodeJoinedRoom + , encodeKnockState + , encodeKnockedRoom + , encodeLeftRoom + , encodePresence + , encodeRoomSummary + , encodeRooms + , encodeState + , encodeStrippedStateEvent + , encodeSync + , encodeThreadNotificationCounts + , encodeTimeline + , encodeUnreadNotificationCounts + , encodeUnsignedData + , ephemeralDecoder + , eventDecoder + , inviteStateDecoder + , invitedRoomDecoder + , joinedRoomDecoder + , knockStateDecoder + , knockedRoomDecoder + , leftRoomDecoder + , presenceDecoder + , roomSummaryDecoder + , roomsDecoder + , stateDecoder + , strippedStateEventDecoder + , syncDecoder + , threadNotificationCountsDecoder + , timelineDecoder + , unreadNotificationCountsDecoder + , unsignedDataDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Internal.Tools.Timestamp exposing (Timestamp, encodeTimestamp, timestampDecoder) +import Json.Decode as D +import Json.Encode as E + + +{-| The private data created by this user in a given context. +-} +type alias AccountData = + { events : List Event + } + + +encodeAccountData : AccountData -> E.Value +encodeAccountData data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +accountDataDecoder : D.Decoder AccountData +accountDataDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Client event that has all data except the room id. +-} +type alias ClientEventWithoutRoomId = + { content : E.Value + , eventId : String + , originServerTs : Timestamp + , sender : String + , stateKey : Maybe String + , contentType : String + , unsigned : Maybe UnsignedData + } + + +encodeClientEventWithoutRoomId : ClientEventWithoutRoomId -> E.Value +encodeClientEventWithoutRoomId data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "event_id", Just <| E.string data.eventId ) + , ( "origin_server_ts", Just <| encodeTimestamp data.originServerTs ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Maybe.map E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + , ( "unsigned", Maybe.map encodeUnsignedData data.unsigned ) + ] + + +clientEventWithoutRoomIdDecoder : D.Decoder ClientEventWithoutRoomId +clientEventWithoutRoomIdDecoder = + D.map7 + (\a b c d e f g -> + { content = a, eventId = b, originServerTs = c, sender = d, stateKey = e, contentType = f, unsigned = g } + ) + (D.field "content" D.value) + (D.field "event_id" D.string) + (D.field "origin_server_ts" timestampDecoder) + (D.field "sender" D.string) + (opField "state_key" D.string) + (D.field "type" D.string) + (opField "unsigned" (D.lazy (\_ -> unsignedDataDecoder))) + + +{-| Ephemeral events in a room that aren't recorded in the timeline or the room state. +-} +type alias Ephemeral = + { events : List Event + } + + +encodeEphemeral : Ephemeral -> E.Value +encodeEphemeral data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +ephemeralDecoder : D.Decoder Ephemeral +ephemeralDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| A blind event that does not give context about itself. +-} +type alias Event = + { content : E.Value + , contentType : String + } + + +encodeEvent : Event -> E.Value +encodeEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "type", Just <| E.string data.contentType ) + ] + + +eventDecoder : D.Decoder Event +eventDecoder = + D.map2 + (\a b -> + { content = a, contentType = b } + ) + (D.field "content" D.value) + (D.field "type" D.string) + + +{-| Room that the user has been invited to. +-} +type alias InvitedRoom = + { inviteState : Maybe InviteState + } + + +encodeInvitedRoom : InvitedRoom -> E.Value +encodeInvitedRoom data = + maybeObject + [ ( "invite_state", Maybe.map encodeInviteState data.inviteState ) + ] + + +invitedRoomDecoder : D.Decoder InvitedRoom +invitedRoomDecoder = + D.map + (\a -> + { inviteState = a } + ) + (opField "invite_state" inviteStateDecoder) + + +{-| The state of a room that the user has been invited to. +-} +type alias InviteState = + { events : List StrippedStateEvent + } + + +encodeInviteState : InviteState -> E.Value +encodeInviteState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +inviteStateDecoder : D.Decoder InviteState +inviteStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has joined. +-} +type alias JoinedRoom = + { accountData : Maybe AccountData + , ephemeral : Maybe Ephemeral + , state : Maybe State + , summary : Maybe RoomSummary + , timeline : Maybe Timeline + , unreadNotifications : Maybe UnreadNotificationCounts + , unreadThreadNotifications : Dict String ThreadNotificationCounts + } + + +encodeJoinedRoom : JoinedRoom -> E.Value +encodeJoinedRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "ephemeral", Maybe.map encodeEphemeral data.ephemeral ) + , ( "state", Maybe.map encodeState data.state ) + , ( "summary", Maybe.map encodeRoomSummary data.summary ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + , ( "unread_notifications", Maybe.map encodeUnreadNotificationCounts data.unreadNotifications ) + , ( "unread_thread_notifications", Just <| E.dict identity encodeThreadNotificationCounts data.unreadThreadNotifications ) + ] + + +joinedRoomDecoder : D.Decoder JoinedRoom +joinedRoomDecoder = + D.map7 + (\a b c d e f g -> + { accountData = a, ephemeral = b, state = c, summary = d, timeline = e, unreadNotifications = f, unreadThreadNotifications = g } + ) + (opField "account_data" accountDataDecoder) + (opField "ephemeral" ephemeralDecoder) + (opField "state" stateDecoder) + (opField "summary" roomSummaryDecoder) + (opField "timeline" timelineDecoder) + (opField "unread_notifications" unreadNotificationCountsDecoder) + (opFieldWithDefault "unread_thread_notifications" Dict.empty (D.dict threadNotificationCountsDecoder)) + + +{-| Room that the user has knocked upon. +-} +type alias KnockedRoom = + { knockState : Maybe KnockState + } + + +encodeKnockedRoom : KnockedRoom -> E.Value +encodeKnockedRoom data = + maybeObject + [ ( "knock_state", Maybe.map encodeKnockState data.knockState ) + ] + + +knockedRoomDecoder : D.Decoder KnockedRoom +knockedRoomDecoder = + D.map + (\a -> + { knockState = a } + ) + (opField "knock_state" knockStateDecoder) + + +{-| The state of a room that the user has knocked upon. +-} +type alias KnockState = + { events : List StrippedStateEvent + } + + +encodeKnockState : KnockState -> E.Value +encodeKnockState data = + maybeObject + [ ( "events", Just <| E.list encodeStrippedStateEvent data.events ) + ] + + +knockStateDecoder : D.Decoder KnockState +knockStateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list strippedStateEventDecoder)) + + +{-| Room that the user has left. +-} +type alias LeftRoom = + { accountData : Maybe AccountData + , state : Maybe State + , timeline : Maybe Timeline + } + + +encodeLeftRoom : LeftRoom -> E.Value +encodeLeftRoom data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "state", Maybe.map encodeState data.state ) + , ( "timeline", Maybe.map encodeTimeline data.timeline ) + ] + + +leftRoomDecoder : D.Decoder LeftRoom +leftRoomDecoder = + D.map3 + (\a b c -> + { accountData = a, state = b, timeline = c } + ) + (opField "account_data" accountDataDecoder) + (opField "state" stateDecoder) + (opField "timeline" timelineDecoder) + + +{-| The updates to the presence status of other users. +-} +type alias Presence = + { events : List Event + } + + +encodePresence : Presence -> E.Value +encodePresence data = + maybeObject + [ ( "events", Just <| E.list encodeEvent data.events ) + ] + + +presenceDecoder : D.Decoder Presence +presenceDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list eventDecoder)) + + +{-| Updates to rooms. +-} +type alias Rooms = + { invite : Dict String InvitedRoom + , join : Dict String JoinedRoom + , knock : Dict String KnockedRoom + , leave : Dict String LeftRoom + } + + +encodeRooms : Rooms -> E.Value +encodeRooms data = + maybeObject + [ ( "invite", Just <| E.dict identity encodeInvitedRoom data.invite ) + , ( "join", Just <| E.dict identity encodeJoinedRoom data.join ) + , ( "knock", Just <| E.dict identity encodeKnockedRoom data.knock ) + , ( "leave", Just <| E.dict identity encodeLeftRoom data.leave ) + ] + + +roomsDecoder : D.Decoder Rooms +roomsDecoder = + D.map4 + (\a b c d -> + { invite = a, join = b, knock = c, leave = d } + ) + (opFieldWithDefault "invite" Dict.empty (D.dict invitedRoomDecoder)) + (opFieldWithDefault "join" Dict.empty (D.dict joinedRoomDecoder)) + (opFieldWithDefault "knock" Dict.empty (D.dict knockedRoomDecoder)) + (opFieldWithDefault "leave" Dict.empty (D.dict leftRoomDecoder)) + + +{-| Information about a room which clients may need to correctly render it to users. +-} +type alias RoomSummary = + { mHeroes : Maybe (List String) + , mInvitedMemberCount : Maybe Int + , mJoinedMemberCount : Maybe Int + } + + +encodeRoomSummary : RoomSummary -> E.Value +encodeRoomSummary data = + maybeObject + [ ( "m.heroes", Maybe.map (E.list E.string) data.mHeroes ) + , ( "m.invited_member_count", Maybe.map E.int data.mInvitedMemberCount ) + , ( "m.joined_member_count", Maybe.map E.int data.mJoinedMemberCount ) + ] + + +roomSummaryDecoder : D.Decoder RoomSummary +roomSummaryDecoder = + D.map3 + (\a b c -> + { mHeroes = a, mInvitedMemberCount = b, mJoinedMemberCount = c } + ) + (opField "m.heroes" (D.list D.string)) + (opField "m.invited_member_count" D.int) + (opField "m.joined_member_count" D.int) + + +{-| Updates to the state of a room. +-} +type alias State = + { events : List ClientEventWithoutRoomId + } + + +encodeState : State -> E.Value +encodeState data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + ] + + +stateDecoder : D.Decoder State +stateDecoder = + D.map + (\a -> + { events = a } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + + +{-| Stripped state events of a room that the user has limited access to. +-} +type alias StrippedStateEvent = + { content : E.Value + , sender : String + , stateKey : String + , contentType : String + } + + +encodeStrippedStateEvent : StrippedStateEvent -> E.Value +encodeStrippedStateEvent data = + maybeObject + [ ( "content", Just <| data.content ) + , ( "sender", Just <| E.string data.sender ) + , ( "state_key", Just <| E.string data.stateKey ) + , ( "type", Just <| E.string data.contentType ) + ] + + +strippedStateEventDecoder : D.Decoder StrippedStateEvent +strippedStateEventDecoder = + D.map4 + (\a b c d -> + { content = a, sender = b, stateKey = c, contentType = d } + ) + (D.field "content" D.value) + (D.field "sender" D.string) + (D.field "state_key" D.string) + (D.field "type" D.string) + + +{-| The sync response the homeserver sends to the user. +-} +type alias Sync = + { accountData : Maybe AccountData + , nextBatch : String + , presence : Maybe Presence + , rooms : Maybe Rooms + } + + +encodeSync : Sync -> E.Value +encodeSync data = + maybeObject + [ ( "account_data", Maybe.map encodeAccountData data.accountData ) + , ( "next_batch", Just <| E.string data.nextBatch ) + , ( "presence", Maybe.map encodePresence data.presence ) + , ( "rooms", Maybe.map encodeRooms data.rooms ) + ] + + +syncDecoder : D.Decoder Sync +syncDecoder = + D.map4 + (\a b c d -> + { accountData = a, nextBatch = b, presence = c, rooms = d } + ) + (opField "account_data" accountDataDecoder) + (D.field "next_batch" D.string) + (opField "presence" presenceDecoder) + (opField "rooms" roomsDecoder) + + +{-| Counts of unread notifications for a given thread. +-} +type alias ThreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeThreadNotificationCounts : ThreadNotificationCounts -> E.Value +encodeThreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +threadNotificationCountsDecoder : D.Decoder ThreadNotificationCounts +threadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| The timeline of messages and state changes in a room. +-} +type alias Timeline = + { events : List ClientEventWithoutRoomId + , limited : Bool + , prevBatch : Maybe String + } + + +encodeTimeline : Timeline -> E.Value +encodeTimeline data = + maybeObject + [ ( "events", Just <| E.list encodeClientEventWithoutRoomId data.events ) + , ( "limited", Just <| E.bool data.limited ) + , ( "prev_batch", Maybe.map E.string data.prevBatch ) + ] + + +timelineDecoder : D.Decoder Timeline +timelineDecoder = + D.map3 + (\a b c -> + { events = a, limited = b, prevBatch = c } + ) + (opFieldWithDefault "events" [] (D.list clientEventWithoutRoomIdDecoder)) + (opFieldWithDefault "limited" False D.bool) + (opField "prev_batch" D.string) + + +{-| Counts of unread notifications for this room. +-} +type alias UnreadNotificationCounts = + { highlightCount : Maybe Int + , notificationCount : Maybe Int + } + + +encodeUnreadNotificationCounts : UnreadNotificationCounts -> E.Value +encodeUnreadNotificationCounts data = + maybeObject + [ ( "highlight_count", Maybe.map E.int data.highlightCount ) + , ( "notification_count", Maybe.map E.int data.notificationCount ) + ] + + +unreadNotificationCountsDecoder : D.Decoder UnreadNotificationCounts +unreadNotificationCountsDecoder = + D.map2 + (\a b -> + { highlightCount = a, notificationCount = b } + ) + (opField "highlight_count" D.int) + (opField "notification_count" D.int) + + +{-| Data that isn't getting signed for Canonical JSON. +-} +type UnsignedData + = UnsignedData + { age : Maybe Int + , prevContent : Maybe E.Value + , redactedBecause : Maybe ClientEventWithoutRoomId + , transactionId : Maybe String + } + + +encodeUnsignedData : UnsignedData -> E.Value +encodeUnsignedData (UnsignedData data) = + maybeObject + [ ( "age", Maybe.map E.int data.age ) + , ( "prev_content", data.prevContent ) + , ( "redacted_because", Maybe.map encodeClientEventWithoutRoomId data.redactedBecause ) + , ( "transaction_id", Maybe.map E.string data.transactionId ) + ] + + +unsignedDataDecoder : D.Decoder UnsignedData +unsignedDataDecoder = + D.map4 + (\a b c d -> + UnsignedData { age = a, prevContent = b, redactedBecause = c, transactionId = d } + ) + (opField "age" D.int) + (opField "prev_content" D.value) + (opField "redacted_because" clientEventWithoutRoomIdDecoder) + (opField "transaction_id" D.string) diff --git a/src/Internal/Api/Sync/V1_5/SpecObjects.yaml b/src/Internal/Api/Sync/V1_5/SpecObjects.yaml new file mode 100644 index 0000000..2c067b8 --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/SpecObjects.yaml @@ -0,0 +1,208 @@ +version: v1.5 +name: SpecObjects +objects: + Sync: + description: The sync response the homeserver sends to the user. + fields: + account_data: + type: AccountData + next_batch: + type: string + required: true + presence: + type: Presence + rooms: + type: Rooms + AccountData: + description: The private data created by this user in a given context. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Event: + description: A blind event that does not give context about itself. + fields: + content: + type: value + required: true + type: + type: string + required: true + Presence: + description: The updates to the presence status of other users. + fields: + events: + type: "[Event]" + required: false + default: "[]" + Rooms: + description: Updates to rooms. + fields: + invite: + type: "{InvitedRoom}" + required: false + default: Dict.empty + join: + type: "{JoinedRoom}" + required: false + default: Dict.empty + knock: + type: "{KnockedRoom}" + required: false + default: Dict.empty + leave: + type: "{LeftRoom}" + required: false + default: Dict.empty + InvitedRoom: + description: Room that the user has been invited to. + fields: + invite_state: + type: InviteState + InviteState: + description: The state of a room that the user has been invited to. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + StrippedStateEvent: + description: Stripped state events of a room that the user has limited access to. + fields: + content: + type: value + required: true + sender: + type: string + required: true + state_key: + type: string + required: true + type: + type: string + required: true + JoinedRoom: + description: Room that the user has joined. + fields: + account_data: + type: AccountData + ephemeral: + type: Ephemeral + state: + type: State + summary: + type: RoomSummary + timeline: + type: Timeline + unread_notifications: + type: UnreadNotificationCounts + unread_thread_notifications: + type: "{ThreadNotificationCounts}" + required: false + default: Dict.empty + Ephemeral: + description: Ephemeral events in a room that aren't recorded in the timeline or the room state. + fields: + events: + type: "[Event]" + required: false + default: "[]" + State: + description: Updates to the state of a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + ClientEventWithoutRoomId: + description: Client event that has all data except the room id. + fields: + content: + type: value + required: true + event_id: + type: string + required: true + origin_server_ts: + type: timestamp + required: true + sender: + type: string + required: true + state_key: + type: string + type: + type: string + required: true + unsigned: + type: UnsignedData + UnsignedData: + anti_recursion: true + description: Data that isn't getting signed for Canonical JSON. + fields: + age: + type: int + prev_content: + type: value + redacted_because: + type: ClientEventWithoutRoomId + transaction_id: + type: string + RoomSummary: + description: Information about a room which clients may need to correctly render it to users. + fields: + m.heroes: + type: "[string]" + m.invited_member_count: + type: int + m.joined_member_count: + type: int + Timeline: + description: The timeline of messages and state changes in a room. + fields: + events: + type: "[ClientEventWithoutRoomId]" + required: false + default: "[]" + limited: + type: bool + required: false + default: "False" + prev_batch: + type: string + UnreadNotificationCounts: + description: Counts of unread notifications for this room. + fields: + highlight_count: + type: int + notification_count: + type: int + ThreadNotificationCounts: + description: Counts of unread notifications for a given thread. + fields: + highlight_count: + type: int + notification_count: + type: int + KnockedRoom: + description: Room that the user has knocked upon. + fields: + knock_state: + type: KnockState + KnockState: + description: The state of a room that the user has knocked upon. + fields: + events: + type: "[StrippedStateEvent]" + required: false + default: "[]" + LeftRoom: + description: Room that the user has left. + fields: + account_data: + type: AccountData + state: + type: State + timeline: + type: Timeline diff --git a/src/Internal/Api/Sync/V1_5/Upcast.elm b/src/Internal/Api/Sync/V1_5/Upcast.elm new file mode 100644 index 0000000..78297ed --- /dev/null +++ b/src/Internal/Api/Sync/V1_5/Upcast.elm @@ -0,0 +1,73 @@ +module Internal.Api.Sync.V1_5.Upcast exposing (..) + +import Dict +import Internal.Api.Sync.V1_4.Objects as PO +import Internal.Api.Sync.V1_5.Objects as O + + +upcast : PO.Sync -> O.Sync +upcast sync = + { accountData = sync.accountData + , nextBatch = sync.nextBatch + , presence = sync.presence + , rooms = Maybe.map upcastRooms sync.rooms + } + + +upcastRooms : PO.Rooms -> O.Rooms +upcastRooms rooms = + { invite = rooms.invite + , join = Dict.map (\_ -> upcastJoinedRoom) rooms.join + , knock = rooms.knock + , leave = Dict.map (\_ -> upcastLeftRoom) rooms.leave + } + + +upcastJoinedRoom : PO.JoinedRoom -> O.JoinedRoom +upcastJoinedRoom room = + { accountData = room.accountData + , ephemeral = room.ephemeral + , state = List.map upcastClientEventWithoutRoomId room.state + , summary = room.summary + , timeline = Maybe.map upcastTimeline room.timeline + , unreadNotifications = room.unreadNotifications + , unreadThreadNotifications = room.unreadThreadNotifications + } + + +upcastClientEventWithoutRoomId : PO.ClientEventWithoutRoomId -> O.ClientEventWithoutRoomId +upcastClientEventWithoutRoomId event = + { content = event.content + , eventId = event.eventId + , originServerTs = event.originServerTs + , sender = event.sender + , stateKey = event.stateKey + , contentType = event.contentType + , unsigned = Maybe.map upcastUnsigned event.unsigned + } + + +upcastUnsigned : PO.UnsignedData -> O.UnsignedData +upcastUnsigned (PO.UnsignedData data) = + O.UnsignedData + { age = data.age + , prevContent = data.prevContent + , redactedBecause = Maybe.map upcastClientEventWithoutRoomId data.redactedBecause + , transactionId = data.transactionId + } + + +upcastTimeline : PO.Timeline -> O.Timeline +upcastTimeline timeline = + { events = List.map upcastClientEventWithoutRoomId timeline.events + , limited = timeline.limited + , prevBatch = timeline.prevBatch + } + + +upcastLeftRoom : PO.LeftRoom -> O.LeftRoom +upcastLeftRoom room = + { accountData = room.accountData + , state = List.map upcastClientEventWithoutRoomId room.state + , timeline = Maybe.map upcastTimeline room.timeline + } diff --git a/src/Internal/Api/VersionControl.elm b/src/Internal/Api/VersionControl.elm new file mode 100644 index 0000000..e074f55 --- /dev/null +++ b/src/Internal/Api/VersionControl.elm @@ -0,0 +1,61 @@ +module Internal.Api.VersionControl exposing (..) + +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +type alias FinalPackage vin vout = + { supportedVersions : List String + , getEvent : String -> vin -> Task X.Error vout + } + + +type alias SingleVersion pIn pOut cIn cOut = + { version : String + , downcast : cIn -> pIn + , current : cIn -> Task X.Error cOut + , upcast : pOut -> cOut + } + + +firstVersion : SingleVersion () () vin vout -> FinalPackage vin vout +firstVersion packet = + { supportedVersions = [ packet.version ] + , getEvent = + \version -> + if packet.version == version then + packet.current + + else + \_ -> Task.fail X.UnsupportedVersion + } + + +updateWith : SingleVersion pIn pOut vin vout -> FinalPackage pIn pOut -> FinalPackage vin vout +updateWith packet oldFinal = + { supportedVersions = packet.version :: oldFinal.supportedVersions + , getEvent = + \version -> + if packet.version == version then + packet.current + + else + packet.downcast >> oldFinal.getEvent version >> Task.map packet.upcast + } + + +toFunction : FinalPackage vin vout -> List String -> vin -> Task X.Error vout +toFunction final versions x = + let + bestVersion : Maybe String + bestVersion = + versions + |> List.filter (\c -> List.member c final.supportedVersions) + |> List.head + in + case bestVersion of + Nothing -> + Task.fail X.UnsupportedVersion + + Just version -> + final.getEvent version x diff --git a/src/Internal/Api/Versions/Api.elm b/src/Internal/Api/Versions/Api.elm new file mode 100644 index 0000000..1c6c19b --- /dev/null +++ b/src/Internal/Api/Versions/Api.elm @@ -0,0 +1,24 @@ +module Internal.Api.Versions.Api exposing (..) + +import Internal.Api.Request as R +import Internal.Api.Versions.Convert as C +import Internal.Api.Versions.Objects as O +import Internal.Api.Versions.SpecObjects as SO +import Internal.Tools.Exceptions as X +import Json.Decode as D +import Task exposing (Task) + + +versionsV1 : { baseUrl : String } -> Task X.Error O.Versions +versionsV1 data = + R.rawApiCall + { headers = R.NoHeaders + , method = "GET" + , baseUrl = data.baseUrl + , path = "/_matrix/client/versions" + , pathParams = [] + , queryParams = [] + , bodyParams = [] + , timeout = Nothing + , decoder = \_ -> D.map C.convert SO.versionsDecoder + } diff --git a/src/Internal/Api/Versions/Convert.elm b/src/Internal/Api/Versions/Convert.elm new file mode 100644 index 0000000..8a84921 --- /dev/null +++ b/src/Internal/Api/Versions/Convert.elm @@ -0,0 +1,32 @@ +module Internal.Api.Versions.Convert exposing (..) + +import Dict +import Internal.Api.Versions.Objects as O +import Internal.Api.Versions.SpecObjects as SO +import Set + + +implementedVersions : List String +implementedVersions = + [ "v1.5", "v1.4", "v1.3", "v1.2", "v1.1" ] + + +convert : SO.Versions -> O.Versions +convert versions = + { supportedVersions = + implementedVersions + |> List.filter (\v -> List.member v versions.versions) + , unstableFeatures = + versions.unstableFeatures + |> Maybe.withDefault Dict.empty + |> Dict.toList + |> List.filterMap + (\( name, enabled ) -> + if enabled then + Just name + + else + Nothing + ) + |> Set.fromList + } diff --git a/src/Internal/Api/Versions/Main.elm b/src/Internal/Api/Versions/Main.elm new file mode 100644 index 0000000..979d711 --- /dev/null +++ b/src/Internal/Api/Versions/Main.elm @@ -0,0 +1,19 @@ +module Internal.Api.Versions.Main exposing (..) + +import Internal.Api.Versions.Api as Api +import Internal.Api.Versions.Objects as O +import Internal.Tools.Exceptions as X +import Task exposing (Task) + + +type alias VersionsInput = + String + + +type alias VersionsOutput = + Task X.Error O.Versions + + +getVersions : VersionsInput -> VersionsOutput +getVersions baseUrl = + Api.versionsV1 { baseUrl = baseUrl } diff --git a/src/Internal/Api/Versions/Objects.elm b/src/Internal/Api/Versions/Objects.elm new file mode 100644 index 0000000..33b3efd --- /dev/null +++ b/src/Internal/Api/Versions/Objects.elm @@ -0,0 +1,9 @@ +module Internal.Api.Versions.Objects exposing (..) + +import Set exposing (Set) + + +type alias Versions = + { supportedVersions : List String + , unstableFeatures : Set String + } diff --git a/src/Internal/Api/Versions/SpecObjects.elm b/src/Internal/Api/Versions/SpecObjects.elm new file mode 100644 index 0000000..89d88af --- /dev/null +++ b/src/Internal/Api/Versions/SpecObjects.elm @@ -0,0 +1,43 @@ +module Internal.Api.Versions.SpecObjects exposing + ( Versions + , encodeVersions + , versionsDecoder + ) + +{-| Automatically generated 'SpecObjects' + +Last generated at Unix time 1673279712 + +-} + +import Dict exposing (Dict) +import Internal.Tools.DecodeExtra exposing (opField) +import Internal.Tools.EncodeExtra exposing (maybeObject) +import Json.Decode as D +import Json.Encode as E + + +{-| Information on what the homeserver supports. +-} +type alias Versions = + { unstableFeatures : Maybe (Dict String Bool) + , versions : List String + } + + +encodeVersions : Versions -> E.Value +encodeVersions data = + maybeObject + [ ( "unstable_features", Maybe.map (E.dict identity E.bool) data.unstableFeatures ) + , ( "versions", Just <| E.list E.string data.versions ) + ] + + +versionsDecoder : D.Decoder Versions +versionsDecoder = + D.map2 + (\a b -> + { unstableFeatures = a, versions = b } + ) + (opField "unstable_features" (D.dict D.bool)) + (D.field "versions" (D.list D.string)) diff --git a/src/Internal/Api/Versions/SpecObjects.yaml b/src/Internal/Api/Versions/SpecObjects.yaml new file mode 100644 index 0000000..329ab9f --- /dev/null +++ b/src/Internal/Api/Versions/SpecObjects.yaml @@ -0,0 +1,11 @@ +version: V_all +name: SpecObjects +objects: + Versions: + description: Information on what the homeserver supports. + fields: + unstable_features: + type: "{bool}" + versions: + type: "[string]" + required: true diff --git a/src/Internal/Config/DefaultSettings.elm b/src/Internal/Config/DefaultSettings.elm index ca21eea..dee906e 100644 --- a/src/Internal/Config/DefaultSettings.elm +++ b/src/Internal/Config/DefaultSettings.elm @@ -1,27 +1,33 @@ module Internal.Config.DefaultSettings exposing (..) + {-| This module hosts default configurations. These configurations are intended to be version-specific and are free to be changed in later releases. Alternatively, one may change these values in a fork of the repository. + -} + {-| This Matrix SDK version -} currentVersion : String -currentVersion = "0.0.0" +currentVersion = + "0.0.0" + {-| Matrix spec versions that this SDK supports, sorted in ascending order of preference. -} supportedVersions : List String -supportedVersions = +supportedVersions = [ "v1.2" , "v1.3" , "v1.4" , "v1.5" ] + {-| The default device name that this SDK will use when logging in. -} defaultDeviceName : String diff --git a/src/Internal/Config/ErrorStrings.elm b/src/Internal/Config/ErrorStrings.elm index 974621e..80b3358 100644 --- a/src/Internal/Config/ErrorStrings.elm +++ b/src/Internal/Config/ErrorStrings.elm @@ -1,7 +1,9 @@ module Internal.Config.ErrorStrings exposing (..) + {-| This module hosts all custom error messages that the SDK can deliver to the user. -} + cannotSyncWithoutAccessToken : String cannotSyncWithoutAccessToken = "UNABLE TO SYNC: you haven't provided login information yet." diff --git a/src/Internal/Config/Leaking.elm b/src/Internal/Config/Leaking.elm new file mode 100644 index 0000000..c172beb --- /dev/null +++ b/src/Internal/Config/Leaking.elm @@ -0,0 +1,41 @@ +module Internal.Config.Leaking exposing (..) + +{-| This module contains data that you're not supposed to see. + +Event types that you're not supposed to encounter, Matrix users that shouldn't exist, etc. + +Values like these usually imply that there is a leakage in the implementation or that there was a small mistake in the refactor. + +-} + +import Time + + +eventId : String +eventId = + "$unknown-event-id" + + +eventType : String +eventType = + "me.noordstar.invalid_type" + + +nextBatch : String +nextBatch = + "this_batch_does_not_exist" + + +originServerTs : Time.Posix +originServerTs = + Time.millisToPosix 0 + + +roomId : String +roomId = + "!unknown-room:example.org" + + +sender : String +sender = + "@alice:example.org" diff --git a/src/Internal/Tools/Exceptions.elm b/src/Internal/Tools/Exceptions.elm index 7464c55..dd41862 100644 --- a/src/Internal/Tools/Exceptions.elm +++ b/src/Internal/Tools/Exceptions.elm @@ -1,12 +1,12 @@ -module Internal.Values.Exceptions exposing (Error(..), ClientError(..), ServerError(..), errorCatches, errorToString) +module Internal.Tools.Exceptions exposing (ClientError(..), Error(..), ServerError(..), errorCatches, errorToString) {-| This module contains all potential errors that may be passed around in the SDK. -} import Dict import Http -import Internal.Tools.DecodeExtra exposing (opField) import Internal.Config.ErrorStrings as ES +import Internal.Tools.DecodeExtra exposing (opField) import Json.Decode as D import Json.Encode as E @@ -23,19 +23,14 @@ notices some internal inconsistencies or if it cannot interpret the server's input. - `ServerReturnsBadJSON` The homeserver sent JSON that does not parse. - - `ServerDoesntFollowJSONSpec` The homeserver sent data that lacks keys - required by spec. - - `ServerDoesntReturnBaseURL` The homeserver does not clarify its API - endpoints. - `CouldntGetTimestamp` The Elm core somehow failed to get the current Unix timestamp. - - `InvalidInputAccordingToSpec` The function contains invalid values. + - `NotSupportedYet` Some part of the SDK is intended to be implemented - but it isn't yet. -} type ClientError = ServerReturnsBadJSON String | CouldntGetTimestamp - | InsufficientCredentials String | NotSupportedYet String