Files
Scylla/src/Scylla/Sync.elm

261 lines
7.0 KiB
Elm

module Scylla.Sync exposing (..)
import Scylla.Api exposing (..)
import Dict exposing (Dict)
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool)
import Json.Decode.Pipeline exposing (required, optional)
-- Special Decoding
decodeJust : Decoder a -> Decoder (Maybe a)
decodeJust = Decode.map Just
maybeDecode : String -> Decoder a -> Decoder (Maybe a -> b) -> Decoder b
maybeDecode s d = optional s (decodeJust d) Nothing
-- General Events
type alias Event =
{ content : Decode.Value
, type_ : String
}
eventDecoder : Decoder Event
eventDecoder =
Decode.succeed Event
|> required "content" value
|> required "type" string
type alias EventContent =
{ avatarUrl : Maybe String
, displayname : Maybe String
, membership : String
, isDirect : Maybe Bool
-- , thirdPartyInvite : Invite
, unsigned : Maybe UnsignedData
}
eventContentDecoder : Decoder EventContent
eventContentDecoder =
Decode.succeed EventContent
|> maybeDecode "avatar_url" string
|> maybeDecode "displayname" string
|> required "membership" string
|> maybeDecode "is_direct" bool
-- |> required "third_party_invite" inviteDecoder
|> maybeDecode "unsigned" unsignedDataDecoder
-- Unsigned Data
type alias UnsignedData =
{ age : Maybe Int
, redactedBecause : Maybe Event
, transactionId : Maybe String
}
unsignedDataDecoder : Decoder UnsignedData
unsignedDataDecoder =
Decode.succeed UnsignedData
|> maybeDecode "age" int
|> maybeDecode "redacted_because" eventDecoder
|> maybeDecode "transaction_id" string
-- State
type alias State =
{ events : Maybe (List StateEvent)
}
stateDecoder : Decoder State
stateDecoder =
Decode.succeed State
|> maybeDecode "events" (list stateEventDecoder)
type alias StateEvent =
{ content : Decode.Value
, type_ : String
, eventId : String
, sender : String
, originServerTs : Int
, unsigned : Maybe UnsignedData
, prevContent : Maybe EventContent
, stateKey : String
}
stateEventDecoder : Decoder StateEvent
stateEventDecoder =
Decode.succeed StateEvent
|> required "content" value
|> required "type" string
|> required "event_id" string
|> required "sender" string
|> required "origin_server_ts" int
|> maybeDecode "unsigned" unsignedDataDecoder
|> maybeDecode "prev_content" eventContentDecoder
|> required "state_key" string
-- Rooms
type alias Rooms =
{ join : Maybe (Dict String JoinedRoom)
, invite : Maybe (Dict String InvitedRoom)
, leave : Maybe (Dict String LeftRoom)
}
roomsDecoder : Decoder Rooms
roomsDecoder =
Decode.succeed Rooms
|> maybeDecode "join" (dict joinedRoomDecoder)
|> maybeDecode "invite" (dict invitedRoomDecoder)
|> maybeDecode "leave" (dict leftRoomDecoder)
type alias JoinedRoom =
{ state : Maybe State
, timeline : Maybe Timeline
, ephemeral : Maybe Ephemeral
, accountData : Maybe AccountData
, unreadNotifications : Maybe UnreadNotificationCounts
}
joinedRoomDecoder : Decoder JoinedRoom
joinedRoomDecoder =
Decode.succeed JoinedRoom
|> maybeDecode "state" stateDecoder
|> maybeDecode "timeline" timelineDecoder
|> maybeDecode "ephemeral" ephemeralDecoder
|> maybeDecode "account_data" accountDataDecoder
|> maybeDecode "unread_notifications" unreadNotificationCountsDecoder
-- Joined Room Data
type alias Timeline =
{ events : Maybe (List RoomEvent)
, limited : Maybe Bool
, prevBatch : Maybe String
}
timelineDecoder =
Decode.succeed Timeline
|> maybeDecode "events" (list roomEventDecoder)
|> maybeDecode "limited" bool
|> maybeDecode "prev_batch" string
type alias RoomEvent =
{ content : Decode.Value
, type_ : String
, eventId : String
, sender : String
, originServerTs : Int
, unsigned : Maybe UnsignedData
}
roomEventDecoder : Decoder RoomEvent
roomEventDecoder =
Decode.succeed RoomEvent
|> required "content" value
|> required "type" string
|> required "event_id" string
|> required "sender" string
|> required "origin_server_ts" int
|> maybeDecode "unsigned" unsignedDataDecoder
type alias Ephemeral =
{ events : Maybe (List Event)
}
ephemeralDecoder : Decoder Ephemeral
ephemeralDecoder =
Decode.succeed Ephemeral
|> maybeDecode "events" (list eventDecoder)
type alias AccountData =
{ events : Maybe (List Event)
}
accountDataDecoder : Decoder AccountData
accountDataDecoder =
Decode.succeed AccountData
|> maybeDecode "events" (list eventDecoder)
type alias UnreadNotificationCounts =
{ highlightCount : Maybe Int
, notificationCount : Maybe Int
}
unreadNotificationCountsDecoder : Decoder UnreadNotificationCounts
unreadNotificationCountsDecoder =
Decode.succeed UnreadNotificationCounts
|> maybeDecode "highlight_count" int
|> maybeDecode "notification_count" int
-- Invited Room Data
type alias InvitedRoom =
{ inviteState : Maybe InviteState
}
invitedRoomDecoder : Decoder InvitedRoom
invitedRoomDecoder =
Decode.succeed InvitedRoom
|> maybeDecode "invite_state" inviteStateDecoder
type alias InviteState =
{ events : Maybe (List StrippedState)
}
inviteStateDecoder : Decoder InviteState
inviteStateDecoder =
Decode.succeed InviteState
|> maybeDecode "events" (list strippedStateDecoder)
type alias StrippedState =
{ content : EventContent
, stateKey : String
, type_ : String
, sender : String
}
strippedStateDecoder : Decoder StrippedState
strippedStateDecoder =
Decode.succeed StrippedState
|> required "content" eventContentDecoder
|> required "state_key" string
|> required "type" string
|> required "sender" string
-- Left Room Data
type alias LeftRoom =
{ state : Maybe State
, timeline : Maybe Timeline
, accountData : Maybe AccountData
}
leftRoomDecoder : Decoder LeftRoom
leftRoomDecoder =
Decode.succeed LeftRoom
|> maybeDecode "state" stateDecoder
|> maybeDecode "timeline" timelineDecoder
|> maybeDecode "account_data" accountDataDecoder
-- General Sync Response
type alias SyncResponse =
{ nextBatch : String
, rooms : Maybe Rooms
, presence : Maybe Presence
, accountData : Maybe AccountData
}
syncResponseDecoder : Decoder SyncResponse
syncResponseDecoder =
Decode.succeed SyncResponse
|> required "next_batch" string
|> maybeDecode "rooms" roomsDecoder
|> maybeDecode "presence" presenceDecoder
|> maybeDecode "account_data" accountDataDecoder
type alias Presence =
{ events : Maybe (List Event)
}
presenceDecoder : Decoder Presence
presenceDecoder =
Decode.succeed Presence
|> maybeDecode "events" (list eventDecoder)
-- Business Logic
mergeSyncResponse : SyncResponse -> SyncResponse -> SyncResponse
mergeSyncResponse l r = r