Made it better
This commit is contained in:
parent
05b7a81139
commit
3e809e360b
1 changed files with 66 additions and 108 deletions
|
@ -39,19 +39,31 @@ pub type Dataset {
|
||||||
Dataset(production_info: ProductionInfo, modules: ModuleDataset)
|
Dataset(production_info: ProductionInfo, modules: ModuleDataset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type State {
|
pub type Credentials {
|
||||||
InitialState(
|
Credentials(username: String, password: String)
|
||||||
username: String,
|
}
|
||||||
password: String,
|
|
||||||
error: option.Option(UpdateError),
|
pub type Cookies {
|
||||||
)
|
Cookies(jar: biscotto.CookieJar, acquired: birl.Time)
|
||||||
LoadedState(
|
}
|
||||||
username: String,
|
|
||||||
password: String,
|
pub type InitialisedState {
|
||||||
cookies: biscotto.CookieJar,
|
InitialisedState(
|
||||||
cookies_acquired: birl.Time,
|
cookies: Cookies,
|
||||||
ids: ModuleIDs,
|
modules: ModuleIDs,
|
||||||
dataset: option.Option(Dataset),
|
dataset: option.Option(Dataset),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type InnerState {
|
||||||
|
Pending
|
||||||
|
Initialised(InitialisedState)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type State {
|
||||||
|
State(
|
||||||
|
credentials: Credentials,
|
||||||
|
inner: InnerState,
|
||||||
error: option.Option(UpdateError),
|
error: option.Option(UpdateError),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -62,153 +74,93 @@ pub type UpdateError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(username: String, password: String) {
|
pub fn start(username: String, password: String) {
|
||||||
actor.start(InitialState(username, password, option.None), handle_message)
|
actor.start(
|
||||||
|
State(Credentials(username, password), Pending, option.None),
|
||||||
|
handle_message,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(message: Message, state: State) -> actor.Next(Message, State) {
|
fn handle_message(message: Message, state: State) -> actor.Next(Message, State) {
|
||||||
let next =
|
let next =
|
||||||
with_loaded_state(
|
with_initialised_state(state, fn(credentials, inner_state) {
|
||||||
state,
|
|
||||||
fn(username, password, cookies, cookies_acquired, ids, dataset) {
|
|
||||||
case message {
|
case message {
|
||||||
Update -> {
|
Update -> {
|
||||||
use #(cookies, cookies_acquired, new_dataset) <- result.try(update(
|
use new_state <- result.try(update(credentials, inner_state))
|
||||||
username,
|
|
||||||
password,
|
|
||||||
cookies,
|
|
||||||
cookies_acquired,
|
|
||||||
ids,
|
|
||||||
dataset,
|
|
||||||
))
|
|
||||||
|
|
||||||
let new_state =
|
Ok(actor.continue(State(..state, inner: Initialised(new_state))))
|
||||||
LoadedState(
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
cookies,
|
|
||||||
cookies_acquired,
|
|
||||||
ids,
|
|
||||||
option.Some(new_dataset),
|
|
||||||
option.None,
|
|
||||||
)
|
|
||||||
|
|
||||||
Ok(actor.continue(new_state))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
case next {
|
case next {
|
||||||
Ok(next) -> next
|
Ok(next) -> next
|
||||||
Error(err) -> {
|
Error(err) -> {
|
||||||
let new_state = case state {
|
let new_state = State(..state, error: option.Some(err))
|
||||||
InitialState(username, password, ..) ->
|
|
||||||
InitialState(username, password, error: option.Some(err))
|
|
||||||
LoadedState(
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
cookies,
|
|
||||||
cookies_acquired,
|
|
||||||
ids,
|
|
||||||
dataset,
|
|
||||||
..,
|
|
||||||
) ->
|
|
||||||
LoadedState(
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
cookies,
|
|
||||||
cookies_acquired,
|
|
||||||
ids,
|
|
||||||
dataset,
|
|
||||||
option.Some(err),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
actor.continue(new_state)
|
actor.continue(new_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_loaded_state(
|
fn with_initialised_state(
|
||||||
state: State,
|
state: State,
|
||||||
fun: fn(
|
fun: fn(Credentials, InitialisedState) ->
|
||||||
String,
|
|
||||||
String,
|
|
||||||
biscotto.CookieJar,
|
|
||||||
birl.Time,
|
|
||||||
ModuleIDs,
|
|
||||||
option.Option(Dataset),
|
|
||||||
) ->
|
|
||||||
Result(actor.Next(Message, State), UpdateError),
|
Result(actor.Next(Message, State), UpdateError),
|
||||||
) {
|
) {
|
||||||
case state {
|
case state.inner {
|
||||||
InitialState(username, password, ..) -> {
|
Pending -> {
|
||||||
use loaded_state <- result.try(
|
use initialised_state <- result.try(
|
||||||
init(username, password) |> result.map_error(APIError),
|
init(state.credentials.username, state.credentials.password)
|
||||||
)
|
|> result.map_error(APIError),
|
||||||
fun(
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
loaded_state.0,
|
|
||||||
loaded_state.1,
|
|
||||||
loaded_state.2,
|
|
||||||
loaded_state.3,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun(state.credentials, initialised_state)
|
||||||
}
|
}
|
||||||
LoadedState(username, password, cookies, cookies_acquired, ids, dataset, ..) ->
|
Initialised(inner) -> fun(state.credentials, inner)
|
||||||
fun(username, password, cookies, cookies_acquired, ids, dataset)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn login(username: String, password: String) {
|
fn login(username: String, password: String) {
|
||||||
use cookies <- result.try(api.login(username, password))
|
use cookies <- result.try(api.login(username, password))
|
||||||
Ok(#(cookies, birl.utc_now()))
|
Ok(Cookies(cookies, birl.utc_now()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(username: String, password: String) {
|
fn init(username: String, password: String) {
|
||||||
use #(cookies, cookies_acquired) <- result.try(login(username, password))
|
use cookies <- result.try(login(username, password))
|
||||||
use module_ids <- result.try(api.get_module_ids(cookies))
|
use module_ids <- result.try(api.get_module_ids(cookies.jar))
|
||||||
|
|
||||||
Ok(#(cookies, cookies_acquired, module_ids, option.None))
|
Ok(InitialisedState(cookies, module_ids, option.None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(credentials: Credentials, state: InitialisedState) {
|
||||||
username: String,
|
|
||||||
password: String,
|
|
||||||
cookies: biscotto.CookieJar,
|
|
||||||
cookies_acquired: birl.Time,
|
|
||||||
module_ids: ModuleIDs,
|
|
||||||
dataset: option.Option(Dataset),
|
|
||||||
) {
|
|
||||||
let now = birl.utc_now()
|
let now = birl.utc_now()
|
||||||
let max_lifetime = duration.seconds(login_cookie_expiry)
|
let max_lifetime = duration.seconds(login_cookie_expiry)
|
||||||
let should_renew = case
|
let should_renew = case
|
||||||
duration.compare(birl.difference(now, cookies_acquired), max_lifetime)
|
duration.compare(birl.difference(now, state.cookies.acquired), max_lifetime)
|
||||||
{
|
{
|
||||||
order.Gt | order.Eq -> True
|
order.Gt | order.Eq -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
}
|
}
|
||||||
|
|
||||||
let cookies_result = case should_renew {
|
let cookies_result = case should_renew {
|
||||||
False -> Ok(#(cookies, cookies_acquired))
|
False -> Ok(state.cookies)
|
||||||
True -> login(username, password)
|
True -> login(credentials.username, credentials.password)
|
||||||
}
|
}
|
||||||
|
|
||||||
use #(cookies, cookies_acquired) <- result.try(
|
use cookies <- result.try(cookies_result |> result.map_error(APIError))
|
||||||
cookies_result |> result.map_error(APIError),
|
|
||||||
)
|
|
||||||
|
|
||||||
use production_info <- result.try(
|
use production_info <- result.try(
|
||||||
api.get_production(cookies) |> result.map_error(APIError),
|
api.get_production(cookies.jar) |> result.map_error(APIError),
|
||||||
)
|
)
|
||||||
use module_datas <- result.try(
|
use module_datas <- result.try(
|
||||||
api.get_module_power(cookies, module_ids) |> result.map_error(APIError),
|
api.get_module_power(cookies.jar, state.modules)
|
||||||
|
|> result.map_error(APIError),
|
||||||
)
|
)
|
||||||
use parsed_module_datas <- result.try(
|
use parsed_module_datas <- result.try(
|
||||||
module_power.decode_api_data(module_datas)
|
module_power.decode_api_data(module_datas)
|
||||||
|> result.map_error(DecodeError),
|
|> result.map_error(DecodeError),
|
||||||
)
|
)
|
||||||
|
|
||||||
let new_dataset = case dataset {
|
let new_dataset = case state.dataset {
|
||||||
option.Some(existing_dataset) ->
|
option.Some(existing_dataset) ->
|
||||||
Dataset(..existing_dataset, production_info: production_info)
|
Dataset(..existing_dataset, production_info: production_info)
|
||||||
option.None ->
|
option.None ->
|
||||||
|
@ -224,7 +176,13 @@ fn update(
|
||||||
modules: add_module_datasets(new_dataset.modules, parsed_module_datas),
|
modules: add_module_datasets(new_dataset.modules, parsed_module_datas),
|
||||||
)
|
)
|
||||||
|
|
||||||
Ok(#(cookies, cookies_acquired, new_dataset))
|
Ok(
|
||||||
|
InitialisedState(
|
||||||
|
..state,
|
||||||
|
cookies: cookies,
|
||||||
|
dataset: option.Some(new_dataset),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_module_datasets(
|
fn add_module_datasets(
|
||||||
|
|
Loading…
Reference in a new issue