misskey_api/endpoint/admin/
show_users.rs1use crate::model::{
2 sort::SortOrder,
3 user::{User, UserOrigin, UserSortKey},
4};
5
6use serde::Serialize;
7use thiserror::Error;
8use typed_builder::TypedBuilder;
9
10#[derive(Serialize, PartialEq, Eq, Clone, Debug, Copy)]
11#[serde(rename_all = "camelCase")]
12pub enum UserState {
13 All,
14 Available,
15 Admin,
17 Moderator,
18 AdminOrModerator,
19 Silenced,
20 Suspended,
21}
22
23#[derive(Debug, Error, Clone)]
24#[error("invalid user state")]
25pub struct ParseUserStateError {
26 _priv: (),
27}
28
29impl std::str::FromStr for UserState {
30 type Err = ParseUserStateError;
31
32 fn from_str(s: &str) -> Result<UserState, Self::Err> {
33 match s {
34 "all" | "All" => Ok(UserState::All),
35 "available" | "Available" => Ok(UserState::Available),
37 "admin" | "Admin" => Ok(UserState::Admin),
38 "moderator" | "Moderator" => Ok(UserState::Moderator),
39 "adminOrModerator" | "AdminOrModerator" => Ok(UserState::AdminOrModerator),
40 "silenced" | "Silenced" => Ok(UserState::Silenced),
41 "suspended" | "Suspended" => Ok(UserState::Suspended),
42 _ => Err(ParseUserStateError { _priv: () }),
43 }
44 }
45}
46
47#[derive(Serialize, Default, Debug, Clone, TypedBuilder)]
48#[serde(rename_all = "camelCase")]
49#[builder(doc)]
50pub struct Request {
51 #[serde(skip_serializing_if = "Option::is_none")]
53 #[builder(default, setter(strip_option))]
54 pub limit: Option<u8>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 #[builder(default, setter(strip_option))]
57 pub offset: Option<u64>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 #[builder(default, setter(strip_option))]
60 pub sort: Option<SortOrder<UserSortKey>>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 #[builder(default, setter(strip_option))]
63 pub state: Option<UserState>,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 #[builder(default, setter(strip_option))]
66 pub origin: Option<UserOrigin>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 #[builder(default, setter(strip_option, into))]
69 pub username: Option<String>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 #[builder(default, setter(strip_option, into))]
72 pub hostname: Option<String>,
73}
74
75impl misskey_core::Request for Request {
76 type Response = Vec<User>;
77 const ENDPOINT: &'static str = "admin/show-users";
78}
79
80impl_offset_pagination!(Request, User);
81
82#[cfg(test)]
83mod tests {
84 use super::{Request, UserState};
85 use crate::test::{ClientExt, TestClient};
86
87 #[tokio::test]
88 async fn request() {
89 let client = TestClient::new();
90 client.admin.test(Request::default()).await;
91 }
92
93 #[tokio::test]
94 async fn request_with_limit() {
95 let client = TestClient::new();
96 client
97 .admin
98 .test(Request {
99 limit: Some(100),
100 offset: None,
101 sort: None,
102 state: None,
103 origin: None,
104 username: None,
105 hostname: None,
106 })
107 .await;
108 }
109
110 #[tokio::test]
111 async fn request_with_offset() {
112 let client = TestClient::new();
113 client
114 .admin
115 .test(Request {
116 limit: None,
117 offset: Some(5),
118 sort: None,
119 state: None,
120 origin: None,
121 username: None,
122 hostname: None,
123 })
124 .await;
125 }
126
127 #[tokio::test]
128 async fn request_with_sort() {
129 use crate::model::{sort::SortOrder, user::UserSortKey};
130
131 let client = TestClient::new();
132
133 client
134 .admin
135 .test(Request {
136 limit: None,
137 offset: None,
138 sort: Some(SortOrder::Ascending(UserSortKey::Follower)),
139 state: None,
140 origin: None,
141 username: None,
142 hostname: None,
143 })
144 .await;
145 client
146 .admin
147 .test(Request {
148 limit: None,
149 offset: None,
150 sort: Some(SortOrder::Ascending(UserSortKey::CreatedAt)),
151 state: None,
152 origin: None,
153 username: None,
154 hostname: None,
155 })
156 .await;
157 client
158 .admin
159 .test(Request {
160 limit: None,
161 offset: None,
162 sort: Some(SortOrder::Descending(UserSortKey::UpdatedAt)),
163 state: None,
164 origin: None,
165 username: None,
166 hostname: None,
167 })
168 .await;
169 }
170
171 #[tokio::test]
172 async fn request_with_state() {
173 let client = TestClient::new();
174
175 client
176 .admin
177 .test(Request {
178 limit: None,
179 offset: None,
180 sort: None,
181 state: Some(UserState::All),
182 origin: None,
183 username: None,
184 hostname: None,
185 })
186 .await;
187 client
188 .admin
189 .test(Request {
190 limit: None,
191 offset: None,
192 sort: None,
193 state: Some(UserState::Admin),
194 origin: None,
195 username: None,
196 hostname: None,
197 })
198 .await;
199 client
200 .admin
201 .test(Request {
202 limit: None,
203 offset: None,
204 sort: None,
205 state: Some(UserState::Available),
206 origin: None,
207 username: None,
208 hostname: None,
209 })
210 .await;
211 client
224 .admin
225 .test(Request {
226 limit: None,
227 offset: None,
228 sort: None,
229 state: Some(UserState::Moderator),
230 origin: None,
231 username: None,
232 hostname: None,
233 })
234 .await;
235 client
247 .admin
248 .test(Request {
249 limit: None,
250 offset: None,
251 sort: None,
252 state: Some(UserState::Silenced),
253 origin: None,
254 username: None,
255 hostname: None,
256 })
257 .await;
258 client
259 .admin
260 .test(Request {
261 limit: None,
262 offset: None,
263 sort: None,
264 state: Some(UserState::Suspended),
265 origin: None,
266 username: None,
267 hostname: None,
268 })
269 .await;
270 }
271
272 #[tokio::test]
273 async fn request_with_origin() {
274 use crate::model::user::UserOrigin;
275
276 let client = TestClient::new();
277
278 client
279 .admin
280 .test(Request {
281 limit: None,
282 offset: None,
283 sort: None,
284 state: None,
285 origin: Some(UserOrigin::Local),
286 username: None,
287 hostname: None,
288 })
289 .await;
290 client
291 .admin
292 .test(Request {
293 limit: None,
294 offset: None,
295 sort: None,
296 state: None,
297 origin: Some(UserOrigin::Remote),
298 username: None,
299 hostname: None,
300 })
301 .await;
302 client
303 .admin
304 .test(Request {
305 limit: None,
306 offset: None,
307 sort: None,
308 state: None,
309 origin: Some(UserOrigin::Combined),
310 username: None,
311 hostname: None,
312 })
313 .await;
314 }
315
316 #[tokio::test]
317 async fn request_with_username_hostname() {
318 let client = TestClient::new();
319
320 client
321 .admin
322 .test(Request {
323 limit: None,
324 offset: None,
325 sort: None,
326 state: None,
327 origin: None,
328 username: Some("admin".to_string()),
329 hostname: Some("host".to_string()),
330 })
331 .await;
332 }
333}