Rewrite to a API trait.
This commit is contained in:
72
gamenight-cli/Cargo.lock
generated
72
gamenight-cli/Cargo.lock
generated
@@ -108,6 +108,15 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
@@ -221,21 +230,6 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
@@ -243,7 +237,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -252,17 +245,6 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
@@ -298,7 +280,6 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
@@ -332,6 +313,7 @@ dependencies = [
|
||||
name = "gamenight-api-client-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -346,8 +328,8 @@ dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"clear_screen",
|
||||
"colored",
|
||||
"dyn-clone",
|
||||
"futures",
|
||||
"gamenight-api-client-rs",
|
||||
"inquire",
|
||||
"jsonwebtoken",
|
||||
@@ -996,12 +978,14 @@ dependencies = [
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
@@ -1236,9 +1220,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.113"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1386,6 +1370,19 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
@@ -1604,6 +1601,19 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.83"
|
||||
|
||||
@@ -15,4 +15,4 @@ jsonwebtoken = "9.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
clear_screen = "0.1"
|
||||
futures = "0.3"
|
||||
colored = "3.0"
|
||||
|
||||
20
gamenight-cli/src/domain/eligable_games.rs
Normal file
20
gamenight-cli/src/domain/eligable_games.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use std::fmt::Display;
|
||||
use colored::Colorize;
|
||||
use crate::domain::location::Location;
|
||||
use crate::domain::owned_games::OwnedGames;
|
||||
|
||||
pub struct EligableGames<'a>(pub &'a OwnedGames, pub &'a Location);
|
||||
|
||||
impl Display for EligableGames<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (k, v) in self.0.0.iter() {
|
||||
writeln!(f, "{}:", k)?;
|
||||
for (g, l) in v.iter() {
|
||||
if l.as_ref().is_none_or(|x| x.id == self.1.id) {
|
||||
writeln!(f, "\t{}", g.name.green())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use chrono::{DateTime, Local};
|
||||
use uuid::Uuid;
|
||||
use crate::domain::eligable_games::EligableGames;
|
||||
use crate::domain::location::Location;
|
||||
use crate::domain::owned_games::OwnedGames;
|
||||
use crate::domain::participants::Participants;
|
||||
use crate::domain::user::User;
|
||||
@@ -9,6 +11,7 @@ use crate::domain::user::User;
|
||||
pub struct Gamenight {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub location: Option<Location>,
|
||||
pub start_time: DateTime<Local>,
|
||||
pub organizer: User,
|
||||
pub participants: Participants,
|
||||
@@ -21,7 +24,12 @@ impl Display for Gamenight {
|
||||
writeln!(f, "Organizer: {}", self.organizer)?;
|
||||
writeln!(f, "Start: {}", self.start_time.to_rfc3339())?;
|
||||
writeln!(f, "Participants: {}", self.participants)?;
|
||||
write!(f, "Owned games:\n{}", self.owned_games)?;
|
||||
if let Some(location) = &self.location {
|
||||
write!(f, "Eligable games:\n{}", EligableGames(&self.owned_games, location))?;
|
||||
} else {
|
||||
write!(f, "Owned games: \n{}", self.owned_games)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use uuid::Uuid;
|
||||
pub struct GamenightSelectData {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub location_id: Option<Uuid>,
|
||||
pub start_time: DateTime<Local>,
|
||||
pub owner_id: Uuid,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::fmt::Display;
|
||||
|
||||
use gamenight_api_client_rs::models;
|
||||
use uuid::Uuid;
|
||||
use crate::flows::FlowError;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Location {
|
||||
@@ -11,14 +12,15 @@ pub struct Location {
|
||||
pub note: Option<String>,
|
||||
}
|
||||
|
||||
impl From<models::Location> for Location {
|
||||
fn from(location: models::Location) -> Self {
|
||||
Self {
|
||||
id: Uuid::parse_str(&location.id).unwrap(),
|
||||
name: location.name,
|
||||
address: location.address,
|
||||
note: location.note
|
||||
}
|
||||
impl TryFrom<models::Location> for Location {
|
||||
type Error = FlowError;
|
||||
fn try_from(value: models::Location) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
id: Uuid::parse_str(&value.id)?,
|
||||
name: value.name,
|
||||
address: value.address,
|
||||
note: value.note
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,4 +6,5 @@ pub mod game;
|
||||
pub mod owned_games;
|
||||
pub mod location;
|
||||
pub mod location_select_data;
|
||||
pub mod gamenight;
|
||||
pub mod gamenight;
|
||||
mod eligable_games;
|
||||
@@ -1,15 +1,16 @@
|
||||
use std::{collections::HashMap, fmt::Display};
|
||||
|
||||
use crate::domain::game::Game;
|
||||
use crate::domain::location::Location;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OwnedGames(pub HashMap<String, Vec<Game>>);
|
||||
pub struct OwnedGames (pub HashMap<String, Vec<(Game, Option<Location>)>>);
|
||||
|
||||
impl Display for OwnedGames {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (k,v) in &self.0 {
|
||||
write!(f, "{k}:\n")?;
|
||||
for g in v {
|
||||
for (g, _) in v {
|
||||
write!(f, "\t{}\n", g.name)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::fmt::Display;
|
||||
use super::*;
|
||||
use crate::flows::own::Own;
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::game_post, models::AddGameRequestBody};
|
||||
use gamenight_api_client_rs::models::AddGameRequestBody;
|
||||
use inquire::Text;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ impl<'a> Flow<'a> for AddGame {
|
||||
let add_game_request = AddGameRequestBody {
|
||||
name
|
||||
};
|
||||
let game_id_response = game_post(&state.api_configuration, Some(add_game_request)).await?;
|
||||
let game_id_response = state.api.game_post(Some(add_game_request)).await?;
|
||||
|
||||
let own_flow = Own::new(Uuid::parse_str(&game_id_response.game_id)?);
|
||||
return self.continue_with(state, &own_flow).await;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
use gamenight_api_client_rs::{apis::default_api::post_gamenight, models};
|
||||
use inquire::{CustomType, DateSelect, Text};
|
||||
use chrono::{self, Local, NaiveTime};
|
||||
|
||||
use gamenight_api_client_rs::models;
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -32,7 +31,7 @@ impl<'a> Flow<'a> for AddGamenight {
|
||||
.to_utc()
|
||||
.to_rfc3339();
|
||||
let add_gamenight = models::AddGamenightRequestBody::new(name, datetime);
|
||||
post_gamenight(&state.api_configuration, Some(add_gamenight)).await?;
|
||||
state.api.post_gamenight(Some(add_gamenight)).await?;
|
||||
|
||||
clear_screen::clear();
|
||||
return Ok((FlowOutcome::Successful, state))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{ffi::OsStr, fmt::Display};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::{location_authorize_post, location_post}, models::{authorize_location_request_body::Op::Grant, AddLocationRequestBody, AuthorizeLocationRequestBody}};
|
||||
use gamenight_api_client_rs::models::{authorize_location_request_body::Op::Grant, AddLocationRequestBody, AuthorizeLocationRequestBody};
|
||||
use inquire::{Editor, Text};
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ impl<'a> Flow<'a> for AddLocation {
|
||||
note
|
||||
};
|
||||
|
||||
let location_id = location_post(&state.api_configuration, Some(add_location_request)).await?;
|
||||
let location_id = state.api.location_post(Some(add_location_request)).await?;
|
||||
|
||||
let add_authorize_request = AuthorizeLocationRequestBody {
|
||||
location_id: location_id.location_id.to_string(),
|
||||
@@ -52,7 +52,7 @@ impl<'a> Flow<'a> for AddLocation {
|
||||
op: Grant
|
||||
};
|
||||
|
||||
location_authorize_post(&state.api_configuration, Some(add_authorize_request)).await?;
|
||||
state.api.location_authorize_post(Some(add_authorize_request)).await?;
|
||||
}
|
||||
Ok((FlowOutcome::Cancelled, state))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::apis::configuration::Configuration;
|
||||
use inquire::Text;
|
||||
|
||||
use crate::{domain::config::{Config, Instance}, flows::{gamenight_menu::GamenightMenu, login::Login, FlowError}};
|
||||
|
||||
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
|
||||
use crate::{domain::config::{Config, Instance}, flows::{gamenight_menu::GamenightMenu, login::Login, FlowError}};
|
||||
use async_trait::async_trait;
|
||||
use inquire::Text;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Connect {
|
||||
@@ -50,37 +47,37 @@ impl Connect {
|
||||
|
||||
}
|
||||
|
||||
pub async fn try_refresh_token_if_exists(&self, instance: &mut Instance, api_configuration: &mut Configuration, config: &mut Config, instance_name: &String) -> Result<bool, FlowError> {
|
||||
pub async fn try_refresh_token_if_exists<'a>(&self, instance: &mut Instance, state: &'a mut GamenightState, instance_name: &String) -> Result<(bool, &'a mut GamenightState), FlowError> {
|
||||
if let Some(token) = &instance.token {
|
||||
api_configuration.bearer_access_token = Some(token.clone());
|
||||
let result = gamenight_api_client_rs::apis::default_api::post_token(api_configuration).await;
|
||||
let state = state.set_bearer_access_token(Some(token.clone()));
|
||||
let result = state.api.post_token().await;
|
||||
if let Ok(token) = result {
|
||||
let instance = config.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
||||
let instance = state.gamenight_configuration.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
||||
instance.token = token.jwt_token.clone();
|
||||
api_configuration.bearer_access_token = token.jwt_token.clone();
|
||||
Config::save(config)?;
|
||||
Ok(true)
|
||||
let state = state.set_bearer_access_token(token.jwt_token.clone());
|
||||
Config::save(&state.gamenight_configuration)?;
|
||||
Ok((true, state))
|
||||
}
|
||||
else {
|
||||
Ok(false)
|
||||
Ok((false, state))
|
||||
}
|
||||
} else {
|
||||
Ok(false)
|
||||
Ok((false, state))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_state_on_logon(&self, instance: &mut Instance, api_configuration: &mut Configuration, config: &mut Config, instance_name: &String) -> Result<(), FlowError> {
|
||||
pub fn update_state_on_logon(&self, instance: &mut Instance, state: &mut GamenightState, instance_name: &String) -> Result<(), FlowError> {
|
||||
if self.instance.is_none() {
|
||||
instance.token = Some(api_configuration.bearer_access_token.clone().unwrap());
|
||||
config.instances.push(instance.clone());
|
||||
instance.token = Some(state.api_configuration.bearer_access_token.clone().unwrap());
|
||||
state.gamenight_configuration.instances.push(instance.clone());
|
||||
}
|
||||
else {
|
||||
let instance = config.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
||||
instance.token = Some(api_configuration.bearer_access_token.clone().unwrap());
|
||||
let instance = state.gamenight_configuration.instances.iter_mut().find(|x| x.name == *instance_name).unwrap();
|
||||
instance.token = Some(state.api_configuration.bearer_access_token.clone().unwrap());
|
||||
}
|
||||
config.last_instance = Some(instance_name.clone());
|
||||
state.gamenight_configuration.last_instance = Some(instance_name.clone());
|
||||
|
||||
Config::save(config)?;
|
||||
Config::save(&state.gamenight_configuration)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -98,9 +95,10 @@ impl<'a> Flow<'a> for Connect {
|
||||
};
|
||||
|
||||
let instance_name = instance.name.clone();
|
||||
state.api_configuration.base_path = instance.url.clone();
|
||||
let state = state.set_api_base_path(instance.url.clone());
|
||||
|
||||
if self.try_refresh_token_if_exists(&mut instance, &mut state.api_configuration, &mut state.gamenight_configuration, &instance_name).await? {
|
||||
let (token_refreshed, state) = self.try_refresh_token_if_exists(&mut instance, state, &instance_name).await?;
|
||||
if token_refreshed {
|
||||
let gamenight_menu_flow = GamenightMenu::new();
|
||||
gamenight_menu_flow.run(state).await
|
||||
}
|
||||
@@ -109,7 +107,7 @@ impl<'a> Flow<'a> for Connect {
|
||||
let (outcome, state) = login_flow.run(state).await?;
|
||||
|
||||
if outcome == FlowOutcome::Successful {
|
||||
self.update_state_on_logon(&mut instance, &mut state.api_configuration, &mut state.gamenight_configuration, &instance_name)?;
|
||||
self.update_state_on_logon(&mut instance, state, &instance_name)?;
|
||||
|
||||
let gamenight_menu_flow = GamenightMenu::new();
|
||||
gamenight_menu_flow.run(state).await
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::disown_post, models::GameId};
|
||||
use gamenight_api_client_rs::models::GameId;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
|
||||
@@ -22,7 +22,7 @@ impl Disown {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Disown {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let _ = disown_post(&state.api_configuration, Some(GameId{game_id: self.game_id.to_string()})).await?;
|
||||
let _ = state.api.disown_post(Some(GameId{game_id: self.game_id.to_string()})).await?;
|
||||
|
||||
clear_screen::clear();
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::join_post, models::GamenightId};
|
||||
use gamenight_api_client_rs::models::GamenightId;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
|
||||
@@ -22,7 +22,7 @@ impl Join {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Join {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let _ = join_post(&state.api_configuration, Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
|
||||
let _ = state.api.join_post(Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
|
||||
|
||||
clear_screen::clear();
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::leave_post, models::GamenightId};
|
||||
use gamenight_api_client_rs::models::GamenightId;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
|
||||
@@ -22,7 +22,7 @@ impl Leave {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Leave {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let _ = leave_post(&state.api_configuration, Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
|
||||
let _ = state.api.leave_post(Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
|
||||
|
||||
clear_screen::clear();
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
use chrono::DateTime;
|
||||
use gamenight_api_client_rs::apis::default_api::get_gamenights;
|
||||
use inquire::Select;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -22,7 +21,7 @@ impl ListGamenights {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for ListGamenights {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let response = get_gamenights(&state.api_configuration).await?;
|
||||
let response = state.api.get_gamenights().await?;
|
||||
|
||||
let mut view_flows: Vec<Box<dyn Flow<'_> + Send>> = vec![];
|
||||
|
||||
@@ -30,6 +29,10 @@ impl<'a> Flow<'a> for ListGamenights {
|
||||
let gamenight = GamenightSelectData {
|
||||
id: Uuid::parse_str(&response.id)?,
|
||||
name: response.name.clone(),
|
||||
location_id: match &response.location_id {
|
||||
None => None,
|
||||
Some(x) => Some(Uuid::parse_str(x)?)
|
||||
},
|
||||
start_time:DateTime::parse_from_rfc3339(&response.datetime)?.into(),
|
||||
owner_id: Uuid::parse_str(&response.owner_id)?
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::apis::default_api::games_get;
|
||||
use inquire::{ui::RenderConfig, Select};
|
||||
|
||||
use crate::flows::{view_game::ViewGame, exit::Exit};
|
||||
@@ -22,7 +21,7 @@ impl ListGames {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for ListGames {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let games = games_get(&state.api_configuration).await?;
|
||||
let games = state.api.games_get().await?;
|
||||
|
||||
let mut flows = games.into_iter().map(|game| -> Box<dyn Flow + Send> {
|
||||
Box::new(ViewGame::new(game.into()))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::apis::default_api::locations_get;
|
||||
use inquire::{ui::RenderConfig, Select};
|
||||
|
||||
use crate::flows::{exit::Exit, view_location::ViewLocation};
|
||||
@@ -22,10 +21,10 @@ impl ListLocations {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for ListLocations {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let locations = locations_get(&state.api_configuration).await?;
|
||||
let locations = state.api.locations_get().await?;
|
||||
|
||||
let mut flows = locations.into_iter().map(|location| -> Box<dyn Flow + Send> {
|
||||
Box::new(ViewLocation::new(location.into()))
|
||||
Box::new(ViewLocation::new(location.try_into().unwrap()))
|
||||
}).collect::<Vec::<Box::<dyn Flow + Send>>>();
|
||||
|
||||
flows.push(Box::new(Exit::new()));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::{self, authorized_location_user_ids_get, users_get}, models::{AuthorizeLocationRequestBody, LocationId, User}};
|
||||
use gamenight_api_client_rs::models::{AuthorizeLocationRequestBody, LocationId, User};
|
||||
use inquire::MultiSelect;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -47,11 +47,11 @@ impl<'a> TryFrom<&'a User> for AuthorizeMultiSelectStruct<'a> {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for LocationAuthorize {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let users = users_get(&state.api_configuration).await?;
|
||||
let users = state.api.users_get().await?;
|
||||
let location_id = LocationId {
|
||||
location_id: self.location_id.to_string()
|
||||
};
|
||||
let authorized_user_ids = authorized_location_user_ids_get(&state.api_configuration, Some(location_id)).await?;
|
||||
let authorized_user_ids = state.api.authorized_location_user_ids_get(Some(location_id)).await?;
|
||||
let authorized_user_ids : Vec<String> = authorized_user_ids.into_iter().map(|x| x.user_id).collect();
|
||||
|
||||
let options: Vec<AuthorizeMultiSelectStruct> = users.iter().map(|x| {x.try_into()}).collect::<Result<Vec<AuthorizeMultiSelectStruct>, FlowError>>()?;
|
||||
@@ -67,7 +67,7 @@ impl<'a> Flow<'a> for LocationAuthorize {
|
||||
if let Some(selections) = &selections {
|
||||
for selection in selections {
|
||||
if authorized_users.iter().find(|x| {x.id == selection.id.to_string()}).is_none() {
|
||||
default_api::location_authorize_post(&state.api_configuration, Some(
|
||||
state.api.location_authorize_post(Some(
|
||||
AuthorizeLocationRequestBody {
|
||||
location_id: self.location_id.to_string(),
|
||||
user_id: selection.id.to_string(),
|
||||
@@ -78,7 +78,7 @@ impl<'a> Flow<'a> for LocationAuthorize {
|
||||
}
|
||||
for authorized_user in authorized_users {
|
||||
if selections.iter().find(|x| {x.id.to_string() == authorized_user.id}).is_none() {
|
||||
default_api::location_authorize_post(&state.api_configuration, Some(
|
||||
state.api.location_authorize_post(Some(
|
||||
AuthorizeLocationRequestBody {
|
||||
location_id: self.location_id.to_string(),
|
||||
user_id: authorized_user.id.to_string(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::{configuration::Configuration, default_api::get_token}, models};
|
||||
use gamenight_api_client_rs::models;
|
||||
use inquire::{Password, Text};
|
||||
|
||||
use super::*;
|
||||
@@ -18,7 +18,6 @@ impl Login {
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Login {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let configuration = Configuration::new();
|
||||
|
||||
let username = Text::new("What is your login?").prompt()?;
|
||||
let password = Password::new("what is your password?")
|
||||
@@ -27,11 +26,11 @@ impl<'a> Flow<'a> for Login {
|
||||
|
||||
let login = models::Login::new(username, password);
|
||||
|
||||
let result = get_token(&configuration, Some(login)).await?;
|
||||
let result = state.api.get_token(Some(login)).await?;
|
||||
|
||||
clear_screen::clear();
|
||||
if let Some(token) = result.jwt_token {
|
||||
state.api_configuration.bearer_access_token = Some(token);
|
||||
state.set_bearer_access_token(Some(token));
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
} else {
|
||||
Err(FlowError{error: "Unexpected response".to_string()})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use gamenight_api_client_rs::apis::default_api::{DefaultApi, DefaultApiClient};
|
||||
use std::{fmt::Display, num::ParseIntError};
|
||||
|
||||
use std::sync::{Arc, MutexGuard, PoisonError};
|
||||
use async_trait::async_trait;
|
||||
use chrono::ParseError;
|
||||
use gamenight_api_client_rs::apis::{configuration::Configuration, Error};
|
||||
@@ -38,10 +39,12 @@ mod location_authorize;
|
||||
mod remove_game;
|
||||
|
||||
pub struct GamenightState {
|
||||
api_configuration: Configuration,
|
||||
api_configuration: Arc<Configuration>,
|
||||
api: Box<dyn DefaultApi>,
|
||||
gamenight_configuration: Config,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Claims {
|
||||
exp: i64,
|
||||
@@ -50,8 +53,10 @@ pub struct Claims {
|
||||
|
||||
impl GamenightState {
|
||||
pub fn new() -> Self{
|
||||
let config = Arc::new(Configuration::new());
|
||||
Self {
|
||||
api_configuration: Configuration::new(),
|
||||
api_configuration: config.clone(),
|
||||
api: Box::new(DefaultApiClient::new(config.clone())),
|
||||
gamenight_configuration: Config::new()
|
||||
}
|
||||
}
|
||||
@@ -67,6 +72,22 @@ impl GamenightState {
|
||||
|
||||
Ok(claims.uid)
|
||||
}
|
||||
|
||||
pub fn set_bearer_access_token(&mut self, token: Option<String>) -> &mut Self {
|
||||
let mut config : Configuration = Arc::<Configuration>::into_inner(self.api_configuration.clone()).unwrap_or(Configuration::new());
|
||||
config.bearer_access_token = token;
|
||||
self.api_configuration = Arc::from(config);
|
||||
self.api = Box::new(DefaultApiClient::new(self.api_configuration.clone()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_api_base_path(&mut self, base_path: String) -> &mut Self {
|
||||
let mut config : Configuration = Arc::<Configuration>::into_inner(self.api_configuration.clone()).unwrap_or(Configuration::new());
|
||||
config.base_path = base_path;
|
||||
self.api_configuration = Arc::from(config);
|
||||
self.api = Box::new(DefaultApiClient::new(self.api_configuration.clone()));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GamenightState {
|
||||
@@ -136,6 +157,30 @@ impl From<jsonwebtoken::errors::Error> for FlowError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PoisonError<&mut Configuration>> for FlowError {
|
||||
fn from(value: PoisonError<&mut Configuration>) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PoisonError<Configuration>> for FlowError {
|
||||
fn from(value: PoisonError<Configuration>) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PoisonError<std::sync::MutexGuard<'_, Configuration>>> for FlowError {
|
||||
fn from(value: PoisonError<MutexGuard<'_, Configuration>>) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum FlowOutcome {
|
||||
Successful,
|
||||
|
||||
@@ -3,9 +3,7 @@ use std::fmt::Display;
|
||||
use super::{Flow, FlowError, FlowOutcome, FlowResult, GamenightState};
|
||||
use crate::domain::location_select_data::LocationSelectData;
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::apis::default_api::locations_get;
|
||||
use gamenight_api_client_rs::models::OwnGameRequestBody;
|
||||
use gamenight_api_client_rs::apis::default_api::own_post;
|
||||
use inquire::{Confirm, Select};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -35,13 +33,13 @@ impl<'a> Flow<'a> for Own {
|
||||
if owned {
|
||||
if let Some(willing_to_travel) = Confirm::new("Are you willing to travel with this game?").prompt_skippable()? {
|
||||
if !willing_to_travel {
|
||||
let locations = locations_get(&state.api_configuration).await?.iter().map(|x| { x.try_into() }).collect::<Result<Vec<LocationSelectData>, FlowError>>()?;
|
||||
let locations = state.api.locations_get().await?.iter().map(|x| { x.try_into() }).collect::<Result<Vec<LocationSelectData>, FlowError>>()?;
|
||||
if let Some(location) = Select::new("What location can this game be played?", locations).prompt_skippable()? {
|
||||
own_game_request.location_id = Some(location.id.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = own_post(&state.api_configuration, Some(own_game_request)).await?;
|
||||
let _ = state.api.own_post(Some(own_game_request)).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ impl<'a> Flow<'a> for RemoveGame {
|
||||
let req = GameId {
|
||||
game_id: self.game.id.to_string()
|
||||
};
|
||||
gamenight_api_client_rs::apis::default_api::game_delete(&state.api_configuration, Some(req)).await?;
|
||||
state.api.game_delete(Some(req)).await?;
|
||||
//Hack to return to right stack item, skipping detail view that doesn't exist.
|
||||
Ok((FlowOutcome::Abort, state))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::default_api::rename_game_post, models::RenameGameRequestBody};
|
||||
use gamenight_api_client_rs::models::RenameGameRequestBody;
|
||||
use inquire::Text;
|
||||
|
||||
use crate::domain::game::Game;
|
||||
@@ -32,7 +32,7 @@ impl<'a> Flow<'a> for RenameGame {
|
||||
id: self.game.id.to_string(),
|
||||
name
|
||||
};
|
||||
rename_game_post(&state.api_configuration, Some(req)).await?;
|
||||
state.api.rename_game_post(Some(req)).await?;
|
||||
|
||||
return Ok((FlowOutcome::Successful, state))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
use gamenight_api_client_rs::{apis::default_api::{game_get, owned_games_get}, models::{GameId, UserId}};
|
||||
use gamenight_api_client_rs::models::{GameId, UserId};
|
||||
use inquire::Select;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -24,15 +24,15 @@ impl ViewGame {
|
||||
impl<'a> Flow<'a> for ViewGame {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let game_id = GameId{ game_id: self.game.id.to_string() };
|
||||
let game: Game = game_get(&state.api_configuration, Some(game_id)).await?.into();
|
||||
let game: Game = state.api.game_get(Some(game_id)).await?.into();
|
||||
|
||||
println!("{}", game);
|
||||
|
||||
let my_uid = state.get_user_id()?;
|
||||
let request = UserId{ user_id: my_uid.to_string() };
|
||||
let owned_games: Vec<Uuid> = owned_games_get(&state.api_configuration, Some(request)).await?
|
||||
let owned_games: Vec<Uuid> = state.api.owned_games_get(Some(request)).await?
|
||||
.iter().map(|x| -> Result<Uuid, FlowError> {
|
||||
Ok(Uuid::parse_str(x)?)
|
||||
Ok(Uuid::parse_str(&x.game_id)?)
|
||||
}).collect::<Result<Vec<Uuid>, FlowError>>()?;
|
||||
|
||||
let own_or_disown: Box<dyn Flow<'a> + Send> =
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use crate::domain::gamenight::Gamenight;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use futures::future::join_all;
|
||||
use gamenight_api_client_rs::{apis::default_api::{game_get, owned_games_get, participants_get, user_get, GameGetError}, models::{self, GameId, GamenightId, UserId}};
|
||||
use gamenight_api_client_rs::models::{GameId, GamenightId, LocationId, OwnedGame, UserId};
|
||||
use inquire::Select;
|
||||
|
||||
use crate::{domain::{game::Game, gamenight_select_data::GamenightSelectData, owned_games::OwnedGames, participants::Participants}, flows::{exit::Exit, join::Join, leave::Leave}};
|
||||
|
||||
use super::*;
|
||||
use crate::{domain::{gamenight_select_data::GamenightSelectData, owned_games::OwnedGames, participants::Participants}, flows::{exit::Exit, join::Join, leave::Leave}};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ViewGamenight {
|
||||
@@ -30,25 +28,35 @@ impl<'a> Flow<'a> for ViewGamenight {
|
||||
id: self.gamenight_select_data.id,
|
||||
start_time: self.gamenight_select_data.start_time,
|
||||
name: self.gamenight_select_data.name.clone(),
|
||||
organizer: user_get(&state.api_configuration, Some(UserId{user_id: self.gamenight_select_data.owner_id.to_string()})).await?.try_into()?,
|
||||
location: None,
|
||||
organizer: state.api.user_get(Some(UserId{user_id: self.gamenight_select_data.owner_id.to_string()})).await?.try_into()?,
|
||||
participants: Participants(vec![]),
|
||||
owned_games: OwnedGames(HashMap::new())
|
||||
};
|
||||
|
||||
let participants = participants_get(&state.api_configuration, Some(GamenightId{gamenight_id: gamenight.id.to_string()})).await?;
|
||||
gamenight.location = match self.gamenight_select_data.location_id {
|
||||
None => None,
|
||||
Some(l) => Some(state.api.location_get(Some(LocationId{location_id: l.to_string()})).await?.try_into()?)
|
||||
};
|
||||
let participants = state.api.participants_get(Some(GamenightId{gamenight_id: gamenight.id.to_string()})).await?;
|
||||
|
||||
for participant in participants.participants.iter() {
|
||||
gamenight.participants.0.push(user_get(&state.api_configuration, Some(UserId{user_id: participant.clone()})).await?.try_into()?);
|
||||
gamenight.participants.0.push(state.api.user_get(Some(UserId{user_id: participant.clone()})).await?.try_into()?);
|
||||
}
|
||||
|
||||
for user in &gamenight.participants.0 {
|
||||
let request = UserId{ user_id: user.id.to_string() };
|
||||
let games: Vec<Game> = join_all(owned_games_get(&state.api_configuration, Some(request)).await?
|
||||
.iter().map(async |game_id| -> Result<models::Game, Error<GameGetError>> {
|
||||
let request = GameId{ game_id: game_id.clone() };
|
||||
game_get(&state.api_configuration, Some(request)).await
|
||||
})).await.into_iter().collect::<Result<Vec<models::Game>, Error<GameGetError>>>()?.into_iter().map(Into::into).collect();
|
||||
gamenight.owned_games.0.insert(user.username.clone(), games);
|
||||
let owned_games_refs: Vec<OwnedGame> = state.api.owned_games_get(Some(request)).await?;
|
||||
let mut owned_games = vec![];
|
||||
for owned_games_ref in owned_games_refs {
|
||||
let game = state.api.game_get(Some(GameId{ game_id: owned_games_ref.game_id.clone()})).await?.into();
|
||||
let location = match owned_games_ref.location_id {
|
||||
None => None,
|
||||
Some(x) => Some(state.api.location_get(Some(LocationId{location_id: x})).await?.try_into()?)
|
||||
};
|
||||
owned_games.push((game, location));
|
||||
}
|
||||
gamenight.owned_games.0.insert(user.username.clone(), owned_games);
|
||||
}
|
||||
|
||||
println!("{}", gamenight);
|
||||
|
||||
@@ -6,9 +6,9 @@ use flows::{main::Main, Flow, GamenightState};
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let mut state = GamenightState::new();
|
||||
let mainflow = Main::new();
|
||||
let main_flow = Main::new();
|
||||
clear_screen::clear();
|
||||
if let Err(x) = mainflow.run(&mut state).await {
|
||||
if let Err(x) = main_flow.run(&mut state).await {
|
||||
println!("{}", x.error);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user