1use crate::{
2 error,
3 options::TaskOptions,
4 response,
5 utils::{value_into_vec, PushExt},
6 Callbacks, Client, InnerClient, Result,
7};
8use base64::prelude::*;
9use serde::Serialize;
10use serde_json::{json, to_value, Map, Value};
11use snafu::prelude::*;
12
13#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
17pub enum PositionHow {
18 #[serde(rename = "POS_SET")]
19 Set,
20 #[serde(rename = "POS_CUR")]
21 Cur,
22 #[serde(rename = "POS_END")]
23 End,
24}
25
26impl InnerClient {
27 async fn custom_tell_multi(
28 &self,
29 method: &str,
30 offset: i32,
31 num: i32,
32 keys: Option<Vec<String>>,
33 ) -> Result<Vec<Map<String, Value>>> {
34 let mut params = value_into_vec(json!([offset, num]));
35 params.push_some(keys)?;
36 self.call_and_wait(method, params).await
37 }
38
39 pub async fn get_version(&self) -> Result<response::Version> {
40 self.call_and_wait("getVersion", vec![]).await
41 }
42
43 async fn returning_gid(&self, method: &str, gid: &str) -> Result<()> {
44 self.call_and_wait::<String>(method, vec![Value::String(gid.to_string())])
45 .await?;
46 Ok(())
47 }
48
49 pub async fn remove(&self, gid: &str) -> Result<()> {
50 self.returning_gid("remove", gid).await
51 }
52
53 pub async fn force_remove(&self, gid: &str) -> Result<()> {
54 self.returning_gid("forceRemove", gid).await
55 }
56
57 pub async fn pause(&self, gid: &str) -> Result<()> {
58 self.returning_gid("pause", gid).await
59 }
60
61 pub async fn pause_all(&self) -> Result<()> {
62 self.call_and_wait::<String>("pauseAll", vec![]).await?;
63 Ok(())
64 }
65
66 pub async fn force_pause(&self, gid: &str) -> Result<()> {
67 self.returning_gid("forcePause", gid).await
68 }
69
70 pub async fn force_pause_all(&self) -> Result<()> {
71 self.call_and_wait::<String>("forcePauseAll", vec![])
72 .await?;
73 Ok(())
74 }
75
76 pub async fn unpause(&self, gid: &str) -> Result<()> {
77 self.returning_gid("unpause", gid).await
78 }
79
80 pub async fn unpause_all(&self) -> Result<()> {
81 self.call_and_wait::<String>("unpauseAll", vec![]).await?;
82 Ok(())
83 }
84
85 pub async fn custom_tell_status(
86 &self,
87 gid: &str,
88 keys: Option<Vec<String>>,
89 ) -> Result<Map<String, Value>> {
90 let mut params = vec![Value::String(gid.to_string())];
91 params.push_some(keys)?;
92 self.call_and_wait("tellStatus", params).await
93 }
94
95 pub async fn tell_status(&self, gid: &str) -> Result<response::Status> {
96 self.call_and_wait("tellStatus", vec![Value::String(gid.to_string())])
97 .await
98 }
99
100 pub async fn get_uris(&self, gid: &str) -> Result<Vec<response::Uri>> {
101 self.call_and_wait("getUris", vec![Value::String(gid.to_string())])
102 .await
103 }
104
105 pub async fn get_files(&self, gid: &str) -> Result<Vec<response::File>> {
106 self.call_and_wait("getFiles", vec![Value::String(gid.to_string())])
107 .await
108 }
109
110 pub async fn get_peers(&self, gid: &str) -> Result<Vec<response::Peer>> {
111 self.call_and_wait("getPeers", vec![Value::String(gid.to_string())])
112 .await
113 }
114
115 pub async fn get_servers(&self, gid: &str) -> Result<Vec<response::GetServersResult>> {
116 self.call_and_wait("getServers", vec![Value::String(gid.to_string())])
117 .await
118 }
119
120 pub async fn tell_active(&self) -> Result<Vec<response::Status>> {
121 self.call_and_wait("tellActive", vec![]).await
122 }
123
124 pub async fn tell_waiting(&self, offset: i32, num: i32) -> Result<Vec<response::Status>> {
125 self.call_and_wait("tellWaiting", value_into_vec(json!([offset, num])))
126 .await
127 }
128
129 pub async fn tell_stopped(&self, offset: i32, num: i32) -> Result<Vec<response::Status>> {
130 self.call_and_wait("tellStopped", value_into_vec(json!([offset, num])))
131 .await
132 }
133
134 pub async fn custom_tell_active(
135 &self,
136 keys: Option<Vec<String>>,
137 ) -> Result<Vec<Map<String, Value>>> {
138 let mut params = Vec::new();
139 params.push_some(keys)?;
140 self.call_and_wait("tellActive", params).await
141 }
142
143 pub async fn custom_tell_waiting(
144 &self,
145 offset: i32,
146 num: i32,
147 keys: Option<Vec<String>>,
148 ) -> Result<Vec<Map<String, Value>>> {
149 self.custom_tell_multi("tellWaiting", offset, num, keys)
150 .await
151 }
152
153 pub async fn custom_tell_stopped(
154 &self,
155 offset: i32,
156 num: i32,
157 keys: Option<Vec<String>>,
158 ) -> Result<Vec<Map<String, Value>>> {
159 self.custom_tell_multi("tellStopped", offset, num, keys)
160 .await
161 }
162
163 pub async fn change_position(&self, gid: &str, pos: i32, how: PositionHow) -> Result<i32> {
164 let params = value_into_vec(json!([gid, pos, how]));
165 self.call_and_wait("changePosition", params).await
166 }
167
168 pub async fn change_uri(
174 &self,
175 gid: &str,
176 file_index: i32,
177 del_uris: Vec<String>,
178 add_uris: Vec<String>,
179 position: Option<i32>,
180 ) -> Result<(i32, i32)> {
181 let mut params = value_into_vec(json!([gid, file_index, del_uris, add_uris]));
182 params.push_some(position)?;
183 self.call_and_wait("changeUri", params).await
184 }
185
186 pub async fn get_option(&self, gid: &str) -> Result<TaskOptions> {
187 self.call_and_wait("getOption", vec![Value::String(gid.to_string())])
188 .await
189 }
190
191 pub async fn change_option(&self, gid: &str, options: TaskOptions) -> Result<()> {
192 self.call_and_wait(
193 "changeOption",
194 vec![
195 Value::String(gid.to_string()),
196 to_value(options).context(error::JsonSnafu)?,
197 ],
198 )
199 .await
200 }
201
202 pub async fn get_global_option(&self) -> Result<TaskOptions> {
203 self.call_and_wait("getGlobalOption", vec![]).await
204 }
205
206 pub async fn change_global_option(&self, options: TaskOptions) -> Result<()> {
207 self.call_and_wait(
208 "changeGlobalOption",
209 vec![to_value(options).context(error::JsonSnafu)?],
210 )
211 .await
212 }
213
214 pub async fn get_global_stat(&self) -> Result<response::GlobalStat> {
215 self.call_and_wait("getGlobalStat", vec![]).await
216 }
217
218 pub async fn purge_download_result(&self) -> Result<()> {
219 self.call_and_wait::<String>("purgeDownloadResult", vec![])
220 .await?;
221 Ok(())
222 }
223
224 pub async fn remove_download_result(&self, gid: &str) -> Result<()> {
225 self.call_and_wait::<String>("removeDownloadResult", vec![Value::String(gid.to_string())])
226 .await?;
227 Ok(())
228 }
229
230 pub async fn get_session_info(&self) -> Result<response::SessionInfo> {
231 self.call_and_wait("getSessionInfo", vec![]).await
232 }
233
234 pub async fn shutdown(&self) -> Result<()> {
235 self.call_and_wait::<String>("shutdown", vec![]).await?;
236 Ok(())
237 }
238
239 pub async fn force_shutdown(&self) -> Result<()> {
240 self.call_and_wait::<String>("forceShutdown", vec![])
241 .await?;
242 Ok(())
243 }
244
245 pub async fn save_session(&self) -> Result<()> {
246 self.call_and_wait::<String>("saveSession", vec![]).await?;
247 Ok(())
248 }
249}
250
251impl Client {
252 fn add_callbacks_option(&self, gid: &str, callbacks: Option<Callbacks>) {
253 if let Some(callbacks) = callbacks {
254 self.add_callbacks(gid.to_string(), callbacks);
255 }
256 }
257
258 pub async fn add_uri(
259 &self,
260 uris: Vec<String>,
261 options: Option<TaskOptions>,
262 position: Option<u32>,
263 callbacks: Option<Callbacks>,
264 ) -> Result<String> {
265 let mut params = vec![to_value(uris).context(error::JsonSnafu)?];
266 params.push_else(options, json!({}))?;
267 params.push_some(position)?;
268
269 let gid: String = self.call_and_wait("addUri", params).await?;
270 self.add_callbacks_option(&gid, callbacks);
271 Ok(gid)
272 }
273
274 pub async fn add_torrent(
275 &self,
276 torrent: impl AsRef<[u8]>,
277 uris: Option<Vec<String>>,
278 options: Option<TaskOptions>,
279 position: Option<u32>,
280 callbacks: Option<Callbacks>,
281 ) -> Result<String> {
282 let mut params = vec![Value::String(BASE64_STANDARD.encode(torrent))];
283 params.push_else(uris, json!([]))?;
284 params.push_else(options, json!({}))?;
285 params.push_some(position)?;
286
287 let gid: String = self.call_and_wait("addTorrent", params).await?;
288 self.add_callbacks_option(&gid, callbacks);
289 Ok(gid)
290 }
291
292 pub async fn add_metalink(
293 &self,
294 metalink: impl AsRef<[u8]>,
295 options: Option<TaskOptions>,
296 position: Option<u32>,
297 callbacks: Option<Callbacks>,
298 ) -> Result<String> {
299 let mut params = vec![Value::String(BASE64_STANDARD.encode(metalink))];
300 params.push_else(options, json!({}))?;
301 params.push_some(position)?;
302
303 let gid: String = self.call_and_wait("addMetalink", params).await?;
304 self.add_callbacks_option(&gid, callbacks);
305 Ok(gid)
306 }
307}