Begin working on Http requests.

This commit is contained in:
Danila Fedorin 2018-12-08 13:49:30 -08:00
parent c292a4c29b
commit 3656b0f3f0
7 changed files with 128 additions and 11 deletions

View File

@ -10,10 +10,13 @@
"elm/browser": "1.0.1",
"elm/core": "1.0.2",
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.2",
"elm/url": "1.0.0"
},
"indirect": {
"elm/bytes": "1.0.7",
"elm/file": "1.0.1",
"elm/time": "1.0.0",
"elm/virtual-dom": "1.0.2"
}

View File

@ -1,28 +1,22 @@
import Browser exposing (application)
import Browser.Navigation as Nav
import Scylla.Sync exposing (..)
import Scylla.Model exposing (..)
import Scylla.Http exposing (..)
import Url exposing (Url)
import Html exposing (div)
import Html exposing (div, text)
type alias Flags =
{ token : Maybe String
}
type alias Model =
{ key : Nav.Key
, token : Maybe String
}
type Msg =
None
| TryUrl Browser.UrlRequest
| ChangeUrl Url
init : Flags -> Url -> Nav.Key -> (Model, Cmd Msg)
init flags url key =
let
model =
{ key = key
, token = flags.token
, apiUrl = "https://matrix.org"
}
cmd = case flags.token of
Just _ -> Cmd.none

15
src/Scylla/Api.elm Normal file
View File

@ -0,0 +1,15 @@
module Scylla.Api exposing (..)
import Http exposing (Header, header)
import Json.Encode as Encode
type alias ApiToken = String
type alias ApiUrl = String
basicHeaders : List Header
basicHeaders =
[ header "Content-Type" "application/json"
]
authenticatedHeaders : ApiToken -> List Header
authenticatedHeaders token =
[ header "Authorization" ("Bearer " ++ token)] ++ basicHeaders

37
src/Scylla/Http.elm Normal file
View File

@ -0,0 +1,37 @@
module Scylla.Http exposing (..)
import Scylla.Model exposing (..)
import Scylla.Api exposing (..)
import Scylla.Sync exposing (syncResponseDecoder)
import Scylla.Login exposing (loginResponseDecoder, Username, Password)
import Json.Encode exposing (object, string)
import Http exposing (request, jsonBody, expectJson)
-- Http Requests
firstSync : ApiUrl -> ApiToken -> Cmd Msg
firstSync apiUrl token = request
{ method = "GET"
, headers = authenticatedHeaders token
, url = apiUrl ++ "/sync"
, body = jsonBody <| object []
, expect = expectJson ReceiveSyncResponse syncResponseDecoder
, timeout = Nothing
, tracker = Nothing
}
login : ApiUrl -> Username -> Password -> Cmd Msg
login apiUrl username password = request
{ method = "POST"
, headers = basicHeaders
, url = apiUrl ++ "/login"
, body = jsonBody <| object
[ ("type", string "m.login.password")
, ("identifier", object
[ ("type", string "m.id.user")
, ("user", string username)
] )
, ("password", string password)
]
, expect = expectJson ReceiveLoginResponse loginResponseDecoder
, timeout = Nothing
, tracker = Nothing
}

20
src/Scylla/Login.elm Normal file
View File

@ -0,0 +1,20 @@
module Scylla.Login exposing (..)
import Scylla.Api exposing (ApiToken)
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool)
import Json.Decode.Pipeline exposing (required, optional)
type alias Username = String
type alias Password = String
type alias LoginResponse =
{ userId : String
, accessToken : ApiToken
, deviceId : String
}
loginResponseDecoder : Decoder LoginResponse
loginResponseDecoder =
Decode.succeed LoginResponse
|> required "user_id" string
|> required "access_token" string
|> required "device_id" string

21
src/Scylla/Model.elm Normal file
View File

@ -0,0 +1,21 @@
module Scylla.Model exposing (..)
import Scylla.Api exposing (..)
import Scylla.Sync exposing (SyncResponse)
import Scylla.Login exposing (LoginResponse)
import Browser.Navigation as Nav
import Browser
import Http
import Url exposing (Url)
type alias Model =
{ key : Nav.Key
, token : Maybe ApiToken
, apiUrl : ApiUrl
}
type Msg =
TryUrl Browser.UrlRequest
| ChangeUrl Url
| ReceiveSyncResponse (Result Http.Error SyncResponse)
| ReceiveLoginResponse (Result Http.Error LoginResponse)

View File

@ -1,8 +1,10 @@
module Scylla.Sync exposing (..)
import Scylla.Api exposing (..)
import Dict exposing (Dict)
import Json.Decode as Decode exposing (Decoder, int, string, float, list, value, dict, bool)
import Json.Decode.Pipeline exposing (required, optional)
-- Special Decoding
decodeJust : Decoder a -> Decoder (Maybe a)
decodeJust = Decode.map Just
@ -227,3 +229,28 @@ leftRoomDecoder =
|> maybeDecode "state" stateDecoder
|> maybeDecode "timeline" timelineDecoder
|> maybeDecode "account_data" accountDataDecoder
-- General Sync Response
type alias SyncResponse =
{ nextBatch : String
, rooms : Maybe Rooms
, presence : Maybe Presence
, accountData : Maybe AccountData
}
syncResponseDecoder : Decoder SyncResponse
syncResponseDecoder =
Decode.succeed SyncResponse
|> required "next_batch" string
|> maybeDecode "rooms" roomsDecoder
|> maybeDecode "presence" presenceDecoder
|> maybeDecode "account_data" accountDataDecoder
type alias Presence =
{ events : Maybe (List Event)
}
presenceDecoder : Decoder Presence
presenceDecoder =
Decode.succeed Presence
|> maybeDecode "events" (list eventDecoder)