1use crate::error::HttpError;
2use crate::HttpClient;
3use serde::{Deserialize, Serialize};
4use titanium_model::{
5 AuditLogEntry, AutoModRule, Channel, GuildMember, Integration, Role, ScheduledEvent, Snowflake,
6 SoundboardSound, User, Webhook,
7};
8
9#[derive(Debug, Deserialize, Serialize)]
15pub struct AuditLog<'a> {
16 pub audit_log_entries: Vec<AuditLogEntry>,
17 pub auto_moderation_rules: Vec<AutoModRule>,
18 pub guild_scheduled_events: Vec<ScheduledEvent<'a>>,
19 pub integrations: Vec<Integration<'a>>,
20 pub threads: Vec<Channel<'a>>,
21 pub users: Vec<User<'a>>,
22 pub webhooks: Vec<Webhook<'a>>,
23}
24
25#[derive(Debug, Default, Serialize)]
26pub struct GetAuditLogParams {
27 pub user_id: Option<Snowflake>,
28 pub action_type: Option<u8>,
29 pub before: Option<Snowflake>,
30 pub after: Option<Snowflake>,
31 pub limit: Option<u32>,
32}
33
34impl HttpClient {
35 pub async fn get_member(
41 &self,
42 guild_id: Snowflake,
43 user_id: Snowflake,
44 ) -> Result<GuildMember<'static>, HttpError> {
45 let route = format!("/guilds/{}/members/{}", guild_id, user_id);
46 self.get(&route).await
47 }
48
49 pub async fn list_members(
51 &self,
52 guild_id: Snowflake,
53 limit: Option<u32>,
54 after: Option<Snowflake>,
55 ) -> Result<Vec<GuildMember<'static>>, HttpError> {
56 #[derive(Serialize)]
57 struct Query {
58 limit: u32,
59 after: Option<Snowflake>,
60 }
61
62 let query = Query {
63 limit: limit.unwrap_or(1),
64 after,
65 };
66
67 let route = format!("/guilds/{}/members", guild_id);
68 self.get_with_query(&route, &query).await
69 }
70
71 pub async fn kick_member(
73 &self,
74 guild_id: Snowflake,
75 user_id: Snowflake,
76 reason: Option<&str>,
77 ) -> Result<(), HttpError> {
78 let route = format!("/guilds/{}/members/{}", guild_id, user_id);
79
80 let headers = reason
81 .map(|r| -> Result<_, HttpError> {
82 let mut h = reqwest::header::HeaderMap::new();
83 h.insert(
84 "X-Audit-Log-Reason",
85 reqwest::header::HeaderValue::from_str(r)?,
86 );
87 Ok(h)
88 })
89 .transpose()?;
90
91 self.delete_with_headers(&route, headers).await
92 }
93
94 pub async fn ban_member(
96 &self,
97 guild_id: Snowflake,
98 user_id: Snowflake,
99 delete_message_seconds: Option<u32>,
100 reason: Option<&str>,
101 ) -> Result<(), HttpError> {
102 #[derive(Serialize)]
103 struct BanBody {
104 delete_message_seconds: Option<u32>,
105 }
106
107 let body = BanBody {
108 delete_message_seconds,
109 };
110 let route = format!("/guilds/{}/bans/{}", guild_id, user_id);
111
112 let headers = reason.and_then(|r| {
113 reqwest::header::HeaderValue::from_str(r).ok().map(|v| {
114 let mut h = reqwest::header::HeaderMap::new();
115 h.insert("X-Audit-Log-Reason", v);
116 h
117 })
118 });
119
120 self.put_with_headers(&route, Some(body), headers).await
121 }
122
123 pub async fn unban_member(
125 &self,
126 guild_id: Snowflake,
127 user_id: Snowflake,
128 reason: Option<&str>,
129 ) -> Result<(), HttpError> {
130 let route = format!("/guilds/{}/bans/{}", guild_id, user_id);
131
132 let headers = reason.and_then(|r| {
133 reqwest::header::HeaderValue::from_str(r).ok().map(|v| {
134 let mut h = reqwest::header::HeaderMap::new();
135 h.insert("X-Audit-Log-Reason", v);
136 h
137 })
138 });
139
140 self.delete_with_headers(&route, headers).await
141 }
142
143 pub async fn modify_member(
145 &self,
146 guild_id: Snowflake,
147 user_id: Snowflake,
148 params: &titanium_model::builder::ModifyMember<'_>,
149 ) -> Result<GuildMember<'static>, HttpError> {
150 let route = format!("/guilds/{}/members/{}", guild_id, user_id);
151 self.patch(&route, params).await
152 }
153
154 pub async fn get_roles(&self, guild_id: Snowflake) -> Result<Vec<Role<'static>>, HttpError> {
160 let route = format!("/guilds/{}/roles", guild_id);
161 self.get(&route).await
162 }
163
164 pub async fn create_role(
166 &self,
167 guild_id: Snowflake,
168 params: &titanium_model::builder::CreateRole<'_>,
169 ) -> Result<Role<'static>, HttpError> {
170 let route = format!("/guilds/{}/roles", guild_id);
171 self.post(&route, params).await
172 }
173
174 pub async fn delete_role(
176 &self,
177 guild_id: Snowflake,
178 role_id: Snowflake,
179 reason: Option<&str>,
180 ) -> Result<(), HttpError> {
181 let route = format!("/guilds/{}/roles/{}", guild_id, role_id);
182
183 let headers = reason
184 .map(|r| -> Result<_, HttpError> {
185 let mut h = reqwest::header::HeaderMap::new();
186 h.insert(
187 "X-Audit-Log-Reason",
188 reqwest::header::HeaderValue::from_str(r)?,
189 );
190 Ok(h)
191 })
192 .transpose()?;
193
194 self.delete_with_headers(&route, headers).await
195 }
196
197 pub async fn get_guild_audit_log(
203 &self,
204 guild_id: Snowflake,
205 params: &GetAuditLogParams,
206 ) -> Result<AuditLog<'static>, HttpError> {
207 let route = format!("/guilds/{}/audit-logs", guild_id);
208 self.get_with_query(&route, params).await
209 }
210
211 pub async fn list_guild_soundboard_sounds(
217 &self,
218 guild_id: Snowflake,
219 ) -> Result<Vec<SoundboardSound<'static>>, HttpError> {
220 self.get(&format!("/guilds/{}/soundboard-sounds", guild_id))
221 .await
222 }
223
224 pub async fn get_guild_soundboard_sound(
226 &self,
227 guild_id: Snowflake,
228 sound_id: Snowflake,
229 ) -> Result<SoundboardSound<'static>, HttpError> {
230 self.get(&format!(
231 "/guilds/{}/soundboard-sounds/{}",
232 guild_id, sound_id
233 ))
234 .await
235 }
236
237 pub async fn create_guild_soundboard_sound(
239 &self,
240 guild_id: Snowflake,
241 payload: &serde_json::Value,
242 ) -> Result<SoundboardSound<'static>, HttpError> {
243 self.post(&format!("/guilds/{}/soundboard-sounds", guild_id), payload)
244 .await
245 }
246
247 pub async fn modify_guild_soundboard_sound(
249 &self,
250 guild_id: Snowflake,
251 sound_id: Snowflake,
252 payload: &serde_json::Value,
253 ) -> Result<SoundboardSound<'static>, HttpError> {
254 self.patch(
255 &format!("/guilds/{}/soundboard-sounds/{}", guild_id, sound_id),
256 payload,
257 )
258 .await
259 }
260
261 pub async fn delete_guild_soundboard_sound(
263 &self,
264 guild_id: Snowflake,
265 sound_id: Snowflake,
266 ) -> Result<(), HttpError> {
267 self.delete(&format!(
268 "/guilds/{}/soundboard-sounds/{}",
269 guild_id, sound_id
270 ))
271 .await
272 }
273}