twilight_model/gateway/payload/outgoing/
request_guild_members.rs1use crate::{
2 gateway::opcode::OpCode,
3 id::{
4 marker::{GuildMarker, UserMarker},
5 Id,
6 },
7};
8use serde::{Deserialize, Serialize};
9use std::{
10 error::Error,
11 fmt::{Display, Formatter, Result as FmtResult},
12};
13
14#[derive(Debug)]
18pub struct UserIdsError {
19 kind: UserIdsErrorType,
20}
21
22impl UserIdsError {
23 #[must_use = "retrieving the type has no effect if left unused"]
25 pub const fn kind(&self) -> &UserIdsErrorType {
26 &self.kind
27 }
28
29 #[allow(clippy::unused_self)]
31 #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
32 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
33 None
34 }
35
36 #[must_use = "consuming the error into its parts has no effect if left unused"]
38 pub fn into_parts(self) -> (UserIdsErrorType, Option<Box<dyn Error + Send + Sync>>) {
39 (self.kind, None)
40 }
41
42 const fn too_many(ids: Vec<Id<UserMarker>>) -> Self {
43 Self {
44 kind: UserIdsErrorType::TooMany { ids },
45 }
46 }
47}
48
49impl Display for UserIdsError {
50 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
51 match &self.kind {
52 UserIdsErrorType::TooMany { ids } => {
53 Display::fmt(&ids.len(), f)?;
54 f.write_str(" user IDs were provided when only a maximum of 100 is allowed")
55 }
56 }
57 }
58}
59
60impl Error for UserIdsError {}
61
62#[derive(Debug)]
64#[non_exhaustive]
65pub enum UserIdsErrorType {
66 TooMany {
68 ids: Vec<Id<UserMarker>>,
70 },
71}
72
73#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
74pub struct RequestGuildMembers {
75 pub d: RequestGuildMembersInfo,
76 pub op: OpCode,
77}
78
79impl RequestGuildMembers {
80 pub const fn builder(guild_id: Id<GuildMarker>) -> RequestGuildMembersBuilder {
85 RequestGuildMembersBuilder::new(guild_id)
86 }
87}
88
89#[derive(Clone, Debug, Eq, PartialEq)]
90pub struct RequestGuildMembersBuilder {
91 guild_id: Id<GuildMarker>,
92 nonce: Option<String>,
93 presences: Option<bool>,
94}
95
96impl RequestGuildMembersBuilder {
97 pub const fn new(guild_id: Id<GuildMarker>) -> Self {
100 Self {
101 guild_id,
102 nonce: None,
103 presences: None,
104 }
105 }
106
107 #[must_use = "has no effect if not built into a RequestGuildMembers"]
111 pub fn nonce(self, nonce: impl Into<String>) -> Self {
112 self._nonce(nonce.into())
113 }
114
115 fn _nonce(mut self, nonce: String) -> Self {
116 self.nonce.replace(nonce);
117
118 self
119 }
120
121 #[must_use = "has no effect if not built into a RequestGuildMembers"]
125 pub fn presences(mut self, presences: bool) -> Self {
126 self.presences.replace(presences);
127
128 self
129 }
130
131 pub fn query(self, query: impl Into<String>, limit: Option<u64>) -> RequestGuildMembers {
159 self._query(query.into(), limit)
160 }
161
162 fn _query(self, query: String, limit: Option<u64>) -> RequestGuildMembers {
163 RequestGuildMembers {
164 d: RequestGuildMembersInfo {
165 guild_id: self.guild_id,
166 limit: Some(limit.unwrap_or_default()),
167 nonce: self.nonce,
168 presences: self.presences,
169 query: Some(query),
170 user_ids: None,
171 },
172 op: OpCode::RequestGuildMembers,
173 }
174 }
175
176 #[allow(clippy::missing_const_for_fn)]
201 pub fn user_id(self, user_id: Id<UserMarker>) -> RequestGuildMembers {
202 RequestGuildMembers {
203 d: RequestGuildMembersInfo {
204 guild_id: self.guild_id,
205 limit: None,
206 nonce: self.nonce,
207 presences: self.presences,
208 query: None,
209 user_ids: Some(RequestGuildMemberId::One(user_id)),
210 },
211 op: OpCode::RequestGuildMembers,
212 }
213 }
214
215 pub fn user_ids(
247 self,
248 user_ids: impl Into<Vec<Id<UserMarker>>>,
249 ) -> Result<RequestGuildMembers, UserIdsError> {
250 self._user_ids(user_ids.into())
251 }
252
253 fn _user_ids(self, user_ids: Vec<Id<UserMarker>>) -> Result<RequestGuildMembers, UserIdsError> {
254 if user_ids.len() > 100 {
255 return Err(UserIdsError::too_many(user_ids));
256 }
257
258 Ok(RequestGuildMembers {
259 d: RequestGuildMembersInfo {
260 guild_id: self.guild_id,
261 limit: None,
262 nonce: self.nonce,
263 presences: self.presences,
264 query: None,
265 user_ids: Some(RequestGuildMemberId::Multiple(user_ids)),
266 },
267 op: OpCode::RequestGuildMembers,
268 })
269 }
270}
271
272#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
273pub struct RequestGuildMembersInfo {
274 pub guild_id: Id<GuildMarker>,
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub limit: Option<u64>,
279 #[serde(skip_serializing_if = "Option::is_none")]
280 pub nonce: Option<String>,
281 #[serde(skip_serializing_if = "Option::is_none")]
282 pub presences: Option<bool>,
283 #[serde(skip_serializing_if = "Option::is_none")]
284 pub query: Option<String>,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 pub user_ids: Option<RequestGuildMemberId<Id<UserMarker>>>,
287}
288
289#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
291#[serde(untagged)]
292pub enum RequestGuildMemberId<T> {
293 One(T),
295 Multiple(Vec<T>),
297}
298
299impl<T> From<T> for RequestGuildMemberId<T> {
300 fn from(id: T) -> Self {
301 Self::One(id)
302 }
303}
304
305impl<T> From<Vec<T>> for RequestGuildMemberId<T> {
306 fn from(ids: Vec<T>) -> Self {
307 Self::Multiple(ids)
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::RequestGuildMembersBuilder;
314 use static_assertions::assert_impl_all;
315 use std::fmt::Debug;
316
317 assert_impl_all!(
318 RequestGuildMembersBuilder: Clone,
319 Debug,
320 Eq,
321 PartialEq,
322 Send,
323 Sync
324 );
325}