bobashare_admin/cli/
create.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::path::PathBuf;

use anyhow::{anyhow, Context};
use bobashare::{generate_randomized_id, storage::file::FileBackend};
use chrono::TimeDelta;
use clap::{Args, Subcommand};
use tokio::{
    fs::File,
    io::{self, AsyncWriteExt},
};
use tracing::{event, instrument, Level};

#[derive(Debug, Clone, Args)]
pub(crate) struct CreateUpload {
    /// How long (in days) before the upload expires and is deleted.
    ///
    /// If not provided, the default is no expiry (permanent).
    #[clap(short, long, value_parser)]
    expiry: Option<u16>,
    #[clap(short, long, value_parser)]
    source_file: PathBuf,

    #[clap(subcommand)]
    name: NameOptions,
}
#[derive(Debug, Clone, Subcommand)]
pub(crate) enum NameOptions {
    /// Use a randomized name for the upload
    Random {
        /// The length of name to randomly generate
        #[clap(short, long, default_value_t = 8)]
        length: u16,
    },
    /// Use a specific name for the upload
    Name {
        #[clap(short, long)]
        name: String,
    },
}

#[instrument(skip(backend))]
pub(crate) async fn create_upload(backend: FileBackend, args: CreateUpload) -> anyhow::Result<()> {
    let expiry = args.expiry.map(|e| TimeDelta::try_days(e.into()).unwrap());
    let name = match args.name {
        // TODO: handle already existing name
        NameOptions::Name { name } => name,
        NameOptions::Random { length } => generate_randomized_id(length.into()),
    };

    let filename = args
        .source_file
        .file_name()
        .ok_or_else(|| anyhow!("invalid filename for source file"))?
        .to_string_lossy()
        .to_string();
    let mut file = File::open(&args.source_file)
        .await
        .with_context(|| format!("error opening file at {:?}", &args.source_file))?;
    let mimetype = mime_guess::from_path(&args.source_file).first_or_octet_stream();

    let mut upload = backend
        .create_upload(name, filename, mimetype, expiry, None)
        .await?;

    println!("{:?}", upload.metadata);

    let copied = io::copy(&mut file, &mut upload.file).await?;

    event!(Level::DEBUG, "Wrote {} bytes to the upload file", copied);
    upload.file.flush().await?;
    upload.flush().await?;

    Ok(())
}