lexoffice_cli/resources/
file.rs1use lexoffice::model::File;
2use lexoffice::request::Request;
3use lexoffice::Client;
4use lexoffice::Result;
5use mime_guess::get_extensions;
6use reqwest::header::CONTENT_TYPE;
7use std::pin::Pin;
8use std::str::FromStr;
9use structopt::StructOpt;
10use tokio::fs;
11use tokio::io::{AsyncWrite, AsyncWriteExt};
12use tokio_stream::StreamExt;
13
14#[derive(Debug, StructOpt)]
16pub enum FileOpt {
17 Upload(UploadOpt),
19 Get(GetOpt),
21}
22
23impl FileOpt {
24 pub async fn exec(&self, client: Client) -> Result<()> {
25 let request = client.request::<File>();
26 match self {
27 Self::Upload(x) => x.exec(request).await,
28 Self::Get(x) => x.exec(request).await,
29 }
30 }
31}
32
33#[derive(Debug, StructOpt)]
34pub struct UploadOpt {
35 file: String,
36}
37
38impl UploadOpt {
39 pub async fn exec(&self, request: Request<File>) -> Result<()> {
40 println!("{}", request.upload_path(self.file.clone()).await?);
41 Ok(())
42 }
43}
44
45#[derive(Debug, StructOpt)]
46pub struct GetOpt {
47 id: String,
48 #[structopt(short, long)]
49 output: Option<String>,
50}
51
52impl GetOpt {
53 pub async fn exec(&self, request: Request<File>) -> Result<()> {
54 let response = request.by_id_str(&self.id).await?;
55 let output = if let Some(output) = &self.output {
56 output.clone()
57 } else {
58 let content_type = response
59 .headers()
60 .get(CONTENT_TYPE)
61 .expect("has Content-Type Header")
62 .to_str()
63 .unwrap();
64 let mime = mime::Mime::from_str(content_type).unwrap();
65 format!(
66 "{}.{}",
67 self.id,
68 get_extensions(mime.type_().as_str(), mime.subtype().as_str())
69 .unwrap()[0]
70 )
71 };
72 let mut output: Pin<Box<dyn AsyncWrite>> = if output == "-" {
73 Box::pin(tokio::io::stdout())
74 } else {
75 Box::pin(fs::File::create(output).await?)
76 };
77 let mut stream = response.bytes_stream();
78 while let Some(x) = stream.next().await {
79 output.write_all(&x?).await?;
80 }
81 Ok(())
82 }
83}