Skip to main content

twapi_v2/api/
post_2_media_upload_initialize.rs

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