twapi_v2/api/
post_2_media_upload_initialize.rs1use crate::responses::errors::Errors;
2use crate::responses::media_upload::MediaUpload;
3use crate::{
4 api::{Authentication, TwapiOptions, 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(builder, "POST", &url, &[])
58 }
59
60 pub async fn execute(
61 &self,
62 authentication: &impl Authentication,
63 ) -> Result<(Response, Headers), Error> {
64 execute_twitter(|| self.build(authentication), &self.twapi_options).await
65 }
66}
67
68#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
69pub struct Response {
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub data: Option<MediaUpload>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub errors: Option<Vec<Errors>>,
74 #[serde(flatten)]
75 pub extra: std::collections::HashMap<String, serde_json::Value>,
76}
77
78impl Response {
79 pub fn is_empty_extra(&self) -> bool {
80 let res = self.extra.is_empty()
81 && self
82 .data
83 .as_ref()
84 .map(|it| it.is_empty_extra())
85 .unwrap_or(true)
86 && self
87 .errors
88 .as_ref()
89 .map(|it| it.iter().all(|item| item.is_empty_extra()))
90 .unwrap_or(true);
91 if !res {
92 println!("Response {:?}", self.extra);
93 }
94 res
95 }
96}