Add reader functions for Event types

3-event
Bram van den Heuvel 2023-12-22 16:59:45 +01:00
parent 14058f4b69
commit ce83d1260f
2 changed files with 142 additions and 23 deletions

View File

@ -1,5 +1,6 @@
module Internal.Values.Event exposing module Internal.Values.Event exposing
( Event ( Event
, content, eventId, eventType, originServerTs, roomId, sender, stateKey
, UnsignedData, age, prevContent, redactedBecause, transactionId , UnsignedData, age, prevContent, redactedBecause, transactionId
, encode, decoder , encode, decoder
) )
@ -15,6 +16,11 @@ of a room.
@docs Event @docs Event
## Get information
@docs content, eventId, eventType, originServerTs, roomId, sender, stateKey
## Unsigned data ## Unsigned data
@docs UnsignedData, age, prevContent, redactedBecause, transactionId @docs UnsignedData, age, prevContent, redactedBecause, transactionId
@ -30,6 +36,7 @@ import Internal.Config.Default as Default
import Internal.Tools.Decode as D import Internal.Tools.Decode as D
import Internal.Tools.Encode as E import Internal.Tools.Encode as E
import Internal.Tools.Timestamp as Timestamp exposing (Timestamp) import Internal.Tools.Timestamp as Timestamp exposing (Timestamp)
import Internal.Values.Envelope as Envelope
import Json.Decode as D import Json.Decode as D
import Json.Encode as E import Json.Encode as E
@ -37,6 +44,10 @@ import Json.Encode as E
{-| The Event type occurs everywhere on a user's timeline. {-| The Event type occurs everywhere on a user's timeline.
-} -}
type alias Event = type alias Event =
Envelope.Envelope IEvent
type alias IEvent =
{ content : E.Value { content : E.Value
, eventId : String , eventId : String
, originServerTs : Timestamp , originServerTs : Timestamp
@ -63,15 +74,30 @@ type UnsignedData
{-| Get the event's age, if at all provided by the homeserver. {-| Get the event's age, if at all provided by the homeserver.
-} -}
age : Event -> Maybe Int age : Event -> Maybe Int
age event = age envelope =
Maybe.andThen (\(UnsignedData data) -> data.age) event.unsigned Envelope.extract
(\event ->
Maybe.andThen
(\(UnsignedData data) -> data.age)
event.unsigned
)
envelope
{-| The Matrix protocol revolves around users being able to send each other
JSON objects. This function reveals the JSON value that the user has sent to
the room.
-}
content : Event -> E.Value
content =
Envelope.extract .content
{-| Decode an Event from a JSON value. {-| Decode an Event from a JSON value.
-} -}
decoder : D.Decoder Event decoder : D.Decoder Event
decoder = decoder =
D.map8 Event D.map8 IEvent
(D.field "content" D.value) (D.field "content" D.value)
(D.field "eventId" D.string) (D.field "eventId" D.string)
(D.field "originServerTs" Timestamp.decoder) (D.field "originServerTs" Timestamp.decoder)
@ -80,6 +106,7 @@ decoder =
(D.opField "stateKey" D.string) (D.opField "stateKey" D.string)
(D.field "eventType" D.string) (D.field "eventType" D.string)
(D.opField "unsigned" decoderUnsignedData) (D.opField "unsigned" decoderUnsignedData)
|> Envelope.decoder
{-| Decode Unsigned Data from a JSON value. {-| Decode Unsigned Data from a JSON value.
@ -96,7 +123,9 @@ decoderUnsignedData =
{-| Encode an Event into a JSON value. {-| Encode an Event into a JSON value.
-} -}
encode : Event -> E.Value encode : Event -> E.Value
encode event = encode envelope =
Envelope.encode
(\event ->
E.maybeObject E.maybeObject
[ ( "content", Just event.content ) [ ( "content", Just event.content )
, ( "eventId", Just <| E.string event.eventId ) , ( "eventId", Just <| E.string event.eventId )
@ -108,6 +137,8 @@ encode event =
, ( "unsigned", Maybe.map encodeUnsignedData event.unsigned ) , ( "unsigned", Maybe.map encodeUnsignedData event.unsigned )
, ( "version", Just <| E.string Default.currentVersion ) , ( "version", Just <| E.string Default.currentVersion )
] ]
)
envelope
{-| Encode Unsigned Data into a JSON value. {-| Encode Unsigned Data into a JSON value.
@ -122,24 +153,105 @@ encodeUnsignedData (UnsignedData data) =
] ]
{-| Every event is assigned a unique id in the room. You can use this event id
to reference or look up events.
-}
eventId : Event -> String
eventId =
Envelope.extract .eventId
{-| To give a hint what the event's [content](#content) might look like, users
can use this eventType value to hint at how the JSON might be decoded.
Standard examples of event types are `m.room.message`, `m.room.member` and
`me.noordstar.game.chess.move`.
-}
eventType : Event -> String
eventType =
Envelope.extract .eventType
{-| Timestamp of at what time the event was originally received by the original
homeserver.
Generally, this timestamp offers a relalatively accurate indicator of when a
message was sent. However, this number isn't completely reliable! The timestamp
can be far in the past due to long network lag, and a (malicious) homeserver can
spoof this number to make it seem like something was sent ridiculously far in
the past - or even in the future.
-}
originServerTs : Event -> Timestamp
originServerTs =
Envelope.extract .originServerTs
{-| Get the old content, if the event has changed or it has been edited. {-| Get the old content, if the event has changed or it has been edited.
-} -}
prevContent : Event -> Maybe E.Value prevContent : Event -> Maybe E.Value
prevContent event = prevContent envelope =
Maybe.andThen (\(UnsignedData data) -> data.prevContent) event.unsigned Envelope.extract
(\event ->
Maybe.andThen
(\(UnsignedData data) -> data.prevContent)
event.unsigned
)
envelope
{-| If the event has been redacted, the homeserver can display the event that {-| If the event has been redacted, the homeserver can display the event that
redacted it here. redacted it here.
-} -}
redactedBecause : Event -> Maybe Event redactedBecause : Event -> Maybe Event
redactedBecause event = redactedBecause envelope =
Maybe.andThen (\(UnsignedData data) -> data.redactedBecause) event.unsigned Envelope.extract
(\event ->
Maybe.andThen
(\(UnsignedData data) -> data.redactedBecause)
event.unsigned
)
envelope
{-| Unique id assigned to the Matrix room. You can use this room id to reference
or look up rooms.
-}
roomId : Event -> String
roomId =
Envelope.extract .roomId
{-| User id of the user that sent this event. You can use this user id to
reference or look up users.
-}
sender : Event -> String
sender =
Envelope.extract .sender
{-| When an event's state key is `Nothing`, it is an ordinary message event in
the timeline.
When the state key is `Just ""` or some other `Just string`, then it is a state
event that affects how the room works. TODO: Explain state events.
-}
stateKey : Event -> Maybe String
stateKey =
Envelope.extract .stateKey
{-| If the user has sent this event to the homeserver, then the homeserver might {-| If the user has sent this event to the homeserver, then the homeserver might
display the original transaction id used for the event. display the original transaction id used for the event.
-} -}
transactionId : Event -> Maybe String transactionId : Event -> Maybe String
transactionId event = transactionId envelope =
Maybe.andThen (\(UnsignedData data) -> data.transactionId) event.unsigned Envelope.extract
(\event ->
Maybe.andThen
(\(UnsignedData data) -> data.transactionId)
event.unsigned
)
envelope

View File

@ -1,4 +1,4 @@
module Types exposing (Vault(..)) module Types exposing (Vault(..), Event(..))
{-| The Elm SDK uses a lot of records and values that are easy to manipulate. {-| The Elm SDK uses a lot of records and values that are easy to manipulate.
Yet, the [Elm design guidelines](https://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret) Yet, the [Elm design guidelines](https://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret)
@ -12,13 +12,20 @@ access their content directly.
The opaque types are placed in a central module so all exposed modules can The opaque types are placed in a central module so all exposed modules can
safely access all exposed data types without risking to create circular imports. safely access all exposed data types without risking to create circular imports.
@docs Vault @docs Vault, Event
-} -}
import Internal.Values.Event as Event
import Internal.Values.Vault as Vault import Internal.Values.Vault as Vault
{-| Opaque type for Matrix Event
-}
type Event
= Event Event.Event
{-| Opaque type for Matrix Vault {-| Opaque type for Matrix Vault
-} -}
type Vault type Vault