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
( Event
, content, eventId, eventType, originServerTs, roomId, sender, stateKey
, UnsignedData, age, prevContent, redactedBecause, transactionId
, encode, decoder
)
@ -15,6 +16,11 @@ of a room.
@docs Event
## Get information
@docs content, eventId, eventType, originServerTs, roomId, sender, stateKey
## Unsigned data
@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.Encode as E
import Internal.Tools.Timestamp as Timestamp exposing (Timestamp)
import Internal.Values.Envelope as Envelope
import Json.Decode as D
import Json.Encode as E
@ -37,6 +44,10 @@ import Json.Encode as E
{-| The Event type occurs everywhere on a user's timeline.
-}
type alias Event =
Envelope.Envelope IEvent
type alias IEvent =
{ content : E.Value
, eventId : String
, originServerTs : Timestamp
@ -63,15 +74,30 @@ type UnsignedData
{-| Get the event's age, if at all provided by the homeserver.
-}
age : Event -> Maybe Int
age event =
Maybe.andThen (\(UnsignedData data) -> data.age) event.unsigned
age envelope =
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.
-}
decoder : D.Decoder Event
decoder =
D.map8 Event
D.map8 IEvent
(D.field "content" D.value)
(D.field "eventId" D.string)
(D.field "originServerTs" Timestamp.decoder)
@ -80,6 +106,7 @@ decoder =
(D.opField "stateKey" D.string)
(D.field "eventType" D.string)
(D.opField "unsigned" decoderUnsignedData)
|> Envelope.decoder
{-| Decode Unsigned Data from a JSON value.
@ -96,18 +123,22 @@ decoderUnsignedData =
{-| Encode an Event into a JSON value.
-}
encode : Event -> E.Value
encode event =
E.maybeObject
[ ( "content", Just event.content )
, ( "eventId", Just <| E.string event.eventId )
, ( "originServerTs", Just <| Timestamp.encode event.originServerTs )
, ( "roomId", Just <| E.string event.roomId )
, ( "sender", Just <| E.string event.sender )
, ( "stateKey", Maybe.map E.string event.stateKey )
, ( "eventType", Just <| E.string event.eventType )
, ( "unsigned", Maybe.map encodeUnsignedData event.unsigned )
, ( "version", Just <| E.string Default.currentVersion )
]
encode envelope =
Envelope.encode
(\event ->
E.maybeObject
[ ( "content", Just event.content )
, ( "eventId", Just <| E.string event.eventId )
, ( "originServerTs", Just <| Timestamp.encode event.originServerTs )
, ( "roomId", Just <| E.string event.roomId )
, ( "sender", Just <| E.string event.sender )
, ( "stateKey", Maybe.map E.string event.stateKey )
, ( "eventType", Just <| E.string event.eventType )
, ( "unsigned", Maybe.map encodeUnsignedData event.unsigned )
, ( "version", Just <| E.string Default.currentVersion )
]
)
envelope
{-| 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.
-}
prevContent : Event -> Maybe E.Value
prevContent event =
Maybe.andThen (\(UnsignedData data) -> data.prevContent) event.unsigned
prevContent envelope =
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
redacted it here.
-}
redactedBecause : Event -> Maybe Event
redactedBecause event =
Maybe.andThen (\(UnsignedData data) -> data.redactedBecause) event.unsigned
redactedBecause envelope =
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
display the original transaction id used for the event.
-}
transactionId : Event -> Maybe String
transactionId event =
Maybe.andThen (\(UnsignedData data) -> data.transactionId) event.unsigned
transactionId envelope =
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.
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
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
{-| Opaque type for Matrix Event
-}
type Event
= Event Event.Event
{-| Opaque type for Matrix Vault
-}
type Vault