Finish 1st version of open types

The code is very messy and there are a few optimizations to be made before the code is both user- and developer-friendly, but at least it works.
pull/1/head
Bram van den Heuvel 2023-03-02 14:55:08 +01:00
parent 7e345c2b05
commit caab0ae0bb
6 changed files with 210 additions and 43 deletions

View File

@ -17,7 +17,7 @@ import Task
import Time
accessToken : String -> AccessToken -> ValueGetter String
accessToken : String -> AccessToken -> ValueGetter X.Error String
accessToken baseUrl t =
{ value =
case t of
@ -37,7 +37,7 @@ accessToken baseUrl t =
}
transactionId : (Int -> String) -> ValueGetter String
transactionId : (Int -> String) -> ValueGetter X.Error String
transactionId seeder =
{ value = Nothing
, getValue =
@ -47,7 +47,7 @@ transactionId seeder =
}
versions : String -> Maybe V.Versions -> ValueGetter V.Versions
versions : String -> Maybe V.Versions -> ValueGetter X.Error V.Versions
versions baseUrl mVersions =
{ value = mVersions
, getValue =

View File

@ -9,11 +9,14 @@ This file combines the internal functions with the API endpoints to create a ful
import Dict
import Internal.Api.All as Api
import Internal.Room as Room
import Internal.Event as Event
import Internal.Room as Room
import Internal.Tools.Exceptions as X
import Internal.Values.Credentials as Internal
import Internal.Values.Event as IEvent
import Internal.Values.Room as IRoom
import Internal.Values.StateManager as StateManager
import Task exposing (Task)
{-| You can consider the `Credentials` type as a large ring of keys,
@ -56,16 +59,23 @@ getRoomById roomId credentials =
}
)
{-| Insert an internal room type into the credentials.
-}
insertInternalRoom : IRoom.Room -> Credentials -> Credentials
insertInternalRoom = Internal.insertRoom
insertInternalRoom =
Internal.insertRoom
{-| Internal a full room type into the credentials. -}
{-| Internal a full room type into the credentials.
-}
insertRoom : Room.Room -> Credentials -> Credentials
insertRoom = Room.internalValue >> insertInternalRoom
insertRoom =
Room.internalValue >> insertInternalRoom
{-| Update the Credentials type with new values -}
{-| Update the Credentials type with new values
-}
updateWith : Api.CredUpdate -> Credentials -> Credentials
updateWith credUpdate credentials =
case credUpdate of
@ -76,7 +86,7 @@ updateWith credUpdate credentials =
case getRoomById input.roomId credentials of
Just room ->
output
|> IEvent.initFromGetEvent
|> Event.initFromGetEvent
|> Room.addInternalEvent
|> (|>) room
|> insertRoom
@ -86,40 +96,91 @@ updateWith credUpdate credentials =
credentials
Api.JoinedMembersToRoom _ _ ->
credentials -- TODO
credentials
-- TODO
Api.MessageEventSent _ _ ->
credentials -- TODO
credentials
-- TODO
Api.StateEventSent _ _ ->
credentials -- TODO
credentials
-- TODO
Api.SyncUpdate input output ->
let
rooms =
jRooms =
output.rooms
|> Maybe.map .join
|> Maybe.withDefault Dict.empty
|> Dict.toList
|> List.map
(\(roomId, jroom)->
(\( roomId, jroom ) ->
case getRoomById roomId credentials of
-- Update existing room
Just room ->
room
|> Room.internalValue
|> IRoom.addEvents
{ events =
jroom.timeline
|> Maybe.map .events
|> Maybe.withDefault []
|> List.map (Event.initFromClientEventWithoutRoomId roomId)
, nextBatch = output.nextBatch
, prevBatch =
jroom.timeline
|> Maybe.andThen .prevBatch
|> Maybe.withDefault (Maybe.withDefault "" input.since)
, stateDelta =
jroom.state
|> Maybe.map
(.events
>> List.map (Event.initFromClientEventWithoutRoomId roomId)
>> StateManager.fromEventList
)
}
-- Add new room
Nothing ->
jroom
Room.initFromJoinedRoom { nextBatch = output.nextBatch, roomId = roomId } jroom
)
in
credentials
List.foldl Internal.insertRoom (Internal.addSince output.nextBatch credentials) jRooms
Api.UpdateAccessToken token ->
Internal.addAccessToken token credentials
Api.UpdateVersions versions ->
Internal.addVersions versions credentials
{-| Synchronize credentials
-}
sync : Credentials -> Task X.Error Api.CredUpdate
sync credentials =
Api.syncCredentials
{ accessToken = Internal.getAccessTokenType credentials
, baseUrl = Internal.getBaseUrl credentials
, filter = Nothing
, fullState = Nothing
, setPresence = Nothing
, since = Internal.getSince credentials
, timeout = Just 30
, versions = Internal.getVersions credentials
}
{-| Get a list of all synchronised rooms.
-}
rooms : Credentials -> List Room.Room
rooms credentials =
credentials
|> Internal.getRooms
|> ({ accessToken = Internal.getAccessTokenType credentials
, baseUrl = Internal.getBaseUrl credentials
, versions = Internal.getVersions credentials
}
|> Room.init
|> List.map
)

View File

@ -10,7 +10,7 @@ resend other events or forward them elsewhere.
import Internal.Api.GetEvent.Main as GetEvent
import Internal.Api.GetEvent.V1.SpecObjects as GetEventSO
import Internal.Api.PreApi.Objects.Versions as V
import Internal.Api.Sync.V1.SpecObjects as SyncSO
import Internal.Api.Sync.V2.SpecObjects as SyncSO
import Internal.Tools.LoginValues exposing (AccessToken)
import Internal.Tools.Timestamp exposing (Timestamp)
import Internal.Values.Event as Internal
@ -86,7 +86,7 @@ initFromClientEventWithoutRoomId rId output =
(\(SyncSO.UnsignedData data) ->
{ age = data.age
, prevContent = data.prevContent
, redactedBecause = Maybe.map (initFromClientEventWithoutRoomId roomId) data.redactedBecause
, redactedBecause = Maybe.map (initFromClientEventWithoutRoomId rId) data.redactedBecause
, transactionId = data.transactionId
}
)

View File

@ -3,13 +3,18 @@ module Internal.Room exposing (..)
{-| The `Room` type represents a Matrix Room. In here, you will find utilities to ask information about a room.
-}
import Dict
import Internal.Api.All as Api
import Internal.Api.PreApi.Objects.Versions as V
import Internal.Api.Sync.V2.SpecObjects as Sync
import Internal.Event as Event exposing (Event)
import Internal.Tools.Exceptions as X
import Internal.Tools.Hashdict as Hashdict
import Internal.Tools.LoginValues exposing (AccessToken)
import Internal.Values.Event as IEvent
import Internal.Values.Room as Internal
import Internal.Values.StateManager as StateManager
import Internal.Values.Timeline as Timeline
import Json.Encode as E
import Task exposing (Task)
@ -31,6 +36,57 @@ type Room
}
{-| Create a new object from a joined room.
-}
initFromJoinedRoom : { roomId : String, nextBatch : String } -> Sync.JoinedRoom -> Internal.Room
initFromJoinedRoom data jroom =
Internal.Room
{ accountData =
jroom.accountData
|> Maybe.map .events
|> Maybe.withDefault []
|> List.map (\{ contentType, content } -> ( contentType, content ))
|> Dict.fromList
, ephemeral =
jroom.ephemeral
|> Maybe.map .events
|> Maybe.withDefault []
|> List.map IEvent.BlindEvent
, events =
jroom.timeline
|> Maybe.map .events
|> Maybe.withDefault []
|> List.map (Event.initFromClientEventWithoutRoomId data.roomId)
|> Hashdict.fromList IEvent.eventId
, roomId = data.roomId
, timeline =
jroom.timeline
|> Maybe.map
(\timeline ->
Timeline.newFromEvents
{ events = List.map (Event.initFromClientEventWithoutRoomId data.roomId) timeline.events
, nextBatch = data.nextBatch
, prevBatch = timeline.prevBatch
, stateDelta =
jroom.state
|> Maybe.map
(.events
>> List.map (Event.initFromClientEventWithoutRoomId data.roomId)
>> StateManager.fromEventList
)
}
)
|> Maybe.withDefault
(Timeline.newFromEvents
{ events = []
, nextBatch = data.nextBatch
, prevBatch = Nothing
, stateDelta = Nothing
}
)
}
{-| Adds an internal event to the `Room`. An internal event is a custom event
that has been generated by the client.
-}
@ -66,6 +122,21 @@ internalValue (Room { room }) =
room
{-| Get the most recent events.
-}
mostRecentEvents : Room -> List Event
mostRecentEvents (Room data) =
data.room
|> Internal.mostRecentEvents
|> List.map
(Event.init
{ accessToken = data.accessToken
, baseUrl = data.baseUrl
, versions = data.versions
}
)
{-| Retrieves the ID of the Matrix room associated with the given `Room`.
-}
roomId : Room -> String

View File

@ -11,7 +11,13 @@ import Internal.Values.Room as Room exposing (Room)
type Credentials
= Credentials { access : AccessToken, baseUrl : String, rooms : Hashdict Room, versions : Maybe V.Versions }
= Credentials
{ access : AccessToken
, baseUrl : String
, rooms : Hashdict Room
, since : Maybe String
, versions : Maybe V.Versions
}
{-| Add a new access token based on prior information.
@ -28,6 +34,13 @@ addVersions versions (Credentials data) =
Credentials { data | versions = Just versions }
{-| Add a new `since` token to sync from.
-}
addSince : String -> Credentials -> Credentials
addSince since (Credentials data) =
Credentials { data | since = Just since }
{-| Get the stringed access token the Credentials type is using, if any.
-}
getAccessToken : Credentials -> Maybe String
@ -64,10 +77,18 @@ defaultCredentials homeserver =
{ access = NoAccess
, baseUrl = homeserver
, rooms = Hashdict.empty Room.roomId
, since = Nothing
, versions = Nothing
}
{-| Get the latest `since` token.
-}
getSince : Credentials -> Maybe String
getSince (Credentials { since }) =
since
{-| Create a Credentials type using an unknown access token.
-}
fromAccessToken : { accessToken : String, homeserver : String } -> Credentials
@ -102,3 +123,10 @@ insertRoom : Room -> Credentials -> Credentials
insertRoom room (Credentials cred) =
Credentials
{ cred | rooms = Hashdict.insert room cred.rooms }
{-| Get a list of all synchronised rooms.
-}
getRooms : Credentials -> List Room
getRooms (Credentials { rooms }) =
Hashdict.values rooms

View File

@ -56,3 +56,10 @@ getEventById eventId (Room room) =
roomId : Room -> String
roomId (Room room) =
room.roomId
{-| Get the most recent events.
-}
mostRecentEvents : Room -> List Event
mostRecentEvents (Room room) =
Timeline.mostRecentEvents room.timeline