1use crate::client::Client;
2use crate::formatting::header;
3use crate::trello_error::TrelloError;
4use crate::trello_object::{Renderable, TrelloObject};
5
6use serde::Deserialize;
7
8type Result<T> = std::result::Result<T, TrelloError>;
9
10#[derive(Deserialize, Debug, Eq, PartialEq, Clone)]
11#[serde(rename_all = "camelCase")]
12pub struct Attachment {
13 pub id: String,
14 pub name: String,
15 pub url: String,
16}
17
18impl Attachment {
19 pub fn get_all(client: &Client, card_id: &str) -> Result<Vec<Attachment>> {
20 let url = client.get_trello_url(
21 &format!("/1/cards/{}/attachments", card_id),
22 &[("fields", &Attachment::get_fields().join(","))],
23 )?;
24
25 Ok(reqwest::get(url)?.error_for_status()?.json()?)
26 }
27
28 pub fn apply(client: &Client, card_id: &str, file: &str) -> Result<Attachment> {
29 let url = client.get_trello_url(&format!("/1/cards/{}/attachments", card_id), &[])?;
30
31 let form = reqwest::multipart::Form::new().file("file", file)?;
32
33 Ok(reqwest::Client::new()
34 .post(url)
35 .multipart(form)
36 .send()?
37 .error_for_status()?
38 .json()?)
39 }
40}
41
42impl TrelloObject for Attachment {
43 fn get_type() -> String {
44 String::from("Attachment")
45 }
46
47 fn get_name(&self) -> &str {
48 &self.name
49 }
50
51 fn get_fields() -> &'static [&'static str] {
52 &["id", "name", "url"]
53 }
54}
55
56impl Renderable for Attachment {
57 fn render(&self) -> String {
58 [header(&self.name, "-").as_str(), &self.url].join("\n")
59 }
60}