Connect internal Credentials, Room, Event
WARNING: contains a few syntax errors - still work in progresspull/1/head
parent
f88c9604dc
commit
7e345c2b05
|
@ -7,8 +7,13 @@ 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.Values.Credentials as Internal
|
||||
import Internal.Values.Event as IEvent
|
||||
import Internal.Values.Room as IRoom
|
||||
|
||||
|
||||
{-| You can consider the `Credentials` type as a large ring of keys,
|
||||
|
@ -50,3 +55,71 @@ getRoomById roomId credentials =
|
|||
, versions = Internal.getVersions credentials
|
||||
}
|
||||
)
|
||||
|
||||
{-| Insert an internal room type into the credentials.
|
||||
-}
|
||||
insertInternalRoom : IRoom.Room -> Credentials -> Credentials
|
||||
insertInternalRoom = Internal.insertRoom
|
||||
|
||||
{-| Internal a full room type into the credentials. -}
|
||||
insertRoom : Room.Room -> Credentials -> Credentials
|
||||
insertRoom = Room.internalValue >> insertInternalRoom
|
||||
|
||||
{-| Update the Credentials type with new values -}
|
||||
updateWith : Api.CredUpdate -> Credentials -> Credentials
|
||||
updateWith credUpdate credentials =
|
||||
case credUpdate of
|
||||
Api.MultipleUpdates updates ->
|
||||
List.foldl updateWith credentials updates
|
||||
|
||||
Api.GetEvent input output ->
|
||||
case getRoomById input.roomId credentials of
|
||||
Just room ->
|
||||
output
|
||||
|> IEvent.initFromGetEvent
|
||||
|> Room.addInternalEvent
|
||||
|> (|>) room
|
||||
|> insertRoom
|
||||
|> (|>) credentials
|
||||
|
||||
Nothing ->
|
||||
credentials
|
||||
|
||||
Api.JoinedMembersToRoom _ _ ->
|
||||
credentials -- TODO
|
||||
|
||||
Api.MessageEventSent _ _ ->
|
||||
credentials -- TODO
|
||||
|
||||
Api.StateEventSent _ _ ->
|
||||
credentials -- TODO
|
||||
|
||||
Api.SyncUpdate input output ->
|
||||
let
|
||||
rooms =
|
||||
output.rooms
|
||||
|> Maybe.map .join
|
||||
|> Maybe.withDefault Dict.empty
|
||||
|> Dict.toList
|
||||
|> List.map
|
||||
(\(roomId, jroom)->
|
||||
case getRoomById roomId credentials of
|
||||
-- Update existing room
|
||||
Just room ->
|
||||
room
|
||||
|> Room.internalValue
|
||||
|> IRoom.addEvents
|
||||
|
||||
|
||||
-- Add new room
|
||||
Nothing ->
|
||||
jroom
|
||||
)
|
||||
in
|
||||
credentials
|
||||
|
||||
Api.UpdateAccessToken token ->
|
||||
Internal.addAccessToken token credentials
|
||||
|
||||
Api.UpdateVersions versions ->
|
||||
Internal.addVersions versions credentials
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
module Internal.Event exposing (..)
|
||||
|
||||
{-| This module represents the event type in the Matrix API.
|
||||
|
||||
Users can use this type to reply to events, to link them, look for other events,
|
||||
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.Tools.LoginValues exposing (AccessToken)
|
||||
import Internal.Tools.Timestamp exposing (Timestamp)
|
||||
import Internal.Values.Event as Internal
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
{-| The central event type. This type will be used by the user and will be directly interacted with.
|
||||
-}
|
||||
type Event
|
||||
= Event
|
||||
{ event : Internal.Event
|
||||
, accessToken : AccessToken
|
||||
, baseUrl : String
|
||||
, versions : Maybe V.Versions
|
||||
}
|
||||
|
||||
|
||||
{-| Using the credentials' background information and an internal event type,
|
||||
create an interactive event type.
|
||||
-}
|
||||
init : { accessToken : AccessToken, baseUrl : String, versions : Maybe V.Versions } -> Internal.Event -> Event
|
||||
init { accessToken, baseUrl, versions } event =
|
||||
Event
|
||||
{ event = event
|
||||
, accessToken = accessToken
|
||||
, baseUrl = baseUrl
|
||||
, versions = versions
|
||||
}
|
||||
|
||||
|
||||
{-| Create an internal event type from an API endpoint event object.
|
||||
This function is placed in this file to respect file hierarchy and avoid circular imports.
|
||||
-}
|
||||
initFromGetEvent : GetEvent.EventOutput -> Internal.Event
|
||||
initFromGetEvent output =
|
||||
Internal.init
|
||||
{ content = output.content
|
||||
, eventId = output.eventId
|
||||
, originServerTs = output.originServerTs
|
||||
, roomId = output.roomId
|
||||
, sender = output.sender
|
||||
, stateKey = output.stateKey
|
||||
, contentType = output.contentType
|
||||
, unsigned =
|
||||
output.unsigned
|
||||
|> Maybe.map
|
||||
(\(GetEventSO.UnsignedData data) ->
|
||||
{ age = data.age
|
||||
, prevContent = data.prevContent
|
||||
, redactedBecause = Maybe.map initFromGetEvent data.redactedBecause
|
||||
, transactionId = data.transactionId
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
{-| Create an internal event type from an API endpoint event object.
|
||||
This function is placed in this file to respect file hierarchy and avoid circular imports.
|
||||
-}
|
||||
initFromClientEventWithoutRoomId : String -> SyncSO.ClientEventWithoutRoomId -> Internal.Event
|
||||
initFromClientEventWithoutRoomId rId output =
|
||||
Internal.init
|
||||
{ content = output.content
|
||||
, eventId = output.eventId
|
||||
, originServerTs = output.originServerTs
|
||||
, roomId = rId
|
||||
, sender = output.sender
|
||||
, stateKey = output.stateKey
|
||||
, contentType = output.contentType
|
||||
, unsigned =
|
||||
output.unsigned
|
||||
|> Maybe.map
|
||||
(\(SyncSO.UnsignedData data) ->
|
||||
{ age = data.age
|
||||
, prevContent = data.prevContent
|
||||
, redactedBecause = Maybe.map (initFromClientEventWithoutRoomId roomId) data.redactedBecause
|
||||
, transactionId = data.transactionId
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
{-| Get the internal event type that is hidden in the interactive event type.
|
||||
-}
|
||||
internalValue : Event -> Internal.Event
|
||||
internalValue (Event { event }) =
|
||||
event
|
||||
|
||||
|
||||
|
||||
{- GETTER FUNCTIONS -}
|
||||
|
||||
|
||||
content : Event -> E.Value
|
||||
content =
|
||||
internalValue >> Internal.content
|
||||
|
||||
|
||||
eventId : Event -> String
|
||||
eventId =
|
||||
internalValue >> Internal.eventId
|
||||
|
||||
|
||||
originServerTs : Event -> Timestamp
|
||||
originServerTs =
|
||||
internalValue >> Internal.originServerTs
|
||||
|
||||
|
||||
roomId : Event -> String
|
||||
roomId =
|
||||
internalValue >> Internal.roomId
|
||||
|
||||
|
||||
sender : Event -> String
|
||||
sender =
|
||||
internalValue >> Internal.sender
|
||||
|
||||
|
||||
stateKey : Event -> Maybe String
|
||||
stateKey =
|
||||
internalValue >> Internal.stateKey
|
||||
|
||||
|
||||
contentType : Event -> String
|
||||
contentType =
|
||||
internalValue >> Internal.contentType
|
||||
|
||||
|
||||
age : Event -> Maybe Int
|
||||
age =
|
||||
internalValue >> Internal.age
|
||||
|
||||
|
||||
redactedBecause : Event -> Maybe Event
|
||||
redactedBecause (Event data) =
|
||||
data.event
|
||||
|> Internal.redactedBecause
|
||||
|> Maybe.map
|
||||
(\event ->
|
||||
Event { data | event = event }
|
||||
)
|
||||
|
||||
|
||||
transactionId : Event -> Maybe String
|
||||
transactionId =
|
||||
internalValue >> Internal.transactionId
|
|
@ -5,14 +5,22 @@ module Internal.Room exposing (..)
|
|||
|
||||
import Internal.Api.All as Api
|
||||
import Internal.Api.PreApi.Objects.Versions as V
|
||||
import Internal.Event as Event exposing (Event)
|
||||
import Internal.Tools.Exceptions as X
|
||||
import Internal.Tools.LoginValues exposing (AccessToken)
|
||||
import Internal.Values.Event as IEvent
|
||||
import Internal.Values.Room as Internal
|
||||
import Json.Encode as E
|
||||
import Task exposing (Task)
|
||||
|
||||
|
||||
{-| The Room type.
|
||||
{-| The `Room` type represents a Matrix Room. It contains context information
|
||||
such as the `accessToken` that allows the retrieval of new information from
|
||||
the Matrix API if necessary.
|
||||
|
||||
The `Room` type contains utilities to inquire about the room and send messages
|
||||
to it.
|
||||
|
||||
-}
|
||||
type Room
|
||||
= Room
|
||||
|
@ -23,6 +31,24 @@ type Room
|
|||
}
|
||||
|
||||
|
||||
{-| Adds an internal event to the `Room`. An internal event is a custom event
|
||||
that has been generated by the client.
|
||||
-}
|
||||
addInternalEvent : IEvent.Event -> Room -> Room
|
||||
addInternalEvent ievent (Room ({ room } as data)) =
|
||||
Room { data | room = Internal.addEvent ievent room }
|
||||
|
||||
|
||||
{-| Adds an `Event` object to the `Room`. An `Event` is a value from the
|
||||
`Internal.Event` module that is used to represent an event in a Matrix room.
|
||||
-}
|
||||
addEvent : Event -> Room -> Room
|
||||
addEvent =
|
||||
Event.internalValue >> addInternalEvent
|
||||
|
||||
|
||||
{-| Creates a new `Room` object with the given parameters.
|
||||
-}
|
||||
init : { accessToken : AccessToken, baseUrl : String, versions : Maybe V.Versions } -> Internal.Room -> Room
|
||||
init { accessToken, baseUrl, versions } room =
|
||||
Room
|
||||
|
@ -33,13 +59,22 @@ init { accessToken, baseUrl, versions } room =
|
|||
}
|
||||
|
||||
|
||||
{-| Get the room's id.
|
||||
{-| Retrieves the `Internal.Room` type contained within the given `Room`.
|
||||
-}
|
||||
internalValue : Room -> Internal.Room
|
||||
internalValue (Room { room }) =
|
||||
room
|
||||
|
||||
|
||||
{-| Retrieves the ID of the Matrix room associated with the given `Room`.
|
||||
-}
|
||||
roomId : Room -> String
|
||||
roomId (Room { room }) =
|
||||
Internal.roomId room
|
||||
roomId =
|
||||
internalValue >> Internal.roomId
|
||||
|
||||
|
||||
{-| Sends a new event to the Matrix room associated with the given `Room`.
|
||||
-}
|
||||
sendEvent : Room -> { eventType : String, content : E.Value } -> Task X.Error Api.CredUpdate
|
||||
sendEvent (Room { room, accessToken, baseUrl, versions }) { eventType, content } =
|
||||
Api.sendMessageEvent
|
||||
|
@ -53,6 +88,8 @@ sendEvent (Room { room, accessToken, baseUrl, versions }) { eventType, content }
|
|||
}
|
||||
|
||||
|
||||
{-| Sends a new text message to the Matrix room associated with the given `Room`.
|
||||
-}
|
||||
sendMessage : Room -> String -> Task X.Error Api.CredUpdate
|
||||
sendMessage (Room { room, accessToken, baseUrl, versions }) text =
|
||||
Api.sendMessageEvent
|
||||
|
|
|
@ -21,6 +21,17 @@ empty hash =
|
|||
Hashdict { hash = hash, values = Dict.empty }
|
||||
|
||||
|
||||
fromList : (a -> String) -> List a -> Hashdict a
|
||||
fromList hash xs =
|
||||
Hashdict
|
||||
{ hash = hash
|
||||
, values =
|
||||
xs
|
||||
|> List.map (\x -> ( hash x, x ))
|
||||
|> Dict.fromList
|
||||
}
|
||||
|
||||
|
||||
get : String -> Hashdict a -> Maybe a
|
||||
get k (Hashdict h) =
|
||||
Dict.get k h.values
|
||||
|
@ -36,6 +47,14 @@ keys (Hashdict h) =
|
|||
Dict.keys h.values
|
||||
|
||||
|
||||
union : Hashdict a -> Hashdict a -> Hashdict a
|
||||
union (Hashdict h1) (Hashdict h2) =
|
||||
Hashdict
|
||||
{ hash = h1.hash
|
||||
, values = Dict.union h1.values h2.values
|
||||
}
|
||||
|
||||
|
||||
values : Hashdict a -> List a
|
||||
values (Hashdict h) =
|
||||
Dict.values h.values
|
||||
|
|
|
@ -22,23 +22,23 @@ HTTP call that needs that value.
|
|||
import Task exposing (Task)
|
||||
|
||||
|
||||
{-| A ValueGetter type takes care of values that MIGHT be available.
|
||||
{-| A ValueGetter x type takes care of values that MIGHT be available.
|
||||
If a value is not available, then the task can be used to get a new value.
|
||||
-}
|
||||
type alias ValueGetter a =
|
||||
type alias ValueGetter x a =
|
||||
{ value : Maybe a, getValue : Task x a }
|
||||
|
||||
|
||||
{-| Convert a `ValueGetter` type to a task. If a previous value has already been given,
|
||||
then use that value. Otherwise, use the `getValue` task to get a new value.
|
||||
-}
|
||||
toTask : ValueGetter a -> Task x a
|
||||
toTask : ValueGetter x a -> Task x a
|
||||
toTask { value, getValue } =
|
||||
Maybe.map Task.succeed value
|
||||
|> Maybe.withDefault getValue
|
||||
|
||||
|
||||
withInfo : (a -> Task x result) -> ValueGetter a -> Task x result
|
||||
withInfo : (a -> Task x result) -> ValueGetter x a -> Task x result
|
||||
withInfo task info1 =
|
||||
Task.andThen
|
||||
(\a ->
|
||||
|
@ -49,8 +49,8 @@ withInfo task info1 =
|
|||
|
||||
withInfo2 :
|
||||
(a -> b -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> Task x result
|
||||
withInfo2 task info1 info2 =
|
||||
Task.andThen
|
||||
|
@ -66,9 +66,9 @@ withInfo2 task info1 info2 =
|
|||
|
||||
withInfo3 :
|
||||
(a -> b -> c -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> Task x result
|
||||
withInfo3 task info1 info2 info3 =
|
||||
Task.andThen
|
||||
|
@ -88,10 +88,10 @@ withInfo3 task info1 info2 info3 =
|
|||
|
||||
withInfo4 :
|
||||
(a -> b -> c -> d -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter d
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> ValueGetter x d
|
||||
-> Task x result
|
||||
withInfo4 task info1 info2 info3 info4 =
|
||||
Task.andThen
|
||||
|
@ -115,11 +115,11 @@ withInfo4 task info1 info2 info3 info4 =
|
|||
|
||||
withInfo5 :
|
||||
(a -> b -> c -> d -> e -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter d
|
||||
-> ValueGetter e
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> ValueGetter x d
|
||||
-> ValueGetter x e
|
||||
-> Task x result
|
||||
withInfo5 task info1 info2 info3 info4 info5 =
|
||||
Task.andThen
|
||||
|
@ -147,12 +147,12 @@ withInfo5 task info1 info2 info3 info4 info5 =
|
|||
|
||||
withInfo6 :
|
||||
(a -> b -> c -> d -> e -> f -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter d
|
||||
-> ValueGetter e
|
||||
-> ValueGetter f
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> ValueGetter x d
|
||||
-> ValueGetter x e
|
||||
-> ValueGetter x f
|
||||
-> Task x result
|
||||
withInfo6 task info1 info2 info3 info4 info5 info6 =
|
||||
Task.andThen
|
||||
|
@ -184,13 +184,13 @@ withInfo6 task info1 info2 info3 info4 info5 info6 =
|
|||
|
||||
withInfo7 :
|
||||
(a -> b -> c -> d -> e -> f -> g -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter d
|
||||
-> ValueGetter e
|
||||
-> ValueGetter f
|
||||
-> ValueGetter g
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> ValueGetter x d
|
||||
-> ValueGetter x e
|
||||
-> ValueGetter x f
|
||||
-> ValueGetter x g
|
||||
-> Task x result
|
||||
withInfo7 task info1 info2 info3 info4 info5 info6 info7 =
|
||||
Task.andThen
|
||||
|
@ -226,14 +226,14 @@ withInfo7 task info1 info2 info3 info4 info5 info6 info7 =
|
|||
|
||||
withInfo8 :
|
||||
(a -> b -> c -> d -> e -> f -> g -> h -> Task x result)
|
||||
-> ValueGetter a
|
||||
-> ValueGetter b
|
||||
-> ValueGetter c
|
||||
-> ValueGetter d
|
||||
-> ValueGetter e
|
||||
-> ValueGetter f
|
||||
-> ValueGetter g
|
||||
-> ValueGetter h
|
||||
-> ValueGetter x a
|
||||
-> ValueGetter x b
|
||||
-> ValueGetter x c
|
||||
-> ValueGetter x d
|
||||
-> ValueGetter x e
|
||||
-> ValueGetter x f
|
||||
-> ValueGetter x g
|
||||
-> ValueGetter x h
|
||||
-> Task x result
|
||||
withInfo8 task info1 info2 info3 info4 info5 info6 info7 info8 =
|
||||
Task.andThen
|
||||
|
|
|
@ -14,6 +14,20 @@ type Credentials
|
|||
= Credentials { access : AccessToken, baseUrl : String, rooms : Hashdict Room, versions : Maybe V.Versions }
|
||||
|
||||
|
||||
{-| Add a new access token based on prior information.
|
||||
-}
|
||||
addAccessToken : String -> Credentials -> Credentials
|
||||
addAccessToken token (Credentials ({ access } as data)) =
|
||||
Credentials { data | access = Login.addToken token access }
|
||||
|
||||
|
||||
{-| Add the list of versions that is supported by the homeserver.
|
||||
-}
|
||||
addVersions : V.Versions -> Credentials -> Credentials
|
||||
addVersions versions (Credentials data) =
|
||||
Credentials { data | versions = Just versions }
|
||||
|
||||
|
||||
{-| Get the stringed access token the Credentials type is using, if any.
|
||||
-}
|
||||
getAccessToken : Credentials -> Maybe String
|
||||
|
|
|
@ -23,6 +23,27 @@ type Event
|
|||
}
|
||||
|
||||
|
||||
init :
|
||||
{ content : E.Value
|
||||
, eventId : String
|
||||
, originServerTs : Timestamp
|
||||
, roomId : String
|
||||
, sender : String
|
||||
, stateKey : Maybe String
|
||||
, contentType : String
|
||||
, unsigned :
|
||||
Maybe
|
||||
{ age : Maybe Int
|
||||
, prevContent : Maybe E.Value
|
||||
, redactedBecause : Maybe Event
|
||||
, transactionId : Maybe String
|
||||
}
|
||||
}
|
||||
-> Event
|
||||
init =
|
||||
Event
|
||||
|
||||
|
||||
|
||||
{- GETTER FUNCTIONS -}
|
||||
|
||||
|
@ -74,12 +95,6 @@ redactedBecause (Event e) =
|
|||
|> Maybe.andThen .redactedBecause
|
||||
|
||||
|
||||
age : Event -> Maybe Int
|
||||
age (Event e) =
|
||||
e.unsigned
|
||||
|> Maybe.andThen .age
|
||||
|
||||
|
||||
transactionId : Event -> Maybe String
|
||||
transactionId (Event e) =
|
||||
e.unsigned
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Internal.Values.Room exposing (..)
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
|
||||
import Internal.Tools.SpecEnums exposing (SessionDescriptionType(..))
|
||||
import Internal.Values.Event as Event exposing (BlindEvent, Event)
|
||||
import Internal.Values.StateManager exposing (StateManager)
|
||||
|
@ -12,12 +13,19 @@ type Room
|
|||
= Room
|
||||
{ accountData : Dict String E.Value
|
||||
, ephemeral : List BlindEvent
|
||||
, events : Dict String Event
|
||||
, events : Hashdict Event
|
||||
, roomId : String
|
||||
, timeline : Timeline
|
||||
}
|
||||
|
||||
|
||||
{-| Add the data of a single event to the hashdict of events.
|
||||
-}
|
||||
addEvent : Event -> Room -> Room
|
||||
addEvent event (Room ({ events } as room)) =
|
||||
Room { room | events = Hashdict.insert event events }
|
||||
|
||||
|
||||
{-| Add new events as the most recent events.
|
||||
-}
|
||||
addEvents :
|
||||
|
@ -31,11 +39,7 @@ addEvents :
|
|||
addEvents ({ events } as data) (Room room) =
|
||||
Room
|
||||
{ room
|
||||
| events =
|
||||
events
|
||||
|> List.map (\e -> ( Event.eventId e, e ))
|
||||
|> Dict.fromList
|
||||
|> (\x -> Dict.union x room.events)
|
||||
| events = List.foldl Hashdict.insert room.events events
|
||||
, timeline = Timeline.addNewEvents data room.timeline
|
||||
}
|
||||
|
||||
|
@ -44,7 +48,7 @@ addEvents ({ events } as data) (Room room) =
|
|||
-}
|
||||
getEventById : String -> Room -> Maybe Event
|
||||
getEventById eventId (Room room) =
|
||||
Dict.get eventId room.events
|
||||
Hashdict.get eventId room.events
|
||||
|
||||
|
||||
{-| Get the room's id.
|
||||
|
|
Loading…
Reference in New Issue