use crate::{Client, RoboatError, User};
use reqwest::header::{self, HeaderValue};
use serde::{Deserialize, Serialize};
mod request_types;
const AUTHENTICATED_USER_DETAILS_API: &str = "https://users.roblox.com/v1/users/authenticated";
const USERS_SEARCH_API: &str = "https://users.roblox.com/v1/users/search";
const USER_DETAILS_API: &str = "https://users.roblox.com/v1/users/{user_id}";
const USER_FROM_USERNAME_API: &str = "https://users.roblox.com/v1/usernames/users";
#[allow(missing_docs)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub(crate) struct ClientUserInformation {
#[serde(alias = "id")]
pub user_id: u64,
#[serde(alias = "name")]
pub username: String,
#[serde(alias = "displayName")]
pub display_name: String,
}
#[allow(missing_docs)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub struct UserDetails {
#[serde(alias = "name")]
pub username: String,
#[serde(alias = "displayName")]
pub display_name: String,
pub id: u64,
pub description: String,
#[serde(alias = "created")]
pub created_at: String,
#[serde(alias = "isBanned")]
pub is_terminated: bool,
#[serde(alias = "hasVerifiedBadge")]
pub has_verified_badge: bool,
}
#[allow(missing_docs)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub struct UsernameUserDetails {
pub requested_username: String,
#[serde(alias = "name")]
pub username: String,
#[serde(alias = "displayName")]
pub display_name: String,
pub id: u64,
#[serde(alias = "hasVerifiedBadge")]
pub has_verified_badge: bool,
}
impl Client {
pub(crate) async fn user_information_internal(
&self,
) -> Result<ClientUserInformation, RoboatError> {
let cookie = self.cookie_string()?;
let request_result = self
.reqwest_client
.get(AUTHENTICATED_USER_DETAILS_API)
.header(header::COOKIE, cookie)
.send()
.await;
let response = Self::validate_request_result(request_result).await?;
let user_information = Self::parse_to_raw::<ClientUserInformation>(response).await?;
self.set_user_information(user_information.clone()).await;
Ok(user_information)
}
pub async fn user_search(&self, keyword: String) -> Result<Vec<User>, RoboatError> {
let formatted_url = format!("{}?keyword={}", USERS_SEARCH_API, keyword);
let cookie_string = self.cookie_string().unwrap_or(HeaderValue::from_static(""));
let request_result = self
.reqwest_client
.get(formatted_url)
.header(header::COOKIE, cookie_string)
.send()
.await;
let response = Self::validate_request_result(request_result).await?;
let raw = Self::parse_to_raw::<request_types::UserSearchResponse>(response).await?;
let mut users = Vec::new();
for user in raw.data {
let user_data = User {
user_id: user.id,
username: user.name,
display_name: user.display_name,
};
users.push(user_data);
}
Ok(users)
}
pub async fn user_details(&self, user_id: u64) -> Result<UserDetails, RoboatError> {
let formatted_url = USER_DETAILS_API.replace("{user_id}", &user_id.to_string());
let request_result = self.reqwest_client.get(formatted_url).send().await;
let response = Self::validate_request_result(request_result).await?;
let user_details = Self::parse_to_raw::<UserDetails>(response).await?;
Ok(user_details)
}
pub async fn username_user_details(
&self,
usernames: Vec<String>,
exclude_banned_users: bool,
) -> Result<Vec<UsernameUserDetails>, RoboatError> {
let request_result = self
.reqwest_client
.post(USER_FROM_USERNAME_API)
.json(&request_types::UsernameUserDetailsRequest {
usernames,
exclude_banned_users,
})
.send()
.await;
let response = Self::validate_request_result(request_result).await?;
let raw =
Self::parse_to_raw::<request_types::UsernameUserDetailsResponse>(response).await?;
let users = raw
.data
.into_iter()
.map(|user| UsernameUserDetails {
requested_username: user.requested_username,
username: user.name,
display_name: user.display_name,
id: user.id,
has_verified_badge: user.has_verified_badge,
})
.collect();
Ok(users)
}
}