Skip to main content

clickup_cli/commands/
attachment.rs

1use clap::Subcommand;
2use crate::client::ClickUpClient;
3use crate::commands::auth::resolve_token;
4use crate::commands::workspace::resolve_workspace;
5use crate::error::CliError;
6use crate::output::OutputConfig;
7use crate::Cli;
8
9#[derive(Subcommand)]
10pub enum AttachmentCommands {
11    /// Upload a file attachment to a task
12    Upload {
13        /// Task ID
14        #[arg(long)]
15        task: String,
16        /// Path to the file to upload
17        file: std::path::PathBuf,
18    },
19    /// List attachments for a task (v3)
20    List {
21        /// Task ID
22        #[arg(long)]
23        task: String,
24    },
25}
26
27const ATTACHMENT_FIELDS: &[&str] = &["id", "title", "url", "date"];
28
29pub async fn execute(command: AttachmentCommands, cli: &Cli) -> Result<(), CliError> {
30    let token = resolve_token(cli)?;
31    let client = ClickUpClient::new(&token, cli.timeout)?;
32    let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
33
34    match command {
35        AttachmentCommands::Upload { task, file } => {
36            let resp = client
37                .upload_file(&format!("/v2/task/{}/attachment", task), &file)
38                .await?;
39            output.print_single(&resp, ATTACHMENT_FIELDS, "id");
40            Ok(())
41        }
42        AttachmentCommands::List { task } => {
43            let team_id = resolve_workspace(cli)?;
44            let resp = client
45                .get(&format!("/v3/workspaces/{}/task/{}/attachments", team_id, task))
46                .await?;
47            let attachments = resp
48                .get("attachments")
49                .and_then(|a| a.as_array())
50                .cloned()
51                .unwrap_or_default();
52            output.print_items(&attachments, ATTACHMENT_FIELDS, "id");
53            Ok(())
54        }
55    }
56}