1use crate::cli::{Cli, Command};
2use crate::config;
3use crate::destinations::Destinations;
4use crate::errors::MusketError;
5use crate::shooters::{bluesky_shooter, linkedin_shooter, mastodon_shooter, turso_shooter};
6use crate::sources::{instapaper, Bookmark};
7use clap::Parser;
8use tracing::{debug, level_filters::LevelFilter};
9use tracing_subscriber::EnvFilter;
10
11#[allow(clippy::too_many_lines)]
17pub async fn run() -> Result<Vec<String>, MusketError> {
18 let mut success_messages: Vec<String> = vec![];
19 let cli = Cli::parse();
20
21 tracing_subscriber::fmt()
22 .with_env_filter(
23 EnvFilter::builder()
24 .with_default_directive(LevelFilter::INFO.into())
25 .from_env_lossy(),
26 )
27 .without_time()
28 .init();
29
30 match cli.cmd {
31 Command::Init { force } => {
32 debug!("Inside run function. Command::Init");
33
34 let overwrite = force.unwrap_or(false);
35
36 if config::configuration_exists()? && !overwrite {
37 return Err(MusketError::Cli {
38 message: "The configuration file already exists. If you want to overwrite it, please run the musket init command with the -f, --force option.".to_string(),
39 });
40 }
41
42 match config::configure() {
43 Ok(_) => {
44 success_messages.push(format!("The configuration file has been created here: \"{}\". \nTo start using Musket, please complete the configuration file with your data.",
45 config::get_configuration_path()
46 .unwrap_or_default()
47 .to_string_lossy()));
48 }
49 Err(e) => return Err(e.into()),
50 }
51 }
52 Command::Fire {
53 url,
54 from,
55 destination,
56 tags,
57 commentary,
58 language,
59 } => {
60 debug!("Inside run function. Command::Fire");
61
62 if !config::configuration_exists()? {
63 return Err(MusketError::Cli {
64 message: "The configuration file does not exist. To send any URL to any destination, please first run the musket init command and next fill the configuration file.".to_string(),
65 });
66 }
67
68 if url.is_none() && from.is_none() {
69 return Err(MusketError::Cli {
70 message: "Neither the url nor the from flags are present. Set, at least, one of them.".to_string(),
71 });
72 }
73
74 if destination.is_none() {
75 return Err(MusketError::Cli {
76 message: "The url cannot be sent to a non-existing destination. Set, at least, one valid destination.".to_string(),
77 });
78 }
79
80 let cfg = config::configure()?;
81 let mut tags = tags.unwrap_or_default();
82 let destinations = destination.unwrap_or_default();
83 let mut url = url.unwrap_or_default();
84 let mut bookmark: Bookmark = Bookmark {
85 id: 0,
86 url: String::new(),
87 tags: vec![],
88 };
89
90 if from.is_some() {
91 let instapaper = instapaper::Instapaper::new(
92 &cfg.instapaper.username,
93 &cfg.instapaper.password,
94 &cfg.instapaper.consumer_key,
95 &cfg.instapaper.consumer_secret,
96 );
97 bookmark = instapaper.get_bookmark().await?;
98 url = bookmark.url;
99 tags = bookmark.tags;
100 success_messages.push(format!(
101 "The bookmark \"{0}\" with this url \"{1}\" has been obtained from Instapaper.",
102 bookmark.id, url
103 ));
104 }
105
106 for target in destinations {
107 match target {
108 Destinations::All => {
109 success_messages.push(
110 bluesky_shooter(
111 &cfg,
112 &url,
113 tags.clone(),
114 commentary.as_ref(),
115 language.as_ref(),
116 )
117 .await?,
118 );
119 success_messages.push(
120 linkedin_shooter(
121 &cfg,
122 &url,
123 tags.clone(),
124 commentary.as_ref(),
125 language.as_ref(),
126 )
127 .await?,
128 );
129 success_messages.push(
130 mastodon_shooter(
131 &cfg,
132 &url,
133 tags.clone(),
134 commentary.as_ref(),
135 language.as_ref(),
136 )
137 .await?,
138 );
139 success_messages.push(turso_shooter(&cfg, &url, tags.clone(), None).await?);
140 }
141 Destinations::Bluesky => {
142 success_messages.push(
143 bluesky_shooter(
144 &cfg,
145 &url,
146 tags.clone(),
147 commentary.as_ref(),
148 language.as_ref(),
149 )
150 .await?,
151 );
152 }
153 Destinations::LinkedIn => {
154 success_messages.push(
155 linkedin_shooter(
156 &cfg,
157 &url,
158 tags.clone(),
159 commentary.as_ref(),
160 language.as_ref(),
161 )
162 .await?,
163 );
164 }
165 Destinations::Mastodon => {
166 success_messages.push(
167 mastodon_shooter(
168 &cfg,
169 &url,
170 tags.clone(),
171 commentary.as_ref(),
172 language.as_ref(),
173 )
174 .await?,
175 );
176 }
177 Destinations::Turso => {
178 success_messages.push(turso_shooter(&cfg, &url, tags.clone(), None).await?);
179 }
180 }
181 }
182
183 if from.is_some() {
184 let instapaper = instapaper::Instapaper::new(
185 &cfg.instapaper.username,
186 &cfg.instapaper.password,
187 &cfg.instapaper.consumer_key,
188 &cfg.instapaper.consumer_secret,
189 );
190 instapaper.delete_bookmark(bookmark.id).await?;
191 success_messages.push(format!(
192 "The bookmark \"{0}\" with this url \"{1}\" has been deleted of Instapaper.",
193 bookmark.id, url
194 ));
195 }
196 }
197 }
198 Ok(success_messages)
199}