1use crate::{
2 parse_response,
3 traits::{Method, Request},
4 util::{Error, NdArray, Result},
5 Ctx, LongPollResponse, Members, RequestBuilder, User,
6};
7use serde::Serialize;
8use serde_json::json;
9use std::sync::Arc;
10use tokio::sync::RwLock;
11
12const VK: &'static str = "https://api.vk.com/method";
13
14#[derive(Debug, Clone)]
15pub struct Methods {
16 pub request: RequestBuilder,
17 pub context: Arc<RwLock<Ctx>>,
18}
19
20impl Method for Methods {
21 fn new(token: String) -> Self {
22 Methods {
23 request: RequestBuilder::new(token),
24 context: Arc::new(RwLock::new(Ctx::default())),
25 }
26 }
27
28 async fn keyboard<T: Serialize, N: NdArray<T>>(
29 &self,
30 message: &str,
31 one_time: bool,
32 inline: bool,
33 buttons: N,
34 ) -> Result<()> {
35 let state = self.context.read().await;
36 let dim_1 = buttons.shape().dims()[1];
37 let dim_2 = buttons.shape().dims()[0];
38
39 if dim_1 > 5 {
43 return Err(Error::DimOutOfRange {
44 shape: buttons.shape(),
45 dim: dim_1 as i32,
46 });
47 } else if dim_2 > 10 {
48 return Err(Error::DimOutOfRange {
49 shape: buttons.shape(),
50 dim: dim_2 as i32,
51 });
52 }
53
54 let button = json!({
55 "one_time": one_time,
56 "inline": inline,
57 "buttons": json!(buttons.slice()),
58 });
59
60 for update in &state.updates {
61 let button = serde_json::to_string(&button).unwrap();
62 self.request
63 .post(
64 VK,
65 "messages.send",
66 &[
67 ("message", message.to_string()),
68 (
69 "peer_id",
70 update.object.message.as_ref().unwrap().peer_id.to_string(),
71 ),
72 ("keyboard", button),
73 ("random_id", String::from("0")),
74 ],
75 {},
76 )
77 .await?;
78 }
79 Ok(())
80 }
81
82 async fn event_answer<
83 'de,
84 T: Serialize,
85 A: serde::de::DeserializeOwned + PartialEq + Serialize,
86 >(
87 &self,
88 event_data: T,
89 payload: A,
90 ) -> Result<Option<A>> {
91 let context = self.context().await;
92
93 for update in &context.updates {
94 if let Some(data) = &update.object.payload {
95 let deserialized_payload = serde_json::from_value::<A>(data.clone())?;
96
97 if deserialized_payload != payload {
98 return Ok(None);
99 }
100
101 let event_data = serde_json::to_string(&event_data).unwrap();
102 let res = self
105 .request
106 .post(
107 VK,
108 "messages.sendMessageEventAnswer",
109 &[
110 ("event_data", event_data),
111 ("user_id", update.object.user_id.unwrap().to_string()),
112 (
113 "event_id",
114 update.object.event_id.as_ref().unwrap().to_string(),
115 ),
116 ("peer_id", update.object.peer_id.unwrap().to_string()),
117 ],
118 {},
119 )
120 .await?;
121
122 if let Ok(response) = parse_response!(res, crate::EventAnswer) {
123 if response.get_status().is_ok() {
124 return Ok(Some(payload));
125 }
126 }
127 }
128 }
129 Ok(None)
131 }
132
133 async fn reply(&self, message: &str) {
134 let state = self.context.read().await;
135 for update in &state.updates {
136 let peer_id = match update.update_type.as_str() {
139 "message_event" => update.object.peer_id.unwrap(),
140 "message_new" => update.object.message.as_ref().unwrap().peer_id,
141 _ => panic!("No peer_id found"),
142 };
143
144 self.request
145 .post(
146 VK,
147 "messages.send",
148 &[
149 ("message", message),
150 ("peer_id", &peer_id.to_string()),
151 ("random_id", "0"),
152 ],
153 {},
154 )
155 .await
156 .expect("Failed to send/get request from `messages.send`");
157 }
158 }
159
160 async fn long_poll(&self, group_id: u32) -> LongPollResponse {
161 let response = self
162 .request
163 .post(
164 VK,
165 "groups.getLongPollServer",
166 &[("group_id", &group_id.to_string())],
167 {},
168 )
169 .await
170 .expect("Unable to get request");
171
172 parse_response!(response, LongPollResponse)
173 .expect("Unable to parse `groups.getLongPollServer` response")
174 }
175
176 async fn connect(&self, server: &str, key: String, ts: String, wait: usize) -> Ctx {
177 let response = self
178 .request
179 .post(
180 server,
181 "",
182 &[
183 ("act", "a_check"),
184 ("key", &key),
185 ("ts", &ts),
186 ("wait", &wait.to_string()),
187 ],
188 {},
189 )
190 .await
191 .expect("Unable to get request");
192
193 parse_response!(response, Ctx).expect("Unable to parse longPoll request")
194 }
195
196 async fn get_users(&self, user_ids: &[i32]) -> Result<Vec<User>> {
197 let serialize = serde_json::to_string(&user_ids[0])?;
198 let response = self
199 .request
200 .post(VK, "users.get", &[("user_ids", &serialize)], {})
201 .await
202 .unwrap();
203 Ok(parse_response!(response, Vec<User>).expect("Unable to parse `users.get` response"))
204 }
205
206 async fn get_members(
208 &self,
209 offset: Option<u16>,
210 count: Option<u16>,
211 extended: bool,
212 ) -> Result<Members> {
213 let context = self.context().await;
214 for update in &context.updates {
215 if let Some(message) = &update.object.message {
216 let mut params = vec![("peer_id", message.peer_id.to_string())];
217
218 if extended {
219 params.push(("extended", String::from("1")));
220 } else {
221 params.push(("extended", String::from("0")));
222 }
223
224 if let Some(offset_val) = offset {
225 params.push(("offset", offset_val.to_string()));
226 }
227 if let Some(count_val) = count {
228 params.push(("count", count_val.to_string()));
229 }
230
231 let res = self
232 .request
233 .post(VK, "messages.getConversationMembers", ¶ms, {})
234 .await?;
235
236 return Ok(parse_response!(res, Members)?);
237 }
238 }
239 Err(Error::NoContent {
240 from: "getConversationMembers",
241 })
242 }
243
244 fn custom_request(&self) -> &RequestBuilder {
245 &self.request
246 }
247
248 async fn context(&self) -> tokio::sync::RwLockReadGuard<'_, Ctx> {
249 self.context.read().await
250 }
251}