use crate::model::{
sort::SortOrder,
user::{User, UserOrigin, UserSortKey},
};
use serde::Serialize;
use thiserror::Error;
use typed_builder::TypedBuilder;
#[derive(Serialize, PartialEq, Eq, Clone, Debug, Copy)]
#[serde(rename_all = "camelCase")]
pub enum UserState {
All,
Available,
Admin,
Moderator,
AdminOrModerator,
Silenced,
Suspended,
}
#[derive(Debug, Error, Clone)]
#[error("invalid user state")]
pub struct ParseUserStateError {
_priv: (),
}
impl std::str::FromStr for UserState {
type Err = ParseUserStateError;
fn from_str(s: &str) -> Result<UserState, Self::Err> {
match s {
"all" | "All" => Ok(UserState::All),
"available" | "Available" => Ok(UserState::Available),
"admin" | "Admin" => Ok(UserState::Admin),
"moderator" | "Moderator" => Ok(UserState::Moderator),
"adminOrModerator" | "AdminOrModerator" => Ok(UserState::AdminOrModerator),
"silenced" | "Silenced" => Ok(UserState::Silenced),
"suspended" | "Suspended" => Ok(UserState::Suspended),
_ => Err(ParseUserStateError { _priv: () }),
}
}
}
#[derive(Serialize, Default, Debug, Clone, TypedBuilder)]
#[serde(rename_all = "camelCase")]
#[builder(doc)]
pub struct Request {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub limit: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub offset: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub sort: Option<SortOrder<UserSortKey>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub state: Option<UserState>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub origin: Option<UserOrigin>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub username: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option, into))]
pub hostname: Option<String>,
}
impl misskey_core::Request for Request {
type Response = Vec<User>;
const ENDPOINT: &'static str = "admin/show-users";
}
impl_offset_pagination!(Request, User);
#[cfg(test)]
mod tests {
use super::{Request, UserState};
use crate::test::{ClientExt, TestClient};
#[tokio::test]
async fn request() {
let client = TestClient::new();
client.admin.test(Request::default()).await;
}
#[tokio::test]
async fn request_with_limit() {
let client = TestClient::new();
client
.admin
.test(Request {
limit: Some(100),
offset: None,
sort: None,
state: None,
origin: None,
username: None,
hostname: None,
})
.await;
}
#[tokio::test]
async fn request_with_offset() {
let client = TestClient::new();
client
.admin
.test(Request {
limit: None,
offset: Some(5),
sort: None,
state: None,
origin: None,
username: None,
hostname: None,
})
.await;
}
#[tokio::test]
async fn request_with_sort() {
use crate::model::{sort::SortOrder, user::UserSortKey};
let client = TestClient::new();
client
.admin
.test(Request {
limit: None,
offset: None,
sort: Some(SortOrder::Ascending(UserSortKey::Follower)),
state: None,
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: Some(SortOrder::Ascending(UserSortKey::CreatedAt)),
state: None,
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: Some(SortOrder::Descending(UserSortKey::UpdatedAt)),
state: None,
origin: None,
username: None,
hostname: None,
})
.await;
}
#[tokio::test]
async fn request_with_state() {
let client = TestClient::new();
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::All),
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::Admin),
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::Available),
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::Moderator),
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::Silenced),
origin: None,
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: Some(UserState::Suspended),
origin: None,
username: None,
hostname: None,
})
.await;
}
#[tokio::test]
async fn request_with_origin() {
use crate::model::user::UserOrigin;
let client = TestClient::new();
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: None,
origin: Some(UserOrigin::Local),
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: None,
origin: Some(UserOrigin::Remote),
username: None,
hostname: None,
})
.await;
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: None,
origin: Some(UserOrigin::Combined),
username: None,
hostname: None,
})
.await;
}
#[tokio::test]
async fn request_with_username_hostname() {
let client = TestClient::new();
client
.admin
.test(Request {
limit: None,
offset: None,
sort: None,
state: None,
origin: None,
username: Some("admin".to_string()),
hostname: Some("host".to_string()),
})
.await;
}
}