Add Matrix.Room

3-room
Bram 2024-04-26 11:31:35 +02:00
parent c309461602
commit df71779620
5 changed files with 152 additions and 20 deletions

View File

@ -9,6 +9,7 @@
"Internal.Values.Timeline",
"Matrix",
"Matrix.Event",
"Matrix.Room",
"Matrix.Settings",
"Matrix.User"
],

View File

@ -1,7 +1,8 @@
module Internal.Values.Room exposing
( Room, init
, Batch, addBatch, addSync, addEvents
, Batch, addBatch, addSync, addEvents, mostRecentEvents
, getAccountData, setAccountData
, coder, encode, decode
)
{-|
@ -26,19 +27,24 @@ room state reflect the homeserver state of the room.
## Timeline
@docs Batch, addBatch, addSync, addEvents
@docs Batch, addBatch, addSync, addEvents, mostRecentEvents
## Account data
@docs getAccountData, setAccountData
## JSON coding
@docs coder, encode, decode
-}
import FastDict as Dict exposing (Dict)
import Internal.Config.Log exposing (log)
import Internal.Config.Text as Text
import Internal.Filter.Timeline exposing (Filter)
import Internal.Filter.Timeline as Filter exposing (Filter)
import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
import Internal.Tools.Json as Json
import Internal.Values.Event as Event exposing (Event)
@ -166,6 +172,20 @@ coder =
)
{-| Decode a Room from JSON format.
-}
decode : Json.Decoder Room
decode =
Json.decode coder
{-| Encode a Room into JSON format.
-}
encode : Json.Encoder Room
encode =
Json.encode coder
{-| Get a piece of account data as information from the room.
-}
getAccountData : String -> Room -> Maybe Json.Value
@ -185,6 +205,19 @@ init roomId =
}
{-| Get the most recent events from the timeline.
-}
mostRecentEvents : Room -> List Event
mostRecentEvents room =
room.timeline
|> Timeline.mostRecentEvents Filter.pass
|> List.map (List.filterMap (\e -> Hashdict.get e room.events))
|> List.sortBy List.length
-- Get the largest list of events
|> List.head
|> Maybe.withDefault []
{-| Set a piece of account data as information about the room.
-}
setAccountData : String -> Json.Value -> Room -> Room

64
src/Matrix/Room.elm Normal file
View File

@ -0,0 +1,64 @@
module Matrix.Room exposing
( Room, mostRecentEvents
, getAccountData
)
{-|
# Room
What is usually called a chat, a channel, a conversation or a group chat on
other platforms, the term used in Matrix is a "room". A room is a conversation
where a group of users talk to each other.
@docs Room, mostRecentEvents
This module exposes various functions that help you inspect various aspects of
a room.
## Account data
Account data is personal information that the user stores about this Matrix
room. This may include information like:
- What type of room this is
- A list of members in the room to ignore
- A list of currently ongoing chess matches in the room
- Personal notes the user may be taking
You may consider the account data as a `Dict String Json.Value` type. Account
data is linked to the user account: other logged in devices can see the account
data too, as the server synchronizes it, but the server shouldn´t show it to
other users.
@docs getAccountData
-}
import Internal.Values.Envelope as Envelope
import Internal.Values.Room as Internal
import Json.Encode as E
import Types exposing (Room(..))
{-| The Matrix Room type representing a room that the Matrix user has joined.
-}
type alias Room =
Types.Room
{-| Get a piece of account data linked to a certain string key.
-}
getAccountData : String -> Room -> Maybe E.Value
getAccountData key (Room room) =
Envelope.extract (Internal.getAccountData key) room
{-| Get a list of the most recent events sent in the room.
-}
mostRecentEvents : Room -> List Types.Event
mostRecentEvents (Room room) =
Envelope.mapList Internal.mostRecentEvents room
|> List.map Types.Event

View File

@ -1,4 +1,4 @@
module Types exposing (Vault(..), Event(..), User(..))
module Types exposing (Vault(..), Event(..), Room(..), User(..))
{-| 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,12 +12,13 @@ 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, Event, User
@docs Vault, Event, Room, User
-}
import Internal.Values.Envelope as Envelope
import Internal.Values.Event as Event
import Internal.Values.Room as Room
import Internal.Values.User as User
import Internal.Values.Vault as Vault
@ -28,6 +29,12 @@ type Event
= Event (Envelope.Envelope Event.Event)
{-| Opaque type for Matrix Room
-}
type Room
= Room (Envelope.Envelope Room.Room)
{-| Opaque type for Matrix User
-}
type User

View File

@ -1,16 +1,19 @@
module Test.Values.Room exposing (..)
import Test exposing (..)
import Expect
import Fuzz exposing (Fuzzer)
import Internal.Values.Room as Room exposing (Room)
import Test.Values.Event as TestEvent
import Test.Filter.Timeline as TestFilter
import Json.Encode as E
import Json.Decode as D
import Expect
import Json.Encode as E
import Test exposing (..)
import Test.Filter.Timeline as TestFilter
import Test.Values.Event as TestEvent
placeholderValue : E.Value
placeholderValue = E.string "foo bar baz"
placeholderValue =
E.string "foo bar baz"
fuzzer : Fuzzer Room
fuzzer =
@ -18,17 +21,24 @@ fuzzer =
|> Fuzz.map Room.init
|> addAFewTimes Fuzz.string (\key -> Room.setAccountData key placeholderValue)
|> addAFewTimes (Fuzz.list TestEvent.fuzzer) Room.addEvents
|> add4AFewTimes (Fuzz.list TestEvent.fuzzer) TestFilter.fuzzer (Fuzz.maybe Fuzz.string) Fuzz.string
|> add4AFewTimes (Fuzz.list TestEvent.fuzzer)
TestFilter.fuzzer
(Fuzz.maybe Fuzz.string)
Fuzz.string
(\a b c d ->
Room.Batch a b c d
|> Room.addBatch
)
|> add4AFewTimes (Fuzz.list TestEvent.fuzzer) TestFilter.fuzzer (Fuzz.maybe Fuzz.string) Fuzz.string
|> add4AFewTimes (Fuzz.list TestEvent.fuzzer)
TestFilter.fuzzer
(Fuzz.maybe Fuzz.string)
Fuzz.string
(\a b c d ->
Room.Batch a b c d
|> Room.addSync
)
addAFewTimes : Fuzzer a -> (a -> Room -> Room) -> Fuzzer Room -> Fuzzer Room
addAFewTimes fuzz f roomFuzzer =
Fuzz.map2
@ -36,31 +46,38 @@ addAFewTimes fuzz f roomFuzzer =
(Fuzz.list fuzz)
roomFuzzer
add2AFewTimes : Fuzzer a -> Fuzzer b -> (a -> b -> Room -> Room) -> Fuzzer Room -> Fuzzer Room
add2AFewTimes fuzz1 fuzz2 f roomFuzzer =
Fuzz.map2
(\items room -> List.foldl (\(a, b) -> f a b) room items)
( Fuzz.list <| Fuzz.pair fuzz1 fuzz2 )
(\items room -> List.foldl (\( a, b ) -> f a b) room items)
(Fuzz.list <| Fuzz.pair fuzz1 fuzz2)
roomFuzzer
add3AFewTimes : Fuzzer a -> Fuzzer b -> Fuzzer c -> (a -> b -> c -> Room -> Room) -> Fuzzer Room -> Fuzzer Room
add3AFewTimes fuzz1 fuzz2 fuzz3 f roomFuzzer =
Fuzz.map2
(\items room -> List.foldl (\(a, b, c) -> f a b c) room items)
( Fuzz.list <| Fuzz.triple fuzz1 fuzz2 fuzz3 )
(\items room -> List.foldl (\( a, b, c ) -> f a b c) room items)
(Fuzz.list <| Fuzz.triple fuzz1 fuzz2 fuzz3)
roomFuzzer
add4AFewTimes : Fuzzer a -> Fuzzer b -> Fuzzer c -> Fuzzer d -> (a -> b -> c -> d -> Room -> Room) -> Fuzzer Room -> Fuzzer Room
add4AFewTimes fuzz1 fuzz2 fuzz3 fuzz4 f roomFuzzer =
Fuzz.map2
(\items room -> List.foldl (\((a, b), (c, d)) -> f a b c d) room items)
( Fuzz.list <| Fuzz.pair (Fuzz.pair fuzz1 fuzz2) (Fuzz.pair fuzz3 fuzz4) )
(\items room -> List.foldl (\( ( a, b ), ( c, d ) ) -> f a b c d) room items)
(Fuzz.list <| Fuzz.pair (Fuzz.pair fuzz1 fuzz2) (Fuzz.pair fuzz3 fuzz4))
roomFuzzer
suite : Test
suite =
describe "Room"
[ fuzz3 fuzzer Fuzz.string Fuzz.string "JSON Account Data can be overridden"
[ fuzz3 fuzzer
Fuzz.string
Fuzz.string
"JSON Account Data can be overridden"
(\room key text ->
room
|> Room.setAccountData key (E.string text)
@ -69,4 +86,14 @@ suite =
|> Maybe.andThen Result.toMaybe
|> Expect.equal (Just text)
)
, fuzz fuzzer
"Room -> JSON -> Room is equal"
(\room ->
room
|> Room.encode
|> D.decodeValue Room.decode
|> Result.toMaybe
|> Maybe.map Tuple.first
|> Expect.equal (Just room)
)
]