twapi_v2/api/
post_2_media_upload_finalize.rs

1use crate::responses::errors::Errors;
2use crate::responses::media_upload::MediaUpload;
3use crate::{
4    api::{apply_options, execute_twitter, make_url, Authentication, TwapiOptions},
5    error::Error,
6    headers::Headers,
7};
8use reqwest::multipart::Form;
9use reqwest::RequestBuilder;
10use serde::{Deserialize, Serialize};
11
12const URL: &str = "/2/media/upload";
13
14#[derive(Debug, Clone, Default)]
15pub struct FormData {
16    pub media_id: String,
17}
18
19impl FormData {
20    fn make_form(self) -> Form {
21        Form::new()
22            .text("command", "FINALIZE")
23            .text("media_id", self.media_id)
24    }
25}
26
27#[derive(Debug, Clone, Default)]
28pub struct Api {
29    form: FormData,
30    twapi_options: Option<TwapiOptions>,
31}
32
33impl Api {
34    pub fn new(form: FormData) -> Self {
35        Self {
36            form,
37            ..Default::default()
38        }
39    }
40
41    pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
42        self.twapi_options = Some(value);
43        self
44    }
45
46    pub fn build(self, authentication: &impl Authentication) -> RequestBuilder {
47        let client = reqwest::Client::new();
48        let url = make_url(&self.twapi_options, URL);
49        let builder = client.post(&url).multipart(self.form.make_form());
50        authentication.execute(
51            apply_options(builder, &self.twapi_options),
52            "POST",
53            &url,
54            &[],
55        )
56    }
57
58    pub async fn execute(
59        self,
60        authentication: &impl Authentication,
61    ) -> Result<(Response, Headers), Error> {
62        execute_twitter(self.build(authentication)).await
63    }
64}
65
66#[derive(Serialize, Deserialize, Debug, Clone, Default)]
67pub struct Response {
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub data: Option<MediaUpload>,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub errors: Option<Vec<Errors>>,
72    #[serde(flatten)]
73    pub extra: std::collections::HashMap<String, serde_json::Value>,
74}
75
76impl Response {
77    pub fn is_empty_extra(&self) -> bool {
78        let res = self.extra.is_empty()
79            && self
80                .data
81                .as_ref()
82                .map(|it| it.is_empty_extra())
83                .unwrap_or(true)
84            && self
85                .errors
86                .as_ref()
87                .map(|it| it.iter().all(|item| item.is_empty_extra()))
88                .unwrap_or(true);
89        if !res {
90            println!("Response {:?}", self.extra);
91        }
92        res
93    }
94}