twapi_v2/api/
post_2_dm_conversations.rs1use crate::{
2 api::{Authentication, TwapiOptions, execute_twitter, make_url},
3 error::Error,
4 headers::Headers,
5};
6use reqwest::RequestBuilder;
7use serde::{Deserialize, Serialize};
8
9const URL: &str = "/2/dm_conversations";
10
11#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
12#[derive(Default)]
13pub enum ConversationType {
14 #[serde(rename = "Group")]
15 #[default]
16 Group,
17}
18
19impl std::fmt::Display for ConversationType {
20 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
21 match self {
22 Self::Group => write!(f, "Group"),
23 }
24 }
25}
26
27
28#[derive(Serialize, Deserialize, Debug, Default, Clone)]
29pub struct Attachment {
30 pub media_id: String,
31}
32
33#[derive(Serialize, Deserialize, Debug, Default, Clone)]
34pub struct Message {
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub attachments: Option<Vec<Attachment>>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub text: Option<String>,
39}
40
41#[derive(Serialize, Deserialize, Debug, Default, Clone)]
42pub struct Body {
43 pub conversation_type: ConversationType,
44 pub participant_ids: Vec<String>,
45 pub message: Message,
46}
47
48#[derive(Debug, Clone, Default)]
49pub struct Api {
50 body: Body,
51 twapi_options: Option<TwapiOptions>,
52}
53
54impl Api {
55 pub fn new(body: Body) -> Self {
56 Self {
57 body,
58 ..Default::default()
59 }
60 }
61
62 pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
63 self.twapi_options = Some(value);
64 self
65 }
66
67 pub fn build(&self, authentication: &impl Authentication) -> RequestBuilder {
68 let client = reqwest::Client::new();
69 let url = make_url(&self.twapi_options, URL);
70 let builder = client.post(&url).json(&self.body);
71 authentication.execute(builder, "POST", &url, &[])
72 }
73
74 pub async fn execute(
75 &self,
76 authentication: &impl Authentication,
77 ) -> Result<(Response, Headers), Error> {
78 execute_twitter(|| self.build(authentication), &self.twapi_options).await
79 }
80}
81
82#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
83pub struct Response {
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub data: Option<Data>,
86 #[serde(flatten)]
87 pub extra: std::collections::HashMap<String, serde_json::Value>,
88}
89
90impl Response {
91 pub fn is_empty_extra(&self) -> bool {
92 let res = self.extra.is_empty()
93 && self
94 .data
95 .as_ref()
96 .map(|it| it.is_empty_extra())
97 .unwrap_or(true);
98 if !res {
99 println!("Response {:?}", self.extra);
100 }
101 res
102 }
103}
104
105#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
106pub struct Data {
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub dm_conversation_id: Option<String>,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub dm_event_id: Option<String>,
111 #[serde(flatten)]
112 pub extra: std::collections::HashMap<String, serde_json::Value>,
113}
114
115impl Data {
116 pub fn is_empty_extra(&self) -> bool {
117 let res = self.extra.is_empty();
118 if !res {
119 println!("Data {:?}", self.extra);
120 }
121 res
122 }
123}