1use serde::{Deserialize, Serialize};
2
3use crate::{source::Item, util::cmd::CommandBuilder};
4
5use super::{multidownload, ClientConfig, DownloadClient, DownloadError, DownloadResult};
6
7#[derive(Serialize, Deserialize, Clone)]
8#[serde(default)]
9pub struct CmdConfig {
10 cmd: String,
11 shell_cmd: String,
12}
13
14pub struct CmdClient;
15
16impl Default for CmdConfig {
17 fn default() -> Self {
18 CmdConfig {
19 #[cfg(windows)]
20 cmd: "curl \"{torrent}\" -o ~\\Downloads\\{file}".to_owned(),
21 #[cfg(unix)]
22 cmd: "curl \"{torrent}\" > ~/{file}".to_owned(),
23
24 shell_cmd: CommandBuilder::default_shell(),
25 }
26 }
27}
28
29pub fn load_config(cfg: &mut ClientConfig) {
30 if cfg.cmd.is_none() {
31 cfg.cmd = Some(CmdConfig::default());
32 }
33}
34
35impl DownloadClient for CmdClient {
36 async fn download(item: Item, conf: ClientConfig, _: reqwest::Client) -> DownloadResult {
37 let cmd = match conf.cmd.to_owned() {
38 Some(c) => c,
39 None => {
40 return DownloadResult::error(DownloadError("Failed to get cmd config".to_owned()));
41 }
42 };
43 let res = CommandBuilder::new(cmd.cmd)
44 .sub("{magnet}", &item.magnet_link)
45 .sub("{torrent}", &item.torrent_link)
46 .sub("{title}", &item.title)
47 .sub("{file}", &item.file_name)
48 .run(cmd.shell_cmd)
49 .map_err(|e| DownloadError(e.to_string()));
50
51 let (success_ids, errors) = match res {
52 Ok(()) => (vec![item.id], vec![]),
53 Err(e) => (vec![], vec![DownloadError(e.to_string())]),
54 };
55 DownloadResult::new(
56 "Successfully ran command".to_owned(),
57 success_ids,
58 errors,
59 false,
60 )
61 }
62
63 async fn batch_download(
64 items: Vec<Item>,
65 conf: ClientConfig,
66 client: reqwest::Client,
67 ) -> DownloadResult {
68 multidownload::<CmdClient, _>(
69 |s| format!("Successfully ran command on {} torrents", s),
70 &items,
71 &conf,
72 &client,
73 )
74 .await
75 }
76}