twapi_v2/api/
get_2_media_upload.rs1use crate::responses::{errors::Errors, includes::Includes, media_upload::MediaUpload};
2use crate::{
3 api::{apply_options, execute_twitter, make_url, Authentication, TwapiOptions},
4 error::Error,
5 headers::Headers,
6};
7use reqwest::RequestBuilder;
8use serde::{Deserialize, Serialize};
9
10const URL: &str = "/2/media/upload";
11
12#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
13pub enum Command {
14 #[serde(rename = "STATUS")]
15 Status,
16}
17
18impl std::fmt::Display for Command {
19 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
20 match self {
21 Self::Status => write!(f, "STATUS"),
22 }
23 }
24}
25
26impl Default for Command {
27 fn default() -> Self {
28 Self::Status
29 }
30}
31
32#[derive(Debug, Clone, Default)]
33pub struct Api {
34 media_id: String,
35 command: Command,
36 twapi_options: Option<TwapiOptions>,
37}
38
39impl Api {
40 pub fn new(media_id: &str, command: Command) -> Self {
41 Self {
42 media_id: media_id.to_owned(),
43 command,
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 query_parameters = vec![
55 ("media_id", self.media_id),
56 ("command", self.command.to_string()),
57 ];
58 let client = reqwest::Client::new();
59 let url = make_url(&self.twapi_options, URL);
60 let builder = client.get(&url).query(&query_parameters);
61 authentication.execute(
62 apply_options(builder, &self.twapi_options),
63 "GET",
64 &url,
65 &query_parameters
66 .iter()
67 .map(|it| (it.0, it.1.as_str()))
68 .collect::<Vec<_>>(),
69 )
70 }
71
72 pub async fn execute(
73 self,
74 authentication: &impl Authentication,
75 ) -> Result<(Response, Headers), Error> {
76 execute_twitter(self.build(authentication)).await
77 }
78}
79
80#[derive(Serialize, Deserialize, Debug, Clone, Default)]
81pub struct Response {
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub data: Option<MediaUpload>,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub errors: Option<Vec<Errors>>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub includes: Option<Includes>,
88 #[serde(flatten)]
89 pub extra: std::collections::HashMap<String, serde_json::Value>,
90}
91
92impl Response {
93 pub fn is_empty_extra(&self) -> bool {
94 let res = self.extra.is_empty()
95 && self
96 .data
97 .as_ref()
98 .map(|it| it.is_empty_extra())
99 .unwrap_or(true)
100 && self
101 .errors
102 .as_ref()
103 .map(|it| it.iter().all(|item| item.is_empty_extra()))
104 .unwrap_or(true)
105 && self
106 .includes
107 .as_ref()
108 .map(|it| it.is_empty_extra())
109 .unwrap_or(true);
110 if !res {
111 println!("Response {:?}", self.extra);
112 }
113 res
114 }
115}