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)
|
||||
}
|
||||
|
||||
pub type State {
|
||||
InitialState(
|
||||
username: String,
|
||||
password: String,
|
||||
error: option.Option(UpdateError),
|
||||
)
|
||||
LoadedState(
|
||||
username: String,
|
||||
password: String,
|
||||
cookies: biscotto.CookieJar,
|
||||
cookies_acquired: birl.Time,
|
||||
ids: ModuleIDs,
|
||||
pub type Credentials {
|
||||
Credentials(username: String, password: String)
|
||||
}
|
||||
|
||||
pub type Cookies {
|
||||
Cookies(jar: biscotto.CookieJar, acquired: birl.Time)
|
||||
}
|
||||
|
||||
pub type InitialisedState {
|
||||
InitialisedState(
|
||||
cookies: Cookies,
|
||||
modules: ModuleIDs,
|
||||
dataset: option.Option(Dataset),
|
||||
)
|
||||
}
|
||||
|
||||
pub type InnerState {
|
||||
Pending
|
||||
Initialised(InitialisedState)
|
||||
}
|
||||
|
||||
pub type State {
|
||||
State(
|
||||
credentials: Credentials,
|
||||
inner: InnerState,
|
||||
error: option.Option(UpdateError),
|
||||
)
|
||||
}
|
||||
|
@ -62,153 +74,93 @@ pub type UpdateError {
|
|||
}
|
||||
|
||||
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) {
|
||||
let next =
|
||||
with_loaded_state(
|
||||
state,
|
||||
fn(username, password, cookies, cookies_acquired, ids, dataset) {
|
||||
with_initialised_state(state, fn(credentials, inner_state) {
|
||||
case message {
|
||||
Update -> {
|
||||
use #(cookies, cookies_acquired, new_dataset) <- result.try(update(
|
||||
username,
|
||||
password,
|
||||
cookies,
|
||||
cookies_acquired,
|
||||
ids,
|
||||
dataset,
|
||||
))
|
||||
use new_state <- result.try(update(credentials, inner_state))
|
||||
|
||||
let new_state =
|
||||
LoadedState(
|
||||
username,
|
||||
password,
|
||||
cookies,
|
||||
cookies_acquired,
|
||||
ids,
|
||||
option.Some(new_dataset),
|
||||
option.None,
|
||||
)
|
||||
|
||||
Ok(actor.continue(new_state))
|
||||
Ok(actor.continue(State(..state, inner: Initialised(new_state))))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
case next {
|
||||
Ok(next) -> next
|
||||
Error(err) -> {
|
||||
let new_state = case state {
|
||||
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),
|
||||
)
|
||||
}
|
||||
let new_state = State(..state, error: option.Some(err))
|
||||
actor.continue(new_state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_loaded_state(
|
||||
fn with_initialised_state(
|
||||
state: State,
|
||||
fun: fn(
|
||||
String,
|
||||
String,
|
||||
biscotto.CookieJar,
|
||||
birl.Time,
|
||||
ModuleIDs,
|
||||
option.Option(Dataset),
|
||||
) ->
|
||||
fun: fn(Credentials, InitialisedState) ->
|
||||
Result(actor.Next(Message, State), UpdateError),
|
||||
) {
|
||||
case state {
|
||||
InitialState(username, password, ..) -> {
|
||||
use loaded_state <- result.try(
|
||||
init(username, password) |> result.map_error(APIError),
|
||||
)
|
||||
fun(
|
||||
username,
|
||||
password,
|
||||
loaded_state.0,
|
||||
loaded_state.1,
|
||||
loaded_state.2,
|
||||
loaded_state.3,
|
||||
case state.inner {
|
||||
Pending -> {
|
||||
use initialised_state <- result.try(
|
||||
init(state.credentials.username, state.credentials.password)
|
||||
|> result.map_error(APIError),
|
||||
)
|
||||
|
||||
fun(state.credentials, initialised_state)
|
||||
}
|
||||
LoadedState(username, password, cookies, cookies_acquired, ids, dataset, ..) ->
|
||||
fun(username, password, cookies, cookies_acquired, ids, dataset)
|
||||
Initialised(inner) -> fun(state.credentials, inner)
|
||||
}
|
||||
}
|
||||
|
||||
fn login(username: String, password: String) {
|
||||
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) {
|
||||
use #(cookies, cookies_acquired) <- result.try(login(username, password))
|
||||
use module_ids <- result.try(api.get_module_ids(cookies))
|
||||
use cookies <- result.try(login(username, password))
|
||||
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(
|
||||
username: String,
|
||||
password: String,
|
||||
cookies: biscotto.CookieJar,
|
||||
cookies_acquired: birl.Time,
|
||||
module_ids: ModuleIDs,
|
||||
dataset: option.Option(Dataset),
|
||||
) {
|
||||
fn update(credentials: Credentials, state: InitialisedState) {
|
||||
let now = birl.utc_now()
|
||||
let max_lifetime = duration.seconds(login_cookie_expiry)
|
||||
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
|
||||
_ -> False
|
||||
}
|
||||
|
||||
let cookies_result = case should_renew {
|
||||
False -> Ok(#(cookies, cookies_acquired))
|
||||
True -> login(username, password)
|
||||
False -> Ok(state.cookies)
|
||||
True -> login(credentials.username, credentials.password)
|
||||
}
|
||||
|
||||
use #(cookies, cookies_acquired) <- result.try(
|
||||
cookies_result |> result.map_error(APIError),
|
||||
)
|
||||
use cookies <- result.try(cookies_result |> result.map_error(APIError))
|
||||
|
||||
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(
|
||||
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(
|
||||
module_power.decode_api_data(module_datas)
|
||||
|> result.map_error(DecodeError),
|
||||
)
|
||||
|
||||
let new_dataset = case dataset {
|
||||
let new_dataset = case state.dataset {
|
||||
option.Some(existing_dataset) ->
|
||||
Dataset(..existing_dataset, production_info: production_info)
|
||||
option.None ->
|
||||
|
@ -224,7 +176,13 @@ fn update(
|
|||
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(
|
||||
|
|
Loading…
Reference in a new issue