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 import Time
accessToken : String -> AccessToken -> ValueGetter String accessToken : String -> AccessToken -> ValueGetter X.Error String
accessToken baseUrl t = accessToken baseUrl t =
{ value = { value =
case t of case t of
@ -37,7 +37,7 @@ accessToken baseUrl t =
} }
transactionId : (Int -> String) -> ValueGetter String transactionId : (Int -> String) -> ValueGetter X.Error String
transactionId seeder = transactionId seeder =
{ value = Nothing { value = Nothing
, getValue = , 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 = versions baseUrl mVersions =
{ value = mVersions { value = mVersions
, getValue = , getValue =

View File

@ -9,11 +9,14 @@ This file combines the internal functions with the API endpoints to create a ful
import Dict import Dict
import Internal.Api.All as Api import Internal.Api.All as Api
import Internal.Room as Room
import Internal.Event as Event 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.Credentials as Internal
import Internal.Values.Event as IEvent import Internal.Values.Event as IEvent
import Internal.Values.Room as IRoom 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, {-| You can consider the `Credentials` type as a large ring of keys,
@ -56,70 +59,128 @@ getRoomById roomId credentials =
} }
) )
{-| Insert an internal room type into the credentials. {-| Insert an internal room type into the credentials.
-} -}
insertInternalRoom : IRoom.Room -> Credentials -> 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.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 : Api.CredUpdate -> Credentials -> Credentials
updateWith credUpdate credentials = updateWith credUpdate credentials =
case credUpdate of case credUpdate of
Api.MultipleUpdates updates -> Api.MultipleUpdates updates ->
List.foldl updateWith credentials updates List.foldl updateWith credentials updates
Api.GetEvent input output -> Api.GetEvent input output ->
case getRoomById input.roomId credentials of case getRoomById input.roomId credentials of
Just room -> Just room ->
output output
|> IEvent.initFromGetEvent |> Event.initFromGetEvent
|> Room.addInternalEvent |> Room.addInternalEvent
|> (|>) room |> (|>) room
|> insertRoom |> insertRoom
|> (|>) credentials |> (|>) credentials
Nothing -> Nothing ->
credentials credentials
Api.JoinedMembersToRoom _ _ ->
credentials -- TODO
Api.MessageEventSent _ _ ->
credentials -- TODO
Api.StateEventSent _ _ ->
credentials -- TODO
Api.JoinedMembersToRoom _ _ ->
credentials
-- TODO
Api.MessageEventSent _ _ ->
credentials
-- TODO
Api.StateEventSent _ _ ->
credentials
-- TODO
Api.SyncUpdate input output -> Api.SyncUpdate input output ->
let let
rooms = jRooms =
output.rooms output.rooms
|> Maybe.map .join |> Maybe.map .join
|> Maybe.withDefault Dict.empty |> Maybe.withDefault Dict.empty
|> Dict.toList |> Dict.toList
|> List.map |> List.map
(\(roomId, jroom)-> (\( roomId, jroom ) ->
case getRoomById roomId credentials of case getRoomById roomId credentials of
-- Update existing room -- Update existing room
Just room -> Just room ->
room room
|> Room.internalValue |> Room.internalValue
|> IRoom.addEvents |> 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 -- Add new room
Nothing -> Nothing ->
jroom Room.initFromJoinedRoom { nextBatch = output.nextBatch, roomId = roomId } jroom
) )
in in
credentials List.foldl Internal.insertRoom (Internal.addSince output.nextBatch credentials) jRooms
Api.UpdateAccessToken token -> Api.UpdateAccessToken token ->
Internal.addAccessToken token credentials Internal.addAccessToken token credentials
Api.UpdateVersions versions -> Api.UpdateVersions versions ->
Internal.addVersions versions credentials 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.Main as GetEvent
import Internal.Api.GetEvent.V1.SpecObjects as GetEventSO import Internal.Api.GetEvent.V1.SpecObjects as GetEventSO
import Internal.Api.PreApi.Objects.Versions as V 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.LoginValues exposing (AccessToken)
import Internal.Tools.Timestamp exposing (Timestamp) import Internal.Tools.Timestamp exposing (Timestamp)
import Internal.Values.Event as Internal import Internal.Values.Event as Internal
@ -86,7 +86,7 @@ initFromClientEventWithoutRoomId rId output =
(\(SyncSO.UnsignedData data) -> (\(SyncSO.UnsignedData data) ->
{ age = data.age { age = data.age
, prevContent = data.prevContent , prevContent = data.prevContent
, redactedBecause = Maybe.map (initFromClientEventWithoutRoomId roomId) data.redactedBecause , redactedBecause = Maybe.map (initFromClientEventWithoutRoomId rId) data.redactedBecause
, transactionId = data.transactionId , 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. {-| 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.All as Api
import Internal.Api.PreApi.Objects.Versions as V 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.Event as Event exposing (Event)
import Internal.Tools.Exceptions as X import Internal.Tools.Exceptions as X
import Internal.Tools.Hashdict as Hashdict
import Internal.Tools.LoginValues exposing (AccessToken) import Internal.Tools.LoginValues exposing (AccessToken)
import Internal.Values.Event as IEvent import Internal.Values.Event as IEvent
import Internal.Values.Room as Internal import Internal.Values.Room as Internal
import Internal.Values.StateManager as StateManager
import Internal.Values.Timeline as Timeline
import Json.Encode as E import Json.Encode as E
import Task exposing (Task) 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 {-| Adds an internal event to the `Room`. An internal event is a custom event
that has been generated by the client. that has been generated by the client.
-} -}
@ -66,6 +122,21 @@ internalValue (Room { 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`. {-| Retrieves the ID of the Matrix room associated with the given `Room`.
-} -}
roomId : Room -> String roomId : Room -> String

View File

@ -11,7 +11,13 @@ import Internal.Values.Room as Room exposing (Room)
type Credentials 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. {-| Add a new access token based on prior information.
@ -28,6 +34,13 @@ addVersions versions (Credentials data) =
Credentials { data | versions = Just versions } 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. {-| Get the stringed access token the Credentials type is using, if any.
-} -}
getAccessToken : Credentials -> Maybe String getAccessToken : Credentials -> Maybe String
@ -64,10 +77,18 @@ defaultCredentials homeserver =
{ access = NoAccess { access = NoAccess
, baseUrl = homeserver , baseUrl = homeserver
, rooms = Hashdict.empty Room.roomId , rooms = Hashdict.empty Room.roomId
, since = Nothing
, versions = 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. {-| Create a Credentials type using an unknown access token.
-} -}
fromAccessToken : { accessToken : String, homeserver : String } -> Credentials fromAccessToken : { accessToken : String, homeserver : String } -> Credentials
@ -102,3 +123,10 @@ insertRoom : Room -> Credentials -> Credentials
insertRoom room (Credentials cred) = insertRoom room (Credentials cred) =
Credentials Credentials
{ cred | rooms = Hashdict.insert room cred.rooms } { 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 -> String
roomId (Room room) = roomId (Room room) =
room.roomId room.roomId
{-| Get the most recent events.
-}
mostRecentEvents : Room -> List Event
mostRecentEvents (Room room) =
Timeline.mostRecentEvents room.timeline