use crate::users::ClientUserInformation;
use crate::RoboatError;
use reqwest::header::HeaderValue;
use tokio::sync::RwLock;
#[derive(Debug, Default)]
pub struct Client {
pub(crate) cookie_string: Option<HeaderValue>,
pub(crate) xcsrf: RwLock<String>,
pub(crate) user_information: RwLock<Option<ClientUserInformation>>,
pub(crate) reqwest_client: reqwest::Client,
}
#[derive(Clone, Debug, Default)]
pub struct ClientBuilder {
roblosecurity: Option<String>,
reqwest_client: Option<reqwest::Client>,
}
impl Client {
pub async fn user_id(&self) -> Result<u64, RoboatError> {
let guard = self.user_information.read().await;
let user_information_opt = &*guard;
match user_information_opt {
Some(user_information) => Ok(user_information.user_id),
None => {
drop(guard);
let user_info = self.user_information_internal().await?;
Ok(user_info.user_id)
}
}
}
pub async fn username(&self) -> Result<String, RoboatError> {
let guard = self.user_information.read().await;
let user_information_opt = &*guard;
match user_information_opt {
Some(user_information) => Ok(user_information.username.clone()),
None => {
drop(guard);
let user_info = self.user_information_internal().await?;
Ok(user_info.username)
}
}
}
pub async fn display_name(&self) -> Result<String, RoboatError> {
let guard = self.user_information.read().await;
let user_information_opt = &*guard;
match user_information_opt {
Some(user_information) => Ok(user_information.display_name.clone()),
None => {
drop(guard);
let user_info = self.user_information_internal().await?;
Ok(user_info.display_name)
}
}
}
pub(crate) async fn set_user_information(&self, user_information: ClientUserInformation) {
*self.user_information.write().await = Some(user_information);
}
pub(crate) async fn set_xcsrf(&self, xcsrf: String) {
*self.xcsrf.write().await = xcsrf;
}
pub(crate) async fn xcsrf(&self) -> String {
self.xcsrf.read().await.clone()
}
pub(crate) fn cookie_string(&self) -> Result<HeaderValue, RoboatError> {
let cookie_string_opt = &self.cookie_string;
match cookie_string_opt {
Some(cookie) => Ok(cookie.clone()),
None => Err(RoboatError::RoblosecurityNotSet),
}
}
}
impl ClientBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn roblosecurity(mut self, roblosecurity: String) -> Self {
self.roblosecurity = Some(roblosecurity);
self
}
pub fn reqwest_client(mut self, reqwest_client: reqwest::Client) -> Self {
self.reqwest_client = Some(reqwest_client);
self
}
pub fn build(self) -> Client {
Client {
cookie_string: self
.roblosecurity
.as_ref()
.map(|x| create_cookie_string_header(x)),
reqwest_client: self.reqwest_client.unwrap_or_default(),
..Default::default()
}
}
}
fn create_cookie_string_header(roblosecurity: &str) -> HeaderValue {
let mut header = HeaderValue::from_str(&format!(".ROBLOSECURITY={}", roblosecurity))
.expect("Invalid roblosecurity characters.");
header.set_sensitive(true);
header
}