Refactor Sync endpoint
parent
a0f19a3fdc
commit
eaa7bc3444
|
@ -1,9 +1,10 @@
|
||||||
module Internal.Api.Sync.Api exposing (..)
|
module Internal.Api.Sync.Api exposing (..)
|
||||||
|
|
||||||
import Internal.Api.Request as R
|
import Internal.Api.Request as R
|
||||||
|
import Internal.Api.Sync.V1.SpecObjects as SO1
|
||||||
|
import Internal.Api.Sync.V2.SpecObjects as SO2
|
||||||
import Internal.Tools.Exceptions as X
|
import Internal.Tools.Exceptions as X
|
||||||
import Internal.Tools.SpecEnums as Enums
|
import Internal.Tools.SpecEnums as Enums
|
||||||
import Json.Decode as D
|
|
||||||
import Task exposing (Task)
|
import Task exposing (Task)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,8 +19,15 @@ type alias SyncInputV1 =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
syncV1 : D.Decoder a -> (a -> b) -> SyncInputV1 -> Task X.Error b
|
type alias SyncOutputV1 =
|
||||||
syncV1 decoder mapping data =
|
Task X.Error SO1.Sync
|
||||||
|
|
||||||
|
type alias SyncOutputV2 =
|
||||||
|
Task X.Error SO2.Sync
|
||||||
|
|
||||||
|
|
||||||
|
syncV1 : SyncInputV1 -> SyncOutputV1
|
||||||
|
syncV1 data =
|
||||||
R.rawApiCall
|
R.rawApiCall
|
||||||
{ headers = R.WithAccessToken data.accessToken
|
{ headers = R.WithAccessToken data.accessToken
|
||||||
, method = "GET"
|
, method = "GET"
|
||||||
|
@ -38,5 +46,29 @@ syncV1 decoder mapping data =
|
||||||
data.timeout
|
data.timeout
|
||||||
|> Maybe.map ((+) 10000)
|
|> Maybe.map ((+) 10000)
|
||||||
|> Maybe.map toFloat
|
|> Maybe.map toFloat
|
||||||
, decoder = \_ -> D.map mapping decoder
|
, decoder = \_ -> SO1.syncDecoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
syncV2 : SyncInputV1 -> SyncOutputV2
|
||||||
|
syncV2 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 = \_ -> SO2.syncDecoder
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
module Internal.Api.Sync.Main exposing (..)
|
module Internal.Api.Sync.Main exposing (..)
|
||||||
|
|
||||||
import Internal.Api.Sync.Api as Api
|
import Internal.Api.Sync.Api as Api
|
||||||
import Internal.Api.Sync.V1_2.Api as V1_2
|
import Internal.Api.Sync.V2.Upcast as U2
|
||||||
import Internal.Api.Sync.V1_3.Api as V1_3
|
import Internal.Tools.VersionControl as VC
|
||||||
import Internal.Api.Sync.V1_4.Api as V1_4
|
import Task
|
||||||
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 : List String -> Maybe (SyncInput -> SyncOutput)
|
||||||
sync =
|
sync versions =
|
||||||
V.firstVersion V1_2.packet
|
VC.withBottomLayer
|
||||||
|> V.updateWith V1_3.packet
|
{ current = Api.syncV1
|
||||||
|> V.updateWith V1_4.packet
|
, version = "v1.2"
|
||||||
|> V.updateWith V1_5.packet
|
}
|
||||||
|> V.toFunction
|
|> VC.sameForVersion "v1.3"
|
||||||
|
|> VC.addMiddleLayer
|
||||||
|
{ current = Api.syncV2
|
||||||
|
, downcast = identity
|
||||||
|
, upcast = Task.map U2.upcastSync
|
||||||
|
, version = "v1.4"
|
||||||
|
}
|
||||||
|
|> VC.sameForVersion "v1.5"
|
||||||
|
|> VC.mostRecentFromVersionList versions
|
||||||
|
|
||||||
|
|
||||||
type alias SyncInput =
|
type alias SyncInput =
|
||||||
|
@ -25,4 +28,4 @@ type alias SyncInput =
|
||||||
|
|
||||||
|
|
||||||
type alias SyncOutput =
|
type alias SyncOutput =
|
||||||
Task X.Error O.Sync
|
Api.SyncOutputV2
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module Internal.Api.Sync.V1_2.SpecObjects exposing
|
module Internal.Api.Sync.V1.SpecObjects exposing
|
||||||
( AccountData
|
( AccountData
|
||||||
, ClientEventWithoutRoomId
|
, ClientEventWithoutRoomId
|
||||||
, Ephemeral
|
, Ephemeral
|
||||||
|
@ -60,7 +60,7 @@ module Internal.Api.Sync.V1_2.SpecObjects exposing
|
||||||
|
|
||||||
{-| Automatically generated 'SpecObjects'
|
{-| Automatically generated 'SpecObjects'
|
||||||
|
|
||||||
Last generated at Unix time 1673279712
|
Last generated at Unix time 1676625734
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: v1.2
|
version: v1
|
||||||
name: SpecObjects
|
name: SpecObjects
|
||||||
objects:
|
objects:
|
||||||
Sync:
|
Sync:
|
|
@ -1,17 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,395 +0,0 @@
|
||||||
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)
|
|
|
@ -1,152 +0,0 @@
|
||||||
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
|
|
|
@ -1,13 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,395 +0,0 @@
|
||||||
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)
|
|
|
@ -1,152 +0,0 @@
|
||||||
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
|
|
|
@ -1,603 +0,0 @@
|
||||||
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)
|
|
|
@ -1,197 +0,0 @@
|
||||||
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
|
|
|
@ -1,72 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,398 +0,0 @@
|
||||||
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)
|
|
|
@ -1,155 +0,0 @@
|
||||||
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
|
|
|
@ -1,635 +0,0 @@
|
||||||
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)
|
|
|
@ -1,208 +0,0 @@
|
||||||
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
|
|
|
@ -1,73 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,398 +0,0 @@
|
||||||
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)
|
|
|
@ -1,155 +0,0 @@
|
||||||
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
|
|
|
@ -1,73 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
module Internal.Api.Sync.V1_5.SpecObjects exposing
|
module Internal.Api.Sync.V2.SpecObjects exposing
|
||||||
( AccountData
|
( AccountData
|
||||||
, ClientEventWithoutRoomId
|
, ClientEventWithoutRoomId
|
||||||
, Ephemeral
|
, Ephemeral
|
||||||
|
@ -63,7 +63,7 @@ module Internal.Api.Sync.V1_5.SpecObjects exposing
|
||||||
|
|
||||||
{-| Automatically generated 'SpecObjects'
|
{-| Automatically generated 'SpecObjects'
|
||||||
|
|
||||||
Last generated at Unix time 1673279712
|
Last generated at Unix time 1676625735
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: v1.5
|
version: v2
|
||||||
name: SpecObjects
|
name: SpecObjects
|
||||||
objects:
|
objects:
|
||||||
Sync:
|
Sync:
|
|
@ -0,0 +1,70 @@
|
||||||
|
module Internal.Api.Sync.V2.Upcast exposing (..)
|
||||||
|
|
||||||
|
import Dict
|
||||||
|
import Internal.Api.Sync.V1.SpecObjects as PO
|
||||||
|
import Internal.Api.Sync.V2.SpecObjects as SO
|
||||||
|
|
||||||
|
upcastSync : PO.Sync -> SO.Sync
|
||||||
|
upcastSync old =
|
||||||
|
{ accountData = old.accountData
|
||||||
|
, nextBatch = old.nextBatch
|
||||||
|
, presence = old.presence
|
||||||
|
, rooms = Maybe.map upcastRooms old.rooms
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastRooms : PO.Rooms -> SO.Rooms
|
||||||
|
upcastRooms old =
|
||||||
|
{ invite = old.invite
|
||||||
|
, join = Dict.map (\_ -> upcastJoinedRoom) old.join
|
||||||
|
, knock = old.knock
|
||||||
|
, leave = Dict.map (\_ -> upcastLeftRoom) old.leave
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastJoinedRoom : PO.JoinedRoom -> SO.JoinedRoom
|
||||||
|
upcastJoinedRoom old =
|
||||||
|
{ accountData = old.accountData
|
||||||
|
, ephemeral = old.ephemeral
|
||||||
|
, state = Maybe.map upcastState old.state
|
||||||
|
, summary = old.summary
|
||||||
|
, timeline = Maybe.map upcastTimeline old.timeline
|
||||||
|
, unreadNotifications = old.unreadNotifications
|
||||||
|
, unreadThreadNotifications = Dict.empty
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastState : PO.State -> SO.State
|
||||||
|
upcastState old =
|
||||||
|
{ events = List.map upcastClientEventWithoutRoomId old.events }
|
||||||
|
|
||||||
|
upcastClientEventWithoutRoomId : PO.ClientEventWithoutRoomId -> SO.ClientEventWithoutRoomId
|
||||||
|
upcastClientEventWithoutRoomId old =
|
||||||
|
{ content = old.content
|
||||||
|
, eventId = old.eventId
|
||||||
|
, originServerTs = old.originServerTs
|
||||||
|
, sender = old.sender
|
||||||
|
, stateKey = old.stateKey
|
||||||
|
, contentType = old.contentType
|
||||||
|
, unsigned = Maybe.map upcastUnsigned old.unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastUnsigned : PO.UnsignedData -> SO.UnsignedData
|
||||||
|
upcastUnsigned (PO.UnsignedData old) =
|
||||||
|
SO.UnsignedData
|
||||||
|
{ age = old.age
|
||||||
|
, prevContent = old.prevContent
|
||||||
|
, redactedBecause = Maybe.map upcastClientEventWithoutRoomId old.redactedBecause
|
||||||
|
, transactionId = old.transactionId
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastTimeline : PO.Timeline -> SO.Timeline
|
||||||
|
upcastTimeline old =
|
||||||
|
{ events = List.map upcastClientEventWithoutRoomId old.events
|
||||||
|
, limited = old.limited
|
||||||
|
, prevBatch = old.prevBatch
|
||||||
|
}
|
||||||
|
|
||||||
|
upcastLeftRoom : PO.LeftRoom -> SO.LeftRoom
|
||||||
|
upcastLeftRoom old =
|
||||||
|
{ accountData = old.accountData
|
||||||
|
, state = Maybe.map upcastState old.state
|
||||||
|
, timeline = Maybe.map upcastTimeline old.timeline
|
||||||
|
}
|
Loading…
Reference in New Issue