Compare commits
	
		
			13 Commits 
		
	
	
		
			487c872d43
			...
			bec1ae4a3b
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						bec1ae4a3b | |
| 
							
							
								 | 
						daf4bcb1b1 | |
| 
							
							
								
								 | 
						b0026617cf | |
| 
							
							
								
								 | 
						7fcef60ec6 | |
| 
							
							
								
								 | 
						2b9370f0c2 | |
| 
							
							
								
								 | 
						12c919b071 | |
| 
							
							
								
								 | 
						567ac5596a | |
| 
							
							
								
								 | 
						b32e0ef123 | |
| 
							
							
								
								 | 
						9e761db4f9 | |
| 
							
							
								
								 | 
						e335c150f0 | |
| 
							
							
								
								 | 
						4349a14a87 | |
| 
							
							
								
								 | 
						42ca8f6c9c | |
| 
							
							
								
								 | 
						ff8b6c043a | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.7 KiB  | 
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					<svg version="1.1" viewBox="0 0 27.9 32" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
 | 
				
			||||||
 | 
					 <title>Matrix (protocol) logo</title>
 | 
				
			||||||
 | 
					 <g transform="translate(-.095 .005)" fill="#040404">
 | 
				
			||||||
 | 
					    <path d="m27.1 31.2v-30.5h-2.19v-0.732h3.04v32h-3.04v-0.732z"/>
 | 
				
			||||||
 | 
					    <g transform="translate(13.95 16) scale(0.03,-0.03)">
 | 
				
			||||||
 | 
					        <polygon fill="#F0AD00" points="-280,-90 0,190 280,-90" transform="translate(0 -210)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#7FD13B" points="-280,-90 0,190 280,-90" transform="translate(-210 0) rotate(-90)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#7FD13B" points="-198,-66 0,132 198,-66" transform="translate(207 207) rotate(-45)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#60B5CC" points="-130,0 0,-130 130,0 0,130" transform="translate(150 0)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#5A6378" points="-191,61 69,61 191,-61 -69,-61" transform="translate(-89 239)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#F0AD00" points="-130,-44 0,86 130,-44" transform="translate(0 106) rotate(-180)"/>
 | 
				
			||||||
 | 
					        <polygon fill="#60B5CC" points="-130,-44 0,86 130,-44" transform="translate(256 -150) rotate(-270)"/>
 | 
				
			||||||
 | 
					    </g>
 | 
				
			||||||
 | 
					    <path d="m0.936 0.732v30.5h2.19v0.732h-3.04v-32h3.03v0.732z"/>
 | 
				
			||||||
 | 
					 </g>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
							
								
								
									
										2
									
								
								elm.json
								
								
								
								
							
							
						
						
									
										2
									
								
								elm.json
								
								
								
								
							| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
    "name": "noordstar/elm-matrix-sdk-beta",
 | 
					    "name": "noordstar/elm-matrix-sdk-beta",
 | 
				
			||||||
    "summary": "Matrix SDK for instant communication. Unstable beta version for testing only.",
 | 
					    "summary": "Matrix SDK for instant communication. Unstable beta version for testing only.",
 | 
				
			||||||
    "license": "EUPL-1.1",
 | 
					    "license": "EUPL-1.1",
 | 
				
			||||||
    "version": "3.1.0",
 | 
					    "version": "3.2.0",
 | 
				
			||||||
    "exposed-modules": [
 | 
					    "exposed-modules": [
 | 
				
			||||||
        "Matrix",
 | 
					        "Matrix",
 | 
				
			||||||
        "Matrix.Event",
 | 
					        "Matrix.Event",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
module Internal.Api.BaseUrl.Api exposing (..)
 | 
					module Internal.Api.BaseUrl.Api exposing (baseUrl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,31 +7,30 @@ module Internal.Api.BaseUrl.Api exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This module looks for the right homeserver address.
 | 
					This module looks for the right homeserver address.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@docs baseUrl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Internal.Api.Chain as C
 | 
					import Internal.Api.Chain as C
 | 
				
			||||||
import Internal.Api.Request as R
 | 
					import Internal.Api.Request as R
 | 
				
			||||||
import Internal.Config.Leaks as L
 | 
					import Internal.Config.Leaks as L
 | 
				
			||||||
import Internal.Config.Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Context as Context
 | 
					import Internal.Values.Context as Context
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
import Internal.Values.Vault as V
 | 
					import Internal.Values.Vault as V
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Get the homeserver base URL of a given server name.
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
baseUrl : BaseUrlInput -> C.TaskChain R.Error (E.EnvelopeUpdate V.VaultUpdate) ph { ph | baseUrl : () }
 | 
					baseUrl : BaseUrlInput -> C.TaskChain R.Error (E.EnvelopeUpdate V.VaultUpdate) ph { ph | baseUrl : () }
 | 
				
			||||||
baseUrl data =
 | 
					baseUrl data =
 | 
				
			||||||
    R.toChain
 | 
					    R.toChain
 | 
				
			||||||
        { logHttp =
 | 
					        { logHttp =
 | 
				
			||||||
            \r ->
 | 
					            \r ->
 | 
				
			||||||
                ( E.HttpRequest r
 | 
					                ( E.HttpRequest r
 | 
				
			||||||
                , String.concat
 | 
					                , Text.logs.httpRequest r.method r.url
 | 
				
			||||||
                    -- TODO: Move this to Internal.Config.Text module
 | 
					 | 
				
			||||||
                    [ "Matrix HTTP: "
 | 
					 | 
				
			||||||
                    , r.method
 | 
					 | 
				
			||||||
                    , " "
 | 
					 | 
				
			||||||
                    , r.url
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
                    |> log.info
 | 
					                    |> log.info
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -48,12 +47,7 @@ baseUrl data =
 | 
				
			||||||
        , toUpdate =
 | 
					        , toUpdate =
 | 
				
			||||||
            \info ->
 | 
					            \info ->
 | 
				
			||||||
                ( E.SetBaseUrl info.homeserver.baseUrl
 | 
					                ( E.SetBaseUrl info.homeserver.baseUrl
 | 
				
			||||||
                , String.concat
 | 
					                , Text.logs.baseUrlFound data.url info.homeserver.baseUrl
 | 
				
			||||||
                    [ "Found baseURL of "
 | 
					 | 
				
			||||||
                    , data.url
 | 
					 | 
				
			||||||
                    , " at address "
 | 
					 | 
				
			||||||
                    , info.homeserver.baseUrl
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
module Internal.Api.Chain exposing
 | 
					module Internal.Api.Chain exposing
 | 
				
			||||||
    ( TaskChain, CompleteChain
 | 
					    ( TaskChain, CompleteChain
 | 
				
			||||||
    , IdemChain, toTask
 | 
					    , IdemChain, toTask
 | 
				
			||||||
    , fail, succeed, andThen, catchWith
 | 
					    , fail, succeed, andThen, catchWith, maybe
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ avoid leaking values passing through the API in unexpected ways.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Operations
 | 
					## Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs fail, succeed, andThen, catchWith
 | 
					@docs fail, succeed, andThen, catchWith, maybe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ retrieve this event e.g. by being a member in the room for this event.
 | 
				
			||||||
import Internal.Api.Api as A
 | 
					import Internal.Api.Api as A
 | 
				
			||||||
import Internal.Api.Request as R
 | 
					import Internal.Api.Request as R
 | 
				
			||||||
import Internal.Config.Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Tools.Timestamp as Timestamp
 | 
					import Internal.Tools.Timestamp as Timestamp
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
| 
						 | 
					@ -85,7 +86,7 @@ getEventV1 { eventId, roomId } =
 | 
				
			||||||
            \event ->
 | 
					            \event ->
 | 
				
			||||||
                ( E.ContentUpdate <| V.MapRoom roomId (Room.AddEvent event)
 | 
					                ( E.ContentUpdate <| V.MapRoom roomId (Room.AddEvent event)
 | 
				
			||||||
                , event.eventId
 | 
					                , event.eventId
 | 
				
			||||||
                    |> (++) "Received event id "
 | 
					                    |> Text.logs.getEventId
 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -109,7 +110,7 @@ getEventV2 { eventId, roomId } =
 | 
				
			||||||
            \event ->
 | 
					            \event ->
 | 
				
			||||||
                ( E.ContentUpdate <| V.MapRoom roomId (Room.AddEvent event)
 | 
					                ( E.ContentUpdate <| V.MapRoom roomId (Room.AddEvent event)
 | 
				
			||||||
                , event.eventId
 | 
					                , event.eventId
 | 
				
			||||||
                    |> (++) "Received event id "
 | 
					                    |> Text.logs.getEventId
 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@ event to the room.
 | 
				
			||||||
import Internal.Api.Api as A
 | 
					import Internal.Api.Api as A
 | 
				
			||||||
import Internal.Api.Request as R
 | 
					import Internal.Api.Request as R
 | 
				
			||||||
import Internal.Config.Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
import Internal.Values.Room as Room
 | 
					import Internal.Values.Room as Room
 | 
				
			||||||
| 
						 | 
					@ -95,13 +96,7 @@ inviteV1 { roomId, user } =
 | 
				
			||||||
        , toUpdate =
 | 
					        , toUpdate =
 | 
				
			||||||
            always
 | 
					            always
 | 
				
			||||||
                ( E.ContentUpdate <| V.MapRoom roomId (Room.Invite user)
 | 
					                ( E.ContentUpdate <| V.MapRoom roomId (Room.Invite user)
 | 
				
			||||||
                , String.concat
 | 
					                , Text.logs.invitedUser (User.toString user) roomId
 | 
				
			||||||
                    -- TODO: Move to Internal.Config.Text
 | 
					 | 
				
			||||||
                    [ "Invited user "
 | 
					 | 
				
			||||||
                    , User.toString user
 | 
					 | 
				
			||||||
                    , " to room "
 | 
					 | 
				
			||||||
                    , roomId
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -125,13 +120,7 @@ inviteV2 { reason, roomId, user } =
 | 
				
			||||||
        , toUpdate =
 | 
					        , toUpdate =
 | 
				
			||||||
            always
 | 
					            always
 | 
				
			||||||
                ( E.ContentUpdate <| V.MapRoom roomId (Room.Invite user)
 | 
					                ( E.ContentUpdate <| V.MapRoom roomId (Room.Invite user)
 | 
				
			||||||
                , String.concat
 | 
					                , Text.logs.invitedUser (User.toString user) roomId
 | 
				
			||||||
                    -- TODO: Move to Internal.Config.Text
 | 
					 | 
				
			||||||
                    [ "Invited user "
 | 
					 | 
				
			||||||
                    , User.toString user
 | 
					 | 
				
			||||||
                    , " to room "
 | 
					 | 
				
			||||||
                    , roomId
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,8 @@ This module allows the user to log in using a username and password.
 | 
				
			||||||
import Internal.Api.Api as A
 | 
					import Internal.Api.Api as A
 | 
				
			||||||
import Internal.Api.Request as R
 | 
					import Internal.Api.Request as R
 | 
				
			||||||
import Internal.Config.Leaks as L
 | 
					import Internal.Config.Leaks as L
 | 
				
			||||||
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Context as Context
 | 
					import Internal.Values.Context as Context
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
| 
						 | 
					@ -22,6 +24,8 @@ import Internal.Values.Vault as V
 | 
				
			||||||
import Json.Encode as E
 | 
					import Json.Encode as E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Log in using a username and password.
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
loginWithUsernameAndPassword : LoginWithUsernameAndPasswordInput -> A.TaskChain (Phantom a) (Phantom { a | accessToken : () })
 | 
					loginWithUsernameAndPassword : LoginWithUsernameAndPasswordInput -> A.TaskChain (Phantom a) (Phantom { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPassword =
 | 
					loginWithUsernameAndPassword =
 | 
				
			||||||
    A.startWithVersion "r0.0.0" loginWithUsernameAndPasswordV1
 | 
					    A.startWithVersion "r0.0.0" loginWithUsernameAndPasswordV1
 | 
				
			||||||
| 
						 | 
					@ -46,8 +50,10 @@ loginWithUsernameAndPassword =
 | 
				
			||||||
        |> A.versionChain
 | 
					        |> A.versionChain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Context needed for logging in with a username and password
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
type alias Phantom a =
 | 
					type alias Phantom a =
 | 
				
			||||||
    { a | baseUrl : (), versions : () }
 | 
					    { a | baseUrl : (), now : (), versions : () }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type alias LoginWithUsernameAndPasswordInput =
 | 
					type alias LoginWithUsernameAndPasswordInput =
 | 
				
			||||||
| 
						 | 
					@ -159,333 +165,354 @@ type alias PhantomV1 a =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV1 : LoginWithUsernameAndPasswordInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV1 : LoginWithUsernameAndPasswordInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV1 { username, password } context =
 | 
					loginWithUsernameAndPasswordV1 { username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyString "password" password
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                [ R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
        , coder = coderV1
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV1
 | 
				
			||||||
        , path = [ "_matrix", "client", "r0", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "r0", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = Nothing
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = Nothing
 | 
				
			||||||
                        , refresh = out.refreshToken
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = out.refreshToken
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV2 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV2 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV2 { deviceId, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV2 { deviceId, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "device_id" deviceId
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                [ R.bodyOpString "device_id" deviceId
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "string" -- Yup. That's what it says.
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "string" -- Yup. That's what it says.
 | 
				
			||||||
        , coder = coderV2
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV2
 | 
				
			||||||
        , path = [ "_matrix", "client", "r0", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "r0", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = Nothing
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = Nothing
 | 
				
			||||||
                        , refresh = Nothing
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = Nothing
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    , out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map E.SetDeviceId
 | 
					                        , out.deviceId
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetDeviceId
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV3 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV3 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV3 { deviceId, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV3 { deviceId, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "address" Nothing
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "device_id" deviceId
 | 
					                [ R.bodyOpString "address" Nothing
 | 
				
			||||||
            , R.bodyValue "identifier"
 | 
					                , R.bodyOpString "device_id" deviceId
 | 
				
			||||||
                (E.object
 | 
					                , R.bodyValue "identifier"
 | 
				
			||||||
                    [ ( "type", E.string "m.id.user" )
 | 
					                    (E.object
 | 
				
			||||||
                    , ( "user", E.string username )
 | 
					                        [ ( "type", E.string "m.id.user" )
 | 
				
			||||||
                    ]
 | 
					                        , ( "user", E.string username )
 | 
				
			||||||
                )
 | 
					                        ]
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                    )
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
				
			||||||
        , coder = coderV3
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV3
 | 
				
			||||||
        , path = [ "_matrix", "client", "r0", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "r0", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = Nothing
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = Nothing
 | 
				
			||||||
                        , refresh = Nothing
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = Nothing
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    , out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map E.SetDeviceId
 | 
					                        , out.deviceId
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetDeviceId
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV4 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV4 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV4 { deviceId, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV4 { deviceId, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "address" Nothing
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "device_id" deviceId
 | 
					                [ R.bodyOpString "address" Nothing
 | 
				
			||||||
            , R.bodyValue "identifier"
 | 
					                , R.bodyOpString "device_id" deviceId
 | 
				
			||||||
                (E.object
 | 
					                , R.bodyValue "identifier"
 | 
				
			||||||
                    [ ( "type", E.string "m.id.user" )
 | 
					                    (E.object
 | 
				
			||||||
                    , ( "user", E.string username )
 | 
					                        [ ( "type", E.string "m.id.user" )
 | 
				
			||||||
                    ]
 | 
					                        , ( "user", E.string username )
 | 
				
			||||||
                )
 | 
					                        ]
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                    )
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
				
			||||||
        , coder = coderV4
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV4
 | 
				
			||||||
        , path = [ "_matrix", "client", "r0", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "r0", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = Nothing
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = Nothing
 | 
				
			||||||
                        , refresh = Nothing
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = Nothing
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    , out.wellKnown
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map (.homeserver >> .baseUrl)
 | 
					                        , out.wellKnown
 | 
				
			||||||
                        |> Maybe.map E.SetBaseUrl
 | 
					                            |> Maybe.map (.homeserver >> .baseUrl)
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetBaseUrl
 | 
				
			||||||
                    , out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map E.SetDeviceId
 | 
					                        , out.deviceId
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetDeviceId
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV5 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV5 : LoginWithUsernameAndPasswordInputV2 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV5 { deviceId, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV5 { deviceId, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "address" Nothing
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "device_id" deviceId
 | 
					                [ R.bodyOpString "address" Nothing
 | 
				
			||||||
            , R.bodyValue "identifier"
 | 
					                , R.bodyOpString "device_id" deviceId
 | 
				
			||||||
                (E.object
 | 
					                , R.bodyValue "identifier"
 | 
				
			||||||
                    [ ( "type", E.string "m.id.user" )
 | 
					                    (E.object
 | 
				
			||||||
                    , ( "user", E.string username )
 | 
					                        [ ( "type", E.string "m.id.user" )
 | 
				
			||||||
                    ]
 | 
					                        , ( "user", E.string username )
 | 
				
			||||||
                )
 | 
					                        ]
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                    )
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
				
			||||||
        , coder = coderV4
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV4
 | 
				
			||||||
        , path = [ "_matrix", "client", "v3", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "v3", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = Nothing
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = Nothing
 | 
				
			||||||
                        , refresh = Nothing
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = Nothing
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    , out.wellKnown
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map (.homeserver >> .baseUrl)
 | 
					                        , out.wellKnown
 | 
				
			||||||
                        |> Maybe.map E.SetBaseUrl
 | 
					                            |> Maybe.map (.homeserver >> .baseUrl)
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetBaseUrl
 | 
				
			||||||
                    , out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map E.SetDeviceId
 | 
					                        , out.deviceId
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetDeviceId
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV6 : LoginWithUsernameAndPasswordInputV3 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV6 : LoginWithUsernameAndPasswordInputV3 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV6 { deviceId, enableRefreshToken, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV6 { deviceId, enableRefreshToken, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "address" Nothing
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "device_id" deviceId
 | 
					                [ R.bodyOpString "address" Nothing
 | 
				
			||||||
            , R.bodyValue "identifier"
 | 
					                , R.bodyOpString "device_id" deviceId
 | 
				
			||||||
                (E.object
 | 
					                , R.bodyValue "identifier"
 | 
				
			||||||
                    [ ( "type", E.string "m.id.user" )
 | 
					                    (E.object
 | 
				
			||||||
                    , ( "user", E.string username )
 | 
					                        [ ( "type", E.string "m.id.user" )
 | 
				
			||||||
                    ]
 | 
					                        , ( "user", E.string username )
 | 
				
			||||||
                )
 | 
					                        ]
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                    )
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyOpBool "refresh_token" enableRefreshToken
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyOpBool "refresh_token" enableRefreshToken
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
				
			||||||
        , coder = coderV5
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV5
 | 
				
			||||||
        , path = [ "_matrix", "client", "v3", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "v3", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = out.expiresInMs
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = out.expiresInMs
 | 
				
			||||||
                        , refresh = out.refreshToken
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = out.refreshToken
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , out.user
 | 
					                            }
 | 
				
			||||||
                        |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
					                        , out.user
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map (V.SetUser >> E.ContentUpdate)
 | 
				
			||||||
                    , out.wellKnown
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map (.homeserver >> .baseUrl)
 | 
					                        , out.wellKnown
 | 
				
			||||||
                        |> Maybe.map E.SetBaseUrl
 | 
					                            |> Maybe.map (.homeserver >> .baseUrl)
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetBaseUrl
 | 
				
			||||||
                    , out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                        |> Maybe.map E.SetDeviceId
 | 
					                        , out.deviceId
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetDeviceId
 | 
				
			||||||
                    ]
 | 
					                            |> E.Optional
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loginWithUsernameAndPasswordV7 : LoginWithUsernameAndPasswordInputV3 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
					loginWithUsernameAndPasswordV7 : LoginWithUsernameAndPasswordInputV3 i -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
 | 
				
			||||||
loginWithUsernameAndPasswordV7 { deviceId, enableRefreshToken, initialDeviceDisplayName, username, password } context =
 | 
					loginWithUsernameAndPasswordV7 { deviceId, enableRefreshToken, initialDeviceDisplayName, username, password } =
 | 
				
			||||||
    A.request
 | 
					    \context ->
 | 
				
			||||||
        { attributes =
 | 
					        A.request
 | 
				
			||||||
            [ R.bodyOpString "address" Nothing
 | 
					            { attributes =
 | 
				
			||||||
            , R.bodyOpString "device_id" deviceId
 | 
					                [ R.bodyOpString "address" Nothing
 | 
				
			||||||
            , R.bodyValue "identifier"
 | 
					                , R.bodyOpString "device_id" deviceId
 | 
				
			||||||
                (E.object
 | 
					                , R.bodyValue "identifier"
 | 
				
			||||||
                    [ ( "type", E.string "m.id.user" )
 | 
					                    (E.object
 | 
				
			||||||
                    , ( "user", E.string username )
 | 
					                        [ ( "type", E.string "m.id.user" )
 | 
				
			||||||
                    ]
 | 
					                        , ( "user", E.string username )
 | 
				
			||||||
                )
 | 
					                        ]
 | 
				
			||||||
            , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
					                    )
 | 
				
			||||||
            , R.bodyString "password" password
 | 
					                , R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
 | 
				
			||||||
            , R.bodyOpBool "refresh_token" enableRefreshToken
 | 
					                , R.bodyString "password" password
 | 
				
			||||||
            , R.bodyString "type" "m.login.password"
 | 
					                , R.bodyOpBool "refresh_token" enableRefreshToken
 | 
				
			||||||
            , R.bodyString "user" username
 | 
					                , R.bodyString "type" "m.login.password"
 | 
				
			||||||
            , R.onStatusCode 400 "M_UNKNOWN"
 | 
					                , R.bodyString "user" username
 | 
				
			||||||
            , R.onStatusCode 403 "M_FORBIDDEN"
 | 
					                , R.onStatusCode 400 "M_UNKNOWN"
 | 
				
			||||||
            , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
					                , R.onStatusCode 403 "M_FORBIDDEN"
 | 
				
			||||||
            ]
 | 
					                , R.onStatusCode 429 "M_LIMIT_EXCEEDED"
 | 
				
			||||||
        , coder = coderV6
 | 
					                ]
 | 
				
			||||||
        , method = "POST"
 | 
					            , coder = coderV6
 | 
				
			||||||
        , path = [ "_matrix", "client", "v3", "login" ]
 | 
					            , method = "POST"
 | 
				
			||||||
        , contextChange =
 | 
					            , path = [ "_matrix", "client", "v3", "login" ]
 | 
				
			||||||
            \out -> Context.setAccessToken out.accessToken
 | 
					            , contextChange =
 | 
				
			||||||
        , toUpdate =
 | 
					                \out -> Context.setAccessToken out.accessToken
 | 
				
			||||||
            \out ->
 | 
					            , toUpdate =
 | 
				
			||||||
                ( E.More
 | 
					                \out ->
 | 
				
			||||||
                    [ E.SetAccessToken
 | 
					                    ( E.More
 | 
				
			||||||
                        { created = Context.getNow context
 | 
					                        [ E.SetAccessToken
 | 
				
			||||||
                        , expiryMs = out.expiresInMs
 | 
					                            { created = Context.getNow context
 | 
				
			||||||
                        , lastUsed = Context.getNow context
 | 
					                            , expiryMs = out.expiresInMs
 | 
				
			||||||
                        , refresh = out.refreshToken
 | 
					                            , lastUsed = Context.getNow context
 | 
				
			||||||
                        , value = out.accessToken
 | 
					                            , refresh = out.refreshToken
 | 
				
			||||||
                        }
 | 
					                            , value = out.accessToken
 | 
				
			||||||
                    , E.ContentUpdate (V.SetUser out.user)
 | 
					                            }
 | 
				
			||||||
                    , out.wellKnown
 | 
					                        , E.ContentUpdate (V.SetUser out.user)
 | 
				
			||||||
                        |> Maybe.map (.homeserver >> .baseUrl)
 | 
					                        , out.wellKnown
 | 
				
			||||||
                        |> Maybe.map E.SetBaseUrl
 | 
					                            |> Maybe.map (.homeserver >> .baseUrl)
 | 
				
			||||||
                        |> E.Optional
 | 
					                            |> Maybe.map E.SetBaseUrl
 | 
				
			||||||
                    , E.SetDeviceId out.deviceId
 | 
					                            |> E.Optional
 | 
				
			||||||
                    ]
 | 
					                        , E.SetDeviceId out.deviceId
 | 
				
			||||||
                , []
 | 
					                        ]
 | 
				
			||||||
                )
 | 
					                    , Text.logs.loggedInAs username
 | 
				
			||||||
        }
 | 
					                        |> log.debug
 | 
				
			||||||
        context
 | 
					                        |> List.singleton
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
coderV1 : Json.Coder LoginWithUsernameAndPasswordOutputV1
 | 
					coderV1 : Json.Coder LoginWithUsernameAndPasswordOutputV1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,8 @@ import Internal.Values.Context as Context
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Update message type that is being returned.
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
type alias Msg =
 | 
					type alias Msg =
 | 
				
			||||||
    Backpack
 | 
					    Backpack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,25 +13,28 @@ Get the current time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Internal.Api.Api as A
 | 
					import Internal.Api.Api as A
 | 
				
			||||||
import Internal.Config.Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Values.Context as Context
 | 
					import Internal.Values.Context as Context
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
import Task
 | 
					import Task
 | 
				
			||||||
import Time
 | 
					import Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Get the current time and place it in the context.
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
getNow : A.TaskChain a { a | now : () }
 | 
					getNow : A.TaskChain a { a | now : () }
 | 
				
			||||||
getNow _ =
 | 
					getNow =
 | 
				
			||||||
    Task.map
 | 
					    \_ ->
 | 
				
			||||||
        (\now ->
 | 
					        Task.map
 | 
				
			||||||
            { messages = [ E.SetNow now ]
 | 
					            (\now ->
 | 
				
			||||||
            , logs =
 | 
					                { messages = [ E.SetNow now ]
 | 
				
			||||||
                [ "Identified current time at Unix time "
 | 
					                , logs =
 | 
				
			||||||
                , now |> Time.posixToMillis |> String.fromInt
 | 
					                    now
 | 
				
			||||||
                ]
 | 
					                        |> Time.posixToMillis
 | 
				
			||||||
                    |> String.concat
 | 
					                        |> Text.logs.getNow
 | 
				
			||||||
                    |> log.debug
 | 
					                        |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                        |> List.singleton
 | 
				
			||||||
            , contextChange = Context.setNow now
 | 
					                , contextChange = Context.setNow now
 | 
				
			||||||
            }
 | 
					                }
 | 
				
			||||||
        )
 | 
					            )
 | 
				
			||||||
        Time.now
 | 
					            Time.now
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -287,7 +287,7 @@ fullBody value _ =
 | 
				
			||||||
    FullBody value
 | 
					    FullBody value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getBody : List ContextAttr -> Json.Value
 | 
					getBody : List ContextAttr -> Maybe Json.Value
 | 
				
			||||||
getBody attributes =
 | 
					getBody attributes =
 | 
				
			||||||
    attributes
 | 
					    attributes
 | 
				
			||||||
        |> List.filterMap
 | 
					        |> List.filterMap
 | 
				
			||||||
| 
						 | 
					@ -301,19 +301,30 @@ getBody attributes =
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        |> List.reverse
 | 
					        |> List.reverse
 | 
				
			||||||
        |> List.head
 | 
					        |> List.head
 | 
				
			||||||
        |> Maybe.withDefault
 | 
					        |> (\fb ->
 | 
				
			||||||
            (List.filterMap
 | 
					                case fb of
 | 
				
			||||||
                (\attr ->
 | 
					                    Just _ ->
 | 
				
			||||||
                    case attr of
 | 
					                        fb
 | 
				
			||||||
                        BodyParam key value ->
 | 
					 | 
				
			||||||
                            Just ( key, value )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _ ->
 | 
					                    Nothing ->
 | 
				
			||||||
                            Nothing
 | 
					                        case
 | 
				
			||||||
                )
 | 
					                            List.filterMap
 | 
				
			||||||
                attributes
 | 
					                                (\attr ->
 | 
				
			||||||
                |> E.object
 | 
					                                    case attr of
 | 
				
			||||||
            )
 | 
					                                        BodyParam key value ->
 | 
				
			||||||
 | 
					                                            Just ( key, value )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        _ ->
 | 
				
			||||||
 | 
					                                            Nothing
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                                attributes
 | 
				
			||||||
 | 
					                        of
 | 
				
			||||||
 | 
					                            [] ->
 | 
				
			||||||
 | 
					                                Nothing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            head :: tail ->
 | 
				
			||||||
 | 
					                                Just <| E.object (head :: tail)
 | 
				
			||||||
 | 
					           )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getHeaders : List ContextAttr -> List Http.Header
 | 
					getHeaders : List ContextAttr -> List Http.Header
 | 
				
			||||||
| 
						 | 
					@ -479,21 +490,21 @@ rawApiCallResolver decoder statusCodeErrors =
 | 
				
			||||||
                    Http.BadUrl s
 | 
					                    Http.BadUrl s
 | 
				
			||||||
                        |> InternetException
 | 
					                        |> InternetException
 | 
				
			||||||
                        |> Tuple.pair
 | 
					                        |> Tuple.pair
 | 
				
			||||||
                        |> (|>) []
 | 
					                        |> (|>) [ log.error ("Encountered bad URL " ++ s) ]
 | 
				
			||||||
                        |> Err
 | 
					                        |> Err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Http.Timeout_ ->
 | 
					                Http.Timeout_ ->
 | 
				
			||||||
                    Http.Timeout
 | 
					                    Http.Timeout
 | 
				
			||||||
                        |> InternetException
 | 
					                        |> InternetException
 | 
				
			||||||
                        |> Tuple.pair
 | 
					                        |> Tuple.pair
 | 
				
			||||||
                        |> (|>) []
 | 
					                        |> (|>) [ log.error "Encountered timeout - maybe the server is down?" ]
 | 
				
			||||||
                        |> Err
 | 
					                        |> Err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Http.NetworkError_ ->
 | 
					                Http.NetworkError_ ->
 | 
				
			||||||
                    Http.NetworkError
 | 
					                    Http.NetworkError
 | 
				
			||||||
                        |> InternetException
 | 
					                        |> InternetException
 | 
				
			||||||
                        |> Tuple.pair
 | 
					                        |> Tuple.pair
 | 
				
			||||||
                        |> (|>) []
 | 
					                        |> (|>) [ log.error "Encountered a network error - the user might be offline" ]
 | 
				
			||||||
                        |> Err
 | 
					                        |> Err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Http.BadStatus_ metadata body ->
 | 
					                Http.BadStatus_ metadata body ->
 | 
				
			||||||
| 
						 | 
					@ -534,7 +545,10 @@ toChain data apiContext =
 | 
				
			||||||
                        { method = call.method
 | 
					                        { method = call.method
 | 
				
			||||||
                        , headers = getHeaders call.attributes
 | 
					                        , headers = getHeaders call.attributes
 | 
				
			||||||
                        , url = getUrl call
 | 
					                        , url = getUrl call
 | 
				
			||||||
                        , body = Http.jsonBody (getBody call.attributes)
 | 
					                        , body =
 | 
				
			||||||
 | 
					                            getBody call.attributes
 | 
				
			||||||
 | 
					                                |> Maybe.map Http.jsonBody
 | 
				
			||||||
 | 
					                                |> Maybe.withDefault Http.emptyBody
 | 
				
			||||||
                        , resolver = rawApiCallResolver (Json.decode data.coder) (getStatusCodes call.attributes)
 | 
					                        , resolver = rawApiCallResolver (Json.decode data.coder) (getStatusCodes call.attributes)
 | 
				
			||||||
                        , timeout = getTimeout call.attributes
 | 
					                        , timeout = getTimeout call.attributes
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -544,7 +558,10 @@ toChain data apiContext =
 | 
				
			||||||
                        { method = call.method
 | 
					                        { method = call.method
 | 
				
			||||||
                        , headers = getHeaders call.attributes
 | 
					                        , headers = getHeaders call.attributes
 | 
				
			||||||
                        , url = getUrl call
 | 
					                        , url = getUrl call
 | 
				
			||||||
                        , body = Http.jsonBody (getBody call.attributes)
 | 
					                        , body =
 | 
				
			||||||
 | 
					                            getBody call.attributes
 | 
				
			||||||
 | 
					                                |> Maybe.map Http.jsonBody
 | 
				
			||||||
 | 
					                                |> Maybe.withDefault Http.emptyBody
 | 
				
			||||||
                        , resolver =
 | 
					                        , resolver =
 | 
				
			||||||
                            rawApiCallResolver
 | 
					                            rawApiCallResolver
 | 
				
			||||||
                                (Json.decode data.coder
 | 
					                                (Json.decode data.coder
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
module Internal.Api.SendMessageEvent.Api exposing (..)
 | 
					module Internal.Api.SendMessageEvent.Api exposing (Phantom, sendMessageEvent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ module Internal.Api.SendMessageEvent.Api exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This module helps send message events to rooms on the Matrix API.
 | 
					This module helps send message events to rooms on the Matrix API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs Phantom
 | 
					@docs Phantom, sendMessageEvent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,10 +15,13 @@ import Internal.Api.Api as A
 | 
				
			||||||
import Internal.Api.Request as R
 | 
					import Internal.Api.Request as R
 | 
				
			||||||
import Internal.Config.Leaks as L
 | 
					import Internal.Config.Leaks as L
 | 
				
			||||||
import Internal.Config.Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Envelope as E
 | 
					import Internal.Values.Envelope as E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Send a message event to the Matrix room.
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
sendMessageEvent : SendMessageEventInput -> A.TaskChain (Phantom a) (Phantom a)
 | 
					sendMessageEvent : SendMessageEventInput -> A.TaskChain (Phantom a) (Phantom a)
 | 
				
			||||||
sendMessageEvent =
 | 
					sendMessageEvent =
 | 
				
			||||||
    A.startWithVersion "r0.0.0" sendMessageEventV1
 | 
					    A.startWithVersion "r0.0.0" sendMessageEventV1
 | 
				
			||||||
| 
						 | 
					@ -44,8 +47,10 @@ sendMessageEvent =
 | 
				
			||||||
        |> A.versionChain
 | 
					        |> A.versionChain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{-| Context needed for sending a message event
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
type alias Phantom a =
 | 
					type alias Phantom a =
 | 
				
			||||||
    a
 | 
					    { a | accessToken : (), baseUrl : (), versions : () }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type alias PhantomV1 a =
 | 
					type alias PhantomV1 a =
 | 
				
			||||||
| 
						 | 
					@ -80,7 +85,7 @@ type alias SendMessageEventOutputV2 =
 | 
				
			||||||
sendMessageEventV1 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
					sendMessageEventV1 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
				
			||||||
sendMessageEventV1 { content, eventType, roomId, transactionId } =
 | 
					sendMessageEventV1 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
    A.request
 | 
					    A.request
 | 
				
			||||||
        { attributes = [ R.fullBody content ]
 | 
					        { attributes = [ R.accessToken, R.fullBody content ]
 | 
				
			||||||
        , coder = coderV1
 | 
					        , coder = coderV1
 | 
				
			||||||
        , contextChange = always identity
 | 
					        , contextChange = always identity
 | 
				
			||||||
        , method = "PUT"
 | 
					        , method = "PUT"
 | 
				
			||||||
| 
						 | 
					@ -89,9 +94,7 @@ sendMessageEventV1 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
            \out ->
 | 
					            \out ->
 | 
				
			||||||
                ( E.More []
 | 
					                ( E.More []
 | 
				
			||||||
                , out.eventId
 | 
					                , out.eventId
 | 
				
			||||||
                    |> Maybe.map ((++) ", received event id ")
 | 
					                    |> Text.logs.sendEvent
 | 
				
			||||||
                    |> Maybe.withDefault ""
 | 
					 | 
				
			||||||
                    |> (++) "Sent event"
 | 
					 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -101,7 +104,7 @@ sendMessageEventV1 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
sendMessageEventV2 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
					sendMessageEventV2 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
				
			||||||
sendMessageEventV2 { content, eventType, roomId, transactionId } =
 | 
					sendMessageEventV2 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
    A.request
 | 
					    A.request
 | 
				
			||||||
        { attributes = [ R.fullBody content ]
 | 
					        { attributes = [ R.accessToken, R.fullBody content ]
 | 
				
			||||||
        , coder = coderV2
 | 
					        , coder = coderV2
 | 
				
			||||||
        , contextChange = always identity
 | 
					        , contextChange = always identity
 | 
				
			||||||
        , method = "PUT"
 | 
					        , method = "PUT"
 | 
				
			||||||
| 
						 | 
					@ -110,7 +113,8 @@ sendMessageEventV2 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
            \out ->
 | 
					            \out ->
 | 
				
			||||||
                ( E.More []
 | 
					                ( E.More []
 | 
				
			||||||
                , out.eventId
 | 
					                , out.eventId
 | 
				
			||||||
                    |> (++) "Sent event, received event id "
 | 
					                    |> Maybe.Just
 | 
				
			||||||
 | 
					                    |> Text.logs.sendEvent
 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -120,7 +124,7 @@ sendMessageEventV2 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
sendMessageEventV3 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
					sendMessageEventV3 : SendMessageEventInputV1 i -> A.TaskChain (PhantomV1 a) (PhantomV1 a)
 | 
				
			||||||
sendMessageEventV3 { content, eventType, roomId, transactionId } =
 | 
					sendMessageEventV3 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
    A.request
 | 
					    A.request
 | 
				
			||||||
        { attributes = [ R.fullBody content ]
 | 
					        { attributes = [ R.accessToken, R.fullBody content ]
 | 
				
			||||||
        , coder = coderV2
 | 
					        , coder = coderV2
 | 
				
			||||||
        , contextChange = always identity
 | 
					        , contextChange = always identity
 | 
				
			||||||
        , method = "PUT"
 | 
					        , method = "PUT"
 | 
				
			||||||
| 
						 | 
					@ -129,7 +133,8 @@ sendMessageEventV3 { content, eventType, roomId, transactionId } =
 | 
				
			||||||
            \out ->
 | 
					            \out ->
 | 
				
			||||||
                ( E.More []
 | 
					                ( E.More []
 | 
				
			||||||
                , out.eventId
 | 
					                , out.eventId
 | 
				
			||||||
                    |> (++) "Sent event, received event id "
 | 
					                    |> Maybe.Just
 | 
				
			||||||
 | 
					                    |> Text.logs.sendEvent
 | 
				
			||||||
                    |> log.debug
 | 
					                    |> log.debug
 | 
				
			||||||
                    |> List.singleton
 | 
					                    |> List.singleton
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -161,7 +166,7 @@ coderV1 =
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "event_id"
 | 
					            { fieldName = "event_id"
 | 
				
			||||||
            , toField = .eventId
 | 
					            , toField = .eventId
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = [ "A unique identifier for the event." ]
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -174,7 +179,7 @@ coderV2 =
 | 
				
			||||||
        , description =
 | 
					        , description =
 | 
				
			||||||
            [ "This endpoint is used to send a message event to a room. Message events allow access to historical events and pagination, making them suited for \"once-off\" activity in a room."
 | 
					            [ "This endpoint is used to send a message event to a room. Message events allow access to historical events and pagination, making them suited for \"once-off\" activity in a room."
 | 
				
			||||||
            , "The body of the request should be the content object of the event; the fields in this object will vary depending on the type of event."
 | 
					            , "The body of the request should be the content object of the event; the fields in this object will vary depending on the type of event."
 | 
				
			||||||
            , "https://spec.matrix.org/legacy/r0.0.0/client_server.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid"
 | 
					            , "https://spec.matrix.org/legacy/client_server/r0.6.1.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid"
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        , init = always SendMessageEventOutputV2
 | 
					        , init = always SendMessageEventOutputV2
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -192,7 +197,7 @@ coderV2 =
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "event_id"
 | 
					            { fieldName = "event_id"
 | 
				
			||||||
            , toField = .eventId
 | 
					            , toField = .eventId
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = [ "A unique identifier for the event." ]
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ type alias UFTask a b =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Get an access token to talk to the Matrix API
 | 
					{-| Get an access token to talk to the Matrix API
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
getAccessToken : UFTask { a | now : () } { a | accessToken : (), now : () }
 | 
					getAccessToken : UFTask { a | baseUrl : (), now : (), versions : () } { a | accessToken : (), baseUrl : (), now : (), versions : () }
 | 
				
			||||||
getAccessToken c =
 | 
					getAccessToken c =
 | 
				
			||||||
    case Context.fromApiFormat c of
 | 
					    case Context.fromApiFormat c of
 | 
				
			||||||
        context ->
 | 
					        context ->
 | 
				
			||||||
| 
						 | 
					@ -149,11 +149,43 @@ finishTask uftask =
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        |> C.catchWith
 | 
					        |> C.catchWith
 | 
				
			||||||
            (\_ ->
 | 
					            (\e ->
 | 
				
			||||||
                { messages = [] -- TODO: Maybe categorize errors?
 | 
					                case e of
 | 
				
			||||||
                , logs = [ log.warn "Encountered unhandled error" ]
 | 
					                    Request.MissingPassword ->
 | 
				
			||||||
                , contextChange = Context.reset
 | 
					                        { messages = []
 | 
				
			||||||
                }
 | 
					                        , logs = [ log.error "Cannot log in - password is missing" ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Request.MissingUsername ->
 | 
				
			||||||
 | 
					                        { messages = []
 | 
				
			||||||
 | 
					                        , logs = [ log.error "Cannot log in - username is missing" ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Request.NoSupportedVersion ->
 | 
				
			||||||
 | 
					                        { messages = []
 | 
				
			||||||
 | 
					                        , logs = [ log.error "No supported version is available to complete the API interaction." ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Request.ServerReturnsBadJSON t ->
 | 
				
			||||||
 | 
					                        { messages = []
 | 
				
			||||||
 | 
					                        , logs = [ log.error ("The server returned invalid JSON: " ++ t) ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Request.ServerReturnsError name _ ->
 | 
				
			||||||
 | 
					                        { messages = []
 | 
				
			||||||
 | 
					                        , logs = [ log.error ("The server returns an error: " ++ name) ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    _ ->
 | 
				
			||||||
 | 
					                        { messages = [] -- TODO: Maybe categorize errors?
 | 
				
			||||||
 | 
					                        , logs = [ log.warn "Encountered unhandled error" ]
 | 
				
			||||||
 | 
					                        , contextChange = Context.reset
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ will assume until overriden by the user.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
currentVersion : String
 | 
					currentVersion : String
 | 
				
			||||||
currentVersion =
 | 
					currentVersion =
 | 
				
			||||||
    "beta 3.1.0"
 | 
					    "beta 3.2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| The default device name that is being communicated with the Matrix API.
 | 
					{-| The default device name that is being communicated with the Matrix API.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,8 @@ decodedDictSize from to =
 | 
				
			||||||
{-| Documentation used for all functions and data types in JSON coders
 | 
					{-| Documentation used for all functions and data types in JSON coders
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
docs :
 | 
					docs :
 | 
				
			||||||
    { context : TypeDocs
 | 
					    { accessToken : TypeDocs
 | 
				
			||||||
 | 
					    , context : TypeDocs
 | 
				
			||||||
    , envelope : TypeDocs
 | 
					    , envelope : TypeDocs
 | 
				
			||||||
    , event : TypeDocs
 | 
					    , event : TypeDocs
 | 
				
			||||||
    , hashdict : TypeDocs
 | 
					    , hashdict : TypeDocs
 | 
				
			||||||
| 
						 | 
					@ -127,9 +128,16 @@ docs :
 | 
				
			||||||
    , timelineFilter : TypeDocs
 | 
					    , timelineFilter : TypeDocs
 | 
				
			||||||
    , unsigned : TypeDocs
 | 
					    , unsigned : TypeDocs
 | 
				
			||||||
    , vault : TypeDocs
 | 
					    , vault : TypeDocs
 | 
				
			||||||
 | 
					    , versions : TypeDocs
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
docs =
 | 
					docs =
 | 
				
			||||||
    { context =
 | 
					    { accessToken =
 | 
				
			||||||
 | 
					        { name = "Access Token"
 | 
				
			||||||
 | 
					        , description =
 | 
				
			||||||
 | 
					            [ "The Access Token type stores information about an access token - its value, when it expires, and how one may get a new access token when the current value expires."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    , context =
 | 
				
			||||||
        { name = "Context"
 | 
					        { name = "Context"
 | 
				
			||||||
        , description =
 | 
					        , description =
 | 
				
			||||||
            [ "The Context is the set of variables that the user (mostly) cannot control."
 | 
					            [ "The Context is the set of variables that the user (mostly) cannot control."
 | 
				
			||||||
| 
						 | 
					@ -223,6 +231,12 @@ docs =
 | 
				
			||||||
            [ "Main type storing all relevant information from the Matrix API."
 | 
					            [ "Main type storing all relevant information from the Matrix API."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    , versions =
 | 
				
			||||||
 | 
					        { name = "Versions"
 | 
				
			||||||
 | 
					        , description =
 | 
				
			||||||
 | 
					            [ "Versions type describing the supported spec versions and MSC properties."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,14 +258,24 @@ failures =
 | 
				
			||||||
what they do and what they are for.
 | 
					what they do and what they are for.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
fields :
 | 
					fields :
 | 
				
			||||||
    { context :
 | 
					    { accessToken :
 | 
				
			||||||
 | 
					        { created : Desc
 | 
				
			||||||
 | 
					        , expiryMs : Desc
 | 
				
			||||||
 | 
					        , lastUsed : Desc
 | 
				
			||||||
 | 
					        , refresh : Desc
 | 
				
			||||||
 | 
					        , value : Desc
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    , context :
 | 
				
			||||||
        { accessToken : Desc
 | 
					        { accessToken : Desc
 | 
				
			||||||
        , baseUrl : Desc
 | 
					        , baseUrl : Desc
 | 
				
			||||||
 | 
					        , deviceId : Desc
 | 
				
			||||||
        , experimental : Desc
 | 
					        , experimental : Desc
 | 
				
			||||||
 | 
					        , now : Desc
 | 
				
			||||||
        , password : Desc
 | 
					        , password : Desc
 | 
				
			||||||
        , refreshToken : Desc
 | 
					        , refreshToken : Desc
 | 
				
			||||||
        , username : Desc
 | 
					        , username : Desc
 | 
				
			||||||
        , serverName : Desc
 | 
					        , serverName : Desc
 | 
				
			||||||
 | 
					        , suggestedAccessToken : Desc
 | 
				
			||||||
        , transaction : Desc
 | 
					        , transaction : Desc
 | 
				
			||||||
        , versions : Desc
 | 
					        , versions : Desc
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -321,25 +345,51 @@ fields :
 | 
				
			||||||
    , vault :
 | 
					    , vault :
 | 
				
			||||||
        { accountData : Desc
 | 
					        { accountData : Desc
 | 
				
			||||||
        , rooms : Desc
 | 
					        , rooms : Desc
 | 
				
			||||||
 | 
					        , user : Desc
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    , versions :
 | 
				
			||||||
 | 
					        { unstableFeatures : Desc
 | 
				
			||||||
 | 
					        , versions : Desc
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
fields =
 | 
					fields =
 | 
				
			||||||
    { context =
 | 
					    { accessToken =
 | 
				
			||||||
 | 
					        { created =
 | 
				
			||||||
 | 
					            [ "Timestamp of when the access token was received." ]
 | 
				
			||||||
 | 
					        , expiryMs =
 | 
				
			||||||
 | 
					            [ "Given time in milliseconds of when the access token might expire." ]
 | 
				
			||||||
 | 
					        , lastUsed =
 | 
				
			||||||
 | 
					            [ "Timestamp of when the access token was last used." ]
 | 
				
			||||||
 | 
					        , refresh =
 | 
				
			||||||
 | 
					            [ "Refresh token used to gain a new access token." ]
 | 
				
			||||||
 | 
					        , value =
 | 
				
			||||||
 | 
					            [ "Secret access token value." ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    , context =
 | 
				
			||||||
        { accessToken =
 | 
					        { accessToken =
 | 
				
			||||||
            [ "The access token used for authentication with the Matrix server."
 | 
					            [ "The access token used for authentication with the Matrix server."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        , baseUrl =
 | 
					        , baseUrl =
 | 
				
			||||||
            [ "The base URL of the Matrix server."
 | 
					            [ "The base URL of the Matrix server."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					        , deviceId =
 | 
				
			||||||
 | 
					            [ "The reported device ID according to the API."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        , experimental =
 | 
					        , experimental =
 | 
				
			||||||
            [ "Experimental features supported by the homeserver."
 | 
					            [ "Experimental features supported by the homeserver."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					        , now =
 | 
				
			||||||
 | 
					            [ "The most recently found timestamp."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        , password =
 | 
					        , password =
 | 
				
			||||||
            [ "The user's password for authentication purposes."
 | 
					            [ "The user's password for authentication purposes."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        , refreshToken =
 | 
					        , refreshToken =
 | 
				
			||||||
            [ "The token used to obtain a new access token upon expiration of the current access token."
 | 
					            [ "The token used to obtain a new access token upon expiration of the current access token."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					        , suggestedAccessToken =
 | 
				
			||||||
 | 
					            [ "An access token provided with no context by the user."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        , username =
 | 
					        , username =
 | 
				
			||||||
            [ "The username of the Matrix account."
 | 
					            [ "The username of the Matrix account."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
| 
						 | 
					@ -510,6 +560,16 @@ fields =
 | 
				
			||||||
        , rooms =
 | 
					        , rooms =
 | 
				
			||||||
            [ "Directory of joined rooms that the user is a member of."
 | 
					            [ "Directory of joined rooms that the user is a member of."
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					        , user =
 | 
				
			||||||
 | 
					            [ "User that the Vault is logging in as."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    , versions =
 | 
				
			||||||
 | 
					        { unstableFeatures =
 | 
				
			||||||
 | 
					            [ "Unstable features such as experimental MSCs that are supported by a homeserver."
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        , versions =
 | 
				
			||||||
 | 
					            [ "Spec versions supported by a homeserver." ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -545,18 +605,51 @@ happened. Most of these unexpected results, are taken account of by the Elm SDK,
 | 
				
			||||||
but logged so that the programmer can do something about it.
 | 
					but logged so that the programmer can do something about it.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
logs :
 | 
					logs :
 | 
				
			||||||
    { keyIsNotAnInt : String -> String
 | 
					    { baseUrlFound : String -> String -> String
 | 
				
			||||||
 | 
					    , getEventId : String -> String
 | 
				
			||||||
 | 
					    , getNow : Int -> String
 | 
				
			||||||
 | 
					    , httpRequest : String -> String -> String
 | 
				
			||||||
 | 
					    , invitedUser : String -> String -> String
 | 
				
			||||||
 | 
					    , keyIsNotAnInt : String -> String
 | 
				
			||||||
 | 
					    , loggedInAs : String -> String
 | 
				
			||||||
 | 
					    , sendEvent : Maybe String -> String
 | 
				
			||||||
    , serverReturnedInvalidJSON : String -> String
 | 
					    , serverReturnedInvalidJSON : String -> String
 | 
				
			||||||
    , serverReturnedUnknownJSON : String -> String
 | 
					    , serverReturnedUnknownJSON : String -> String
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
logs =
 | 
					logs =
 | 
				
			||||||
    { keyIsNotAnInt =
 | 
					    { baseUrlFound =
 | 
				
			||||||
 | 
					        \url baseUrl ->
 | 
				
			||||||
 | 
					            String.concat [ "Found baseURL of ", url, " at address ", baseUrl ]
 | 
				
			||||||
 | 
					    , getEventId = (++) "Received event with id = "
 | 
				
			||||||
 | 
					    , getNow =
 | 
				
			||||||
 | 
					        \now ->
 | 
				
			||||||
 | 
					            String.concat
 | 
				
			||||||
 | 
					                [ "Identified current time at Unix time "
 | 
				
			||||||
 | 
					                , String.fromInt now
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					    , httpRequest =
 | 
				
			||||||
 | 
					        \method url -> String.concat [ "Matrix HTTP: ", method, " ", url ]
 | 
				
			||||||
 | 
					    , invitedUser =
 | 
				
			||||||
 | 
					        \userId roomId ->
 | 
				
			||||||
 | 
					            String.concat [ "Invited user ", userId, " to room ", roomId ]
 | 
				
			||||||
 | 
					    , keyIsNotAnInt =
 | 
				
			||||||
        \key ->
 | 
					        \key ->
 | 
				
			||||||
            String.concat
 | 
					            String.concat
 | 
				
			||||||
                [ "Encountered a key `"
 | 
					                [ "Encountered a key `"
 | 
				
			||||||
                , key
 | 
					                , key
 | 
				
			||||||
                , "` that cannot be converted to an Int"
 | 
					                , "` that cannot be converted to an Int"
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
 | 
					    , loggedInAs =
 | 
				
			||||||
 | 
					        \username ->
 | 
				
			||||||
 | 
					            String.concat [ "Successfully logged in as user ", username ]
 | 
				
			||||||
 | 
					    , sendEvent =
 | 
				
			||||||
 | 
					        \eventId ->
 | 
				
			||||||
 | 
					            case eventId of
 | 
				
			||||||
 | 
					                Just e ->
 | 
				
			||||||
 | 
					                    "Sent event, received event id " ++ e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Nothing ->
 | 
				
			||||||
 | 
					                    "Sent event, event id not known - make sure to check transaction id"
 | 
				
			||||||
    , serverReturnedInvalidJSON = (++) "The server returned invalid JSON: "
 | 
					    , serverReturnedInvalidJSON = (++) "The server returned invalid JSON: "
 | 
				
			||||||
    , serverReturnedUnknownJSON = (++) "The server returned JSON that doesn't seem to live up to spec rules: "
 | 
					    , serverReturnedUnknownJSON = (++) "The server returned JSON that doesn't seem to live up to spec rules: "
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,8 +50,6 @@ for interacting with the Matrix API.
 | 
				
			||||||
import Internal.Config.Text as Text
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Grammar.UserId as U
 | 
					import Internal.Grammar.UserId as U
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					 | 
				
			||||||
import Set exposing (Set)
 | 
					import Set exposing (Set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,14 +174,14 @@ coder =
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "deviceId"
 | 
					            { fieldName = "deviceId"
 | 
				
			||||||
            , toField = .deviceId
 | 
					            , toField = .deviceId
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.context.deviceId
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "now"
 | 
					            { fieldName = "now"
 | 
				
			||||||
            , toField = .now
 | 
					            , toField = .now
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.context.now
 | 
				
			||||||
            , coder = Timestamp.coder
 | 
					            , coder = Timestamp.coder
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ coder =
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "suggestedAccessToken"
 | 
					            { fieldName = "suggestedAccessToken"
 | 
				
			||||||
            , toField = always Nothing -- Do not save
 | 
					            , toField = always Nothing -- Do not save
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.context.suggestedAccessToken
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -241,42 +241,42 @@ coder =
 | 
				
			||||||
coderAccessToken : Json.Coder AccessToken
 | 
					coderAccessToken : Json.Coder AccessToken
 | 
				
			||||||
coderAccessToken =
 | 
					coderAccessToken =
 | 
				
			||||||
    Json.object5
 | 
					    Json.object5
 | 
				
			||||||
        { name = Debug.todo "Needs docs"
 | 
					        { name = Text.docs.accessToken.name
 | 
				
			||||||
        , description = Debug.todo "Needs docs"
 | 
					        , description = Text.docs.accessToken.description
 | 
				
			||||||
        , init = AccessToken
 | 
					        , init = AccessToken
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "created"
 | 
					            { fieldName = "created"
 | 
				
			||||||
            , toField = .created
 | 
					            , toField = .created
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.accessToken.created
 | 
				
			||||||
            , coder = Timestamp.coder
 | 
					            , coder = Timestamp.coder
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "expiryMs"
 | 
					            { fieldName = "expiryMs"
 | 
				
			||||||
            , toField = .expiryMs
 | 
					            , toField = .expiryMs
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.accessToken.expiryMs
 | 
				
			||||||
            , coder = Json.int
 | 
					            , coder = Json.int
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "lastUsed"
 | 
					            { fieldName = "lastUsed"
 | 
				
			||||||
            , toField = .lastUsed
 | 
					            , toField = .lastUsed
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.accessToken.lastUsed
 | 
				
			||||||
            , coder = Timestamp.coder
 | 
					            , coder = Timestamp.coder
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.optional.value
 | 
					        (Json.field.optional.value
 | 
				
			||||||
            { fieldName = "refresh"
 | 
					            { fieldName = "refresh"
 | 
				
			||||||
            , toField = .refresh
 | 
					            , toField = .refresh
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.accessToken.refresh
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "value"
 | 
					            { fieldName = "value"
 | 
				
			||||||
            , toField = .value
 | 
					            , toField = .value
 | 
				
			||||||
            , description = Debug.todo "Needs docs"
 | 
					            , description = Text.fields.accessToken.value
 | 
				
			||||||
            , coder = Json.string
 | 
					            , coder = Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -318,23 +318,28 @@ init sn =
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
mostPopularToken : Context -> Maybe String
 | 
					mostPopularToken : Context -> Maybe String
 | 
				
			||||||
mostPopularToken c =
 | 
					mostPopularToken c =
 | 
				
			||||||
    c.accessTokens
 | 
					    case c.suggestedAccessToken of
 | 
				
			||||||
        |> Hashdict.values
 | 
					        Just _ ->
 | 
				
			||||||
        |> List.sortBy
 | 
					            c.suggestedAccessToken
 | 
				
			||||||
            (\token ->
 | 
					 | 
				
			||||||
                case token.expiryMs of
 | 
					 | 
				
			||||||
                    Nothing ->
 | 
					 | 
				
			||||||
                        ( 0, Timestamp.toMs token.created )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Just e ->
 | 
					        Nothing ->
 | 
				
			||||||
                        ( 1
 | 
					            c.accessTokens
 | 
				
			||||||
                        , token.created
 | 
					                |> Hashdict.values
 | 
				
			||||||
                            |> Timestamp.add e
 | 
					                |> List.sortBy
 | 
				
			||||||
                            |> Timestamp.toMs
 | 
					                    (\token ->
 | 
				
			||||||
                        )
 | 
					                        case token.expiryMs of
 | 
				
			||||||
            )
 | 
					                            Nothing ->
 | 
				
			||||||
        |> List.head
 | 
					                                ( 0, Timestamp.toMs token.created )
 | 
				
			||||||
        |> Maybe.map .value
 | 
					
 | 
				
			||||||
 | 
					                            Just e ->
 | 
				
			||||||
 | 
					                                ( 1
 | 
				
			||||||
 | 
					                                , token.created
 | 
				
			||||||
 | 
					                                    |> Timestamp.add e
 | 
				
			||||||
 | 
					                                    |> Timestamp.toMs
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                |> List.head
 | 
				
			||||||
 | 
					                |> Maybe.map .value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Reset the phantom type of the Context, effectively forgetting all values.
 | 
					{-| Reset the phantom type of the Context, effectively forgetting all values.
 | 
				
			||||||
| 
						 | 
					@ -417,21 +422,21 @@ setVersions value (APIContext c) =
 | 
				
			||||||
versionsCoder : Json.Coder Versions
 | 
					versionsCoder : Json.Coder Versions
 | 
				
			||||||
versionsCoder =
 | 
					versionsCoder =
 | 
				
			||||||
    Json.object2
 | 
					    Json.object2
 | 
				
			||||||
        { name = Debug.todo "Add name" -- Text.docs.versions.name
 | 
					        { name = Text.docs.versions.name
 | 
				
			||||||
        , description = Debug.todo "Add description" -- Text.docs.versions.description
 | 
					        , description = Text.docs.versions.description
 | 
				
			||||||
        , init = Versions
 | 
					        , init = Versions
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "versions"
 | 
					            { fieldName = "versions"
 | 
				
			||||||
            , toField = .versions
 | 
					            , toField = .versions
 | 
				
			||||||
            , description = Debug.todo "Add description"
 | 
					            , description = Text.fields.versions.versions
 | 
				
			||||||
            , coder = Json.list Json.string
 | 
					            , coder = Json.list Json.string
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (Json.field.optional.withDefault
 | 
					        (Json.field.optional.withDefault
 | 
				
			||||||
            { fieldName = "unstableFeatures"
 | 
					            { fieldName = "unstableFeatures"
 | 
				
			||||||
            , toField = .unstableFeatures
 | 
					            , toField = .unstableFeatures
 | 
				
			||||||
            , description = Debug.todo "Add description"
 | 
					            , description = Text.fields.versions.unstableFeatures
 | 
				
			||||||
            , coder = Json.set Json.string
 | 
					            , coder = Json.set Json.string
 | 
				
			||||||
            , default = ( Set.empty, [] )
 | 
					            , default = ( Set.empty, [] )
 | 
				
			||||||
            , defaultToString = Json.encode (Json.set Json.string) >> E.encode 0
 | 
					            , defaultToString = Json.encode (Json.set Json.string) >> E.encode 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Event as Event exposing (Event)
 | 
					import Internal.Values.Event as Event exposing (Event)
 | 
				
			||||||
import Internal.Values.StateManager as StateManager exposing (StateManager)
 | 
					import Internal.Values.StateManager as StateManager exposing (StateManager)
 | 
				
			||||||
import Internal.Values.Timeline as Timeline exposing (Timeline)
 | 
					import Internal.Values.Timeline as Timeline exposing (Timeline)
 | 
				
			||||||
import Internal.Values.User as User exposing (User)
 | 
					import Internal.Values.User exposing (User)
 | 
				
			||||||
import Json.Encode as E
 | 
					import Json.Encode as E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,7 @@ update ru room =
 | 
				
			||||||
        AddSync batch ->
 | 
					        AddSync batch ->
 | 
				
			||||||
            addSync batch room
 | 
					            addSync batch room
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Invite user ->
 | 
					        Invite _ ->
 | 
				
			||||||
            -- TODO: Invite user
 | 
					            -- TODO: Invite user
 | 
				
			||||||
            room
 | 
					            room
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ Since the username is safely parsed, one can get these parts of the username.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Internal.Config.Log as Log exposing (log)
 | 
					import Internal.Config.Log exposing (log)
 | 
				
			||||||
import Internal.Grammar.ServerName as ServerName
 | 
					import Internal.Grammar.ServerName as ServerName
 | 
				
			||||||
import Internal.Grammar.UserId as UserId
 | 
					import Internal.Grammar.UserId as UserId
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,8 +33,6 @@ Rooms are environments where people can have a conversation with each other.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import FastDict as Dict exposing (Dict)
 | 
					import FastDict as Dict exposing (Dict)
 | 
				
			||||||
import Internal.Api.Request as Request
 | 
					 | 
				
			||||||
import Internal.Config.Log exposing (Log)
 | 
					 | 
				
			||||||
import Internal.Config.Text as Text
 | 
					import Internal.Config.Text as Text
 | 
				
			||||||
import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
 | 
					import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
| 
						 | 
					@ -86,7 +84,7 @@ coder =
 | 
				
			||||||
        (Json.field.required
 | 
					        (Json.field.required
 | 
				
			||||||
            { fieldName = "user"
 | 
					            { fieldName = "user"
 | 
				
			||||||
            , toField = .user
 | 
					            , toField = .user
 | 
				
			||||||
            , description = Debug.todo "Needs description"
 | 
					            , description = Text.fields.vault.user
 | 
				
			||||||
            , coder = User.coder
 | 
					            , coder = User.coder
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
module Matrix exposing
 | 
					module Matrix exposing
 | 
				
			||||||
    ( Vault
 | 
					    ( Vault, fromUserId
 | 
				
			||||||
    , VaultUpdate, update
 | 
					    , VaultUpdate, update
 | 
				
			||||||
    , sendMessageEvent, fromUserId
 | 
					    , addAccessToken, sendMessageEvent
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
| 
						 | 
					@ -29,16 +29,16 @@ support a monolithic public registry. (:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Debugging
 | 
					## Debugging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs sendMessageEvent
 | 
					@docs addAccessToken, sendMessageEvent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Internal.Api.Main as Api
 | 
					import Internal.Api.Main as Api
 | 
				
			||||||
import Internal.Values.Envelope as Envelope
 | 
					import Internal.Values.Envelope as Envelope
 | 
				
			||||||
 | 
					import Internal.Values.User as User
 | 
				
			||||||
import Internal.Values.Vault as Internal
 | 
					import Internal.Values.Vault as Internal
 | 
				
			||||||
import Json.Encode as E
 | 
					import Json.Encode as E
 | 
				
			||||||
import Types exposing (Vault(..), VaultUpdate(..))
 | 
					import Types exposing (Vault(..), VaultUpdate(..))
 | 
				
			||||||
import Internal.Values.User as User
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| The Vault type stores all relevant information about the Matrix API.
 | 
					{-| The Vault type stores all relevant information about the Matrix API.
 | 
				
			||||||
| 
						 | 
					@ -56,18 +56,22 @@ type alias Vault =
 | 
				
			||||||
type alias VaultUpdate =
 | 
					type alias VaultUpdate =
 | 
				
			||||||
    Types.VaultUpdate
 | 
					    Types.VaultUpdate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
addAccessToken : String -> Vault -> Vault
 | 
					addAccessToken : String -> Vault -> Vault
 | 
				
			||||||
addAccessToken token (Vault vault) =
 | 
					addAccessToken token (Vault vault) =
 | 
				
			||||||
    
 | 
					    Envelope.mapContext (\c -> { c | suggestedAccessToken = Just token }) vault
 | 
				
			||||||
 | 
					        |> Vault
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Use a fully-fledged Matrix ID to connect.
 | 
					{-| Use a fully-fledged Matrix ID to connect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Matrix.fromUserId "@alice:example.org" of
 | 
					    case Matrix.fromUserId "@alice:example.org" of
 | 
				
			||||||
        Just vault ->
 | 
					        Just vault ->
 | 
				
			||||||
            "We got a vault!"
 | 
					            "We got a vault!"
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        Nothing ->
 | 
					        Nothing ->
 | 
				
			||||||
            "Invalid username"
 | 
					            "Invalid username"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
fromUserId : String -> Maybe Vault
 | 
					fromUserId : String -> Maybe Vault
 | 
				
			||||||
fromUserId =
 | 
					fromUserId =
 | 
				
			||||||
| 
						 | 
					@ -75,12 +79,13 @@ fromUserId =
 | 
				
			||||||
        >> Maybe.map
 | 
					        >> Maybe.map
 | 
				
			||||||
            (\u ->
 | 
					            (\u ->
 | 
				
			||||||
                Envelope.init
 | 
					                Envelope.init
 | 
				
			||||||
                    { serverName = User.domain u
 | 
					                    { serverName = "https://" ++ User.domain u
 | 
				
			||||||
                    , content = Internal.init u
 | 
					                    , content = Internal.init u
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        >> Maybe.map Vault
 | 
					        >> Maybe.map Vault
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Send a message event to a room.
 | 
					{-| Send a message event to a room.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This function can be used in a scenario where the user does not want to sync
 | 
					This function can be used in a scenario where the user does not want to sync
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,13 @@ module Test.Values.Context exposing (..)
 | 
				
			||||||
import Expect
 | 
					import Expect
 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Config.Leaks as Leaks
 | 
					import Internal.Config.Leaks as Leaks
 | 
				
			||||||
import Internal.Values.Context as Context exposing (Context)
 | 
					import Internal.Tools.Hashdict as Hashdict
 | 
				
			||||||
 | 
					import Internal.Values.Context as Context exposing (Context, Versions)
 | 
				
			||||||
import Json.Decode as D
 | 
					import Json.Decode as D
 | 
				
			||||||
import Json.Encode as E
 | 
					import Json.Encode as E
 | 
				
			||||||
 | 
					import Set
 | 
				
			||||||
import Test exposing (..)
 | 
					import Test exposing (..)
 | 
				
			||||||
 | 
					import Test.Tools.Timestamp as TestTimestamp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fuzzer : Fuzzer Context
 | 
					fuzzer : Fuzzer Context
 | 
				
			||||||
| 
						 | 
					@ -16,14 +19,31 @@ fuzzer =
 | 
				
			||||||
        maybeString =
 | 
					        maybeString =
 | 
				
			||||||
            Fuzz.maybe Fuzz.string
 | 
					            Fuzz.maybe Fuzz.string
 | 
				
			||||||
    in
 | 
					    in
 | 
				
			||||||
    Fuzz.map7 Context
 | 
					    Fuzz.map8 (\a b c d e ( f, g ) ( h, i ) ( j, k ) -> Context a b c d e f g h i j k)
 | 
				
			||||||
 | 
					        (Fuzz.constant <| Hashdict.empty .value)
 | 
				
			||||||
        maybeString
 | 
					        maybeString
 | 
				
			||||||
        maybeString
 | 
					        maybeString
 | 
				
			||||||
 | 
					        (Fuzz.maybe TestTimestamp.fuzzer)
 | 
				
			||||||
        maybeString
 | 
					        maybeString
 | 
				
			||||||
        maybeString
 | 
					        (Fuzz.pair
 | 
				
			||||||
        maybeString
 | 
					            maybeString
 | 
				
			||||||
        maybeString
 | 
					            Fuzz.string
 | 
				
			||||||
        (Fuzz.maybe <| Fuzz.list Fuzz.string)
 | 
					        )
 | 
				
			||||||
 | 
					        (Fuzz.pair
 | 
				
			||||||
 | 
					            maybeString
 | 
				
			||||||
 | 
					            maybeString
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        (Fuzz.pair
 | 
				
			||||||
 | 
					            maybeString
 | 
				
			||||||
 | 
					            (Fuzz.maybe <| versionsFuzzer)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					versionsFuzzer : Fuzzer Versions
 | 
				
			||||||
 | 
					versionsFuzzer =
 | 
				
			||||||
 | 
					    Fuzz.map2 Versions
 | 
				
			||||||
 | 
					        (Fuzz.list Fuzz.string)
 | 
				
			||||||
 | 
					        (Fuzz.map Set.fromList <| Fuzz.list Fuzz.string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| If a leak is spotted, make sure to change the leaking value and then test
 | 
					{-| If a leak is spotted, make sure to change the leaking value and then test
 | 
				
			||||||
| 
						 | 
					@ -64,7 +84,7 @@ leaks =
 | 
				
			||||||
                    |> Expect.notEqual Leaks.transaction
 | 
					                    |> Expect.notEqual Leaks.transaction
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        , fuzz2 fuzzer
 | 
					        , fuzz2 fuzzer
 | 
				
			||||||
            (Fuzz.list Fuzz.string)
 | 
					            versionsFuzzer
 | 
				
			||||||
            "Versions"
 | 
					            "Versions"
 | 
				
			||||||
            (\context value ->
 | 
					            (\context value ->
 | 
				
			||||||
                context
 | 
					                context
 | 
				
			||||||
| 
						 | 
					@ -110,7 +130,7 @@ apiContext =
 | 
				
			||||||
                    |> Expect.equal value
 | 
					                    |> Expect.equal value
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        , fuzz2 fuzzer
 | 
					        , fuzz2 fuzzer
 | 
				
			||||||
            (Fuzz.list Fuzz.string)
 | 
					            versionsFuzzer
 | 
				
			||||||
            "Versions"
 | 
					            "Versions"
 | 
				
			||||||
            (\context value ->
 | 
					            (\context value ->
 | 
				
			||||||
                context
 | 
					                context
 | 
				
			||||||
| 
						 | 
					@ -126,7 +146,7 @@ json : Test
 | 
				
			||||||
json =
 | 
					json =
 | 
				
			||||||
    describe "JSON encode + JSON decode"
 | 
					    describe "JSON encode + JSON decode"
 | 
				
			||||||
        [ test "Empty is {}"
 | 
					        [ test "Empty is {}"
 | 
				
			||||||
            (Context.init
 | 
					            (Context.init ""
 | 
				
			||||||
                |> Context.encode
 | 
					                |> Context.encode
 | 
				
			||||||
                |> E.encode 0
 | 
					                |> E.encode 0
 | 
				
			||||||
                |> Expect.equal "{}"
 | 
					                |> Expect.equal "{}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ suite =
 | 
				
			||||||
                [ fuzz Fuzz.string
 | 
					                [ fuzz Fuzz.string
 | 
				
			||||||
                    "currentVersion"
 | 
					                    "currentVersion"
 | 
				
			||||||
                    (\s ->
 | 
					                    (\s ->
 | 
				
			||||||
                        s
 | 
					                        { content = s, serverName = "" }
 | 
				
			||||||
                            |> Envelope.init
 | 
					                            |> Envelope.init
 | 
				
			||||||
                            |> Envelope.extractSettings .currentVersion
 | 
					                            |> Envelope.extractSettings .currentVersion
 | 
				
			||||||
                            |> Expect.equal Default.currentVersion
 | 
					                            |> Expect.equal Default.currentVersion
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ suite =
 | 
				
			||||||
                , fuzz Fuzz.string
 | 
					                , fuzz Fuzz.string
 | 
				
			||||||
                    "deviceName"
 | 
					                    "deviceName"
 | 
				
			||||||
                    (\s ->
 | 
					                    (\s ->
 | 
				
			||||||
                        s
 | 
					                        { content = s, serverName = "" }
 | 
				
			||||||
                            |> Envelope.init
 | 
					                            |> Envelope.init
 | 
				
			||||||
                            |> Envelope.extractSettings .deviceName
 | 
					                            |> Envelope.extractSettings .deviceName
 | 
				
			||||||
                            |> Expect.equal Default.deviceName
 | 
					                            |> Expect.equal Default.deviceName
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ suite =
 | 
				
			||||||
                , fuzz Fuzz.string
 | 
					                , fuzz Fuzz.string
 | 
				
			||||||
                    "syncTime"
 | 
					                    "syncTime"
 | 
				
			||||||
                    (\s ->
 | 
					                    (\s ->
 | 
				
			||||||
                        s
 | 
					                        { content = s, serverName = "" }
 | 
				
			||||||
                            |> Envelope.init
 | 
					                            |> Envelope.init
 | 
				
			||||||
                            |> Envelope.extractSettings .syncTime
 | 
					                            |> Envelope.extractSettings .syncTime
 | 
				
			||||||
                            |> Expect.equal Default.syncTime
 | 
					                            |> Expect.equal Default.syncTime
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
module Test.Values.Room exposing (..)
 | 
					module Test.Values.Room exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Expect
 | 
					 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Values.Room as Room exposing (Room)
 | 
					import Internal.Values.Room as Room exposing (Room)
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					import Json.Encode as E
 | 
				
			||||||
import Test exposing (..)
 | 
					import Test exposing (..)
 | 
				
			||||||
import Test.Filter.Timeline as TestFilter
 | 
					import Test.Filter.Timeline as TestFilter
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ module Test.Values.Timeline exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Expect
 | 
					import Expect
 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
					import Internal.Filter.Timeline as Filter
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Timeline as Timeline exposing (Batch, Timeline)
 | 
					import Internal.Values.Timeline as Timeline exposing (Batch, Timeline)
 | 
				
			||||||
import Json.Decode as D
 | 
					import Json.Decode as D
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					module Test.Values.User exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
 | 
					import Internal.Grammar.ServerName as SN
 | 
				
			||||||
 | 
					import Internal.Values.User exposing (User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fuzzer : Fuzzer User
 | 
				
			||||||
 | 
					fuzzer =
 | 
				
			||||||
 | 
					    Fuzz.constant
 | 
				
			||||||
 | 
					        { localpart = "temporary"
 | 
				
			||||||
 | 
					        , domain = { host = SN.DNS "matrix.org", port_ = Nothing }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,22 @@
 | 
				
			||||||
module Test.Values.Vault exposing (..)
 | 
					module Test.Values.Vault exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import FastDict as Dict exposing (Dict)
 | 
					import FastDict as Dict
 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Tools.Json as Json
 | 
					import Internal.Tools.Json as Json
 | 
				
			||||||
import Internal.Values.Vault exposing (Vault)
 | 
					import Internal.Values.Vault exposing (Vault)
 | 
				
			||||||
import Test exposing (..)
 | 
					import Test exposing (..)
 | 
				
			||||||
import Test.Tools.Hashdict as TestHashdict
 | 
					import Test.Tools.Hashdict as TestHashdict
 | 
				
			||||||
import Test.Values.Room as TestRoom
 | 
					import Test.Values.Room as TestRoom
 | 
				
			||||||
 | 
					import Test.Values.User as TestUser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vault : Fuzzer Vault
 | 
					vault : Fuzzer Vault
 | 
				
			||||||
vault =
 | 
					vault =
 | 
				
			||||||
    Fuzz.map2 Vault
 | 
					    Fuzz.map3 Vault
 | 
				
			||||||
        (Fuzz.string
 | 
					        (Fuzz.string
 | 
				
			||||||
            |> Fuzz.map (\k -> ( k, Json.encode Json.int 0 ))
 | 
					            |> Fuzz.map (\k -> ( k, Json.encode Json.int 0 ))
 | 
				
			||||||
            |> Fuzz.list
 | 
					            |> Fuzz.list
 | 
				
			||||||
            |> Fuzz.map Dict.fromList
 | 
					            |> Fuzz.map Dict.fromList
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        (TestHashdict.fuzzer .roomId TestRoom.fuzzer)
 | 
					        (TestHashdict.fuzzer .roomId TestRoom.fuzzer)
 | 
				
			||||||
 | 
					        TestUser.fuzzer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue