1#![warn(missing_docs, clippy::unwrap_used)]
5
6pub mod args;
8pub mod config;
10pub mod error;
12pub mod upload;
14
15use crate::args::Args;
16use crate::config::Config;
17use crate::error::{Error, Result};
18use crate::upload::Uploader;
19use colored::Colorize;
20use std::fs;
21use std::io::IsTerminal;
22use std::io::{self, Read};
23
24const CONFIG_FILE: &str = "config.toml";
26
27pub fn run(args: Args) -> Result<()> {
29 let mut config = Config::default();
30 if let Some(ref config_path) = args.config {
31 config = toml::from_str(&fs::read_to_string(config_path)?)?
32 } else {
33 for path in [
34 dirs_next::home_dir().map(|p| p.join(".rustypaste").join(CONFIG_FILE)),
35 #[cfg(target_os = "macos")]
36 Some(config.retrieve_xdg_config_on_macos().join(CONFIG_FILE)),
37 dirs_next::config_dir().map(|p| p.join("rustypaste").join(CONFIG_FILE)),
38 ]
39 .iter()
40 .filter_map(|v| v.as_ref())
41 {
42 if path.exists() {
43 config = toml::from_str(&fs::read_to_string(path)?)?;
44 break;
45 }
46 }
47 }
48 config.parse_token_files();
49 config.update_from_args(&args);
50 if config.server.address.is_empty() {
51 return Err(Error::NoServerAddressError);
52 }
53
54 let uploader = Uploader::new(&config);
55 if args.print_server_version {
56 println!("rustypaste-server {}", uploader.retrieve_version()?.trim());
57 return Ok(());
58 }
59
60 if args.list_files {
61 let prettify = args.prettify
62 || config
63 .style
64 .as_ref()
65 .map(|style| style.prettify)
66 .unwrap_or(false);
67 uploader.retrieve_list(&mut io::stdout(), prettify)?;
68 return Ok(());
69 }
70
71 let mut results = Vec::new();
72 if let Some(ref url) = args.url {
73 results.push(uploader.upload_url(url));
74 } else if let Some(ref remote_url) = args.remote {
75 results.push(uploader.upload_remote_url(remote_url));
76 } else if !std::io::stdin().is_terminal() || args.files.contains(&String::from("-")) {
77 let mut buffer = Vec::new();
78 let mut stdin = io::stdin();
79 stdin.read_to_end(&mut buffer)?;
80 results.push(uploader.upload_stream(&*buffer));
81 } else {
82 for file in args.files.iter() {
83 if !args.delete {
84 results.push(uploader.upload_file(file))
85 } else {
86 results.push(uploader.delete_file(file))
87 }
88 }
89 }
90 let prettify = args.prettify
91 || config
92 .style
93 .as_ref()
94 .map(|style| style.prettify)
95 .unwrap_or(false);
96 let format_padding = prettify
97 .then(|| results.iter().map(|v| v.0.len()).max())
98 .flatten()
99 .unwrap_or(1);
100 for (data, result) in results.iter().map(|v| (v.0, v.1.as_ref())) {
101 let data = if prettify {
102 format!(
103 "{:p$} {} ",
104 data,
105 if result.is_ok() {
106 "=>".green().bold()
107 } else {
108 "=>".red().bold()
109 },
110 p = format_padding,
111 )
112 } else {
113 String::new()
114 };
115 match result {
116 Ok(url) => println!("{}{}", data, url.trim()),
117 Err(e) => eprintln!("{data}{e}"),
118 }
119 }
120
121 Ok(())
122}